coriolis/katana/src/PreProcess.cpp

451 lines
17 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | K i t e - D e t a i l e d R o u t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | =============================================================== |
// | C++ Module : "./PreProcess.cpp" |
// +-----------------------------------------------------------------+
#include <sstream>
#include "hurricane/DebugSession.h"
#include "hurricane/Bug.h"
#include "hurricane/Warning.h"
#include "hurricane/Net.h"
#include "hurricane/Name.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Horizontal.h"
#include "anabatic/AutoContactTerminal.h"
#include "katana/DataNegociate.h"
#include "katana/TrackElement.h"
#include "katana/Track.h"
#include "katana/RoutingPlane.h"
#include "katana/NegociateWindow.h"
#include "katana/Session.h"
#include "katana/KatanaEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace CRL;
using namespace Katana;
using Anabatic::perpandicularTo;
using Anabatic::AutoSegment;
using Anabatic::AutoContactTerminal;
using Anabatic::AutoSegments_OnContact;
using Anabatic::AutoSegments;
class SortAcByXY {
public:
inline bool operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 ) const;
};
inline bool SortAcByXY::operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 ) const
{
DbU::Unit x1 = contact1->getX();
DbU::Unit x2 = contact2->getX();
if (x1 == x2) {
DbU::Unit y1 = contact1->getY();
DbU::Unit y2 = contact2->getY();
if (y1 == y2) return false;
return (y1 < y2);
}
return (x1 < x2);
}
void getPerpandiculars ( TrackElement* segment
, Anabatic::AutoContact* from
, Flags direction
, vector<TrackElement*>& perpandiculars
)
{
TrackElement* perpandicular;
for( Segment* osegment : segment->base()->getAutoSource()->getSlaveComponents().getSubSet<Segment*>() ) {
perpandicular = Session::lookup ( osegment );
cdebug_log(159,0) << "S " << perpandicular << endl;
if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue;
perpandiculars.push_back ( perpandicular );
}
for( Segment* osegment : segment->base()->getAutoTarget()->getSlaveComponents().getSubSet<Segment*>() ) {
perpandicular = Session::lookup ( osegment );
cdebug_log(159,0) << "T " << perpandicular << endl;
if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue;
perpandiculars.push_back ( perpandicular );
}
}
void findFailedPerpandiculars ( RoutingPad* rp, Flags direction, set<TrackElement*>& faileds )
{
cdebug_log(159,0) << "Find failed caging: " << rp << endl;
TrackElement* parallel;
for( Segment* osegment : rp->getSlaveComponents().getSubSet<Segment*>() ) {
parallel = Session::lookup ( osegment );
cdebug_log(159,0) << "* " << parallel << endl;
if ( parallel->isFixed () ) continue;
if ( parallel->getDirection() != direction ) continue;
Anabatic::AutoContact* contact = parallel->base()->getAutoSource();
if ( contact->base()->getAnchor() != rp ) contact = NULL;
if ( contact == NULL ) contact = parallel->base()->getAutoTarget();
if ( contact->base()->getAnchor() != rp ) continue;
//parallel->makeDogLeg ( contact->getGCell() );
faileds.insert ( parallel );
}
}
void propagateCagedConstraints ( TrackElement* segment, set<TrackElement*>& faileds )
{
cdebug_log(159,0) << "propagateCagedConstraints(): " << segment << endl;
if (not segment->isFixed()) return;
Track* track = segment->getTrack();
//Flags direction = Session::getRoutingGauge()->getLayerDirection(segment->getLayer());
Flags direction = segment->getDirection();
Anabatic::AutoContact* source = segment->base()->getAutoSource();
RoutingPad* rp = NULL;
Interval uside = source->getGCell()->getSide(direction);
DbU::Unit minConstraint = DbU::Min;
DbU::Unit maxConstraint = DbU::Max;
vector<TrackElement*> perpandiculars;
if ( not track ) {
cerr << Bug( "%s is not inserted in a <Track>", getString(segment).c_str() ) << endl;
return;
}
// Computing constraints from fixed only TrackElements (caging).
TrackElement* parallel;
size_t i = track->find( segment );
while ( (i != Track::npos) and (i > 0) ) {
parallel = track->getSegment( --i );
if (not parallel) continue;
if (parallel->getTargetU() < uside.getVMin()) break;
if (parallel->getNet() == segment->getNet()) continue;
if (not parallel->isFixed()) continue;
cdebug_log(159,0) << "Min Constraint from: " << parallel << endl;
minConstraint = max( minConstraint, parallel->getTargetU() );
}
i = track->find( segment );
while ( i < track->getSize()-1 ) {
parallel = track->getSegment( ++i );
if (not parallel) continue;
if (parallel->getSourceU() > uside.getVMax()) break;
if (parallel->getNet() == segment->getNet()) continue;
if (not parallel->isFixed()) continue;
cdebug_log(159,0) << "Max Constraint from: " << parallel << endl;
maxConstraint = min( maxConstraint, parallel->getSourceU() );
}
if (minConstraint > maxConstraint) {
cerr << Bug( "%s have too tight caging constraints.", getString(segment).c_str() ) << endl;
return;
}
if ( (minConstraint <= uside.getVMin()) and (maxConstraint >= uside.getVMax()) ) {
cdebug_log(159,0) << "No constraints [" << DbU::getValueString(minConstraint)
<< ":" << DbU::getValueString(maxConstraint)
<< " vs. " << uside << endl;
return;
}
// Finding perpandiculars, by way of the source & target RoutingPad.
if (source->getAnchor()) {
rp = dynamic_cast<RoutingPad*>(source->getAnchor());
if (rp) {
TrackElement* parallel;
for( Segment* osegment : rp->getSlaveComponents().getSubSet<Segment*>() ) {
parallel = Session::lookup( osegment );
if (not parallel) continue;
cdebug_log(159,0) << "* " << parallel << endl;
if (parallel->isFixed ()) continue;
if (parallel->isGlobal()) continue;
getPerpandiculars( parallel, source, direction, perpandiculars );
getPerpandiculars( parallel, segment->base()->getAutoTarget(), direction, perpandiculars );
}
} else {
cerr << Bug( "%s is not anchored on a <RoutingPad>\n (%s)"
, getString(source).c_str()
, getString(source->getAnchor()).c_str() ) << endl;
}
}
// Apply caging constraints to perpandiculars.
cdebug_tabw(159,1);
if (perpandiculars.size() == 0) {
cdebug_log(159,0) << "No perpandiculars to " << segment << endl;
cdebug_tabw(159,-1);
return;
}
Interval constraints ( minConstraint, maxConstraint );
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
cdebug_log(159,0) << "Caged: " << constraints << " " << perpandiculars[iperpand] << endl;
perpandiculars[iperpand]->base()->mergeUserConstraints( constraints );
if (perpandiculars[iperpand]->base()->getUserConstraints().isEmpty()) {
cdebug_log(159,0) << "Cumulative caged constraints are too tight on " << perpandiculars[iperpand] << endl;
findFailedPerpandiculars( rp, direction, faileds );
}
}
cdebug_tabw(159,-1);
}
#if THIS_IS_DISABLED
void moveUpCaged ( TrackElement* segment )
{
DebugSession::open( segment->getNet(), 150, 160 );
cdebug_log(159,1) << "::moveUpCaged() " << segment << endl;
//Configuration* configuration = Session::getConfiguration();
//const Layer* metal2 = configuration->getRoutingLayer( 1 );
//const Layer* metal3 = configuration->getRoutingLayer( 2 );
Anabatic::AutoContact* support = segment->base()->getAutoSource();
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
for( Component* component : rp->getSlaveComponents() ) {
Horizontal* baseSegment = dynamic_cast<Horizontal*>( component );
TrackElement* accessSegment = Session::lookup( baseSegment );
if (accessSegment and not accessSegment->isFixed()) {
accessSegment->moveUp( Flags::NoFlags );
}
}
cdebug_tabw(159,-1);
DebugSession::close();
}
#endif
void protectCagedTerminals ( Track* track )
{
cdebug_log(159,1) << "protectCagedTerminals() " << track << endl;
DbU::Unit lastMovedUp = track->getMin();
uint32_t moveUpCount = 0;
Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 );
//const Layer* metal3 = configuration->getRoutingLayer( 2 );
Net* neighborNet = NULL;
RoutingPlane* metal3plane = track->getRoutingPlane()->getTop();
if (track->getLayer() != metal2) {
cdebug_tabw(159,-1);
return;
}
for ( size_t i=0 ; i<track->getSize() ; ++i ) {
TrackElement* segment = track->getSegment(i);
if (not segment or segment->isRouted()) continue;
if (segment and segment->isFixed() and segment->isTerminal()) {
DbU::Unit ppitch = segment->getPPitch();
//DbU::Unit pitch = segment->getPitch();
if ( ((segment->getSourceU() - track->getMin()) < 2*ppitch)
or ((track->getMax() - segment->getTargetU()) < 2*ppitch) ) continue;
Interval freeInterval = track->getFreeInterval( segment->getSourceU(), segment->getNet() );
//if (freeInterval.getSize() < ppitch*6) {
if ( (segment->getSourceU() - freeInterval.getVMin() < ppitch*3)
or (freeInterval.getVMax() - segment->getTargetU() < ppitch*3) ) {
cparanoid << "[INFO] Caged terminal: " << segment << endl;
Anabatic::AutoContact* support = NULL;
Anabatic::AutoContact* turn = NULL;
if (segment->base()->isSourceTerminal()) {
support = segment->base()->getAutoSource();
turn = segment->base()->getAutoTarget();
} else {
support = segment->base()->getAutoTarget();
turn = segment->base()->getAutoSource();
}
DbU::Unit supportLength = support->getConstraintBox().getWidth();
cdebug_log(159,0) << "Support length (rp): " << DbU::getValueString(supportLength) << endl;
if ( (segment->getLayer () != metal2)
//or (segment->getLength() >= ppitch)
or (supportLength >= ppitch)
or (segment->getNet () == neighborNet) ) {
neighborNet = segment->getNet();
continue;
}
cdebug_log(159,0) << "Protect " << segment << endl;
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() );
turn->restrictConstraintBox( freeInterval.getVMin()
, freeInterval.getVMax()
, Flags::Vertical );
if (metal3track->getFreeInterval(segment->getAxis(),segment->getNet()).isEmpty()) {
cparanoid << "[INFO] Cannot protect caged terminal because top layer (metal3) is obstructed." << endl;
continue;
}
if (segment->getSourceU() - lastMovedUp < ppitch*4) {
++moveUpCount;
if (moveUpCount % 2 == 0) {
//moveUpCaged( segment );
}
} else {
moveUpCount = 0;
}
lastMovedUp = segment->getSourceU();
#if NOT_NEEDED_AFTER_6502_OPTIM
Anabatic::AutoContact* source
= Anabatic::AutoContactTerminal::create( support->getGCell()
, rp
, metal3
, rp->getSourcePosition()
, DbU::fromLambda(1.0), DbU::fromLambda(1.0)
);
source->setFlags( Anabatic::CntIgnoreAnchor|Anabatic::CntFixed );
Anabatic::AutoContact* target =
Anabatic::AutoContactTerminal::create( support->getGCell()
, rp
, metal3
, rp->getSourcePosition()
, DbU::fromLambda(1.0), DbU::fromLambda(1.0)
);
target->setFlags( Anabatic::CntIgnoreAnchor|Anabatic::CntFixed );
AutoSegment* fixedSegment = AutoSegment::create( source, target, Flags::Vertical );
fixedSegment->setFlags( AutoSegment::SegFixed );
Session::getNegociateWindow()->createTrackSegment( fixedSegment, Flags::LoadingStage );
#endif
}
neighborNet = segment->getNet();
}
}
cdebug_tabw(159,-1);
}
#if THIS_IS_DISABLED
void metal2protect ( AutoContactTerminal* contact )
{
const Layer* metal2 = Session::getRoutingLayer(1);
RoutingPlane* metal3plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( 2 );
DbU::Unit metal3axis = metal3plane->getTrackByPosition( contact->getY() )->getAxis();
RoutingPad* rp = dynamic_cast<RoutingPad*>( contact->getAnchor() );
DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0);
Point position ( contact->getX(), metal3axis );
AutoContact* sourceVia12 = AutoContactTerminal::create( contact->getGCell()
, rp
, metal2
, position
, viaSideProtect, viaSideProtect
);
AutoContact* targetVia12 = AutoContactTerminal::create( contact->getGCell()
, rp
, metal2
, position
, viaSideProtect, viaSideProtect
);
AutoSegment* segment = AutoSegment::create( sourceVia12, targetVia12, Flags::Vertical );
sourceVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
targetVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
segment->setFlags( AutoSegment::SegFixed );
Session::getNegociateWindow()->createTrackSegment( segment, Flags::LoadingStage );
cdebug_log(145,0) << "Hard protect: " << contact << endl;
cdebug_log(145,0) << "X:" << DbU::getValueString(position.getX())
<< " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl;
}
#endif
} // End of local namespace.
namespace Katana {
using Hurricane::Bug;
using Hurricane::Net;
using Hurricane::Name;
using Anabatic::AutoSegmentLut;
void KatanaEngine::preProcess ()
{
//DebugSession::open( 145, 150 );
for ( size_t i=0 ; i<_routingPlanes.size() ; ++i ) {
RoutingPlane* plane = _routingPlanes[i];
Track* track = plane->getTrackByIndex( 0 );
while ( track ) {
protectCagedTerminals( track );
track = track->getNextTrack();
}
}
//DebugSession::close();
Session::revalidate ();
}
void KatanaEngine::_computeCagedConstraints ()
{
set<TrackElement*> faileds;
TrackElement* segment = NULL;
AutoSegmentLut::const_iterator isegment = _getAutoSegmentLut().begin();
for ( ; isegment != _getAutoSegmentLut().end() ; isegment++ ) {
segment = _lookup( isegment->second );
if (not segment or not segment->isFixed()) continue;
DebugSession::open( segment->getNet(), 150, 160 );
propagateCagedConstraints( segment, faileds );
DebugSession::close();
}
}
} // Katana namespace.