// -*- mode: C++; explicit-buffer-name: "Dijkstra.cpp" -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2016-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | A n a b a t i c - Global Routing Toolbox | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./anabatic/Dijkstra.cpp" | // +-----------------------------------------------------------------+ #include #include #include "hurricane/Error.h" #include "hurricane/Warning.h" #include "hurricane/Net.h" #include "hurricane/Pin.h" #include "hurricane/RoutingPad.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/UpdateSession.h" #include "hurricane/DebugSession.h" #include "crlcore/Utilities.h" #include "anabatic/AnabaticEngine.h" #include "anabatic/Dijkstra.h" #include "hurricane/DataBase.h" #include "hurricane/viewer/CellViewer.h" #include "hurricane/Technology.h" #include "hurricane/NetRoutingProperty.h" namespace Anabatic { using std::cerr; using std::endl; using std::numeric_limits; using Hurricane::ForEachIterator; using Hurricane::Error; using Hurricane::Warning; using Hurricane::Component; using Hurricane::Pin; using Hurricane::Segment; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::RoutingPad; using Hurricane::UpdateSession; using Hurricane::DebugSession; using Hurricane::NetRoutingExtension; DbU::Unit calcDistance( Point p1, Point p2 ) { return abs(p1.getX()-p2.getX()) + abs(p1.getY()-p2.getY()); } DbU::Unit calcMidIntersection( DbU::Unit imin1, DbU::Unit imax1, DbU::Unit imin2, DbU::Unit imax2 ) { if ( (imin1 > imax1) || (imin2 > imax2) ){ cerr << "DbU::Unit calcMidIntersection(...): Wrong parameters." << endl; return 0; } if ( (imin1 > imax2) || (imax1 < imin2) ) { cerr << "DbU::Unit calcMidIntersection(...): No intersection." << endl; return 0; } return ( max(imin1, imin2) + min(imax1, imax2) )/2; } // ------------------------------------------------------------------- // Class : "Anabatic::IntervalC". IntervalC::IntervalC() { _min = Vertex::unreached; _max = Vertex::unreached; _axis = Vertex::unreached; _flags = 0; } IntervalC::IntervalC(IntervalC& i) { _min = i.getMin(); _max = i.getMax(); _axis = i.getAxis(); setFlags(i.getFlags()); } IntervalC::IntervalC(const IntervalC& i) { _min = i.getMin(); _max = i.getMax(); _axis = i.getAxis(); setFlags(i.getFlags()); } IntervalC::IntervalC( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { _min = min; _max = max; _axis = axis; setiSet(); } IntervalC::~IntervalC() {} void IntervalC::set ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { _min = min; _max = max; _axis = axis; setiSet(); } void IntervalC::setRange( DbU::Unit vmin, DbU::Unit vmax ) { if (vmin < vmax){ _min = vmin; _max = vmax; setiSet(); } else { _min = vmax; _max = vmin; setiSet(); } } void IntervalC::extendMin( DbU::Unit vmin ) { if (_min > vmin) _min = vmin; } void IntervalC::extendMax( DbU::Unit vmax ) { if (_max < vmax) _max = vmax; } void IntervalC::print() const { cdebug_log(112,0) << "[IntervalC]: min: " << DbU::getValueString(_min) << ", max:" << DbU::getValueString(_max) << ", axis:" << DbU::getValueString(_axis) << endl; } void IntervalC::reset() { _min = Vertex::unreached; _max = Vertex::unreached; _axis = Vertex::unreached; _flags &= ~iSet; } // ------------------------------------------------------------------- // Class : "Anabatic::GRAData". GRAData::GRAData () : _intervfrom (IntervalC()) , _interv (IntervalC()) , _from2 (NULL) , _intervfrom2 (IntervalC()) {} GRAData::~GRAData() {} GRAData* GRAData::create() { return new GRAData(); } void GRAData::resetIntervals() { _interv.reset(); _intervfrom.reset(); } void GRAData::clearFrom2 () { _from2 = NULL; } // ------------------------------------------------------------------- // Class : "Anabatic::Vertex". DbU::Unit Vertex::unreached = std::numeric_limits::max(); DbU::Unit Vertex::unreachable = std::numeric_limits::max()-1; bool Vertex::hasValidStamp () const { return _stamp == getAnabatic()->getStamp(); } Edge* Vertex::getFrom() const { if (hasValidStamp()) return _from; else return NULL; } void Vertex::setRestricted () { setNRestricted(); setSRestricted(); setERestricted(); setWRestricted(); } void Vertex::clearRestriction () { unsetFlags(NRestricted); unsetFlags(SRestricted); unsetFlags(ERestricted); unsetFlags(WRestricted); } bool Vertex::hasRP ( Net* net ) const { if (getGCell() != NULL ){ Cell* cell = getGCell()->getAnabatic()->getCell(); RoutingPad* rp = NULL; for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){ rp = dynamic_cast( component ); if (rp) { if (rp->getNet() == net) return true; } } } return false; } bool Vertex::hasVRP ( Net* net ) const { if (getGCell() != NULL){ Cell* cell = getGCell()->getAnabatic()->getCell(); RoutingPad* rp = NULL; for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){ rp = dynamic_cast( component ); if (rp) { if (rp->getNet() == net) break; } } if (rp) { Vertical* v = dynamic_cast(rp->_getEntityAs()); if (v) { return true; } } } return false; } bool Vertex::hasHRP ( Net* net ) const { if (getGCell() != NULL){ Cell* cell = getGCell()->getAnabatic()->getCell(); RoutingPad* rp = NULL; for ( Component* component : cell->getComponentsUnder(getGCell()->getBoundingBox().inflate(-1)) ){ rp = dynamic_cast( component ); if (rp) { if (rp->getNet() == net) break; } } if (rp) { Horizontal* h = dynamic_cast(rp->_getEntityAs()); if (h) { return true; } } } return false; } bool Vertex::isRestricted ( const Vertex* v1, const Vertex* v2, const Edge* e, DbU::Unit hpitch, DbU::Unit vpitch, Net* net ) { bool restricted = true; GCell* c1 = v1->getGCell(); GCell* c2 = v2->getGCell(); // Check from GCell 1 if ( c1->isNorth(c2) and not v1->isNRestricted() ) restricted = false; else if ( c1->isSouth(c2) and not v1->isSRestricted() ) restricted = false; else if ( c1->isEast (c2) and not v1->isERestricted() ) restricted = false; else if ( c1->isWest (c2) and not v1->isWRestricted() ) restricted = false; // else { // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n" // " v1:%s\n" // " v2:%s" // , getString(v1).c_str() // , getString(v2).c_str() // ) << endl; // return true; // } if (restricted) { cdebug_log(112,0) << "v1 -> v2 edge is restricted." << endl; return true; } if ( e->isVertical() and (c1->getWidth() < hpitch) ) { cdebug_log(112,0) << "GCell 1 is too narrow for V edges." << endl; return true; } if ( e->isHorizontal() and (c1->getHeight() < vpitch) ) { cdebug_log(112,0) << "GCell 1 is too narrow for H edges." << endl; return true; } restricted = true; // Check from GCell 2 if ( c2->isNorth(c1) and not v2->isNRestricted() ) restricted = false; else if ( c2->isSouth(c1) and not v2->isSRestricted() ) restricted = false; else if ( c2->isEast (c1) and not v2->isERestricted() ) restricted = false; else if ( c2->isWest (c1) and not v2->isWRestricted() ) restricted = false; // else { // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n" // " v1:%s\n" // " v2:%s" // , getString(v1).c_str() // , getString(v2).c_str() // ) << endl; // return true; // } if (restricted) { cdebug_log(112,0) << "v2 -> v1 edge is restricted." << endl; return true; } if ( e->isVertical() and (c2->getWidth() < hpitch) ) { cdebug_log(112,0) << "GCell 2 is too narrow for V edges." << endl; return true; } if ( e->isHorizontal() and (c2->getHeight() < vpitch) ) { cdebug_log(112,0) << "GCell 2 is too narrow for H edges." << endl; return true; } if ( v2->getGCell()->isStrut() and e->isMaxCapacity(net) ) { cdebug_log(112,0) << "Overcapacity:" << e << endl; return true; } return false; } Point Vertex::getNextPathPoint ( Point pcurr, const Vertex* vnext ) const { cdebug_log(112,1) << "Point Dijkstra::getNextPathPoint( Point pcurr, const Vertex* vnext )" << endl; if (vnext == NULL){ cdebug_tabw(112,-1); return Point(0,0); } //<<<<<<< HEAD /*if (vnext->getGCell()->isMatrix()) { ======= if (not vnext->getGCell()->isAnalog()) { >>>>>>> 987289653831df12933bd4490d9559415e61f220 cdebug_tabw(112,-1); return Point(vnext->getGCell()->getXCenter(), vnext->getGCell()->getYCenter()); }*/ GCell* gnext = vnext->getGCell(); GCell* gcurr = getGCell(); DbU::Unit x = 0; DbU::Unit y = 0; if (vnext->isV()){ //cdebug_log(112,0) << "Case next: Vertical: " << vnext->isiSet() << endl; //", d:" << vnext->getDistance() << endl; if ((vnext->isiSet())&&(vnext->hasValidStamp())){ //cdebug_log(112,0) << "Case set" << endl; x = vnext->getIAxis(); if (isNorth(vnext)) y = vnext->getIMin(); else if (isSouth(vnext)) y = vnext->getIMax(); else if ((isWest(vnext))||(isEast(vnext))) { if ( pcurr.getY() > vnext->getIMax() ) y = vnext->getIMax(); else if ( pcurr.getY() < vnext->getIMin() ) y = vnext->getIMin(); else y = pcurr.getY(); } else cdebug_log(112,0) << "[ERROR](Point Vertex::getNextPathPoint2(...) const: Something is wrong.1" << endl; } else { //cdebug_log(112,0) << "Case not set" << endl; if (isNorth(vnext)){ y = gcurr->getYMax(); if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin(); else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax(); else x = pcurr.getX(); } else if (isSouth(vnext)){ y = gcurr->getYMin(); if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin(); else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax(); else x = pcurr.getX(); } else if (isWest(vnext)){ x = gcurr->getXMin(); if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin(); else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax(); else y = pcurr.getY(); } else if (isEast(vnext)){ x = gcurr->getXMax(); if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin(); else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax(); else y = pcurr.getY(); } else cdebug_log(112,0) << "[ERROR](Point Vertex::getNextPathPoint2(...) const: Something is wrong.2" << endl; } } else if (vnext->isH()) { //cdebug_log(112,0) << "Case next: Horizontal: " << vnext->isiSet() << endl; //", d:" << vnext->getDistance() << endl; if ((vnext->isiSet())&&(vnext->hasValidStamp())){ //cdebug_log(112,0) << "Case set" << endl; y = vnext->getIAxis(); if (isEast (vnext)) x = vnext->getIMin(); else if (isWest (vnext)) x = vnext->getIMax(); else if ((isNorth(vnext))||(isSouth(vnext))) { if ( pcurr.getX() > vnext->getIMax() ) x = vnext->getIMax(); else if ( pcurr.getX() < vnext->getIMin() ) x = vnext->getIMin(); else x = pcurr.getX(); } else cdebug_log(112,0) << "[ERROR](Point Vertex::getNextPathPoint2(...) const: Something is wrong.3" << endl; } else { //cdebug_log(112,0) << "Case not set" << endl; if (isNorth(vnext)){ y = gcurr->getYMax(); if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin(); else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax(); else x = pcurr.getX(); } else if (isSouth(vnext)){ y = gcurr->getYMin(); if (pcurr.getX() < gnext->getXMin()) x = gnext->getXMin(); else if (pcurr.getX() > gnext->getXMax()) x = gnext->getXMax(); else x = pcurr.getX(); } else if (isWest(vnext)){ x = gcurr->getXMin(); if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin(); else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax(); else y = pcurr.getY(); } else if (isEast(vnext)){ x = gcurr->getXMax(); if (pcurr.getY() < gnext->getYMin()) y = gnext->getYMin(); else if (pcurr.getY() > gnext->getYMax()) y = gnext->getYMax(); else y = pcurr.getY(); } else cdebug_log(112,0) << "[ERROR](Point Vertex::getNextPathPoint2(...) const: Something is wrong.4" << endl; } } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getNextPathPoint2(...) const: Something is wrong.5: " << vnext << endl; } cdebug_tabw(112,-1); return Point(x,y); } Point Vertex::getStartPathPoint ( const Vertex* next ) const { cdebug_log(112,1) << "Point Vertex::getStartPathPoint( const Vertex* next ) const:" << this << endl; GCell* gcurr = getGCell(); GCell* gnext = next->getGCell(); DbU::Unit x = 0; DbU::Unit y = 0; IntervalC intervfrom = IntervalC(); if (_adata == NULL){ //cdebug_log(112,0) << "Point Vertex::getStartPathPoint( const Vertex* next ) const: Digital vertex." << endl; cdebug_tabw(112,-1); return Point(0,0); } if (gcurr->isMatrix()){ GCell* gprev = getGPrev(); cdebug_log(112,-1) << endl; if (gprev) { Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (isNorth(vprev)) return Point (gcurr->getXCenter(), gcurr->getYMax() ); else if (isSouth(vprev)) return Point (gcurr->getXCenter(), gcurr->getYMin() ); else if (isWest (vprev)) return Point (gcurr->getXMin() , gcurr->getYCenter() ); else if (isEast (vprev)) return Point (gcurr->getXMax() , gcurr->getYCenter() ); else return Point (gcurr->getXCenter(), gcurr->getYCenter() ); } else return Point (gcurr->getXCenter(), gcurr->getYCenter() ); } else if (gcurr->isDevice ()){ cdebug_log(112,0) << "Case device" << endl; cdebug_log(112,0) << "seed isH(): " << isH() << endl; cdebug_log(112,0) << "seed isV(): " << isV() << endl; if (isH()){ cdebug_log(112,0) << "hinterval: " << DbU::getValueString(getIAxis()) << endl; y = getIAxis(); if ((gnext->getXMax() < getIMin())||(isWest (next))) x = getIMin(); else if ((gnext->getXMin() > getIMax())||(isEast (next))) x = getIMax(); else x = (max(gnext->getXMin(), getIMin())+min(gnext->getXMax(), getIMax()))/2; } else if (isV()){ cdebug_log(112,0) << "vinterval" << endl; x = getIAxis(); if ((gnext->getYMax() < getIMin())||(isSouth(next))) y = getIMin(); else if ((gnext->getYMin() > getIMax())||(isNorth(next))) y = getIMax(); else y = (max(gnext->getYMin(), getIMin())+min(gnext->getYMax(), getIMax()))/2 ; } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint( const Vertex * next ) const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } } else if (isH()) { cdebug_log(112,0) << "Case horizontal: " << isiSet() << endl; GCell* gprev = getGPrev(Vertex::From2Mode); intervfrom = getIntervFrom(From2Mode); Vertex* prev = NULL; if (gprev) prev = gprev->getObserver(GCell::Observable::Vertex); cdebug_log(112,0) << "PREV: " << prev << " "; intervfrom.print(); if (isiSet()||(prev == NULL)){ cdebug_log(112,0) << "isiSet: "; printInterv(); y = getIAxis(); if ((gnext->getXMax() < getIMin())||(isWest (next))) x = getIMin(); else if ((gnext->getXMin() > getIMax())||(isEast (next))) x = getIMax(); else x = (max(gnext->getXMin(), getIMin())+min(gnext->getXMax(), getIMax()))/2; } else { if (prev->isH()){ cdebug_log(112,0) << "prev is H" << endl; if (gnext->getXMax() < intervfrom.getMin()) x = intervfrom.getMin(); else if (gnext->getXMin() > intervfrom.getMax()) x = intervfrom.getMax(); else x = (max(gnext->getXMin(), intervfrom.getMin())+min(gnext->getXMax(), intervfrom.getMax()))/2; if (isNorth(prev)) y = gcurr->getYMax(); else if (isSouth(prev)) y = gcurr->getYMin(); else y = intervfrom.getAxis(); } else if (prev->isV()){ cdebug_log(112,0) << "prev is V" << endl; if (isNorth(prev)){ x = intervfrom.getAxis(); y = gcurr->getYMax(); } else if (isSouth(prev)){ x = intervfrom.getAxis(); y = gcurr->getYMin(); } else if (isWest (prev)){ x = gcurr->getXMin(); if (isNorth(next)){ if (intervfrom.getMax() > gcurr->getYMax()) y = gcurr->getYMax(); else y = intervfrom.getMax(); } else if (isSouth(next)){ if (intervfrom.getMin() < gcurr->getYMin()) y = gcurr->getYMin(); else y = intervfrom.getMin(); } else { // East side if ( intervfrom.getMin() < gcurr->getYMin() ){ y = gcurr->getYMin(); } else if ( intervfrom.getMax() > gcurr->getYMax() ){ y = gcurr->getYMax(); } else { y = (intervfrom.getMin() + intervfrom.getMax())/2 ; } } } else if (isEast (prev)){ x = gcurr->getXMax(); if (isNorth(next)){ if (intervfrom.getMax() > gcurr->getYMax()) y = gcurr->getYMax(); else y = intervfrom.getMax(); } else if (isSouth(next)){ if (intervfrom.getMin() < gcurr->getYMin()) y = gcurr->getYMin(); else y = intervfrom.getMin(); } else { // West side if ( intervfrom.getMin() < gcurr->getYMin() ){ y = gcurr->getYMin(); } else if ( intervfrom.getMax() > gcurr->getYMax() ){ y = gcurr->getYMax(); } else { y = (intervfrom.getMin() + intervfrom.getMax())/2 ; } } } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint() const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } cdebug_log(112,0) << "x: " << DbU::getValueString(x) << ", y:" << DbU::getValueString(y) << endl; } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint() const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } } } else if (isV()) { cdebug_log(112,0) << "Case vertical: " << isiSet() << endl; //GCell* gprev = NULL; GCell* gprev = getGPrev(Vertex::From2Mode); intervfrom = getIntervFrom(From2Mode); Vertex* prev = NULL; if (gprev) prev = gprev->getObserver(GCell::Observable::Vertex); cdebug_log(112,0) << "PREV: " << prev << " "; intervfrom.print(); if (isiSet()||(prev == NULL)){ cdebug_log(112,0) << "isiSet: "; printInterv(); x = getIAxis(); if ((gnext->getYMax() <= getIMin())||(isSouth(next))){ y = getIMin(); } else if ((gnext->getYMin() >= getIMax())||(isNorth(next))){ y = getIMax(); } else { y = (max(gnext->getYMin(), getIMin())+min(gnext->getYMax(), getIMax()))/2 ; } } else { if (prev->isH()){ cdebug_log(112,0) << "prev is H" << endl; if (isNorth(prev)){ y = gcurr->getYMax(); if (isNorth(next)){ if (intervfrom.getMax() > gcurr->getXMax()) x = gcurr->getXMax(); else x = intervfrom.getMax(); } else if (isSouth(next)){ if (intervfrom.getMin() < gcurr->getXMin()) x = gcurr->getXMin(); else x = intervfrom.getMin(); } else { // West side if ( intervfrom.getMin() < gcurr->getXMin() ){ x = gcurr->getXMin(); } else if ( intervfrom.getMax() > gcurr->getXMax() ){ x = gcurr->getXMax(); } else { x = (intervfrom.getMin() + intervfrom.getMax())/2 ; } } } else if (isSouth(prev)){ y = gcurr->getYMin(); if (isEast(next)){ if (intervfrom.getMax() > gcurr->getXMax()) x = gcurr->getXMax(); else x = intervfrom.getMax(); } else if (isWest(next)){ if (intervfrom.getMin() < gcurr->getXMin()) x = gcurr->getXMin(); else x = intervfrom.getMin(); } else { // Northside if ( intervfrom.getMin() < gcurr->getXMin() ){ x = gcurr->getXMin(); } else if ( intervfrom.getMax() > gcurr->getXMax() ){ x = gcurr->getXMax(); } else { x = (intervfrom.getMin() + intervfrom.getMax())/2 ; } } } else if (isWest (prev)){ x = gcurr->getXMin(); y = intervfrom.getAxis(); } else if (isEast (prev)){ x = gcurr->getXMax(); y = intervfrom.getAxis(); } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint() const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } } else if (prev->isV()){ cdebug_log(112,0) << "prev is V" << endl; if (gnext->getYMax() < intervfrom.getMin()) { y = intervfrom.getMin(); } else if (gnext->getYMin() > intervfrom.getMax()){ y = intervfrom.getMax(); } else{ y = (max(gnext->getYMin(), intervfrom.getMin())+min(gnext->getYMax(), intervfrom.getMax()))/2; } if (isEast(prev)) x = gcurr->getXMax(); else if (isWest(prev)) x = gcurr->getXMin(); else x = intervfrom.getAxis(); } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint() const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } } } else { cdebug_log(112,0) << "[ERROR](Point Vertex::getStartPathPoint() const: Something is wrong." << endl; cdebug_tabw(112,-1); return Point(0,0); } cdebug_tabw(112,-1); return Point(x,y); } bool Vertex::isH () const { GCell* gcell = getGCell(); if (gcell->isDevice()) return isiHorizontal(); else if ((gcell->isHChannel())||(gcell->isHRail())) return true; else if (gcell->isStrut()| gcell->isMatrix() ) return ((gcell->getWidth() > gcell->getHeight())||(gcell->getWidth() == gcell->getHeight())); else return false; } bool Vertex::isV () const { GCell* gcell = getGCell(); if (gcell->isDevice()) return isiVertical(); else if ((gcell->isVChannel())||(gcell->isVRail())) return true; else if (gcell->isStrut()|| gcell->isMatrix()) return gcell->getWidth() < gcell->getHeight(); else return false; } void Vertex::setIntervals ( Vertex* vcurr ) { cdebug_log(112,1) << "!SETINTERVALS! ( Vertex* vcurr )" << endl; Point pcurr; if (isFromFrom2()){ vcurr->setFlags(Vertex::From2Mode); pcurr = vcurr->getStartPathPoint(this); vcurr->unsetFlags(Vertex::From2Mode); } else { pcurr = vcurr->getStartPathPoint(this); } Point pnext = vcurr->getNextPathPoint( pcurr, this ); cdebug_log(112,0) << "Pcurrent : X:" << DbU::getValueString(pcurr.getX()) << ", Y:" << DbU::getValueString(pcurr.getY()) << endl; cdebug_log(112,0) << "Pneighbour: X:" << DbU::getValueString(pnext.getX()) << ", Y:" << DbU::getValueString(pnext.getY()) << endl; DbU::Unit min, max, axis; if (vcurr->isH()){ cdebug_log(112,0) << "case vcurr: Horizontal" << endl; if ((vcurr->isiSet())&&(vcurr->hasValidStamp())){ cdebug_log(112,0) << "case set" << endl; if (vcurr->getIMin() > pnext.getX()) { min = pnext.getX(); max = vcurr->getIMax(); axis = vcurr->getIAxis(); } else if (vcurr->getIMax() < pnext.getX()) { min = vcurr->getIMin(); max = pnext.getX(); axis = vcurr->getIAxis(); } else { min = vcurr->getIMin(); max = vcurr->getIMax(); axis = vcurr->getIAxis(); } } else { cdebug_log(112,0) << "case not set" << endl; axis = pcurr.getY(); bool hh = false; if (vcurr->hasValidStamp() && (vcurr->getFrom() != NULL)){ GCell* gprev = vcurr->getGPrev(Vertex::UseFromFrom2); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (vprev->isH()) { cdebug_log(112,0) << "----------------------------" << endl; cdebug_log(112,0) << "HHCASE:" << endl; cdebug_log(112,0) << "prev: " << vprev << endl; cdebug_log(112,0) << "curr: " << vcurr << endl; cdebug_log(112,0) << "next: " << this << endl; cdebug_log(112,0) << "----------------------------" << endl; hh = true; } } if (hh){ GCell* gcurr = vcurr->getGCell(); GCell* gnext = getGCell(); IntervalC intervfrom = vcurr->getIntervFrom(UseFromFrom2); vcurr->printIntervfrom(); if (gnext->getXMin() > intervfrom.getMax()){ //cdebug_log(112,0) << "1" << endl; min = intervfrom.getMax(); max = gnext->getXMin(); } else if (gnext->getXMax() < intervfrom.getMin()){ //cdebug_log(112,0) << "2" << endl; min = gnext->getXMax(); max = intervfrom.getMin(); } else { //cdebug_log(112,0) << "3" << endl; min = std::max(gcurr->getXMin(), intervfrom.getMin()); max = std::min(gcurr->getXMax(), intervfrom.getMax()); } } else { if (pcurr.getX() < pnext.getX()){ //cdebug_log(112,0) << "4" << endl; min = pcurr.getX(); max = pnext.getX(); } else { //cdebug_log(112,0) << "5" << endl; max = pcurr.getX(); min = pnext.getX(); } } } } else if (vcurr->isV()){ cdebug_log(112,0) << "case vcurr: Vertical" << endl; if ((vcurr->isiSet())&&(vcurr->hasValidStamp())){ cdebug_log(112,0) << "case set" << endl; if (vcurr->getIMin() > pnext.getY()) { min = pnext.getY(); max = vcurr->getIMax(); axis = vcurr->getIAxis(); } else if (vcurr->getIMax() < pnext.getY()) { min = vcurr->getIMin(); max = pnext.getY(); axis = vcurr->getIAxis(); } else { min = vcurr->getIMin(); max = vcurr->getIMax(); axis = vcurr->getIAxis(); } } else { cdebug_log(112,0) << "case not set" << endl; axis = pcurr.getX(); bool vv = false; if (vcurr->hasValidStamp() && (vcurr->getFrom() != NULL)){ GCell* gprev = vcurr->getGPrev(Vertex::UseFromFrom2); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if ((vprev->isV())) { cdebug_log(112,0) << "----------------------------" << endl; cdebug_log(112,0) << "VVCASE:" << endl; cdebug_log(112,0) << "prev: " << vprev << endl; cdebug_log(112,0) << "curr: " << vcurr << endl; cdebug_log(112,0) << "next: " << this << endl; cdebug_log(112,0) << "----------------------------" << endl; vv = true; } } if (vv){ GCell* gcurr = vcurr->getGCell(); GCell* gnext = getGCell(); IntervalC intervfrom = vcurr->getIntervFrom(UseFromFrom2); if (gnext->getYMin() > intervfrom.getMax()){ //cdebug_log(112,0) << "1" << endl; min = intervfrom.getMax(); max = gnext->getYMin(); } else if (gnext->getYMax() < intervfrom.getMin()){ //cdebug_log(112,0) << "2" << endl; min = gnext->getYMax(); max = intervfrom.getMin(); } else { //cdebug_log(112,0) << "3" << endl; min = std::max(gcurr->getYMin(), intervfrom.getMin()); max = std::min(gcurr->getYMax(), intervfrom.getMax()); } } else { if (pcurr.getY() < pnext.getY()){ //cdebug_log(112,0) << "4" << endl; min = pcurr.getY(); max = pnext.getY(); } else { //cdebug_log(112,0) << "5" << endl; max = pcurr.getY(); min = pnext.getY(); } } } } else { cdebug_log(112,0) << "[ERROR](void Vertex::setIntervals(...)): Something is wrong." << endl; cdebug_tabw(112,-1); return; } cdebug_log(112,0) << "IntervFrom => min: " << DbU::getValueString(min) << ", max: " << DbU::getValueString(max) << ", axis:" << DbU::getValueString(axis) << endl; if (isFrom2Mode()) { cdebug_log(112,0) << "SetIntervfrom2" << endl; setIntervfrom2(min, max, axis); } else { cdebug_log(112,0) << "SetIntervfrom" << endl; setIntervfrom(min, max, axis); } cdebug_tabw(112,-1); } bool Vertex::areSameSide ( const Vertex* v1, const Vertex* v2 ) const { if ( (isNorth(v1) and isNorth(v2)) || (isSouth(v1) and isSouth(v2)) || (isWest (v1) and isWest (v2)) || (isEast (v1) and isEast (v2)) ) return true; else return false; } void Vertex::createAData () { if (!getGCell()->isMatrix()){ if (_adata == NULL) _adata = GRAData::create(); } } bool Vertex::isiSet () const { if (_adata) return _adata->isiSet(); else return false; } DbU::Unit Vertex::getIAxis () const { if (_adata) return _adata->getIAxis(); else { if (_from){ //cdebug_log(112,0) << "DbU::Unit Vertex::getIAxis() const: Digital vertex. " << endl; GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (isNorth(vprev)||isSouth(vprev)) return calcMidIntersection(gcurr->getXMin(), gcurr->getXMax(), gprev->getXMin(), gprev->getXMax()); else if (isWest (vprev)||isEast (vprev)) return calcMidIntersection(gcurr->getYMin(), gcurr->getYMax(), gprev->getYMin(), gprev->getYMax()); else { cdebug_log(112,0) << "DbU::Unit Vertex::getIAxis() const: Not a neighbour GCell. " << endl; return 0; } } else { if (isH()) return getGCell()->getXCenter(); else return getGCell()->getYCenter(); } } } DbU::Unit Vertex::getIMax () const { if (_adata){ return _adata->getIMax(); } else { if (_from){ //cdebug_log(112,0) << "DbU::Unit Vertex::getIMax() const: Digital vertex. " << endl; GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (isH()){ if (isNorth(vprev)||isSouth(vprev)||isWest (vprev)) return getGCell()->getXCenter(); else if (isEast (vprev)) return getGCell()->getXMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getIMax() const: Not a neighbour GCell. " << endl; return 0; } } else { if (isWest(vprev)||isEast(vprev)||isSouth (vprev)) return getGCell()->getYCenter(); else if (isNorth (vprev)) return getGCell()->getYMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getIMax() const: Not a neighbour GCell. " << endl; return 0; } } } else { if (isH()) return getGCell()->getXCenter(); else return getGCell()->getYCenter(); } } } DbU::Unit Vertex::getIMin () const { if (_adata){ return _adata->getIMin(); } else { if (_from) { GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver( GCell::Observable::Vertex ); if (isH()){ if (isNorth(vprev) or isSouth(vprev) or isEast (vprev)) return getGCell()->getXCenter(); else if (isWest (vprev)) return getGCell()->getXMin(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getIMin() const: Not a neighbour GCell. " << endl; return 0; } } else { if (isWest (vprev) or isEast(vprev) or isNorth (vprev)) return getGCell()->getYCenter(); else if (isSouth(vprev)) return getGCell()->getYMin(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getIMin() const: Not a neighbour GCell. " << endl; return 0; } } } else { if (isH()) return getGCell()->getXCenter(); else return getGCell()->getYCenter(); } } } DbU::Unit Vertex::getPIAxis () const { if (_adata){ return _adata->getPIAxis(); } else { //cdebug_log(112,0) << "DbU::Unit Vertex::getPIAxis() const: Digital vertex. " << endl; if (_from){ GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (vprev->isH()){ if (vprev->isWest(this)||vprev->isEast (this)) return gprev->getYCenter(); else if (vprev->isSouth (this)) return gprev->getYMin(); else if (vprev->isNorth (this)) return gprev->getYMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIAxis() const: Not a neighbour GCell. " << endl; return 0; } } else { if (vprev->isNorth(this)||vprev->isSouth (this)) return gprev->getXCenter(); else if (vprev->isWest (this)) return gprev->getXMin(); else if (vprev->isEast (this)) return gprev->getXMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIAxis() const: Not a neighbour GCell. " << endl; return 0; } } } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIAxis() const: Inappropriate usage of GRAData. " << endl; return 0; } } } DbU::Unit Vertex::getPIMax () const { if (_adata){ return _adata->getPIMax(); } else { //cdebug_log(112,0) << "DbU::Unit Vertex::getPIMax() const: Digital vertex. " << endl; if (_from){ GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (vprev->isH()){ if (vprev->isSouth(this)||vprev->isWest(this)||vprev->isNorth(this)) return gprev->getXCenter(); else if (vprev->isEast (this)) return gprev->getXMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMax() const: Not a neighbour GCell. " << endl; return 0; } } else { if (vprev->isSouth(this)||vprev->isWest(this)||vprev->isEast(this)) return gprev->getYCenter(); else if (vprev->isNorth (this)) return gprev->getYMax(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMax() const: Not a neighbour GCell. " << endl; return 0; } } } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMax() const: Inappropriate usage of GRAData. " << endl; return 0; } } } DbU::Unit Vertex::getPIMin () const { if (_adata){ return _adata->getPIMin(); } else { //cdebug_log(112,0) << "DbU::Unit Vertex::getPIMin() const: Digital vertex. " << endl; if (_from){ GCell* gcurr = getGCell(); GCell* gprev = _from->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if (vprev->isH()){ if (vprev->isSouth(this)||vprev->isWest(this)||vprev->isNorth(this)) return gprev->getXCenter(); else if (vprev->isWest (this)) return gprev->getXMin(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMin() const: Not a neighbour GCell. " << endl; return 0; } } else { if (vprev->isNorth(this)||vprev->isWest(this)||vprev->isEast(this)) return gprev->getYCenter(); else if (vprev->isSouth (this)) return gprev->getYMin(); else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMin() const: Not a neighbour GCell. " << endl; return 0; } } } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMin() const: Inappropriate usage of GRAData. " << endl; return 0; } } } void Vertex::setInterv ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { if (_adata){ _adata->setInterv(min, max, axis); } else { cdebug_log(112,0) << "void Vertex::setInterv( DbU::Unit min, DbU::Unit max, DbU::Unit axis ): Inappropriate usage of GRAData. " << endl; } } void Vertex::setIntervfrom ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { if (_adata){ _adata->setIntervfrom(min, max, axis); } else { cdebug_log(112,0) << "void Vertex::setIntervfrom( DbU::Unit min, DbU::Unit max, DbU::Unit axis ): Inappropriate usage of GRAData. " << endl; } } void Vertex::setIntervfrom2 ( DbU::Unit min, DbU::Unit max, DbU::Unit axis ) { if (_adata){ _adata->setIntervfrom2(min, max, axis); } else { cdebug_log(112,0) << "void Vertex::setIntervfrom2( DbU::Unit min, DbU::Unit max, DbU::Unit axis ): Inappropriate usage of GRAData. " << endl; } } void Vertex::resetIntervals () { if (_adata){ _adata->resetIntervals(); } /*else { cdebug_log(112,0) << "void Vertex::resetIntervals(): Inappropriate usage of GRAData. " << endl; }*/ unsetFlags(iSet); } void Vertex::clearFrom2 () { if (_adata){ _adata->clearFrom2(); } } Edge* Vertex::getFrom2() const { if (_adata){ if (hasValidStamp()) return _adata->getFrom2(); else return NULL; } else { //cdebug_log(112,0) << "Edge* Vertex::getFrom2() const: Inappropriate usage of GRAData. " << endl; return NULL; } } void Vertex::setFrom2( Edge* from ) { if (_adata){ _adata->setFrom2(from); } else { if (from) cdebug_log(112,0) << "void Vertex::setFrom2( Edge* from ): Inappropriate usage of GRAData. " << endl; } } DbU::Unit Vertex::getPIMax2() const { if (_adata){ return _adata->getPIMax2(); } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMax2() const: Inappropriate usage of GRAData. " << endl; return 0; } } DbU::Unit Vertex::getPIMin2() const { if (_adata){ return _adata->getPIMin2(); } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIMin2() const: Inappropriate usage of GRAData. " << endl; return 0; } } DbU::Unit Vertex::getPIAxis2() const { if (_adata){ return _adata->getPIAxis2(); } else { cdebug_log(112,0) << "DbU::Unit Vertex::getPIAxis2() const: Inappropriate usage of GRAData. " << endl; return 0; } } IntervalC Vertex::getIntervFrom2() const { if (_adata){ return _adata->getIntervFrom2(); } else { cdebug_log(112,0) << "DbU::Unit Vertex::getIntervFrom2() const: Inappropriate usage of GRAData. " << endl; return IntervalC(); } } IntervalC Vertex::getIntervFrom( uint32_t criteria ) const { if (_adata){ switch (criteria){ case Vertex::From2Mode: if ((isFrom2Mode())&&(getFrom2() != NULL)){ cdebug_log(112,0) << "getIntervFrom:From2Mode:UseFrom2. " << endl; return _adata->getIntervFrom2(); } else { cdebug_log(112,0) << "getIntervFrom:From2Mode:UseFrom1. " << endl; return _adata->getIntervFrom(); } case Vertex::UseFromFrom2: if ((isFromFrom2())&&(getFrom2() != NULL)){ cdebug_log(112,0) << "getIntervFrom:UseFromFrom2:UseFrom2. " << endl; return _adata->getIntervFrom2(); } else { cdebug_log(112,0) << "getIntervFrom:UseFromFrom2:UseFrom1. " << endl; return _adata->getIntervFrom(); } case 0: cdebug_log(112,0) << "getIntervFrom:Default:UseFrom1. " << endl; return _adata->getIntervFrom(); default: cdebug_log(112,0) << "getIntervFrom:Default:UseFrom1. " << endl; return _adata->getIntervFrom(); } } else { //cdebug_log(112,0) << "DbU::Unit Vertex::getIntervFrom(Flags criteria) const: Inappropriate usage of GRAData. " << endl; return IntervalC(getPIMin(), getPIMax(), getPIAxis()); } } GCell* Vertex::getGPrev( uint32_t criteria ) const { if (_adata){ switch (criteria){ case Vertex::From2Mode: if ((isFrom2Mode())&&(getFrom2() != NULL)){ cdebug_log(112,0) << "getGPrev:From2Mode:UseFrom2. " << endl; return _adata->getFrom2()->getOpposite(getGCell()); } else { cdebug_log(112,0) << "getGPrev:From2Mode:UseFrom1. " << endl; if (_from) return getFrom()->getOpposite(getGCell()); else return NULL; } case Vertex::UseFromFrom2: if ((isFromFrom2())&&(getFrom2() != NULL)){ cdebug_log(112,0) << "getGPrev:UseFromFrom2:UseFrom2. " << endl; return _adata->getFrom2()->getOpposite(getGCell()); } else { cdebug_log(112,0) << "getGPrev:UseFromFrom2:UseFrom1. " << endl; if (_from) return getFrom()->getOpposite(getGCell()); else return NULL; } case 0: cdebug_log(112,0) << "getGPrev:Default:UseFrom1. " << endl; if (_from) return getFrom()->getOpposite(getGCell()); else return NULL; default: cdebug_log(112,0) << "getGPrev:Default:UseFrom1. " << endl; if (_from) return getFrom()->getOpposite(getGCell()); else return NULL; } } else { if (_from) return getFrom()->getOpposite(getGCell()); else return NULL; } } IntervalC Vertex::getInterv() const { if (_adata){ return _adata->getInterv(); } else { cdebug_log(112,0) << "DbU::Unit Vertex::getInterv() const: Inappropriate usage of GRAData. " << endl; return IntervalC(); } } void Vertex::printInterv() const { if (_adata){ _adata->printInterv(); } else { cdebug_log(112,0) << "Interv => this is a digital vertex." << endl; } } void Vertex::printIntervfrom() const { if (_adata){ _adata->printIntervfrom(); } else { cdebug_log(112,0) << "IntervFrom => this is a digital vertex." << endl; } } string Vertex::_getString () const { if (not _gcell) { string s = ""; return s; } string s = "getXMin()) + " " + DbU::getValueString(_gcell->getYMin()) + " " + DbU::getValueString(_gcell->getXMax()) + " " + DbU::getValueString(_gcell->getYMax()) + "]" //+ " rps:" + getString(_rpCount) + " deg:" + getString(_degree) + " connexId:" + ((_connexId >= 0) ? getString(_connexId) : "None") + " d:" + ((_distance == unreached) ? "unreached" : ((_distance == unreachable) ? "unreachable" : DbU::getValueString(_distance)) ) //+ "+" + getString(_branchId) //+ " stamp:" + (hasValidStamp() ? "valid" : "outdated") + " from:" + ((_from) ? "set" : "NULL") //+ " from2:" + ((_adata) ? _adata->getFrom2() : "NULL") + " restricted:" + (isNRestricted() ? "N" : "-") + (isSRestricted() ? "S" : "-") + (isERestricted() ? "E" : "-") + (isWRestricted() ? "W" : "-") //+ " isiSet:" +(isiSet() ? "1" : "0") + ">"; return s; } void Vertex::notify ( Vertex* vertex, unsigned int flags ) { cdebug_log(111,0) << "Vertex::notify() " << vertex << endl; // Take into account the GCell modification here. } // ------------------------------------------------------------------- // Class : "Anabatic::PrioriryQueue::CompareByDistance". PriorityQueue* PriorityQueue::CompareByDistance::_pqueue = NULL; bool PriorityQueue::CompareByDistance::operator() ( const Vertex* lhs, const Vertex* rhs ) const { if (lhs->getDistance() == rhs->getDistance()) { if (_pqueue and _pqueue->hasAttractor()) { DbU::Unit lhsDistance = _pqueue->getAttractor().manhattanDistance( lhs->getCenter() ); DbU::Unit rhsDistance = _pqueue->getAttractor().manhattanDistance( rhs->getCenter() ); cdebug_log(112,0) << "CompareByDistance: lhs:" << DbU::getValueString(lhsDistance) << " rhs:" << DbU::getValueString(rhsDistance) << endl; if (lhsDistance != rhsDistance) return lhsDistance < rhsDistance; } return lhs->getBranchId() > rhs->getBranchId(); } return lhs->getDistance() < rhs->getDistance(); } // ------------------------------------------------------------------- // Class : "Anabatic::Dijkstra". Dijkstra::Mode::~Mode () { } string Dijkstra::Mode::_getTypeName () const { return "Anabatic::Dijkstra::Mode"; } string Dijkstra::Mode::_getString () const { string s = ""; s += (_flags & Standart ) ? 'S' : '-'; s += (_flags & Monotonic) ? 'M' : '-'; return s; } DbU::Unit Dijkstra::_distance ( const Vertex* current, const Vertex* vneighbour, const Edge* e ) { if (Vertex::isRestricted(current, vneighbour, e)) return Vertex::unreachable; else return current->getDistance() + e->getDistance(); } /*U::Unit calcDistance( Point p1, Point p2 ) { return abs(p1.getX()-p2.getX()) + abs(p1.getY()-p2.getY()); } DbU::Unit calcMidIntersection( DbU::Unit imin1, DbU::Unit imax1, DbU::Unit imin2, DbU::Unit imax2 ) { if ( (imin1 > imax1) || (imin2 > imax2) ){ cerr << "DbU::Unit calcMidIntersection(...): Wrong parameters." << endl; return 0; } if ( (imin1 > imax2) || (imax1 < imin2) ) { cerr << "DbU::Unit calcMidIntersection(...): No intersection." << endl; return 0; } return ( max(imin1, imin2) + min(imax1, imax2) )/2; }*/ Dijkstra::Dijkstra ( AnabaticEngine* anabatic ) : _anabatic (anabatic) , _vertexes () , _distanceCb (_distance) , _mode (Mode::Standart) , _net (NULL) , _stamp (-1) , _sources () , _targets () , _searchArea () , _searchAreaHalo(0) , _connectedsId (-1) , _queue () , _flags (0) { const vector& gcells = _anabatic->getGCells(); for ( GCell* gcell : gcells ) { _vertexes.push_back( new Vertex (gcell) ); } _anabatic->getMatrix()->show(); } Dijkstra::~Dijkstra () { for ( Vertex* vertex : _vertexes ) delete vertex; } DbU::Unit Dijkstra::getAntennaGateMaxWL () const { return _anabatic->getAntennaGateMaxWL(); } Point Dijkstra::_getPonderedPoint() const { vector rps; int cpt = 0; DbU::Unit x = 0; DbU::Unit y = 0; for ( Component* component : _net->getComponents() ) { RoutingPad* rp = dynamic_cast( component ); if (rp) rps.push_back( rp ); } for ( auto rp : rps ) { x += rp->getBoundingBox().getCenter().getX(); y += rp->getBoundingBox().getCenter().getY(); cpt++; } return Point(x/cpt, y/cpt); } void Dijkstra::loadFixedGlobal ( Net* net ) { NetData* netData = _anabatic->getNetData( net ); netData->setGlobalRouted( true ); netData->setGlobalFixed ( true ); for ( Component* component : net->getComponents() ) { Horizontal* horizontal = dynamic_cast( component ); if (horizontal) { if (not Session::isGLayer(horizontal->getLayer())) { cerr << Error( "Dijsktra::loadFixedGlobal(): A component of \"%s\" has not a global layer.\n" " (%s)" , getString(net->getName()).c_str() , getString(component).c_str() ) << endl; continue; } GCell* begin = _anabatic->getGCellUnder( horizontal->getSource()->getPosition() ); GCell* end = _anabatic->getGCellUnder( horizontal->getTarget()->getPosition() ); for ( Edge* edge : _anabatic->getEdgesUnderPath(begin,end) ) edge->add( horizontal ); } Vertical* vertical = dynamic_cast( component ); if (vertical) { if (not Session::isGLayer(vertical->getLayer())) { cerr << Error( "Dijsktra::loadFixedGlobal(): A component of \"%s\" has not a global layer.\n" " (%s)" , getString(net->getName()).c_str() , getString(component).c_str() ) << endl; continue; } GCell* begin = _anabatic->getGCellUnder( vertical->getSource()->getPosition() ); GCell* end = _anabatic->getGCellUnder( vertical->getTarget()->getPosition() ); for ( Edge* edge : _anabatic->getEdgesUnderPath(begin,end,Flags::NorthPath) ) edge->add( vertical ); } } } void Dijkstra::load ( Net* net ) { _cleanup(); _net = net; _stamp = _anabatic->incStamp(); DebugSession::open( _net, 112, 120 ); cdebug_log(112,1) << "Dijkstra::load() " << _net << endl; vector rps; NetRoutingState* state = NetRoutingExtension::get( _net ); if (state) { if (state->isSelfSym()) { cdebug_log(112,0) << "Dijkstra::SELF SYMMETRY CASE " << DbU::getValueString(state->getSymAxis()) << endl; } state->unsetFlags( NetRoutingState::HasAntenna ); } for ( Component* component : _net->getComponents() ) { RoutingPad* rp = dynamic_cast( component ); if (rp) { if (_attachSymContactsHook(rp)) continue; // ANALOG cdebug_log(112,0) << "@ frp:" << rp << endl; rps.push_back( rp ); } } if (rps.size() < 2) { cdebug_tabw(112,-1); return; } uint32_t driverCount = 0; for ( auto rp : rps ) { if (not _anabatic->getConfiguration()->selectRpComponent(rp)) cerr << Warning( "Dijktra::load(): %s has no components on grid.", getString(rp).c_str() ) << endl; cdebug_log(112,0) << "@ rp: " << rp << ", getCenter(): " << rp->getBoundingBox().getCenter() << endl; Point center = rp->getBoundingBox().getCenter(); GCell* gcell = _anabatic->getGCellUnder( center ); Box bb = rp->getBoundingBox(); bool isDriver = false; cdebug_log(112,0) << bb.getXMin() << " " << bb.getXMax() << endl; cdebug_log(112,0) << "center X:" << center.getX() << " gcell Xmax:" << gcell->getXMax() << endl; if (state and state->isSymmetric()) _limitSymSearchArea( rp ); if (not gcell) { cerr << Error( "Dijkstra::load(): %s\n" " @%s of %s is not under any GCell.\n" " It will be ignored so the routing may be incomplete." , getString(rp).c_str() , getString(center).c_str() , getString(_net).c_str() ) << endl; continue; } Net* rpNet = NULL; Plug* plug = dynamic_cast( rp->getPlugOccurrence().getEntity() ); if (plug) { rpNet = plug->getMasterNet(); if (rpNet->getDirection() & Net::Direction::DirOut) { cdebug_log(112,0) << "Driver/cell: " << rp << endl; cdebug_log(112,0) << "masterNet: " << rpNet << endl; ++driverCount; isDriver = true; } } else { Pin* pin = dynamic_cast( rp->getPlugOccurrence().getEntity() ); if (pin) { rpNet = pin->getNet(); if (rpNet->getDirection() & Net::Direction::DirIn) { cdebug_log(112,0) << "Driver/pin: " << rp << endl; cdebug_log(112,0) << "masterNet: " << rpNet << endl; ++driverCount; isDriver = true; } } } _searchArea.merge( gcell->getBoundingBox() ); // TO CHANGE cdebug_log(112,0) << "| Merged search area: " << _searchArea << ", gcell: " << gcell << endl; Vertex* seed = gcell->getObserver(GCell::Observable::Vertex); GCell* gseed = seed->getGCell(); if (gseed->isAnalog()) _setSourcesGRAData( seed, rp ); // ANALOG cdebug_log(112,0) << "| seed->isH(): " << seed->isH() << " seed->isV(): " << seed->isV() << endl; if (seed->getConnexId() < 0) { VertexSet connecteds; _getConnecteds( seed, connecteds ); ++_connectedsId; for ( Vertex* vertex : connecteds ) { vertex->getGCell()->flags().reset( Flags::GoStraight ); vertex->setDistance ( Vertex::unreached ); vertex->setStamp ( _stamp ); vertex->setConnexId ( _connectedsId ); vertex->setBranchId ( 0 ); vertex->setDegree ( 0 ); vertex->setRpCount ( 0 ); vertex->setFrom ( NULL ); if (isDriver) vertex->setDriver( true ); vertex->setFrom2 ( NULL); vertex->unsetFlags ( Vertex::UseFromFrom2 ); vertex->clearRestriction(); _targets.insert( vertex ); } for ( Vertex* vertex : connecteds ) { int degree = 0; for ( Edge* edge : vertex->getGCell()->getEdges() ) { Vertex* neighbor = vertex->getNeighbor( edge ); if (vertex->hasValidStamp() and neighbor->hasValidStamp()) ++degree; } vertex->setDegree( degree ); cdebug_log(112,0) << "| Add: " << vertex << endl; } } seed->incRpCount(); Contact* vcontact = seed->getGContact( _net ); rp->getBodyHook()->detach(); rp->getBodyHook()->attach( vcontact->getBodyHook() ); } if (driverCount == 0) { cerr << Error( "Diskstra::load(): Net \"%s\" do not have a driver.\n" , getString(_net->getName()).c_str() ) << endl; } if (driverCount > 1) { cerr << Error( "Diskstra::load(): Net \"%s\" have multiple drivers (%u).\n" , getString(_net->getName()).c_str(), driverCount ) << endl; } if (state and state->isSymmetric() and not state->isSelfSym() and state->isSymMaster()) { if (state->isSymVertical()) { if ( (_searchArea.getXMin() < state->getSymAxis()) and (_searchArea.getXMax() > state->getSymAxis()) ) { cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n" " Vertical symmetry axis @%s is inside the net area %s." , getString(_net->getName()).c_str() , getString(state->getSymNet()->getName()).c_str() , DbU::getValueString(state->getSymAxis()).c_str() , getString(_searchArea).c_str() ) << endl; } } if (state->isSymHorizontal()) { if ( (_searchArea.getYMin() < state->getSymAxis()) and (_searchArea.getYMax() > state->getSymAxis()) ) { cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n" " Horizontal symmetry axis @%s is inside the net area %s." , getString(_net->getName()).c_str() , getString(state->getSymNet()->getName()).c_str() , DbU::getValueString(state->getSymAxis()).c_str() , getString(_searchArea).c_str() ) << endl; } } } _searchArea.inflate( _searchAreaHalo ); cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl; cdebug_log(112,0) << "Search area: " << _searchArea << endl; setAxisTargets(); cdebug_tabw(112,-1); DebugSession::close(); } void Dijkstra::unsetAxisTargets () { NetRoutingState* state = NetRoutingExtension::get( _net ); if (state){ if (state->isSelfSym()){ Cell* cell = _anabatic->getCell(); _queue.clear(); GCell* gcell = NULL; if (state->isSymVertical()){ gcell = _anabatic->getGCellUnder( Point( state->getSymAxis() , _anabatic->getCell()->getAbutmentBox().getYMin() ) ); } else if (state->isSymHorizontal()){ gcell = _anabatic->getGCellUnder( Point( _anabatic->getCell()->getAbutmentBox().getXMin() , state->getSymAxis() ) ); } if (gcell) { _queue.push(gcell->getObserver(GCell::Observable::Vertex)); } while ( not _queue.empty() ) { Vertex* current = _queue.top(); _queue.pop(); if ( (state->isSymVertical() && (!current->isNRestricted()) && (!current->isSRestricted())) ||(state->isSymHorizontal() && (!current->isERestricted()) && (!current->isWRestricted())) ){ current->unsetFlags(Vertex::AxisTarget); } if (state->isSymVertical()){ // check North for ( Edge* edge : current->getGCell()->getNorthEdges() ) { GCell* gnext = edge->getOpposite(current->getGCell()); Vertex* vnext = gnext->getObserver(GCell::Observable::Vertex); if ( (gnext->getXCenter() == state->getSymAxis()) && (gnext->getYMin() <= cell->getAbutmentBox().getYMax()) ) _queue.push( vnext ); } } else if (state->isSymHorizontal()){ // check East for ( Edge* edge : current->getGCell()->getNorthEdges() ) { GCell* gnext = edge->getOpposite(current->getGCell()); Vertex* vnext = gnext->getObserver(GCell::Observable::Vertex); if ( (gnext->getXCenter() == state->getSymAxis()) && (gnext->getXMin() <= cell->getAbutmentBox().getXMax()) ) _queue.push( vnext ); } } } } } } void Dijkstra::setAxisTargets () { NetRoutingState* state = NetRoutingExtension::get( _net ); if (state){ if (state->isSelfSym()){ cdebug_log(112,0) << "void Dijkstra::setAxisTargets (): " << endl; Cell* cell = _anabatic->getCell(); _queue.clear(); GCell* gcell = NULL; if (state->isSymVertical()){ gcell = _anabatic->getGCellUnder( Point( state->getSymAxis() , _anabatic->getCell()->getAbutmentBox().getYMin() ) ); } else if (state->isSymHorizontal()){ gcell = _anabatic->getGCellUnder( Point( _anabatic->getCell()->getAbutmentBox().getXMin() , state->getSymAxis() ) ); } if (gcell) { _queue.push(gcell->getObserver(GCell::Observable::Vertex)); setFlags(Mode::AxisTarget); cdebug_log(112,0) << "Find axis targets: " << endl; } while ( not _queue.empty() ) { Vertex* current = _queue.top(); GCell* gcurr = current->getGCell(); _queue.pop(); if ( (state->isSymVertical() && (!current->isNRestricted()) && (!current->isSRestricted()) && (gcurr->getXCenter() == state->getSymAxis()) ) ||(state->isSymHorizontal() && (!current->isERestricted()) && (!current->isWRestricted()) && (gcurr->getYCenter() == state->getSymAxis()) ) ){ current->setDistance ( Vertex::unreached ); current->setStamp ( _stamp ); current->setConnexId( -1 ); current->setFlags(Vertex::AxisTarget); cdebug_log(112,0) << "isAxisTarget: " << current << endl; } if (state->isSymVertical()){ // check North for ( Edge* edge : current->getGCell()->getNorthEdges() ) { GCell* gnext = edge->getOpposite(current->getGCell()); Vertex* vnext = gnext->getObserver(GCell::Observable::Vertex); if ( ( (state->getSymAxis() >= gnext->getXMin()) && (state->getSymAxis() <= gnext->getXMax()) ) && (gnext->getYMin() <= cell->getAbutmentBox().getYMax()) ){ _queue.push( vnext ); } else { cdebug_log(112,0) << "isNOT: " << gnext << endl; } } } else if (state->isSymHorizontal()){ // check East for ( Edge* edge : current->getGCell()->getEastEdges() ) { GCell* gnext = edge->getOpposite(current->getGCell()); Vertex* vnext = gnext->getObserver(GCell::Observable::Vertex); if ( ( (state->getSymAxis() >= gnext->getYMin()) && (state->getSymAxis() <= gnext->getYMax()) ) && (gnext->getXMin() <= cell->getAbutmentBox().getXMax()) ) { _queue.push( vnext ); } else { cdebug_log(112,0) << "isNOT: " << gnext << endl; } } } } } } } void Dijkstra::_selectFirstSource () { if (_targets.empty()) { #if 0 cparanoid << Error( "Dijkstra::_selectFirstSource(): %s has no vertexes to route, ignored." , getString(_net).c_str() ) << endl; #endif return; } Vertex* firstSource = NULL; VertexSet drivers; for ( Vertex* vertex : _targets ) { if (vertex->isDriver()) drivers.insert( vertex ); } if (drivers.empty()) drivers = _targets; #if THIS_IS_DISABLED if (_mode & Mode::Monotonic) { if (_targets.size() == 2) { auto ivertex = _targets.begin(); Vertex* v1 = *ivertex; Vertex* v2 = *(++ivertex); firstSource = (v1->getCenter().getX() <= v2->getCenter().getY()) ? v1 : v2; } else { cerr << Error( "Dijkstra::_selectFirstSource(): %s cannot be routed in monotonic mode.\n" " Must have exactly two terminals (%u), revert to Standart." , getString(_net).c_str() , _targets.size() ) << endl; _mode = Mode::Standart; } } #endif if (not firstSource) { // Standart routing. bool hasDevice = false; for ( Vertex* vertex : drivers ) { if (vertex->getGCell()->isDevice()) hasDevice = true; } Point areaCenter; if (hasDevice) areaCenter = _getPonderedPoint(); else areaCenter = _searchArea.getCenter(); auto ivertex = drivers.begin(); firstSource = *ivertex++; DbU::Unit minDistance = areaCenter.manhattanDistance( firstSource->getCenter() ); for ( ; ivertex != drivers.end() ; ++ivertex ) { DbU::Unit distance = areaCenter.manhattanDistance( (*ivertex)->getCenter() ); if (distance < minDistance) { minDistance = distance; firstSource = *ivertex; } } } for ( auto ivertex = _targets.begin() ; ivertex != _targets.end() ; ) { auto inext = ivertex; inext++; if ((*ivertex)->getConnexId() == firstSource->getConnexId()) { _sources.insert( *ivertex ); _targets.erase ( ivertex ); } ivertex = inext; } cdebug_log(112,0) << "Dijkstra::_selectFirstSource() " << *_sources.begin() << endl; } void Dijkstra::_cleanup () { //_checkEdges(); _sources.clear(); _targets.clear(); _queue.clear(); _searchArea.makeEmpty(); _connectedsId = 0; } bool Dijkstra::_propagate ( Flags enabledSides ) { cdebug_log(112,1) << "Dijkstra::_propagate() " << _net << endl; while ( not _queue.empty() ) { cdebug_log(111,0) << "Number of targets left: " << _targets.size() << " and needaxis? " << needAxisTarget() << endl; _queue.dump(); Vertex* current = _queue.top(); GCell* gcurrent = current->getGCell(); cdebug_log(111,1) << "Current:" << current << endl; //cdebug_log(111,0) << "isAxisTarget():" << current->isAxisTarget() << endl; _queue.pop(); if ( current->isAxisTarget() and needAxisTarget()) unsetFlags(Mode::AxisTarget); else if ((current->getConnexId() == _connectedsId) or (current->getConnexId() < 0)) { cdebug_log(111,0) << "Looking for neighbors:" << endl; for ( Edge* edge : current->getGCell()->getEdges() ) { cdebug_log(111,0) << "@ Edge " << edge << endl; if (edge == current->getFrom()) { cdebug_log(111,0) << "> Reject: edge == current->getFrom()" << endl; continue; } if ((gcurrent->isAnalog()) and _checkFrom2(edge, current)) { cdebug_log(111,0) << "> Reject: _checkFrom2()" << endl; continue; } Vertex* vneighbor = current->getNeighbor( edge ); if (vneighbor->isAnalog()) vneighbor->createAData(); cdebug_log(111,0) << "| Neighbor:" << vneighbor << endl; if (vneighbor->getConnexId() == _connectedsId) { cdebug_log(111,0) << "> Reject: Neighbor already reached (has connectedsId)" << endl; continue; } if (not _searchArea.intersect(vneighbor->getBoundingBox())) { cdebug_log(111,0) << "> Reject: not in _searchArea: " << _searchArea << ", vneighbor area: " << vneighbor->getBoundingBox() << endl; continue; } ////////////////////////////////////// DEBUG ////////////////////////////////////// //if (current->getFrom()) { // cdebug_log(111,0) << "| From: " << current->getFrom()->getOpposite(gcurrent) << endl; ////current->getIntervFrom().print(); //} //if (gcurrent->isAnalog() and current->getFrom2()) { // cdebug_log(111,0) << "| From2: " << current->getFrom2()->getOpposite(gcurrent) << endl; // current->getIntervFrom2().print(); //} //if ( (vneighbor->getFrom() != NULL) and (vneighbor->hasValidStamp()) ) { // cdebug_log(111,0) << "| Neighbor GETFROM:" << vneighbor->getFrom()->getOpposite( gneighbor ) << endl; // cdebug_log(111,0) << "Distance prev : " << DbU::getValueString(vneighbor->getDistance()) << endl; //} /////////////////////////////////////////////////////////////////////////////////// DbU::Unit distance = _distanceCb( current, vneighbor, edge ); cdebug_log(111,0) << "| Distance:" << Vertex::getValueString(distance) << endl; bool isDistance2shorter = false; if (gcurrent->isAnalog() and vneighbor->isAnalog()) isDistance2shorter = _isDistance2Shorter ( distance, current, vneighbor, edge ); bool push = false; if (distance != Vertex::unreachable){ if (not vneighbor->hasValidStamp()) { cdebug_log(111,0) << "> Vertex reached for the first time" << endl; vneighbor->setConnexId( -1 ); vneighbor->setStamp ( _stamp ); vneighbor->setDegree ( 1 ); vneighbor->setRpCount ( 0 ); vneighbor->unsetFlags(Vertex::AxisTarget); vneighbor->resetIntervals(); push = true; } else { if ( (distance == vneighbor->getDistance()) and (vneighbor->isAnalog()) and (vneighbor->getFrom2() == NULL) ) { _pushEqualDistance( distance, isDistance2shorter, current, vneighbor, edge ); // ANALOG } else if (distance < vneighbor->getDistance()) { if (vneighbor->getDistance() != Vertex::unreached) _queue.erase( vneighbor ); cdebug_log(111,0) << "> Vertex reached through a shorter path (prev: " << DbU::getValueString(vneighbor->getDistance()) << ")" << endl; push = true; } else { cdebug_log(111,0) << "> Reject: Vertex reached through a *longer* path or unreachable:" << boolalpha << (distance == Vertex::unreachable) << endl; } } } else { cdebug_log(111,0) << "> Reject: Vertex unreachable" << endl; } if (push){ if (vneighbor->isAnalog()) // Vneighbor only not current gcell _updateGRAData( vneighbor, isDistance2shorter, current ); vneighbor->setBranchId( current->getBranchId() ); vneighbor->setDistance( distance ); cdebug_log(111,0) << "| setFrom1: " << vneighbor << endl; vneighbor->setFrom ( edge ); _queue.push( vneighbor ); cdebug_log(111,0) << "| Push: (size:" << _queue.size() << ") " << vneighbor << ", isFromFrom2: " << vneighbor->isFromFrom2() << endl; } } /* ------------------------------------------------------------------- */ /*if ( (distance == vneighbor->getDistance()) and gcurrent->isAnalog() and gneighbor->isAnalog() and (vneighbor->getFrom2() == NULL) ) { _pushEqualDistance( distance, isDistance2shorter, current, vneighbor, edge ); // ANALOG } else { if ((distance != Vertex::unreachable) and (not vneighbor->hasValidStamp())) { cdebug_log(111,0) << "Vertex reached for the first time" << endl; vneighbor->setConnexId( -1 ); vneighbor->setStamp ( _stamp ); vneighbor->setDegree ( 1 ); vneighbor->setRpCount ( 0 ); vneighbor->unsetFlags(Vertex::AxisTarget); vneighbor->resetIntervals(); //cdebug_log(111,0) << "Vertex reached through a shorter path" << endl; if (gneighbor->isAnalog()) // Gneighbor only not current gcell _updateGRAData( vneighbor, isDistance2shorter, current ); vneighbor->setBranchId( current->getBranchId() ); vneighbor->setDistance( distance ); cdebug_log(111,0) << "setFrom1: " << vneighbor << endl; vneighbor->setFrom ( edge ); if (gneighbor->isAnalog()) vneighbor->setFrom2( NULL ); _queue.push( vneighbor ); cdebug_log(111,0) << "Push: (size:" << _queue.size() << ") " << vneighbor << endl; } else { if ( (distance < vneighbor->getDistance()) and (distance != Vertex::unreachable) ) { if (vneighbor->getDistance() != Vertex::unreached) _queue.erase( vneighbor );*/ /*else { if (not vneighbor->hasValidStamp()) { cdebug_log(111,0) << "Vertex reached for the first time" << endl; vneighbor->setConnexId( -1 ); vneighbor->setStamp ( _stamp ); vneighbor->setDegree ( 1 ); vneighbor->setRpCount ( 0 ); vneighbor->unsetFlags(Vertex::AxisTarget); vneighbor->resetIntervals(); }*/ // } //} /*cdebug_log(111,0) << "Vertex reached through a shorter path" << endl; if (gneighbor->isAnalog()) // Gneighbor only not current gcell _updateGRAData( vneighbor, isDistance2shorter, current ); vneighbor->setBranchId( current->getBranchId() ); vneighbor->setDistance( distance ); cdebug_log(111,0) << "setFrom1: " << vneighbor << endl; vneighbor->setFrom ( edge ); if (gneighbor->isAnalog()) vneighbor->setFrom2( NULL ); _queue.push( vneighbor ); cdebug_log(111,0) << "Push: (size:" << _queue.size() << ") " << vneighbor << endl; } else { cdebug_log(111,0) << "Reject: Vertex reached through a *longer* path or unreachable:" << boolalpha << (distance == Vertex::unreachable) << endl; } } } }*/ cdebug_tabw(111,-1); continue; } cdebug_tabw(111,-1); // We did reach another target (different ). // Tag back the path, with a higher . _traceback( current ); cdebug_tabw(112,-1); return true; } cerr << Error( "Dijkstra::propagate(): %s has unreachable targets." , getString(_net).c_str() ) << endl; cdebug_log(112, 0) << "Unreached targets:" << endl; for ( Vertex* v : _targets ) cdebug_log(112, 0) << "| " << v << endl; cdebug_tabw(112,-1); return false; } void Dijkstra::_traceback ( Vertex* current ) { cdebug_log(112,1) << "Dijkstra::_traceback() " << _net << " branchId:" << _sources.size() << endl; cdebug_log(112,0) << "From: " << current << endl; int branchId = _sources.size(); _toSources( current, _connectedsId ); bool isfirst = true; bool useFrom2 = false; if (current->isAnalog()) { _initiateUpdateIntervals( current ); } else { current->incDegree(); current = current->getPredecessor(); isfirst = false; } Edge* from = NULL; while ( current ) { cdebug_log(112,0) << "+ " << current << endl; if (current->isAnalog()) { if (_updateIntervals( isfirst, current, useFrom2, branchId, from )) break; Vertex* next = NULL; next = current->getPredecessor(); if (current == next){ cdebug_log(112,0) << "[ERROR] Current's predecessor is current." << endl; break; } if (current->isFromFrom2()) { useFrom2 = true; current->unsetFlags( Vertex::UseFromFrom2 ); } else { useFrom2 = false; } current = next; } else { current->incDegree(); if (current->getConnexId() == _connectedsId) break; from = current->getFrom(); if (not from) break; current->setDistance( 0.0 ); current->setConnexId( _connectedsId ); current->setBranchId( branchId ); _sources.insert( current ); _queue.push( current ); current = current->getPredecessor(); } } cdebug_tabw(112,-1); } void Dijkstra::_materialize () { cdebug_log(112,1) << "Dijkstra::_materialize() " << _net << " _sources:" << _sources.size() << endl; if (_sources.size() < 2) NetRoutingExtension::create( _net )->setFlags( NetRoutingState::ShortNet | NetRoutingState::AutomaticGlobalRoute ); if (_sources.size() < 2) { cdebug_tabw(112,-1); return; } DbU::Unit gWL = 0; NetRoutingState* state = NetRoutingExtension::get( _net ); //cerr << "state: " << state << endl; for ( Vertex* startVertex : _sources ) { cdebug_log(112,0) << "@ " << startVertex << endl; if (not startVertex->getFrom()) { cdebug_log(112,0) << "> skip: no getFrom()." << endl; continue; } if ( not startVertex->hasGContact(_net) and not startVertex->getRpCount() and (startVertex->getDegree() < 3) and not startVertex->isAxisTarget() ) { cdebug_log(112,0) << "> skip: not a good starting point." << endl; continue; } Vertex* source = startVertex; while ( source ) { cdebug_log(112,0) << "@ " << source << endl; bool isAnalog = source->getGCell()->isAnalog(); //if (isAnalog) source->resetIntervals(); Edge* from = source->getFrom(); vector aligneds; aligneds.push_back( from ); Vertex* target = source->getPredecessor(); Interval constraint = from->getSide(); source->setFrom( NULL ); cdebug_log(112,0) << "| " << target << endl; if (target->getConnexId() < 0) { cdebug_log(112,0) << "> break (abort: false start)." << endl; break; } while ( true ) { from = target->getFrom(); if ( not from or (target->getGCell()->isAnalog()) or (target->hasGContact(_net)) or (target->getRpCount()) or (target->getDegree() > 2) or (aligneds.back()->isHorizontal() xor from->isHorizontal()) or not constraint.intersect(from->getSide())) break; // U-turn detection. All edges must have the same *spin*. if ( (aligneds[0]->getSource() == source->getGCell()) xor (from ->getSource() == target->getGCell()) ) break; // Always break vertical in channel (2M routing). if (target->getGCell()->isChannelRow() and aligneds.back()->isVertical()) break; aligneds.push_back( from ); constraint.merge( from->getSide() ); Vertex* nextTarget = target->getPredecessor(); target->setFrom( NULL ); target = nextTarget; cdebug_log(112,0) << "| " << target << endl; } Contact* sourceContact = source->breakGoThrough( _net ); Contact* targetContact = target->breakGoThrough( _net ); Segment* segment = NULL; cdebug_log(112,0) << "> aligneds.front():" << aligneds.front() << " isHorizontal():" << aligneds.front()->isHorizontal() << endl; if (aligneds.front()->isHorizontal()) { if (sourceContact->getX() > targetContact->getX()) std::swap( sourceContact, targetContact ); DbU::Unit width = Session::getGHorizontalPitch(); if (state) width *= state->getWPitch(); segment = Horizontal::create( sourceContact , targetContact , _anabatic->getConfiguration()->getGHorizontalLayer() , constraint.getCenter() , width ); gWL += segment->getLength(); cdebug_log(112,0) << "| ref: " << segment << endl; for ( Edge* through : aligneds ) through->add( segment ); if (state) { if (state->isSymmetric()) _createSelfSymSeg ( segment ); } } else { if (sourceContact->getY() > targetContact->getY()) std::swap( sourceContact, targetContact ); DbU::Unit width = Session::getGVerticalPitch(); if (state) width *= state->getWPitch(); segment = Vertical::create( sourceContact , targetContact , _anabatic->getConfiguration()->getGVerticalLayer() , constraint.getCenter() , width ); gWL += segment->getLength(); cdebug_log(112,0) << "| ref: " << segment << endl; for ( Edge* through : aligneds ) through->add( segment ); if (state) { if (state->isSymmetric()) _createSelfSymSeg ( segment ); } } cdebug_log(112,0) << "| break (U-turn, turn, branch or terminal)." << endl; cdebug_log(112,0) << "+ " << segment << endl; Vertex* prevSource = source; source = (target->getFrom()) ? target : NULL; if (isAnalog) prevSource->clearFrom2(); } } if (gWL > getAntennaGateMaxWL()) { cdebug_log(113,0) << "| \"" << _net->getName() << "\" may have antenna effect, " << DbU::getValueString(gWL) << endl; if (state) state->setFlags( NetRoutingState::HasAntenna ); } cdebug_tabw(112,-1); } void Dijkstra::run ( Dijkstra::Mode mode ) { DebugSession::open( _net, 111, 120 ); cdebug_log(112,1) << "Dijkstra::run() on " << _net << " mode:" << mode << endl; _mode = mode; _selectFirstSource(); if (_sources.empty()) { cdebug_log(112,0) << "No source to start, not routed." << endl; cdebug_tabw(112,-1); return; } Flags enabledEdges = Flags::AllSides; if (_mode & Mode::Monotonic) { if ((*_sources.begin())->getCenter().getY() <= (*_targets.begin())->getCenter().getY()) enabledEdges = Flags::EastSide | Flags::NorthSide; else enabledEdges = Flags::EastSide | Flags::SouthSide; } _queue.clear(); _queue.setAttractor( _searchArea.getCenter() ); _connectedsId = (*_sources.begin())->getConnexId(); for ( Vertex* source : _sources ) { _queue.push( source ); source->setDistance( 0.0 ); cdebug_log(112,0) << "Push source: (size:" << _queue.size() << ") " << source << " _connectedsId:" << _connectedsId << endl; } while ( ((not _targets.empty()) || needAxisTarget()) and _propagate(enabledEdges) ); _queue.clear(); _materialize(); unsetAxisTargets(); _anabatic->getNetData( _net )->setGlobalRouted( true ); cdebug_tabw(112,-1); DebugSession::close(); } void Dijkstra::_toSources ( Vertex* source, int connexId ) { cdebug_log(112,1) << "Dijkstra::_toSources() " << endl; cdebug_log(112,0) << "* from: " << source << endl; source->setConnexId( connexId ); source->setDistance( 0.0 ); _targets.erase ( source ); _sources.insert( source ); _queue.push( source ); VertexSet stack; stack.insert( source ); while ( not stack.empty() ) { Vertex* current = *stack.begin(); stack.erase( current ); cdebug_log(112,0) << "@ source:" << current << " stack.size():" << stack.size() << endl; for ( Edge* edge : current->getEdges() ) { if (not edge->hasNet(_net)) { cdebug_log(110,0) << "| Not connected:" << edge << " to:" << (current->getNeighbor(edge)) << endl; continue; } Vertex* vneighbor = current->getNeighbor( edge ); cdebug_log(110,0) << "| connected to: " << vneighbor<< endl; if (not vneighbor->hasValidStamp()) continue; if (vneighbor->getConnexId() == connexId) continue; vneighbor->setConnexId( connexId ); vneighbor->setDistance( 0.0 ); if (vneighbor != source) vneighbor->setFrom( NULL ); _targets.erase ( vneighbor ); _sources.insert( vneighbor ); _queue.push( vneighbor ); stack.insert( vneighbor ); } } cdebug_tabw(112,-1); } void Dijkstra::_getConnecteds ( Vertex* source, VertexSet& connecteds ) { cdebug_log(112,1) << "Dijkstra::_getConnecteds()" << endl; connecteds.clear(); connecteds.insert( source ); VertexSet stack; stack.insert( source ); while ( not stack.empty() ) { source = *stack.begin(); stack.erase( source ); cdebug_log(112,0) << "| source:" << source << " stack.size():" << stack.size() << endl; for ( Edge* edge : source->getGCell()->getEdges() ) { if (not edge->hasNet(_net)) { cdebug_log(110,0) << " Not connected:" << edge << endl; continue; } Vertex* vneighbor = source->getNeighbor( edge ); if (connecteds.find(vneighbor) != connecteds.end()) continue; stack.insert( vneighbor ); connecteds.insert( vneighbor ); } } cdebug_tabw(112,-1); } void Dijkstra::_checkEdges () const { cdebug_log(112,1) << "Dijkstra::_checkEdges()" << endl; // for ( Vertex* vertex : _vertexes ) { // for ( Edge* edge : vertex->getGCell()->getEdges(Flags::EastSide|Flags::NorthSide) ) { // } // } cdebug_tabw(112,-1); } void Dijkstra::_createSelfSymSeg ( Segment* segment ) { cdebug_log(112,1) << "Dijkstra::_createSelfSymSeg(): " << segment << endl; NetRoutingState* state = NetRoutingExtension::get( _net ); if (state and segment) { Horizontal* h = dynamic_cast(segment); Vertical* v = dynamic_cast(segment); Point sp; Point tp; DbU::Unit axis; Component* sourceContact = segment->getSource(); Component* targetContact = segment->getTarget(); cdebug_log(112,0) << "source: " << sourceContact << endl; cdebug_log(112,0) << "target: " << targetContact << endl; cdebug_log(112,0) << "sym axis: " << DbU::getValueString(state->getSymAxis()) << endl; if (h) { if (state->isSymHorizontal()) { cdebug_log(112,0) << "Horizontal + Horizontal symmetry." << endl; sp = Point( sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); tp = Point( targetContact->getX(), state->getSymValue(targetContact->getY()) ); axis = state->getSymValue( segment->getY() ); } else if (state->isSymVertical()) { cdebug_log(112,0) << "Horizontal + Vertical symmetry." << endl; sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() ); tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() ); axis = segment->getY(); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Horizontal + Unknown symmetry. " << endl; cdebug_tabw(112,-1); return; } cdebug_log(112,0) << "sp: " << sp << endl; cdebug_log(112,0) << "tp: " << tp << endl; GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* tgcell = _anabatic->getGCellUnder( tp ); cdebug_log(112,0) << "GCell: " << sgcell << endl; cdebug_log(112,0) << "GCell: " << tgcell << endl; Vertex* svertex = sgcell->getObserver(GCell::Observable::Vertex); Vertex* tvertex = tgcell->getObserver(GCell::Observable::Vertex); Contact* sourceSym = NULL; Contact* targetSym = NULL; if (state->isSelfSym()) { cdebug_log(112,0) << "Symmetrical to myself (isSelfSym)." << endl; sourceSym = svertex->getGContact( _net ); targetSym = tvertex->getGContact( _net ); } else if (state->isSymMaster()){ cdebug_log(112,0) << "Symmetrical to (isSymPair): " << state->getSymNet() << endl; sourceSym = svertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() ); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Unknown Net pairing symmetry. " << endl; cdebug_tabw(112,-1); return; } cdebug_log(112,0) << "sourceSym:" << sourceSym << endl; cdebug_log(112,0) << "targetSym:" << targetSym << endl; Segment* segment2 = Horizontal::create( sourceSym , targetSym , _anabatic->getConfiguration()->getGHorizontalLayer() , axis , state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")) ); cdebug_log(112,0) << "| dup:" << segment2 << endl; } else if (v) { if (state->isSymVertical()){ //cerr << "V case Vertical" << endl; sp = Point(state->getSymValue(sourceContact->getX()), sourceContact->getY() ); tp = Point(state->getSymValue(targetContact->getX()), targetContact->getY() ); axis = state->getSymValue(segment->getX()); } else if (state->isSymHorizontal()){ //cerr << "V case Horizontal" << endl; sp = Point( targetContact->getX(), state->getSymValue(targetContact->getY()) ); tp = Point( sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); axis = segment->getX(); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; cdebug_tabw(112,-1); return; } GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* tgcell = _anabatic->getGCellUnder( tp ); Vertex* svertex = sgcell->getObserver(GCell::Observable::Vertex); Vertex* tvertex = tgcell->getObserver(GCell::Observable::Vertex); Contact* sourceSym = NULL; Contact* targetSym = NULL; if (state->isSelfSym()){ sourceSym = svertex->getGContact( _net ); targetSym = tvertex->getGContact( _net ); } else if (state->isSymMaster()){ sourceSym = svertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() ); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; cdebug_tabw(112,-1); return; } cdebug_log(112,0) << "sourceSym:" << sourceSym << endl; cdebug_log(112,0) << "targetSym:" << targetSym << endl; Segment* segment2 = Vertical::create( sourceSym , targetSym , _anabatic->getConfiguration()->getGVerticalLayer() , axis , state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3")) ); cdebug_log(112,0) << "|| " << segment2 << endl; } } cdebug_tabw(112,-1); } bool Dijkstra::_checkFrom2 ( Edge* edge, Vertex* current ) { if (current->getFrom2()){ if (edge == current->getFrom2()) { cdebug_log(111,0) << "edge == current->getFrom2()" << endl; return true; } else { //cdebug_log(111,0) << "edge != current->getFrom2(): " << current->getFrom2() << endl; return false; } } else { //cdebug_log(111,0) << "current->getFrom2() = NULL" << endl; return false; } } bool Dijkstra::_isDistance2Shorter ( DbU::Unit& distance, Vertex* current, Vertex* vneighbor, Edge* edge ) { cdebug_log(111,1) << "Dijkstra::_isDistance2Shorter()" << endl; DbU::Unit distance2 = Vertex::unreachable; bool isDistance2shorter = false; GCell* gneighbor = edge->getOpposite(current->getGCell()); if (current->getFrom2()) { cdebug_log(111,0) << "Has second ::getFrom()" << edge << endl; current->setFlags(Vertex::From2Mode); distance2 = _distanceCb( current, vneighbor, edge ); current->unsetFlags(Vertex::From2Mode); cdebug_log(111,0) << "Distance 1 from current: " << DbU::getValueString(distance) << endl; cdebug_log(111,0) << "Distance 2 from current: " << DbU::getValueString(distance2) << endl; if (distance > distance2) { cdebug_log(111,0) << "* Distance 2 is shorter" << endl; isDistance2shorter = true; distance = distance2; } else if (distance == distance2) { cdebug_log(111,0) << "* Distance 1 equal Distance 2" << endl; Point pcurr = current->getStartPathPoint(vneighbor); current->setFlags( Vertex::From2Mode ); Point pcurr2 = current->getStartPathPoint(vneighbor); current->unsetFlags( Vertex::From2Mode ); Point pnext = gneighbor->getCenter(); if (calcDistance(pcurr,pnext) > calcDistance(pcurr2,pnext)) { cdebug_log(111,0) << "* Distance 2 is shorter" << endl; isDistance2shorter = true; distance = distance2; } else { cdebug_log(111,0) << "* Distance 1 is shorter" << endl; } } else { cdebug_log(111,0) << "* Distance 1 is shorter" << endl; } } else { cdebug_log(111,0) << "No second ::getFrom()" << endl; cdebug_log(111,0) << "Distance 1 from current: " << DbU::getValueString(distance) << endl; } cdebug_tabw(111,-1); return isDistance2shorter; } void Dijkstra::_pushEqualDistance ( DbU::Unit distance, bool isDistance2shorter, Vertex* current, Vertex* vneighbor, Edge* edge ) { GCell* gneighbor = edge->getOpposite(current->getGCell()); GCell* gnext = vneighbor->getGCell(); GCell* gprev = vneighbor->getFrom()->getOpposite(gnext); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); if ((distance == vneighbor->getDistance()) and vneighbor->areSameSide(vprev, current)){ cdebug_log(111,0) << "[case: Distance EQUAL + SameSide]" << endl; cdebug_log(111,0) << "Previous getfrom:" << vneighbor->getFrom()->getOpposite( gneighbor ) << endl; cdebug_log(111,0) << "[case: Other GetFROM]" << endl; cdebug_log(111,0) << "setFrom2: " << vneighbor << endl; vneighbor->setFrom2 ( edge ); vneighbor->setFlags(Vertex::From2Mode); vneighbor->setIntervals( current ); vneighbor->unsetFlags(Vertex::From2Mode); if (isDistance2shorter) { vneighbor->setFlags(Vertex::UseFromFrom2); //cdebug_log(111,0) << "setFromFrom2: " << vneighbor << endl; } cdebug_log(111,0) << "Push BIS : " << vneighbor << endl; cdebug_log(111,0) << "From1: " << vneighbor->getFrom()->getOpposite(vneighbor->getGCell()) << endl; cdebug_log(111,0) << "From2: " << vneighbor->getFrom2()->getOpposite(vneighbor->getGCell()) << endl; vneighbor->getIntervFrom().print(); vneighbor->getIntervFrom2().print(); } } void Dijkstra::_updateGRAData ( Vertex* vneighbor, bool isDistance2shorter, Vertex* current ) { vneighbor->unsetFlags(Vertex::UseFromFrom2); //cdebug_log(111,0) << "unsetFromFrom2: " << vneighbor << endl; vneighbor->clearFrom2(); if (isDistance2shorter) { vneighbor->setFlags(Vertex::UseFromFrom2); cdebug_log(111,0) << "setFlags(Vertex::UseFromFrom2): " << vneighbor << endl; } else { vneighbor->unsetFlags(Vertex::UseFromFrom2); cdebug_log(111,0) << "unsetFlags(Vertex::UseFromFrom2): " << vneighbor << endl; } // else cdebug_log(111,0) << "setFrom1: " << vneighbor << endl; vneighbor->setIntervals( current ); vneighbor->getIntervFrom().print(); } void Dijkstra::_initiateUpdateIntervals ( Vertex* current ) { if (!current->getGCell()->isMatrix()){ GCell* gcurr = current->getGCell(); GCell* gprev = current->getFrom()->getOpposite(gcurr); Vertex* vprev = gprev->getObserver(GCell::Observable::Vertex); Point pcurrent = vprev->getStartPathPoint(current); Point pentry = vprev->getNextPathPoint( pcurrent, current ); //cdebug_log(112,0) << "current : " << gcurr << endl; //cdebug_log(112,0) << "previous: " << gprev << endl; //cdebug_log(112,0) << "pcurr : x: " << DbU::getValueString(pcurrent.getX()) << ", y: " << DbU::getValueString(pcurrent.getY()) << endl; //cdebug_log(112,0) << "pentry: x: " << DbU::getValueString(pentry.getX()) << ", y: " << DbU::getValueString(pentry.getY()) << endl; //cdebug_log(112,0) << "| " << current << " | " << endl; if (current->isH()){ if (pentry.getX() < current->getIMin()){ current->setInterv(pentry.getX(), current->getIMax(), current->getIAxis()); cdebug_log(112,0) << "[Interval update1]: min : " << DbU::getValueString(pentry.getX()); cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getIMax()); cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl; } else if (pentry.getX() > current->getIMax()){ current->setInterv(current->getIMin(), pentry.getX(), current->getIAxis()); cdebug_log(112,0) << "[Interval update2]: min : " << DbU::getValueString(current->getIMin()); cdebug_log(112,0) << ", max : " << DbU::getValueString(pentry.getX()); cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl; } } else if (current->isV()){ if (pentry.getY() < current->getIMin()){ current->setInterv(pentry.getY(), current->getIMax(), current->getIAxis()); cdebug_log(112,0) << "[Interval update3]: min : " << DbU::getValueString(pentry.getY()); cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getIMax()); cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl; } else if (pentry.getY() > current->getIMax()){ current->setInterv(current->getIMin(), pentry.getY(), current->getIAxis()); cdebug_log(112,0) << "[Interval update4]: min : " << DbU::getValueString(current->getIMin()); cdebug_log(112,0) << ", max : " << DbU::getValueString(pentry.getY()); cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getIAxis()) << endl; } } //cdebug_log(112,0) << "isiSet: " << current->isiSet() << endl; } } bool Dijkstra::_updateIntervals( bool& isfirst, Vertex* current, bool& useFrom2, int& branchId, Edge* from ) { if (!isfirst){ //cdebug_log(112,0) << "Is not first" << endl; current->incDegree(); if (current->getConnexId() == _connectedsId){ cdebug_log(112,0) << "| (current->getConnexId() == _connectedsId)" << endl; return true; } from = NULL; if (useFrom2) { if (current->getFrom2()) { //cdebug_log(112,0) << "| USE FROM2: " << endl; //cdebug_log(112,0) << "| current->getFrom2(): " << current->getFrom2() << endl; //cdebug_log(112,0) << "| current->getGCell(): " << current->getGCell() << endl; //cdebug_log(112,0) << "| getOpposite(): " << current->getFrom2()->getOpposite(current->getGCell()) << endl; current->setFrom(current->getFrom2()); current->setIntervfrom(current->getPIMin2(), current->getPIMax2(), current->getPIAxis2()); current->clearFrom2(); } else { cdebug_log(112,0) << "[Warning]: Current has no getfrom2 anymore. " << endl; } } from = current->getFrom(); if (not from) return true; current->setDistance( 0.0 ); current->setConnexId( _connectedsId ); current->setBranchId( branchId ); _sources.insert( current ); _queue.push( current ); } else { //cdebug_log(112,0) << "Is first" << endl; isfirst = false; } if ((current->getPredecessor() != NULL)&&(!current->getGCell()->isMatrix())){ //cdebug_log(112,0) << "Predecessor() : " << current->getPredecessor() << endl; //cdebug_log(112,0) << "| [Interval update]: min : " << DbU::getValueString(current->getPIMin()); //cdebug_log(112,0) << ", max : " << DbU::getValueString(current->getPIMax()); //cdebug_log(112,0) << ", axis: " << DbU::getValueString(current->getPIAxis()) << endl; current->getPredecessor()->setInterv(current->getPIMin(), current->getPIMax(), current->getPIAxis()); //current->getIntervFrom().print(); //if (current->getPredecessor()->getGCell()->isStrut()) _updateRealOccupancy( current ); } return false; } bool Dijkstra::_attachSymContactsHook( RoutingPad* rp ) { NetRoutingState* state = NetRoutingExtension::get( _net ); if (state){ if (state->isSelfSym()){ if ( ( (state->isSymHorizontal())&&(rp->getBoundingBox().getYMin() > state->getSymAxis()) ) ||( (state->isSymVertical() )&&(rp->getBoundingBox().getXMin() > state->getSymAxis()) ) ){ Point center = rp->getBoundingBox().getCenter(); GCell* gcell = _anabatic->getGCellUnder( center ); Vertex* seed = gcell->getObserver(GCell::Observable::Vertex); Contact* vcontact = seed->getGContact( _net ); rp->getBodyHook()->detach(); rp->getBodyHook()->attach( vcontact->getBodyHook() ); return true; } } } return false; } void Dijkstra::_limitSymSearchArea( RoutingPad* rp ) { NetRoutingState* state = NetRoutingExtension::get( _net ); Point center = rp->getBoundingBox().getCenter(); GCell* gcell = _anabatic->getGCellUnder( center ); if (state){ if (state->isSymHorizontal()){ _searchArea.merge( Box( _net->getCell()->getAbutmentBox().getXMin() , _net->getCell()->getAbutmentBox().getYMin() , _net->getCell()->getAbutmentBox().getXMax() , state->getSymAxis() ) ); } else if (state->isSymVertical()){ _searchArea.merge( Box( _net->getCell()->getAbutmentBox().getXMin() , _net->getCell()->getAbutmentBox().getYMin() , state->getSymAxis() , _net->getCell()->getAbutmentBox().getYMax() ) ); } else if (gcell->isDevice()){ _searchArea.merge( _net->getCell()->getAbutmentBox() ); } } else if (gcell->isDevice()){ _searchArea.merge( _net->getCell()->getAbutmentBox() ); } } void Dijkstra::_setSourcesGRAData( Vertex* seed, RoutingPad* rp ) { cdebug_log(112,0) << "void Dijkstra::_setSourcesGRAData() : " << seed << endl; GCell* gseed = seed->getGCell(); Horizontal* h = dynamic_cast(rp->_getEntityAs()); Vertical* v = dynamic_cast (rp->_getEntityAs()); if (h) { cdebug_log(112,0) << "case H " << endl; seed->unsetFlags(Vertex::iHorizontal); seed->unsetFlags(Vertex::iVertical); seed->setFlags(Vertex::iHorizontal); if (!gseed->isMatrix()){ seed->createAData(); seed->setInterv( max(rp->getBoundingBox().getXMin(), gseed->getXMin()) , min(rp->getBoundingBox().getXMax(), gseed->getXMax()) , rp->getBoundingBox().getYCenter() ); } } else if (v) { cdebug_log(112,0) << "case V " << endl; seed->unsetFlags(Vertex::iHorizontal); seed->unsetFlags(Vertex::iVertical); seed->setFlags(Vertex::iVertical); if (!gseed->isMatrix()) { seed->createAData(); seed->setInterv( max(rp->getBoundingBox().getYMin(), gseed->getYMin()) , min(rp->getBoundingBox().getYMax(), gseed->getYMax()) , rp->getBoundingBox().getXCenter() ); } } } void Dijkstra::_updateRealOccupancy ( Vertex* current ) { //cerr << "void Dijkstra::_updateRealOccupancy ( Vertex* current ): " << current << endl; GCell* gcurrent = current->getGCell(); GCell* gnext = current->getPredecessor()->getGCell(); Edge* e = gcurrent->getEdgeTo(gnext); NetRoutingState* state = NetRoutingExtension::get( _net ); //cerr << "e: " << e << endl; e->incRealOccupancy2(state->getWPitch()); //cerr << "e: " << e << endl; if (current->getGCell()->getWestEdge()) cerr << "W occupancy: " << current->getGCell()->getWestEdge()->getRealOccupancy() << "/" << current->getGCell()->getWestEdge()->getCapacity() << endl; if (current->getGCell()->getEastEdge()) cerr << "E occupancy: " << current->getGCell()->getEastEdge()->getRealOccupancy() << "/" << current->getGCell()->getEastEdge()->getCapacity() << endl; if (current->getGCell()->getNorthEdge()) cerr << "N occupancy: " << current->getGCell()->getNorthEdge()->getRealOccupancy() << "/" << current->getGCell()->getNorthEdge()->getCapacity() << endl; if (current->getGCell()->getSouthEdge()) cerr << "S occupancy: " << current->getGCell()->getSouthEdge()->getRealOccupancy() << "/" << current->getGCell()->getSouthEdge()->getCapacity() << endl; } } // Anabatic namespace.