// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved // // =================================================================== // // $Id$ // // x-----------------------------------------------------------------x // | | // | 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" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include "hurricane/Bug.h" #include "hurricane/Warning.h" #include "hurricane/Net.h" #include "hurricane/Name.h" #include "hurricane/RoutingPad.h" #include "katabatic/AutoContact.h" #include "kite/GCell.h" #include "kite/DataNegociate.h" #include "kite/TrackElement.h" #include "kite/Track.h" #include "kite/RoutingPlane.h" #include "kite/Session.h" #include "kite/KiteEngine.h" namespace { using namespace std; using namespace Hurricane; using namespace CRL; using namespace Kite; void getPerpandiculars ( TrackElement* segment , AutoContact* from , unsigned int direction , vector& perpandiculars ) { //AutoContact* to = segment->base()->getAutoSource(); //to = (to != from) ? to : segment->base()->getAutoTarget(); TrackElement* perpandicular; forEach ( Segment*, isegment, segment->base()->getAutoSource()->getSlaveComponents().getSubSet() ) { perpandicular = Session::lookup ( *isegment ); ltrace(200) << "S " << perpandicular << endl; if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue; perpandiculars.push_back ( perpandicular ); } forEach ( Segment*, isegment, segment->base()->getAutoTarget()->getSlaveComponents().getSubSet() ) { perpandicular = Session::lookup ( *isegment ); ltrace(200) << "T " << perpandicular << endl; if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue; perpandiculars.push_back ( perpandicular ); } } void propagateCagedConstraints ( TrackElement* segment ) { if ( not segment->isFixed() ) return; ltrace(200) << "Propagate caging: " << segment << endl; Track* track = segment->getTrack(); unsigned int direction = Session::getRoutingGauge()->getLayerDirection(segment->getLayer()); AutoContact* source = segment->base()->getAutoSource(); Interval uside = source->getGCell()->getUSide(direction); DbU::Unit minConstraint = DbU::Min; DbU::Unit maxConstraint = DbU::Max; vector perpandiculars; if ( not track ) { cerr << Bug("%s is not inserted in a ",getString(segment).c_str()) << endl; return; } // Computing constraints from fixed only TrackElements (caging). TrackElement* parallel; size_t i = segment->getIndex(); while ( 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; ltrace(200) << "Min Constraint from: " << parallel << endl; minConstraint = max ( minConstraint, parallel->getTargetU() ); } i = segment->getIndex(); 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; ltrace(200) << "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()) ) { ltrace(200) << "No constraints [" << DbU::getValueString(minConstraint) << ":" << DbU::getValueString(maxConstraint) << " vs. " << uside << endl; return; } // Finding perpandiculars, by way of the source & target RoutingPad. if ( source->getAnchor() ) { RoutingPad* rp = dynamic_cast(source->getAnchor()); if ( rp ) { TrackElement* parallel; forEach ( Segment*, isegment, rp->getSlaveComponents().getSubSet() ) { parallel = Session::lookup ( *isegment ); ltrace(200) << "* " << 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 \n (%s)" ,getString(source).c_str() ,getString(source->getAnchor()).c_str()) << endl; } } // Apply caging constraints to perpandiculars. ltracein(200); if ( perpandiculars.size() == 0 ) { ltrace(200) << "No perpandiculars to " << segment << endl; } Interval constraints ( minConstraint, maxConstraint ); for ( size_t iperpand=0 ; iperpandbase()->mergeUserConstraints ( constraints ); } ltraceout(200); } void freeCagedTerminals ( Track* track ) { Configuration* configuration = Session::getConfiguration (); const Layer* metal2 = configuration->getRoutingLayer ( 1 ); const Layer* metal3 = configuration->getRoutingLayer ( 2 ); for ( size_t i=0 ; igetSize() ; i++ ) { TrackElement* segment = track->getSegment ( i ); if ( segment and segment->isFixed() and segment->isTerminal() ) { Interval freeInterval = track->getFreeInterval ( segment->getSourceU(), segment->getNet() ); if ( freeInterval.getSize() < DbU::lambda(30.0) ) { cinfo << "Caged terminal: " << segment << endl; if ( segment->getLayer() != metal2 ) continue; if ( segment->getLength() >= DbU::lambda(5.0) ) continue; AutoContact* support = segment->base()->getAutoSource(); RoutingPad* rp = dynamic_cast(support->getAnchor()); GCell* gcell = Session::lookup ( support->getGCell() ); #if 0 Point point ( segment->base()->getSourceU(), track->getAxis() ); GCell* gcell = Session::lookup ( segment->base()->getAutoSource()->getGCell() ); AutoContact* source = AutoContact::create ( gcell->base(), segment->getNet(), metal3 ); AutoContact* target = AutoContact::create ( gcell->base(), segment->getNet(), metal3 ); source->setPosition ( point ); target->setPosition ( point ); #endif AutoContact* source = AutoContact::fromRp ( gcell->base() , rp , metal3 , rp->getSourcePosition() , DbU::lambda(1.0), DbU::lambda(1.0) , true ); AutoContact* target = AutoContact::fromRp ( gcell->base() , rp , metal3 , rp->getSourcePosition() , DbU::lambda(1.0), DbU::lambda(1.0) , true ); AutoSegment* segment = AutoSegment::create ( source , target , Constant::Vertical , AutoSegment::Local , true , false ); segment->setFixed ( true ); GCell::addTrackSegment ( gcell, segment, true ); #if DISABLED // Force slackening. bool breakFlag = false; forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet() ) { forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet() ) { TrackElement* trackSegment = Session::lookup(*isegment); if ( not trackSegment or trackSegment->isFixed() ) continue; if ( trackSegment->isHorizontal() ) { ltrace(200) << "M2 to slacken for " << rp << endl; breakFlag = true; const vector& dogLegs = Session::getDogLegs(); trackSegment->base()->makeDogLeg ( gcell->base(), true ); GCell::addTrackSegment ( gcell, dogLegs[1], true ); GCell::addTrackSegment ( gcell, dogLegs[2], true ); Session::revalidate (); } if ( breakFlag ) break; } if ( breakFlag ) break; } #endif } } } } } // End of local namespace. namespace Kite { using Hurricane::Bug; using Hurricane::Net; using Hurricane::Name; void KiteEngine::preProcess () { for ( size_t i=0 ; i<_routingPlanes.size() ; i++ ) { RoutingPlane* plane = _routingPlanes[i]; Track* track = plane->getTrackByIndex ( 0 ); while ( track ) { freeCagedTerminals ( track ); track = track->getNext (); } } Session::revalidate (); } void KiteEngine::_computeCagedConstraints () { TrackElementLut::iterator isegment = _trackSegmentLut.begin(); for ( ; isegment != _trackSegmentLut.end() ; isegment++ ) { if ( not isegment->second->isFixed() ) continue; propagateCagedConstraints ( isegment->second ); } } void KiteEngine::_computeCagedConstraints ( Net* net ) { TrackElement* segment = NULL; forEach ( Segment*, isegment, net->getComponents().getSubSet() ) { segment = Session::lookup ( *isegment ); if ( not segment ) continue; segment->base()->resetUserConstraints(); } forEach ( Segment*, isegment, net->getComponents().getSubSet() ) { segment = Session::lookup ( *isegment ); if ( not segment ) continue; propagateCagedConstraints ( segment ); } } } // End of Kite namespace.