#include #include "hurricane/Warning.h" #include "hurricane/Name.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/RoutingPad.h" #include "hurricane/Component.h" #include "hurricane/Net.h" #include "hurricane/Cell.h" #include "hurricane/Technology.h" #include "hurricane/DataBase.h" #include "hurricane/UpdateSession.h" #include "hurricane/Breakpoint.h" #include "crlcore/Utilities.h" #include "crlcore/AllianceFramework.h" #include "crlcore/RoutingGauge.h" #include "crlcore/RoutingLayerGauge.h" #include "knik/Configuration.h" #include "knik/Graph.h" #include "knik/Vertex.h" #include "knik/Edge.h" #include "knik/HEdge.h" #include "knik/VEdge.h" #include "knik/flute.h" //#define __USE_SLICINGTREE__ #define __USE_MATRIXVERTEX__ #define EPSILON 10e-4 #define FLUTE_LIMIT 150 #define HISTORIC_INC 1.5 // define the increment of historic cost for ripup & reroute namespace Knik { int depthMaterialize; unsigned countDijkstra = 0; unsigned countMonotonic = 0; unsigned countMaterialize = 0; bool debugging; Name debugName = Name(""); bool __ripupMode__; extern float __edge_capacity_percent__; extern unsigned __congestion__; extern unsigned __precongestion__; using namespace CRL; STuple::STuplePQIter STuple::_stuplePQEnd; Name STuple::CostProperty::_name = "Knik::CostProperty"; struct segmentStat { unsigned nbDep; unsigned nbTot; unsigned sumOv; segmentStat(unsigned dep, unsigned tot, unsigned ov) { nbDep=dep; nbTot=tot; sumOv=ov; }; segmentStat() {}; ~segmentStat() {}; void incNbDep() { nbDep++; }; void incNbTot() { nbTot++; }; void incSumOv ( unsigned inc ) { sumOv+=inc; }; unsigned getNbDep() const { return nbDep; }; unsigned getNbTot() const { return nbTot; }; unsigned getSumOv() const { return sumOv; }; }; Graph::Graph ( Cell* cell, RoutingGrid* routingGrid, bool benchMode, bool useSegments ) // ********************************************************************************************** : _cell ( cell ) , _benchMode ( benchMode ) , _useSegments ( useSegments ) , _slicingTree ( NULL ) , _matrixVertex ( NULL ) , _routingGrid ( routingGrid ) , _working_net ( NULL ) , _vertexes_to_route() , _lowerLeftVertex ( NULL ) , _all_vertexes() , _all_edges() , _nbSplitters ( 0 ) , _vtuplePriorityQueue() , _stuplePriorityQueue() , _searchingArea() , _xSize ( 0 ) , _ySize ( 0 ) //, _estimateOccupancyWindow ( NULL ) //, _occupancyWindow ( NULL ) , _maxEstimateOccupancy ( 0.0 ) , _maxXEstimateOccupancy ( 0.0 ) , _maxYEstimateOccupancy ( 0.0 ) , _maxOccupancy ( 0 ) , _maxXOccupancy ( 0 ) , _maxYOccupancy ( 0 ) , _hEdgeNormalisedLength ( 1.0 ) // au cas ou , _vEdgeNormalisedLength ( 1.0 ) // au cas ou { __ripupMode__ = false; } Graph* Graph::create ( Cell* cell, RoutingGrid* routingGrid, bool benchMode, bool useSegments ) // ****************************************************************************************************** { Graph* _graph = new Graph ( cell, routingGrid, benchMode, useSegments ); _graph->_postCreate(); return _graph; } void Graph::_postCreate() // ********************** { _netStamp = 1; // initializing netStamp here instead of in Knik::Route function (for reroute, it seems good) //Cell* cell = _nimbus->getCell(); //DisplaySlot* vertexDS = DisplaySlot::create( cell, Name("KnikVertexDS"),192, 0 ,192,"FFFFFFFFFFFFFFFF",1,192, 0 ,192,"FFFFFFFFFFFFFFFF",1 ); //DisplaySlot* edgeDS = DisplaySlot::create( cell, Name("KnikEdgeDS") ,153,100, 17,"55AA55AA55AA55AA",1,153,100, 17,"55AA55AA55AA55AA",1 ); // XXX On supprime tout ce qui concerne NIMBUS et on considère qu'il existe toujours une _routingGrid XXX if ( !_routingGrid ) { #ifdef __USE_MATRIXVERTEX__ _matrixVertex = MatrixVertex::create(this); if( !_matrixVertex ) throw Error ("Graph::_postCreate(): cannot create MatrixVertex"); _lowerLeftVertex = _matrixVertex->createRegularMatrix (); cmess2 << " - Initialization done (without routingGrid)" << endl; #else throw Error ("Graph::_postCreate(): cannot use another method than MatrixVertex"); #endif // il faut définir les normalisedLength, pour l'instant on le fait pas } else { cmess2 << " - Size from routingGrid : " << _routingGrid->getNbXTiles() << ", " << _routingGrid->getNbYTiles() << endl; #ifdef __USE_MATRIXVERTEX__ _matrixVertex = MatrixVertex::create(this); if( !_matrixVertex ) throw Error ("Graph::_postCreate(): cannot create MatrixVertex"); _lowerLeftVertex = _matrixVertex->createRegularMatrix ( _routingGrid ); // initialisation des normalisedLength float hEdgeLength = _routingGrid->getTileWidth(); float vEdgeLength = _routingGrid->getTileHeight(); _hEdgeNormalisedLength = hEdgeLength <= vEdgeLength ? 1.0 : hEdgeLength / vEdgeLength; _vEdgeNormalisedLength = hEdgeLength <= vEdgeLength ? vEdgeLength / hEdgeLength : 1.0; cmess2 << " - Initialization done." << endl; #else throw Error ("Graph::_postCreate(): cannot use another method than MatrixVertex"); #endif } // #ifdef __USE_MATRIXVERTEX__ // _matrixVertex = MatrixVertex::create(this); // if ( _routingGrid ) { // _matrixVertex->createXRegular ( _routingGrid ); // _matrixVertex->createYRegular ( _routingGrid ); // } // else { // _matrixVertex->createXIrregular ( _nimbus ); // _matrixVertex->createYIrregular ( _nimbus ); // } // #endif // #ifdef __USE_SLICINGTREE__ // _slicingTree = SlicingTree::create ( _nimbus ); // #endif // // unsigned compteur = 0; // for_each_gcell ( gcell, _nimbus->getRoutingLeaves() ) // { // compteur++; // Vertex* vertex = Vertex::create ( gcell, this ); // if ( !_lowerLeftVertex ) // _lowerLeftVertex = vertex; // else { // if ( vertex->getX() <= _lowerLeftVertex->getX() ) { // if ( vertex->getY() <= _lowerLeftVertex->getY() ) // _lowerLeftVertex = vertex; // } // } // _all_vertexes.push_back ( vertex ); // #ifdef __USE_MATRIXVERTEX__ // _matrixVertex->setVertex ( gcell->getCenter(), vertex ); // #endif // #ifdef __USE_SLICINGTREE__ // SlicingTreeNode* terminalNode = _slicingTree->getTerminalNode ( gcell->getCenter() ); // terminalNode->setVertex ( vertex ); // #endif // end_for; // } // cmess2 << " - Parcours des gcells pour créer les vertex terminé : " << compteur << " vertex" << endl; // // Vertex* currentVertex = _lowerLeftVertex; // while ( currentVertex ) { // Vertex* firstLineVertex = currentVertex; // while ( currentVertex ) { // GCell* source = currentVertex->getGCell(); // Fence* fenceUP = source->getUpFence(); // GCell* targetUP = source->getUpOfMe(); // if ( targetUP ) // createVEdge ( currentVertex, getVertex ( targetUP->getCenter() ), fenceUP ); // Fence* fenceRIGHT = source->getRightFence(); // GCell* targetRIGHT = source->getRightOfMe(); // if ( targetRIGHT ) { // Vertex* rightVertex = getVertex ( targetRIGHT->getCenter() ); // createHEdge ( currentVertex, rightVertex, fenceRIGHT ); // currentVertex = rightVertex; // } // else // break; // } // Edge* vEdgeOut = firstLineVertex->getVEdgeOut(); // if ( vEdgeOut ) // currentVertex = vEdgeOut->getOpposite ( firstLineVertex ); // else // break; // } // cmess2 << " - Parcours des gcells puis des fences pour créer les edges terminé" << endl; for ( unsigned i = 0 ; i < _all_vertexes.size() ; i++ ) { _all_vertexes[i]->sortEdges(); } cmess2 << " - Tri des edges terminé" << endl; STuple::setSTuplePQEnd ( _stuplePriorityQueue.end() ); // cmess2 << "Petites stats :" << endl // << " gcell : " << sizeof(GCell) << endl // << " fence : " << sizeof(Fence) << endl // << " vertex : " << sizeof(Vertex) << endl // << " edge : " << sizeof (Edge) << endl // << " net : " << sizeof(Net) << endl // << " pin : " << sizeof(Pin) << endl // << " splitter : " << sizeof(Splitter) << endl // << " splitterContact : " << sizeof(SplitterContact) << endl; } void Graph::destroy() // ***************** { _preDestroy(); delete this; } void Graph::_preDestroy() // ********************* { // Destruction of all VTuples for ( VTuplePQIter pqit = _vtuplePriorityQueue.begin() ; pqit != _vtuplePriorityQueue.end() ; pqit++ ) { (*pqit)->destroy(); } // Destrucion of all Edges and Vertexes Vertex* currentVertex = _lowerLeftVertex; while ( currentVertex ) { Vertex* nextVVertex; if ( Edge* vEdgeOut = currentVertex->getVEdgeOut() ) nextVVertex = vEdgeOut->getOpposite ( currentVertex ); else nextVVertex = NULL; while ( currentVertex ) { if ( Edge* vEdgeOut = currentVertex->getVEdgeOut() ) vEdgeOut->destroy(); Vertex* nextHVertex; if ( Edge* hEdgeOut = currentVertex->getHEdgeOut() ) { nextHVertex = hEdgeOut->getOpposite ( currentVertex ); hEdgeOut->destroy(); } else nextHVertex = NULL; currentVertex->destroy(); currentVertex = nextHVertex; } currentVertex = nextVVertex; } //// Destruction of all Edges //for ( unsigned i = 0 ; i < _all_edges.size() ; i++ ) { // _all_edges[i]->destroy(); //} //// Destruction of all Vertexes //for ( unsigned i = 0 ; i < _all_vertexes.size() ; i++ ) { // _all_vertexes[i]->destroy(); //} #ifdef __USE_MATRIXVERTEX__ _matrixVertex->destroy(); #endif #ifdef __USE_SLICINGTREE__ _slicingTree->destroy(); #endif } Vertex* Graph::getPredecessor ( const Vertex* vertex ) // *************************************************** { assert( vertex->getPredecessor() ); return vertex->getPredecessor()->getOpposite ( vertex ); } Vertex* Graph::getCentralVertex() // ****************************** { assert ( _vertexes_to_route.begin() != _vertexes_to_route.end() ); // This function skims the _vertexes_to_route set and returns the most centered vertex. // // first pass : builds the bounding box of all vertexes Box vertexesBBox; VertexSetIter vsit = _vertexes_to_route.begin(); while ( vsit != _vertexes_to_route.end() ) { vertexesBBox.merge((*vsit)->getPosition()); vsit++; } // second pass : finds the most centered vertex Point boxCenter = vertexesBBox.getCenter(); vsit = _vertexes_to_route.begin(); Vertex* mostCentered = (*vsit); DbU::Unit minDistance = boxCenter.manhattanDistance ( mostCentered->getPosition() ); vsit++; while ( vsit != _vertexes_to_route.end() ) { Vertex* currentVertex = (*vsit); DbU::Unit currentDistance = boxCenter.manhattanDistance( currentVertex->getPosition() ); if ( currentDistance < minDistance ) { mostCentered = currentVertex; minDistance = currentDistance; } vsit++; } return mostCentered; } Vertex* Graph::getVertex ( Point p ) // ********************************* { Vertex* vertex; #ifdef __USE_MATRIXVERTEX__ vertex = _matrixVertex->getVertex(p); assert(vertex); #endif #ifdef __USE_SLICINGTREE__ vertex = _slicingTree->getVertex ( p ); assert ( vertex ); //#else // Ce n'est plus une option ! // GCell* gcell = _nimbus->getRoutingLeafContaining ( p ); // assert ( gcell ); // vertex = getVertexOfGCell ( gcell ); // assert ( vertex ); #endif return vertex; } Vertex* Graph::getVertex ( DbU::Unit x, DbU::Unit y ) // ************************************************** { return getVertex ( Point(x,y) ); } unsigned Graph::getGridLength ( Segment* segment ) // *********************************************** { // new time-optimized version 02/02/09 unsigned sourceColId = _matrixVertex->getColumnIndex ( segment->getSourceX() ); unsigned targetColId = _matrixVertex->getColumnIndex ( segment->getTargetX() ); unsigned sourceRowId = _matrixVertex->getLineIndex ( segment->getSourceY() ); unsigned targetRowId = _matrixVertex->getLineIndex ( segment->getTargetY() ); if ( sourceColId == targetColId ) return targetRowId - sourceRowId; else return targetColId - sourceColId; //if ( isAGlobalRoutingSegment(segment) ) { // if ( Horizontal* horiz = dynamic_cast(segment) ) { // unsigned sourceId = _matrixVertex->getColumnIndex ( horiz->getSourceX() ); // unsigned targetId = _matrixVertex->getColumnIndex ( horiz->getTargetX() ); // assert ( sourceId != targetId ); // return targetId - sourceId; // On considere que les segments sont bien orientes !!!! // } // else if ( Vertical* verti = dynamic_cast(segment) ) { // unsigned sourceId = _matrixVertex->getLineIndex ( verti->getSourceY() ); // unsigned targetId = _matrixVertex->getLineIndex ( verti->getTargetY() ); // assert ( sourceId != targetId ); // return targetId - sourceId; // meme hypothese !!! // } // else // throw Error ( "Graph::getGridLength(): segment is neither horizontal nor vertical." ); //} return 0; } unsigned Graph::getCongestEdgeNb ( Segment* segment ) // ************************************************** { if ( !isAGlobalRoutingSegment(segment) ) { string message = "getCongestEdgeNb only treats global routing segment for now : "; message += getString(segment); throw Warning ( message ); } unsigned nbEdge = 0; if ( dynamic_cast(segment) ) { Vertex* current = getVertex ( segment->getSource()->getCenter() ); Vertex* target = getVertex ( segment->getTarget()->getCenter() ); while ( current != target ) { Edge* edge = current->getHEdgeOut(); if ( !edge ) throw Error ("Graph::getCongestEdgeNb(): Wow! NULL horizontal Edge."); if ( edge->isCongested() ) nbEdge++; current = edge->getTo(); } } else if ( dynamic_cast(segment) ) { Vertex* current = getVertex ( segment->getSource()->getCenter() ); Vertex* target = getVertex ( segment->getTarget()->getCenter() ); while ( current != target ) { Edge* edge = current->getVEdgeOut(); if ( !edge ) throw Error ("Graph::getCongestEdgeNb(): Wow! NULL vertical Edge."); if ( edge->isCongested() ) nbEdge++; current = edge->getTo(); } } else throw Error ( "Graph::getCongestEdgeNb(): segment is neither horizontal nor vertical." ); return nbEdge++; } Segment* Graph::createSegment ( Contact* initialContact, Contact* reachedContact ) // ******************************************************************************* { //cerr << "Graph::createSegment: " << initialContact << " -- " << reachedContact << endl; if ( initialContact->getX() == reachedContact->getX() ) { const Layer* layer = Configuration::getGMetalV(); DbU::Unit xCoord = initialContact->getX(); DbU::Unit width = DbU::lambda(2); if ( initialContact->getY() <= reachedContact->getY() ) return Vertical::create ( initialContact, reachedContact, layer, xCoord, width ); else return Vertical::create ( reachedContact, initialContact, layer, xCoord, width ); } else if ( initialContact->getY() == reachedContact->getY() ) { const Layer* layer = Configuration::getGMetalH(); DbU::Unit yCoord = initialContact->getY(); DbU::Unit height = DbU::lambda(2); if ( initialContact->getX() <= reachedContact->getX() ) return Horizontal::create ( initialContact, reachedContact, layer, yCoord, height ); else return Horizontal::create ( reachedContact, initialContact, layer, yCoord, height ); } else throw Error ( "Graph::createSegment(): Contacts are not aligneds." ); } void Graph::sortHVertexes ( Vertex*& from, Vertex*& to ) // ***************************************************** { // This function sorts 2 vertexes horizontally: // from will be the leftest one assert (from); assert (to); if ( from->getX() > to->getX() ) { Vertex* temp = from; from = to; to = temp; } } void Graph::sortVVertexes ( Vertex*& from, Vertex*& to ) // ***************************************************** { // This function sorts 2 vertexes vertically: // from will be the downest one assert (from); assert (to); if ( from->getY() > to->getY() ) { Vertex* temp = from; from = to; to = temp; } } Vertex* Graph::createVertex ( Point position, DbU::Unit halfWidth, DbU::Unit halfHeight ) // ************************************************************************************** { Vertex* vertex = Vertex::create ( this, position, halfWidth, halfHeight ); assert ( vertex ); _all_vertexes.push_back ( vertex ); return vertex; } void Graph::createHEdge ( Vertex* from, Vertex* to, float ecp ) // ************************************************************** { unsigned int capacity = 0; if ( _routingGrid ) { capacity = _routingGrid->getHCapacity(); //cerr << "createHEdge capacity:" << capacity << " ecp:" << ecp << endl; } else { vector rtLGauges = AllianceFramework::get()->getRoutingGauge()->getLayerGauges(); for ( vector::iterator it = rtLGauges.begin() ; it != rtLGauges.end() ; it++ ) { RoutingLayerGauge* routingLayerGauge = (*it); if (routingLayerGauge->getType() != Constant::Default) continue; if (routingLayerGauge->getDirection() != Constant::Horizontal) continue; capacity += routingLayerGauge->getTrackNumber ( from->getYMin(), from->getYMax() ) - 1; } //cerr << "createHEdge capacity:" << capacity << " ecp:" << ecp << endl; } Edge* newEdge = HEdge::create ( from, to, (unsigned)((float)(capacity)*ecp) ); _all_edges.push_back ( newEdge ); newEdge->setCost(1); Edge* previousEdge = from->getHEdgeOut(); if ( previousEdge ) newEdge->setNextFrom ( previousEdge ); from->setHEdgeOut ( newEdge ); previousEdge = to->getHEdgeIn(); if ( previousEdge ) newEdge->setNextTo ( previousEdge ); to->setHEdgeIn ( newEdge ); } void Graph::createVEdge ( Vertex* from, Vertex* to, float ecp ) // ************************************************************ { unsigned int capacity = 0; if ( _routingGrid ) capacity = _routingGrid->getVCapacity(); else { vector rtLGauges = AllianceFramework::get()->getRoutingGauge()->getLayerGauges(); for ( vector::iterator it = rtLGauges.begin() ; it != rtLGauges.end() ; it++ ) { RoutingLayerGauge* routingLayerGauge = (*it); if (routingLayerGauge->getType() != Constant::Default) continue; if (routingLayerGauge->getDirection() != Constant::Vertical) continue; capacity += routingLayerGauge->getTrackNumber ( from->getXMin(), from->getXMax() ) - 1; } //cerr << "createVEdge capacity:" << capacity << " ecp:" << ecp << endl; } Edge* newEdge = VEdge::create ( from, to, (unsigned)((float)(capacity)*ecp) ); _all_edges.push_back ( newEdge ); newEdge->setCost(1); Edge* previousEdge = from->getVEdgeOut(); if ( previousEdge ) newEdge->setNextFrom ( previousEdge ); from->setVEdgeOut ( newEdge ); previousEdge = to->getVEdgeIn(); if ( previousEdge ) newEdge->setNextTo ( previousEdge ); to->setVEdgeIn ( newEdge ); } void Graph::initConnexComp ( Vertex* vertex, int newConnexID ) // *********************************************************** { initConnexComp ( vertex, NULL, newConnexID ); } void Graph::initConnexComp ( Vertex* vertex, Edge* arrivalEdge, int newConnexID ) // ****************************************************************************** { // This recursive function initializes all vertexes of same connexID and connected through edges of same connexID, // which means that the vertex's distance is set to 0 and the vertex is inserted in the VTuplePriorityQueue // If newConnexID is different from -1, then the connexID is set to newConnexID int vertexConnex = vertex->getConnexID(); assert ( vertexConnex != -1 ); for_each_edge ( edge, vertex->getAdjacentEdges() ) { if ( edge == arrivalEdge ) { continue; } if ( (edge->getNetStamp() == _netStamp) && (edge->getConnexID() == vertexConnex) ) { initConnexComp ( edge->getOpposite(vertex), edge, newConnexID ); if ( newConnexID != -1 ) { edge->setConnexID(newConnexID); } } end_for; } vertex->setDistance(0); if ( newConnexID != -1 ) { vertex->setConnexID ( newConnexID ); } if ( VTuple* vtuple = vertex->getVTuple() ) { //cerr << " Vertex " << vertex << " already has a vtuple : " << vtuple << endl; assert ( vtuple->getVertex() == vertex ); increaseVTuplePriority ( vtuple, 0 ); } else { VTuple* vtuple = VTuple::create ( vertex, 0 ); //cerr << " Vertex " << vertex << " has now a new vtuple : " << vtuple << endl; addVTupleToPriorityQueue ( vtuple ); } } void Graph::UpdateConnexComp ( VertexList reachedVertexes, Vertex* firstVertex ) // ***************************************************************************** { // XXX PLUTOT QUE DE PASSER UNE LISTE DE VERTEX EN ARG, ON DEVRAIT PASSER SEULEMENT UN VERTEX XXX // XXX proviens du fait qu'au depart on voulait reellement passer une liste mais du fait de la possiblité de chemins paralleles on evite XXX int firstConnexID = firstVertex->getConnexID(); VertexListIter lvit = reachedVertexes.begin(); // Pour essayer d'éviter le bug des chemins parallèles si 2 vertex sont atteints avec la meme distance, on ne va updater que le premier //while ( lvit != reachedVertexes.end() ) { Vertex* currentVertex = (*lvit); int currentConnexID = currentVertex->getConnexID(); //cerr << "Gonna updateConnexComp : first: " << firstVertex << ", reached: " << currentVertex << endl; //cerr << " vertexes_to_route :" << endl; //for ( VertexSetIter vsit = _vertexes_to_route.begin() ; vsit != _vertexes_to_route.end() ; vsit++ ) // cerr << " " << (*vsit) << endl; // the vertex must be removed from the _vertexes_to_route // XXX Woowoo il ne faut pas faire un erase du vertex atteint, mais rechercher le représentant de la composante connexe atteinte dans les _vertexes_to_route et faire un erase dessus ! Vertex* toErase = NULL; for ( VertexSetIter vsit = _vertexes_to_route.begin() ; vsit != _vertexes_to_route.end() ; vsit++ ) { if ( (*vsit)->getConnexID() == currentConnexID ) toErase = (*vsit); } //cerr << " gonna erase : " << toErase << endl; // on veut updater toute la composante connexe représenter par le currentVertex #ifndef NDEBUG unsigned deleteVertex = _vertexes_to_route.erase ( toErase ); assert ( deleteVertex == 1 ); #else _vertexes_to_route.erase ( toErase ); #endif // the connexe component corresponding to the vertex must be initialize with the firstConnexID initConnexComp ( currentVertex, firstConnexID ); // create the new connex component and initializes it : while ( Edge* predecessor = currentVertex->getPredecessor() ) { currentVertex->setPredecessor ( NULL ); predecessor->setConnexID ( firstConnexID ); currentVertex = predecessor->getOpposite ( currentVertex ); // si jamais on réatteint un vertex dejà mis à jour. if ( currentVertex->getConnexID() == firstConnexID ) break; currentVertex->setDistance(0); currentVertex->setConnexID(firstConnexID); if ( VTuple* vtuple = currentVertex->getVTuple() ) { increaseVTuplePriority ( vtuple, 0); } else { VTuple* vtuple = VTuple::create ( currentVertex, 0 ); addVTupleToPriorityQueue ( vtuple ); } } //} } // VTuplePriorityQueue Utility Methods // *********************************** Vertex* Graph::extractMinFromPriorityQueue() // ***************************************** { if ( _vtuplePriorityQueue.begin() == _vtuplePriorityQueue.end() ) return NULL; VTuple* vtuple = *(_vtuplePriorityQueue.begin()); Vertex* vertex = vtuple->getVertex(); _vtuplePriorityQueue.erase ( _vtuplePriorityQueue.begin() ); vtuple->destroy(); vertex->setVTuple ( NULL ); return vertex; } Vertex* Graph::getMinFromPriorityQueue() // ************************************* { if ( _vtuplePriorityQueue.begin() == _vtuplePriorityQueue.end() ) return NULL; VTuple* vtuple = *(_vtuplePriorityQueue.begin()); Vertex* vertex = vtuple->getVertex(); return vertex; } void Graph::PopMinFromPriorityQueue() // ********************************** { if ( _vtuplePriorityQueue.begin() != _vtuplePriorityQueue.end() ) { VTuple* vtuple = *(_vtuplePriorityQueue.begin()); Vertex* vertex = vtuple->getVertex(); _vtuplePriorityQueue.erase ( _vtuplePriorityQueue.begin() ); vtuple->destroy(); vertex->setVTuple ( NULL ); } } void Graph::addVTupleToPriorityQueue ( VTuple* vtuple ) // ************************************************* { assert ( vtuple ); assert ( vtuple->getVertex()->getVTuple() == vtuple ); assert ( _vtuplePriorityQueue.find ( vtuple ) == _vtuplePriorityQueue.end() ); //if (debugging) // cerr << " ADDING vtuple to priority queue : " << vtuple->_getString() << endl; _vtuplePriorityQueue.insert ( vtuple ); //pair p = _vtuplePriorityQueue.insert ( vtuple ); //assert ( p.second ); } void Graph::increaseVTuplePriority ( VTuple* vtuple, float distance ) // *************************************************************** { assert ( vtuple ); //if ( debugging ) // cerr << " " << vtuple->getVertex() << " : " << vtuple->getDistance() << " > " << distance << endl; assert ( vtuple->getDistance() > distance ); // Copy removeVTupleFromPriorityQueue without vtuple->destroy() VTuplePQIter pqit = _vtuplePriorityQueue.find ( vtuple ); if ( pqit != _vtuplePriorityQueue.end() ) { assert ( vtuple->getVertex() == (*pqit)->getVertex() ); _vtuplePriorityQueue.erase ( pqit ); } // end copy vtuple->setDistance ( distance ); _vtuplePriorityQueue.insert ( vtuple ); } void Graph::printVTuplePriorityQueue() // ********************************** { cmess2 << "*** printing VTuplePriorityQueue ***" << endl; VTuplePQIter pqit = _vtuplePriorityQueue.begin(); while ( pqit != _vtuplePriorityQueue.end() ) { cmess2 << (*pqit)->getVertex() << " : " << (*pqit)->getDistance() << endl; pqit++; } cmess2 << "***********************************" << endl; } void Graph::clearPriorityQueue() // ***************************** { for ( VTuplePQIter pqit = _vtuplePriorityQueue.begin() ; pqit != _vtuplePriorityQueue.end() ; pqit++ ) { (*pqit)->destroy(); } _vtuplePriorityQueue.clear(); } // STuplePriorityQueue Utility Methods // *********************************** Segment* Graph::extractMaxFromSTuplePQ() // ************************************* { if ( _stuplePriorityQueue.begin() == STuple::_stuplePQEnd ) return NULL; STuple* stuple = *(_stuplePriorityQueue.begin()); Segment* segment = stuple->getSegment(); _stuplePriorityQueue.erase ( _stuplePriorityQueue.begin() ); stuple->destroy(); return segment; } STuple* Graph::getMaxFromSTuplePQ() // ******************************** { if ( _stuplePriorityQueue.begin() == STuple::_stuplePQEnd ) return NULL; STuple* stuple = *(_stuplePriorityQueue.begin()); return stuple; } void Graph::popMaxFromSTuplePQ() // ********************************* { if ( _stuplePriorityQueue.begin() != STuple::_stuplePQEnd ) { STuple* stuple = *(_stuplePriorityQueue.begin()); #ifndef NDEBUG STuple::CostProperty* costProperty = stuple->getCostProperty(); assert ( costProperty ); assert ( (*costProperty->getPQIter()) == stuple ); #endif stuple->destroy(); _stuplePriorityQueue.erase ( _stuplePriorityQueue.begin()); } } void Graph::addToSTuplePQ ( STuple* stuple ) // ***************************************** { assert ( stuple ); STuple::CostProperty* costProperty = stuple->getCostProperty(); assert ( costProperty ); costProperty->setPQIter ( _stuplePriorityQueue.insert ( stuple ) ); STuple::STuplePQIter pqit = costProperty->getPQIter(); assert ( (*pqit) == stuple ); } void Graph::updateSTupleCost ( STuple* stuple, unsigned cost ) // *********************************************************** { assert ( stuple ); STuple::CostProperty* costProperty = stuple->getCostProperty(); assert ( costProperty ); STuple::STuplePQIter pqit = costProperty->getPQIter(); assert ( (*pqit) == stuple ); _stuplePriorityQueue.erase ( pqit ); stuple->setCost ( cost ); costProperty->setPQIter ( _stuplePriorityQueue.insert ( stuple ) ); } void Graph::printSTuplePQ() // ************************ { cmess1 << "*** printing STuplePriorityQueue ***" << endl; STuple::STuplePQIter pqit = _stuplePriorityQueue.begin(); while ( pqit != STuple::_stuplePQEnd ) { cmess1 << getString(*pqit) << endl; pqit++; } cmess1 << "***********************************" << endl; } void Graph::clearSTuplePQ() // ************************ { for ( STuple::STuplePQIter pqit = _stuplePriorityQueue.begin() ; pqit != STuple::_stuplePQEnd ; pqit++ ) { (*pqit)->destroy(); } _stuplePriorityQueue.clear(); } void Graph::testSTuplePQ() // *********************** { // unsigned count = 0; // Component* compo1 = NULL; // Component* compo2 = NULL; // for_each_component ( component, _nimbus->getCell()->getComponents() ) { // if ( dynamic_cast(component) ) { // STuple::CostProperty* costProperty = STuple::CostProperty::create (count ); // component->put ( costProperty ); // STuple* stuple = STuple::create ( costProperty ); // addToSTuplePQ ( stuple ); // if ( count == 4 ) compo1 = component; // if ( count == 8 ) compo2 = component; // count++; // if ( count >= 10 ) // break; // } // end_for; // } // printSTuplePQ(); // STuple::CostProperty* costProperty = dynamic_cast(compo1->getProperty ( "Knik::CostProperty" )); // updateSTupleCost ( (*costProperty->getPQIter()), 18 ); // cmess2 << "updateSTupleCost ( (*costProperty->getPQIter()), 18 )" << endl; // printSTuplePQ(); // costProperty = dynamic_cast(compo2->getProperty ( "Knik::CostProperty")); // updateSTupleCost ( (*costProperty->getPQIter()), 2 ); // cmess2 << "updateSTupleCost ( (*costProperty->getPQIter()), 2 )" << endl; // printSTuplePQ(); // popMaxFromSTuplePQ(); // cmess2 << "popMaxFromSTuplePQ()" << endl; // printSTuplePQ(); // cmess2 << "getString ( getMaxFromSTuplePQ() )" << endl; // cmess2 << getString ( getMaxFromSTuplePQ() ) << endl; // printSTuplePQ(); // cmess2 << "getString ( extractMaxFromSTuplePQ() )" << endl; // cmess2 << getString ( extractMaxFromSTuplePQ() ) << endl; // printSTuplePQ(); // clearSTuplePQ(); // cmess2 << "clearSTuplePQ()" << endl; // printSTuplePQ(); } int Graph::countVertexes ( Net* net ) // ********************************** { assert ( net ); _working_net = net; forEach ( Component*, component, net->getComponents() ) { if ( RoutingPad* routingPad = dynamic_cast(*component) ) { //cerr << routingPad << endl << routingPad->getCenter()<< endl; //if ( routingPad->getCenter().getY() < 0 ) { // CEditor* editor = getCEditor ( getCell() ); // editor->Select ( routingPad ); // editor->Refresh(); // editor->Stop ( "RoutingPad" ); // editor->Unselect( routingPad ); //} Vertex* vertex = getVertex ( routingPad->getCenter() ); assert(vertex); if ( _vertexes_to_route.find ( vertex ) == _vertexes_to_route.end() ) { _vertexes_to_route.insert ( vertex ); } } } return _vertexes_to_route.size(); } int Graph::initRouting ( Net* net ) // ******************************** { assert ( net ); _working_net = net; //cerr << "[DEBUG]: Net: " << _working_net << endl; //cerr << "[DEBUG]: vertexes_to_route size: " << _vertexes_to_route.size() << endl; //CEditor* editor = getCEditor( _nimbus->getCell() ); //editor->Refresh(); //editor->Stop ("Going to init"); int currentConnexID = 0; vector vContacts; vector vRoutingPads; unsigned compoSize = net->getComponents().getSize(); vContacts.reserve ( compoSize ); vRoutingPads.reserve ( compoSize ); for_each_component ( component, net->getComponents() ) { if ( dynamic_cast(component) ) vRoutingPads.push_back ( static_cast(component) ); if ( dynamic_cast(component) ) { Contact* contact = static_cast(component); if ( isAGlobalRoutingContact ( contact ) ) vContacts.push_back ( contact ); } end_for; } //cerr << " vContacts size : " << vContacts.size() << endl; //cerr << " vRoutingPads size : " << vRoutingPads.size() << endl; UpdateSession::open(); for ( unsigned index = 0; index < vContacts.size() ; index++ ) { Contact* contact = vContacts[index]; //cerr << " contact : " << contact << "" << endl; Vertex* contactVertex = getVertex ( contact->getCenter() ); Contact* vContact = contactVertex->getContact(); if ( (vContact == contact) && (contactVertex->getNetStamp() == _netStamp) ) { //cerr << " on a deja un contact associe avec le meme netStamp !" << endl; continue; // on la déjà traité à travers le parcourt de composante connexe } else { //cerr << " rebuild connexe component " << contact << "" << endl; rebuildConnexComponent ( contact, currentConnexID, NULL ); //cerr << " done" << endl; if ( _vertexes_to_route.find ( contactVertex ) == _vertexes_to_route.end() ) { //cerr << " Adding vertex to _vertexes_to_route: continue" << endl; _vertexes_to_route.insert ( contactVertex ); _searchingArea.merge ( contactVertex->getBox() ); contactVertex->setDistance((float)(HUGE)); contactVertex->setPredecessor(NULL); currentConnexID++; } } } //cerr << " traitement pour les contacts : OK" << endl; //OoOoooOoooOoO A QUOI SERT CE BOOLEEN OoOoooOoooOoO ==>> pour le //5 le connexID ne doit pas avoir été augmenté ! ou alors connexID-1 !! //bool useConnexID = false; for ( unsigned index = 0 ; index < vRoutingPads.size() ; index ++ ) { RoutingPad* routingPad = vRoutingPads[index]; //cerr << " RoutingPad :" << routingPad << endl; Vertex* rpVertex = getVertex ( routingPad->getCenter() ); //cerr << " Vertex :" << rpVertex << endl; Contact* rpContact = rpVertex->getContact(); if ( rpContact && (rpContact->getNet() == routingPad->getNet()) ) { // s'il existe deja un contact pour ce vertex pour ce net, on s'y attache //cerr << " Contact already exists: attaching hooks" << endl; // le contact a deja ete cree, il suffit d'ajouter le routingPad à la ronde du contact. routingPad->getBodyHook()->detach(); routingPad->getBodyHook()->attach ( rpVertex->getContact()->getBodyHook() ); } else { // sinon on crée un contact et on s'y attache Contact* contact = Contact::create ( _working_net , DataBase::getDB()->getTechnology()->getLayer("metal2") , rpVertex->getPosition().getX() , rpVertex->getPosition().getY() , rpVertex->getHalfWidth()/5 , rpVertex->getHalfHeight()/5 ); rpVertex->setContact ( contact ); routingPad->getBodyHook()->detach(); routingPad->getBodyHook()->attach ( contact->getBodyHook() ); if ( _vertexes_to_route.find ( rpVertex ) == _vertexes_to_route.end() ) { //cerr << " Adding vertex to _vertexes_to_route: continue" << endl; _vertexes_to_route.insert ( rpVertex ); _searchingArea.merge ( rpVertex->getBox() ); rpVertex->setConnexID ( currentConnexID ); rpVertex->setNetStamp ( _netStamp ); rpVertex->setDistance((float)(HUGE)); rpVertex->setPredecessor(NULL); currentConnexID++; } } } // for ripup & reroute purpose if ( __ripupMode__ ) _searchingArea = _cell->getAbutmentBox(); // recherche sur toute la surface : trop long pour gros circuits //_searchingArea.inflate((_searchingArea.getWidth()*10)/100, (_searchingArea.getHeight()*10)/100); // raté ça ne marche pas avec les nets plats //cerr << " traitement pour les routingPads : OK" << endl; UpdateSession::close(); //cerr << "[DEBUG]: vertexes_to_route size (after init): " << _vertexes_to_route.size() << endl; //editor->Refresh(); //editor->Stop("initDone"); // 8/10/2007 // { // Expand seaching area //int bottomLineIdx = (int)_matrixVertex->getLineIndex ( _searchingArea.getYMin() +1 ); //int topLineIdx = (int)_matrixVertex->getLineIndex ( _searchingArea.getYMax() -1 ); //int leftColumnIdx = (int)_matrixVertex->getColumnIndex ( _searchingArea.getXMin() +1 ); //int rightColumnIdx = (int)_matrixVertex->getColumnIndex ( _searchingArea.getXMax() -1 ); //if ( _matrixVertex->isLineIndexValid ( bottomLineIdx - 2 ) ) // bottomLineIdx -= 2; //else if ( _matrixVertex->isLineIndexValid ( bottomLineIdx - 1 ) ) // bottomLineIdx -= 1; //if ( _matrixVertex->isLineIndexValid ( topLineIdx + 2 ) ) // topLineIdx += 2; //else if ( _matrixVertex->isLineIndexValid ( topLineIdx + 1 ) ) // topLineIdx += 1; //if ( _matrixVertex->isColumnIndexValid ( leftColumnIdx - 2 ) ) // leftColumnIdx -= 2; //else if ( _matrixVertex->isColumnIndexValid ( leftColumnIdx - 1 ) ) // leftColumnIdx -= 1; //if ( _matrixVertex->isColumnIndexValid ( rightColumnIdx + 2 ) ) // rightColumnIdx += 2; //else if ( _matrixVertex->isColumnIndexValid ( rightColumnIdx + 1 ) ) // rightColumnIdx += 1; //_searchingArea.merge ( _matrixVertex->getVertexFromIndexes(bottomLineIdx, leftColumnIdx)->getGCell()->getBox() ); //_searchingArea.merge ( _matrixVertex->getVertexFromIndexes(topLineIdx, rightColumnIdx)->getGCell()->getBox() ); //cerr << "net " << net << " has " << _vertexes_to_route.size() << " vertexes to route." << endl; //} return _vertexes_to_route.size(); } void Graph::Dijkstra() // ******************* { //checkEmptyPriorityQueue(); //CEditor* editor = getCEditor( _nimbus->getCell() ); countDijkstra++; // first we need to choose the closest to center vertex in _vertexes_to_route Vertex* centralVertex = getCentralVertex(); //ltrace(435) << " most centered vertex is " << centralVertex << endl; // we want to prepare all vertexes of the 'composante connexe' // set the distance to 0 // insert each vertex in the vtuplePriorityQueue initConnexComp ( centralVertex ); // create a copy of _vertexes_to_route vector fo method UpdateEstimateCongestion //set copy_vertex = _vertexes_to_route; // This is no more useful //#if defined ( __USE_DYNAMIC_PRECONGESTION__ ) if ( !__ripupMode__ && (__precongestion__ == 2) ) UpdateEstimateCongestion(); //#endif debugging = (_working_net->getName() == debugName ); //bool debugging = false; if (debugging) { cerr << "Dijkstra for net " << _working_net << " : " << _netStamp << endl; cerr << " central vertex : " << centralVertex << endl; cerr << " _vertexes_to_route.size : " << _vertexes_to_route.size() << endl; Breakpoint::stop(1, "
Dijkstra
initialized
"); } while ( _vertexes_to_route.size() > 1 ) { // Now, let's expanse the top of the queue VertexList reachedVertexes; float reachedDistance = (float)(HUGE); //checkGraphConsistency(); // DEBUG // if ( debugging ) { cerr << " _vertexes_to_route :" << endl; VertexSetIter vsit = _vertexes_to_route.begin(); while ( vsit != _vertexes_to_route.end() ) { cerr << " " << (*vsit) << endl; vsit++; } } if ( debugging ) { cerr << " source component" << endl; printVTuplePriorityQueue(); cerr.flush(); Breakpoint::stop(1, "
Dijkstra
source connexe component
"); } //if ( debugging && (editor->getStopLevel() >= 1) ) { // editor->Refresh(); // string stopMessage = "Source connexe component."; // editor->Stop(stopMessage); //} Vertex* firstVertex = getMinFromPriorityQueue(); assert ( firstVertex ); Vertex* currentVertex = firstVertex; int firstVertexConnex = firstVertex->getConnexID(); while ( currentVertex && (currentVertex->getDistance() < reachedDistance) ) { PopMinFromPriorityQueue(); assert ( !currentVertex->getVTuple() ); // IMPORTANT : each currentVertex considered here has been getFromPriorityQueue() // which means its NetStamp and ConnexID are set for the current _working_net : no need to check netStamp int currentVertexConnex = currentVertex->getConnexID() ; if ( (currentVertexConnex != -1) && (currentVertexConnex != firstVertexConnex) ) { reachedDistance = currentVertex->getDistance(); reachedVertexes.clear(); if (debugging ) { cerr << " reachedVertexes : clear + push_back vertex found in priorityQueue: " << currentVertex << endl; } reachedVertexes.push_back ( currentVertex ); break; } Edge* arrivalEdgeCurrentVertex = currentVertex->getPredecessor(); for_each_edge ( edge, currentVertex->getAdjacentEdges() ) { if ( (edge->getNetStamp() == _netStamp) && (edge->getConnexID() == firstVertexConnex) ) { // already visited edge // ok because to reach a connex component the algorithm first reach a vertex !! continue; } edge->setConnexID(-1); // reinitialize connexID for edge (was done by CleanRoutingState) //edge->setSplitter(NULL); edge->setNetStamp(_netStamp); Vertex* oppositeVertex = edge->getOpposite ( currentVertex ); assert ( oppositeVertex ); if ( !_searchingArea.contains ( oppositeVertex->getPosition() ) ) continue; float newDistance = currentVertex->getDistance() + edge->getCost ( arrivalEdgeCurrentVertex ); bool updateOppositeVertex = false; // reinitialize the oppositeVertex if its netStamp is < _netStamp if ( oppositeVertex->getNetStamp() < _netStamp ) { //oppositeVertex->setLocalRingHook(NULL); oppositeVertex->setContact(NULL); oppositeVertex->setConnexID(-1); updateOppositeVertex = true; } int oppositeConnex = oppositeVertex->getConnexID(); float oppositeDistance = oppositeVertex->getDistance(); if ( updateOppositeVertex || (newDistance + EPSILON < oppositeDistance) ) { assert ( oppositeConnex != firstVertexConnex ); oppositeVertex->setPredecessor ( edge ); oppositeVertex->setDistance ( newDistance ); oppositeVertex->setNetStamp ( _netStamp ); if ( VTuple* oppositeVTuple = oppositeVertex->getVTuple() ) { //if (debugging) { // cerr << " increasing Priority for vertex : " << oppositeVertex // << " and corresponding vtuple : " << oppositeVTuple->_getString() << endl; //} increaseVTuplePriority ( oppositeVTuple, newDistance ); // XXX du fait de la reinit ce n'est plus seulement un increase ! // Non c'est bon si on garde le CleanRoutingState (avec clearPriorityQueue) } else { VTuple* newOppositeVTuple = VTuple::create ( oppositeVertex, newDistance ); //if (debugging) // cerr << " Creating new vtuple for vertex: " << oppositeVertex << "," << newDistance // << " --> " << newOppositeVTuple->_getString() << endl; addVTupleToPriorityQueue ( newOppositeVTuple ); } //if ( debugging ) { // cerr << " distance has been updated : " << edge << endl; // //cerr << " current reachedDistance: " << reachedDistance << " for: " << (*(reachedVertexes.begin())) << endl; // cerr << " current reachedDistance: " << reachedDistance << endl; // printVTuplePriorityQueue(); // Breakpoint::stop(1, "
Dijkstra
distance has been updated
"); //} //if ( debugging && (editor->getStopLevel() >= 2) ) { // editor->Refresh(); // string stopMessage = "distance has been updated: "; // stopMessage += getString ( edge ); // editor->Stop(stopMessage); //} } if ( (oppositeConnex != -1) && (oppositeConnex != firstVertexConnex) ) { // verifier si la newDistance est inférieure a la reachedDistance, // si oui vider la liste des reachedVertex et ajouter l'oppositeVertex // si == ajouter l'oppositeVertex a la liste (a condition qu'il n'y soit pas déjà) // si > rien a faire (a verifier que la pile de priorité se comporte bien) if ( newDistance < reachedDistance ) { reachedDistance = newDistance; reachedVertexes.clear(); //if (debugging ) { // cerr << " second, push_back : " << oppositeVertex << endl; // cerr << " reachedVertexes : clear + push_back reached vertex with < distance " << oppositeVertex << endl; //} reachedVertexes.push_back ( oppositeVertex ); } else if ( newDistance == reachedDistance ) { VertexListIter lvit = reachedVertexes.begin(); bool foundVertex = false; // on pourrait simplifier grandement tout ca : 1 seul vertex atteint sauvergardé ! conclusion qu'il ait le meme connexID ou pas // on ne fait rien, on en a deja atteint un avec la meme distance ... while ( lvit != reachedVertexes.end() ) { // the following test depends on the fact we authorize multiple representant (vertex) // of the same connexe component in reachedVertexes list //if ( (*lvit)->getConnexID() == oppositeConnex ) if ( (*lvit) == oppositeVertex ) { foundVertex = true; break; } lvit++; } if ( !foundVertex ) { //if (debugging ) { // cerr << " reachedVertexes : clear + push_back reached vertex with == distance " << oppositeVertex << endl; //} reachedVertexes.push_back ( oppositeVertex ); } } else { // Nothing to do ? } } end_for; } currentVertex = getMinFromPriorityQueue(); } assert ( !reachedVertexes.empty() ); assert ( reachedDistance < (float)(HUGE) ); //if(debugging) { // cerr << " updating 2 connex components : " << (*(reachedVertexes.begin())) << " & " << firstVertex << endl; // cerr.flush(); // editor->Refresh(); // editor->Stop("Dijkstra on 2 connex comopnents, gonna Update"); //} UpdateConnexComp ( reachedVertexes, firstVertex ); //if(debugging) { // editor->Refresh(); // editor->Stop("Update done"); //} } //cerr << "check before materialize _vertexes_to_route.size = " << _vertexes_to_route.size() << endl; //checkGraphConsistency(); MaterializeRouting ( *(_vertexes_to_route.begin()) ); //_vertexes_to_route.clear(); // no more useful //_vertexes_to_route = copy_vertex ; } void Graph::Monotonic() // ******************** { // This function execute an algorithm of monotonic routing // it assumes that _vertexes_to_route.sze is 2 (only 2 pin nets can be route with monotonic routing) assert ( _vertexes_to_route.size() == 2 ); countMonotonic++; //cerr << "Monotonic for net " << _working_net << " : " << _netStamp << endl; //cerr << " check start monotonic" << endl; //checkGraphConsistency(); Vertex* source = (*_vertexes_to_route.begin()); Vertex* target = (*_vertexes_to_route.rbegin()); assert ( source != target ); DbU::Unit sourceX = source->getPosition().getX(); DbU::Unit targetX = target->getPosition().getX(); if ( sourceX > targetX ) { Vertex* temp = source; source = target; target = temp; } else if ( sourceX == targetX ) { if ( source->getPosition().getY() > target->getPosition().getY() ) { Vertex* temp = source; source = target; target = temp; } } // POUR SIMPLIFIER : PAS DE TRAITEMENT D'UN GRAPHE DE ROUTAGE IRREGULIER POUR L'INSTANT sourceX = source->getPosition().getX(); targetX = target->getPosition().getX(); DbU::Unit sourceY = source->getPosition().getY(); DbU::Unit targetY = target->getPosition().getY(); source->setDistance ( 0 ); if ( sourceY <= targetY ) { // 1st case : monotonic directions : top and right // marquing all vertexes which y-coordinates are equal to sourceY Vertex* predecessor = source; Edge* rightEdge = predecessor->getHEdgeOut(); while ( rightEdge ) { Vertex* currentVertex = rightEdge->getOpposite ( predecessor ); if ( currentVertex->getPosition().getX() <= targetX ) { currentVertex->setDistance ( predecessor->getDistance() + rightEdge->getCost( predecessor->getPredecessor() ) ); currentVertex->setPredecessor ( rightEdge ); predecessor = currentVertex; rightEdge = predecessor->getHEdgeOut(); } else break; } // marquing all vertexes which x-coordinates are equal to sourceX predecessor = source; Edge* topEdge = predecessor->getVEdgeOut(); while ( topEdge ) { //while ( topEdge->getNextFrom() != NULL ) // topEdge = topEdge->getNextFrom(); Vertex* currentVertex = topEdge->getOpposite ( predecessor ); if ( currentVertex->getPosition().getY() <= targetY ) { currentVertex->setDistance ( predecessor->getDistance() + topEdge->getCost( predecessor->getPredecessor() ) ); currentVertex->setPredecessor ( topEdge ); predecessor = currentVertex; topEdge = predecessor->getVEdgeOut(); } else break; } // marquing all others vertexes by column predecessor = source; rightEdge = predecessor->getHEdgeOut(); while ( rightEdge ) { Vertex* baseColumn = rightEdge->getOpposite ( predecessor ); if ( baseColumn->getPosition().getX() <= targetX ) { Vertex* vertPred = baseColumn; Edge* topEdge = vertPred->getVEdgeOut(); while ( topEdge ) { Vertex* currentVertex = topEdge->getOpposite ( vertPred ); if ( currentVertex->getPosition().getY() <= targetY ) { float vertDistance = (float)(HUGE); float horzDistance = (float)(HUGE); vertDistance = vertPred->getDistance() + topEdge->getCost ( vertPred->getPredecessor() ); Edge* leftEdge = currentVertex->getHEdgeIn(); if ( leftEdge ) { Vertex* horzPred = leftEdge->getOpposite ( currentVertex ); horzDistance = horzPred->getDistance() + leftEdge->getCost ( horzPred->getPredecessor() ); } if ( vertDistance < horzDistance ) { currentVertex->setDistance ( vertDistance ); currentVertex->setPredecessor ( topEdge ); } else { currentVertex->setDistance ( horzDistance ); currentVertex->setPredecessor ( leftEdge ); } vertPred = currentVertex; topEdge = vertPred->getVEdgeOut(); } else break; } predecessor = baseColumn; rightEdge = predecessor->getHEdgeOut(); } else break; } } else { // 2nd case : monotonic directions : down and right // marquing all vertexes which y-coordinates are equal to sourceY Vertex* predecessor = source; Edge* rightEdge = predecessor->getHEdgeOut(); while ( rightEdge ) { Vertex* currentVertex = rightEdge->getOpposite ( predecessor ); if ( currentVertex->getPosition().getX() <= targetX ) { currentVertex->setDistance ( predecessor->getDistance() + rightEdge->getCost ( predecessor->getPredecessor() ) ); currentVertex->setPredecessor ( rightEdge ); predecessor = currentVertex; rightEdge = predecessor->getHEdgeOut(); } else break; } // marquing all vertexes which x-coordinates are equal to sourceX predecessor = source; Edge* bottomEdge = predecessor->getVEdgeIn(); while ( bottomEdge ) { //while ( topEdge->getNextFrom() != NULL ) // topEdge = topEdge->getNextFrom(); Vertex* currentVertex = bottomEdge->getOpposite ( predecessor ); if ( currentVertex->getPosition().getY() >= targetY ) { currentVertex->setDistance ( predecessor->getDistance() + bottomEdge->getCost ( predecessor->getPredecessor() ) ); currentVertex->setPredecessor ( bottomEdge ); predecessor = currentVertex; bottomEdge = predecessor->getVEdgeIn(); } else break; } // marquing all others vertexes by column predecessor = source; rightEdge = predecessor->getHEdgeOut(); while ( rightEdge ) { Vertex* baseColumn = rightEdge->getOpposite ( predecessor ); if ( baseColumn->getPosition().getX() <= targetX ) { Vertex* vertPred = baseColumn; Edge* bottomEdge = vertPred->getVEdgeIn(); while ( bottomEdge ) { Vertex* currentVertex = bottomEdge->getOpposite ( vertPred ); if ( currentVertex->getPosition().getY() >= targetY ) { float vertDistance = (float)(HUGE); float horzDistance = (float)(HUGE); vertDistance = vertPred->getDistance() + bottomEdge->getCost ( vertPred->getPredecessor() ); Edge* leftEdge = currentVertex->getHEdgeIn(); if ( leftEdge ) { Vertex* horzPred = leftEdge->getOpposite ( currentVertex ); horzDistance = horzPred->getDistance() + leftEdge->getCost (horzPred->getPredecessor() ); } if ( vertDistance < horzDistance ) { currentVertex->setDistance ( vertDistance ); currentVertex->setPredecessor ( bottomEdge ); } else { currentVertex->setDistance ( horzDistance ); currentVertex->setPredecessor ( leftEdge ); } vertPred = currentVertex; bottomEdge = vertPred->getVEdgeIn(); if (!bottomEdge) break; currentVertex = bottomEdge->getOpposite ( vertPred ); } else break; } predecessor = baseColumn; rightEdge = predecessor->getHEdgeOut(); } else break; } } // On crée la nouvelle composante connexe à partir du chemin monotone trouvé : int sourceID = source->getConnexID(); Vertex* currentVertex = target; while ( Edge* predecessor = currentVertex->getPredecessor() ) { currentVertex->setConnexID ( sourceID ); currentVertex->setNetStamp ( _netStamp ); predecessor->setConnexID ( sourceID ); predecessor->setNetStamp ( _netStamp ); currentVertex = predecessor->getOpposite ( currentVertex ); } source->setNetStamp ( _netStamp ); assert ( currentVertex == source ); MaterializeRouting ( source ); //#if defined ( __USE_DYNAMIC_PRECONGESTION__ ) if ( __precongestion__ == 2 ) UpdateEstimateCongestion(); //#endif } FTree Graph::createFluteTree() // *************************** { int accuracy = 3; // accuracy for flute (by default 3) int d = _vertexes_to_route.size(); // degre du net, ie nombre de routingPads int *x = new int [d]; // x coordinates of the vertexes int *y = new int [d]; // y coordinates of the vertexes FTree flutetree; // the flute Steiner Tree //cout << "Net : " << _working_net << endl; // scans _working_net to find x,y coordinates and fill x, y and d // parcours des _vertexes_to_route VertexSetIter vsit = _vertexes_to_route.begin(); int cpt = 0; while ( vsit != _vertexes_to_route.end() ) { Point position = (*vsit)->getPosition(); x[cpt] = position.getX(); y[cpt] = position.getY(); vsit++; cpt++; } assert ( d == cpt ); flutetree = flute ( d, x, y, accuracy ); //printtree ( flutetree ); //plottree ( flutetree ); //cout << endl; return flutetree; } void Graph::UpdateEstimateCongestion ( bool create ) // ************************************************* { if ( _vertexes_to_route.size() < 2 ) return; if ( _vertexes_to_route.size() >= FLUTE_LIMIT ) { if ( create ) cerr << "[INFO] Graph::UpdateEstiateGongestion(): Net " << _working_net << " has more than " << getString(FLUTE_LIMIT) << " vertexes and can not be handled by FLUTE." << endl; return; } //cerr << "Running FLUTE for net : " << _working_net << endl; FTree flutetree = createFluteTree(); //parcours des branches du FTree pour créer la congestion estimée for ( int i = 0 ; i < 2*flutetree.deg-2 ; i++ ) { // int sourceX = flutetree.branch[i].x; // int sourceY = flutetree.branch[i].y; // int targetX = flutetree.branch[flutetree.branch[i].n].x; // int targetY = flutetree.branch[flutetree.branch[i].n].y; Vertex* source = getVertex ( flutetree.branch[i].x , flutetree.branch[i].y ); Vertex* target = getVertex ( flutetree.branch[flutetree.branch[i].n].x, flutetree.branch[flutetree.branch[i].n].y ); assert ( source ); assert ( target ); //Si source et target alignée -> ajoute 1 a toutes les edges sur le chemin if ( source->isVerticallyAligned ( target ) ) { sortVVertexes ( source, target ); Vertex* currentVertex = source; while ( currentVertex != target ) { Edge* edge = currentVertex->getVEdgeOut(); assert ( edge ); edge->addSubEstimateOccupancy ( 1.0, create ); currentVertex = edge->getOpposite ( currentVertex ); assert ( currentVertex ); } } else if ( source->isHorizontallyAligned ( target ) ) { sortHVertexes ( source, target ); Vertex* currentVertex = source; while( currentVertex != target ) { Edge* edge = currentVertex->getHEdgeOut(); assert ( edge ); edge->addSubEstimateOccupancy ( 1.0, create ); currentVertex = edge->getOpposite ( currentVertex ); assert ( currentVertex ); } } else { sortHVertexes ( source, target ); if ( source->getY() < target->getY() ) { // 1st case : // +-------T +-------T T // | | | | // | | = | 0.5 + 0.5 | // | | | | // S-------+ S S-------+ Vertex* currentVertex = source; while ( currentVertex->getY() < target->getY() ) { Edge* edge = currentVertex->getVEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } while ( currentVertex != target ) { Edge* edge = currentVertex->getHEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } currentVertex = source; while ( currentVertex->getX() < target->getX() ) { Edge* edge = currentVertex->getHEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } while ( currentVertex != target ) { Edge* edge = currentVertex->getVEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( edge ); } } else { // 2nd case : // S-------+ S S-------+ // | | | | // | | = | 0.5 + 0.5 | // | | | | // +-------T +-------T T Vertex* currentVertex = source; while ( currentVertex->getY() > target->getY() ) { Edge* edge = currentVertex->getVEdgeIn(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } while ( currentVertex != target ) { Edge* edge = currentVertex->getHEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } currentVertex = source; while ( currentVertex->getX() < target->getX() ) { Edge* edge = currentVertex->getHEdgeOut(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( currentVertex ); } while ( currentVertex != target ) { Edge* edge = currentVertex->getVEdgeIn(); // assert ( edge ); edge->addSubEstimateOccupancy ( 0.5, create ); currentVertex = edge->getOpposite ( currentVertex ); // assert ( edge ); } } } } } void Graph::UpdateMaxEstimateCongestion() // ************************************** { Vertex* currentVertex = _lowerLeftVertex; while ( currentVertex ) { Vertex* firstLineVertex = currentVertex; while ( currentVertex ) { Edge* hEdgeOut = currentVertex->getHEdgeOut(); unsigned max = 0; float maxEsti = 0.0; if ( hEdgeOut ) { unsigned maxX = hEdgeOut->getRealOccupancy(); float maxXEsti = hEdgeOut->getEstimateOccupancy(); max += maxX; maxEsti += maxXEsti; if ( maxX > _maxXOccupancy ) _maxXOccupancy = maxX; if ( maxXEsti > _maxXEstimateOccupancy ) _maxXEstimateOccupancy = maxXEsti; } Edge* vEdgeOut = currentVertex->getVEdgeOut(); if ( vEdgeOut ) { unsigned maxY = vEdgeOut->getRealOccupancy(); float maxYEsti = vEdgeOut->getEstimateOccupancy(); max += maxY; maxEsti += maxYEsti; if ( maxY > _maxYOccupancy ) _maxYOccupancy = maxY; if ( maxYEsti > _maxYEstimateOccupancy ) _maxYEstimateOccupancy = maxYEsti; } if ( max > _maxOccupancy ) _maxOccupancy = max; if ( maxEsti > _maxEstimateOccupancy ) _maxEstimateOccupancy = maxEsti; if ( hEdgeOut ) currentVertex = hEdgeOut->getOpposite ( currentVertex ); else break; } Edge* vEdgeOut = firstLineVertex->getVEdgeOut(); if ( vEdgeOut ) currentVertex = vEdgeOut->getOpposite ( firstLineVertex ); else break; } } void Graph::UpdateEdgeCapacity ( unsigned col1, unsigned row1, unsigned col2, unsigned row2, unsigned cap ) // ******************************************************************************************************** { if ( col1 == col2 ) { if ( row1 == row2 ) throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be different." ); Vertex* bottomVertex = NULL; Vertex* topVertex = NULL; if ( ( row1 < row2 ) && ( row2 == row1 + 1 ) ) { bottomVertex = _matrixVertex->getVertex ( pair(col1, row1) ); topVertex = _matrixVertex->getVertex ( pair(col1, row2) ); } else if ( row1 == row2 + 1 ) { bottomVertex = _matrixVertex->getVertex ( pair(col1, row2) ); topVertex = _matrixVertex->getVertex ( pair(col1, row1) ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be contiguous." ); Edge* edge = bottomVertex->getVEdgeOut(); assert ( edge->getOpposite(bottomVertex) == topVertex ); edge->setCapacity ( cap ); } else if ( row1 == row2 ) { Vertex* leftVertex = NULL; Vertex* rightVertex = NULL; if ( ( col1 < col2 ) && ( col2 == col1 + 1 ) ) { leftVertex = _matrixVertex->getVertex ( pair(col1, row1) ); rightVertex = _matrixVertex->getVertex ( pair(col2, row1) ); } else if ( col1 == col2 + 1 ) { leftVertex = _matrixVertex->getVertex ( pair(col2, row1) ); rightVertex = _matrixVertex->getVertex ( pair(col1, row1) ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be contiguous." ); Edge* edge = leftVertex->getHEdgeOut(); assert ( edge->getOpposite(leftVertex) == rightVertex ); edge->setCapacity ( cap ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be vertically or horizontally aligned." ); } void Graph::increaseEdgeCapacity ( unsigned col1, unsigned row1, unsigned col2, unsigned row2, int cap ) // ***************************************************************************************************** { if ( col1 == col2 ) { if ( row1 == row2 ) throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be different." ); Vertex* bottomVertex = NULL; Vertex* topVertex = NULL; if ( ( row1 < row2 ) && ( row2 == row1 + 1 ) ) { bottomVertex = _matrixVertex->getVertex ( pair(col1, row1) ); topVertex = _matrixVertex->getVertex ( pair(col1, row2) ); } else if ( row1 == row2 + 1 ) { bottomVertex = _matrixVertex->getVertex ( pair(col1, row2) ); topVertex = _matrixVertex->getVertex ( pair(col1, row1) ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be contiguous." ); Edge* edge = bottomVertex->getVEdgeOut(); assert ( edge->getOpposite(bottomVertex) == topVertex ); edge->increaseCapacity ( cap ); } else if ( row1 == row2 ) { Vertex* leftVertex = NULL; Vertex* rightVertex = NULL; if ( ( col1 < col2 ) && ( col2 == col1 + 1 ) ) { leftVertex = _matrixVertex->getVertex ( pair(col1, row1) ); rightVertex = _matrixVertex->getVertex ( pair(col2, row1) ); } else if ( col1 == col2 + 1 ) { leftVertex = _matrixVertex->getVertex ( pair(col2, row1) ); rightVertex = _matrixVertex->getVertex ( pair(col1, row1) ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be contiguous." ); Edge* edge = leftVertex->getHEdgeOut(); assert ( edge->getOpposite(leftVertex) == rightVertex ); edge->increaseCapacity ( cap ); } else throw Error ( "Graph::UpdateEdgeCapacity(): the two specified vertices must be vertically or horizontally aligned." ); } void Graph::updateEdgesOccupancy ( Segment* segment, bool add ) // ************************************************************ { if ( Horizontal* horiz = dynamic_cast(segment) ) { Vertex* currentVertex = _matrixVertex->getVertex ( Point ( horiz->getSourceX(), horiz->getY() ) ); Vertex* targetVertex = _matrixVertex->getVertex ( Point ( horiz->getTargetX(), horiz->getY() ) ); while ( currentVertex != targetVertex ) { Edge* edge = currentVertex->getHEdgeOut(); assert ( edge ); if ( add ) edge->insertSegment ( segment ); else edge->removeSegment ( segment ); currentVertex = edge->getOpposite ( currentVertex ); assert ( currentVertex ); } } else if ( Vertical* verti = dynamic_cast(segment) ) { Vertex* currentVertex = _matrixVertex->getVertex ( Point ( verti->getX(), verti->getSourceY() ) ); Vertex* targetVertex = _matrixVertex->getVertex ( Point ( verti->getX(), verti->getTargetY() ) ); while ( currentVertex != targetVertex ) { Edge* edge = currentVertex->getVEdgeOut(); assert ( edge ); if ( add ) edge->insertSegment ( segment ); else edge->removeSegment ( segment ); currentVertex = edge->getOpposite ( currentVertex ); assert ( currentVertex ); } } } void Graph::rebuildConnexComponent ( Contact* contact, int connexID, Segment* arrivalSegment ) // ******************************************************************************************* { //CEditor* editor = getCEditor ( _nimbus->getCell() ); Vertex* contactVertex = getVertex ( contact->getCenter() ); contactVertex->setContact ( contact ); contactVertex->setConnexID ( connexID ); contactVertex->setNetStamp ( _netStamp ); contactVertex->setDistance((float)(HUGE)); contactVertex->setPredecessor(NULL); //cerr << "from :" << contact << endl; //cerr << "arrivalSegment: " << arrivalSegment << endl; for_each_component ( component, contact->getSlaveComponents() ) { if ( dynamic_cast(component) ) { Segment* segment = static_cast(component); //cerr << " a segment " << segment << endl; //editor->Stop("Guess what to do"); if ( segment == arrivalSegment ) continue; //cerr << " not arrivalSegment -> setNetStampConnexID" << endl; setNetStampConnexID ( segment, connexID ); //cerr << " done" << endl; if ( !dynamic_cast( segment->getOppositeAnchor(contact) ) ) throw Error ("Graph::rebuildConnexComponent(): For the moment we do not consider Segments that anchors on something else than a Contact."); Contact* oppositeContact = static_cast(segment->getOppositeAnchor(contact)); //cerr << " now recursive call on oppositeContact: " << oppositeContact << endl; //editor->Stop("See what has been done"); rebuildConnexComponent ( oppositeContact, connexID, segment ); //cerr << " done" << endl; } end_for; } } void Graph::setNetStampConnexID ( Segment* segment, int connexID ) // *************************************************************** { unsigned int sourceColumnIdx = _matrixVertex->getColumnIndex ( segment->getSourceX() ); unsigned int sourceLineIdx = _matrixVertex->getLineIndex ( segment->getSourceY() ); unsigned int targetColumnIdx = _matrixVertex->getColumnIndex ( segment->getTargetX() ); unsigned int targetLineIdx = _matrixVertex->getLineIndex ( segment->getTargetY() ); if ( sourceColumnIdx == targetColumnIdx ) { // vertical segment for ( unsigned line = sourceLineIdx ; line < targetLineIdx ; line++ ) { Vertex* vertex = _matrixVertex->getVertexFromIndexes ( line, sourceColumnIdx ); assert(vertex); vertex->setNetStamp ( _netStamp ); vertex->setConnexID ( connexID ); vertex->setDistance((float)(HUGE)); Edge* edge = vertex->getVEdgeOut(); assert(edge); edge->setNetStamp ( _netStamp ); edge->setConnexID ( connexID ); } Vertex* vertex = _matrixVertex->getVertexFromIndexes ( targetLineIdx, targetColumnIdx ); assert(vertex); vertex->setNetStamp ( _netStamp ); vertex->setConnexID ( connexID ); vertex->setDistance((float)(HUGE)); return; } if ( sourceLineIdx == targetLineIdx ) { // horizontal segment for ( unsigned column = sourceColumnIdx ; column < targetColumnIdx ; column++ ) { Vertex* vertex = _matrixVertex->getVertexFromIndexes ( sourceLineIdx, column ); assert(vertex); vertex->setNetStamp ( _netStamp ); vertex->setConnexID ( connexID ); vertex->setDistance((float)(HUGE)); Edge* edge = vertex->getHEdgeOut(); assert(edge); edge->setNetStamp ( _netStamp ); edge->setConnexID ( connexID ); } Vertex* vertex = _matrixVertex->getVertexFromIndexes ( targetLineIdx, targetColumnIdx ); assert(vertex); vertex->setNetStamp ( _netStamp ); vertex->setConnexID ( connexID ); vertex->setDistance((float)(HUGE)); return; } throw Error ( "Graph::setNetStampConnexId(): what sort of segment is that, a diagonal one?" ); } void Graph::insertSegment ( Segment* segment ) // ******************************************* { updateEdgesOccupancy ( segment, true ); } void Graph::removeSegment ( Segment* segment ) // ******************************************* { updateEdgesOccupancy ( segment, false ); } float Graph::getSegmentCost ( Segment* segment ) // ********************************************* { unsigned nbDep = 0; unsigned nbTot = 0; unsigned sumDep = 0; Vertex* currentVertex = getVertex ( segment->getSourcePosition() ); Vertex* targetVertex = getVertex ( segment->getTargetPosition() ); if ( segment->getSourceY() == segment->getTargetY() ) { // which means : if it's a horizontal segment while ( currentVertex != targetVertex ) { // attention pour faire simple on code pour un grpahe regulier Edge* edge = currentVertex->getHEdgeOut(); // il faudrait choisir la bonne HEdgeOut pour un graphe irregulier unsigned ov = edge->getOverflow(); if ( ov ) { nbDep++; sumDep += ov; } nbTot++; currentVertex = edge->getOpposite ( currentVertex ); } } else { while ( currentVertex != targetVertex ) { Edge* edge = currentVertex->getVEdgeOut(); unsigned ov = edge->getOverflow(); if ( ov ) { nbDep++; sumDep += ov; } nbTot++; currentVertex = edge->getOpposite ( currentVertex ); } } if ( !nbTot ) return 0; return (float(nbDep)/float(nbTot))*sumDep; } unsigned Graph::analyseRouting ( set& segmentsToUnroute ) // **************************************************************** { // This function construct the list of segments that participate to congestion // empty Priority queue : easier than update each semgent when removing a semgent ... clearSTuplePQ(); // 30/01/09 on remplace le parcours des nets/segments par un parcours des // edges avec un map trié sur pointeur de segments et définissant un record: // nbDep nBTot + sumOv pour chaque segment. unsigned nbEdgesTot = 0; unsigned nbEdgesOv = 0; unsigned overflow = 0; unsigned maxOv = 0; unsigned wirelength = 0; unsigned viaWirelength = 0; map segmentsMap; for ( unsigned i = 0 ; i < _all_edges.size() ; i++ ) { Edge* edge = _all_edges[i]; nbEdgesTot++; if ( edge->isCongested() ) { nbEdgesOv++; unsigned edgeOv = 2*edge->getOverflow(); overflow += edgeOv; maxOv = edgeOv > maxOv ? edgeOv : maxOv; edge->addSubEstimateOccupancy ( HISTORIC_INC, true ); // add historic cost for each overflowed edge } forEach ( Segment*, segment, edge->getSegments() ) { map::iterator it = segmentsMap.find(*segment); if ( it != segmentsMap.end() ) { (*it).second.incNbTot(); if ( edge->isCongested() ) { (*it).second.incNbDep(); (*it).second.incSumOv(edge->getOverflow()); } } else { if ( edge->isCongested() ) segmentsMap[*segment]=segmentStat(1,1,edge->getOverflow()); else segmentsMap[*segment]=segmentStat(0,1,0); } } } unsigned nbDep = 0; unsigned nbTot = 0; float minimalCost = 0; float maximalCost = 0; for ( map::iterator it = segmentsMap.begin() ; it != segmentsMap.end() ; it++ ) { assert((*it).second.getNbTot() != 0); nbTot++; wirelength += getGridLength ( (*it).first ); float segmentCost = (float((*it).second.getNbDep())/float((*it).second.getNbTot()))*(*it).second.getSumOv(); if ( segmentCost ) { if (minimalCost == 0) minimalCost = segmentCost; minimalCost = segmentCost < minimalCost ? segmentCost : minimalCost; maximalCost = segmentCost > maximalCost ? segmentCost : maximalCost; STuple* stuple = STuple::create((*it).first, segmentCost); addToSTuplePQ(stuple); nbDep++; } } forEach ( Net*, net, _cell->getNets() ) { forEach ( Contact*, contact, net->getContacts() ) { const Layer* cLayer = contact->getLayer(); if ( cLayer == Configuration::getGContact() || cLayer == Configuration::getGMetalV() ) viaWirelength += 3; } } //forEach ( Net*, net, _cell->getNets() ) { // forEach ( Segment*, segment, net->getSegments() ) { // if ( isAGlobalRoutingSegment ( *segment ) ) { // float segmentCost = getSegmentCost ( *segment ); // if ( segmentCost ) { // nbDep++; // STuple* stuple = NULL; // // si une CostProperty est attaché au segment et que son iterateur est différent de _stuplePQEnd // // on recupere le STuple // // sinon on cree un stuple // Hurricane::Property* property = segment->getProperty ( STuple::CostProperty::_name ); // if ( STuple::CostProperty* cprop = dynamic_cast(property) ) { // STuple::STuplePQIter pqit = cprop->getPQIter(); // if ( pqit != STuple::_stuplePQEnd ) // stuple = (*pqit); // } // if ( !stuple ) // stuple = STuple::create ( *segment, segmentCost ); // addToSTuplePQ ( stuple ); // } // nbTot++; // } // } //} cmess1 << " o Analyse routing :" << endl << " - Number of overcapacity edges : " << nbEdgesOv << " / " << nbEdgesTot << endl << " - # of overflow : " << overflow << endl << " - max of overflow : " << maxOv << endl << " - avg overflow : " << (float)overflow / (float)nbEdgesTot << endl << " - grid wirelength : " << wirelength << endl << " - # of via : " << viaWirelength/3 << endl << " - total wirelength : " << wirelength + viaWirelength << endl << " - Overflowed segments : " << nbDep << " / " << nbTot << endl; // construct the list on segments to unroute if ( _stuplePriorityQueue.empty() ) { cmess1 << " - Nothing to reroute !" << endl; cmess1 << " - Maximum segment cost : 0" << endl; } else { STuple* topSTuple = getMaxFromSTuplePQ(); float maxCost = topSTuple->getCost(); cmess1 << " - Maximum segment cost : " << maxCost << endl; float minCost = 0.20; if (_stuplePriorityQueue.size() <= 100) minCost = 0.0; //if ( maxCost > 1 ) // minCost = maxCost * 0.20; //cmess1 << " - Minimum segment cost considered : " << minCost << endl; //cmess1 << " - Minimal computed segment cost : " << minimalCost << endl // << " - Maximal computed segment cost : " << maximalCost << endl; segmentsToUnroute.insert ( topSTuple->getSegment() ); //debugName = topSTuple->getSegment()->getNet()->getName(); popMaxFromSTuplePQ(); topSTuple = getMaxFromSTuplePQ(); //bool fullSkim = true; //printSTuplePQ(); while ( topSTuple != NULL ) { if ( topSTuple->getCost() >= minCost ) { segmentsToUnroute.insert ( topSTuple->getSegment() ); popMaxFromSTuplePQ(); topSTuple = getMaxFromSTuplePQ(); } else { //fullSkim = false; break; } } //cerr << " - fullSkim : " << fullSkim << endl; //printSTuplePQ(); } return overflow; } void Graph::getHorizontalCutLines ( vector& horizontalCutLines ) // ************************************************************************ { horizontalCutLines.clear(); Vertex* currentVertex = _lowerLeftVertex; horizontalCutLines.push_back ( currentVertex->getYMin() ); while ( currentVertex ) { horizontalCutLines.push_back ( currentVertex->getYMax() ); Edge* edge = currentVertex->getVEdgeOut(); if ( edge ) currentVertex = edge->getTo(); else break; } } void Graph::getVerticalCutLines ( vector& verticalCutLines ) // ******************************************************************** { verticalCutLines.clear(); Vertex* currentVertex = _lowerLeftVertex; verticalCutLines.push_back ( currentVertex->getXMin() ); while ( currentVertex ) { verticalCutLines.push_back ( currentVertex->getXMax() ); Edge* edge = currentVertex->getHEdgeOut(); if ( edge) currentVertex = edge->getTo(); else break; } } bool Graph::hasGlobalRouting ( RoutingPad* routingPad ) // **************************************************** { Hook* rpHook = routingPad->getBodyHook(); Vertex* rpVertex = _matrixVertex->getVertex ( routingPad->getX(), routingPad->getY() ); Hook* currentHook = rpHook->getNextHook(); while ( currentHook != rpHook ) { if ( dynamic_cast(currentHook) ) { Segment* seg = dynamic_cast(currentHook->getComponent()); if ( getVertex ( seg->getTargetX(), seg->getTargetY() ) == rpVertex ) return true; } if ( dynamic_cast(currentHook) ) { Segment* seg = dynamic_cast(currentHook->getComponent()); if ( getVertex ( seg->getSourceX(), seg->getSourceY() ) == rpVertex ) return true; } currentHook = currentHook->getNextHook(); } return false; } bool Graph::isAGlobalRoutingContact ( Contact* contact ) // ***************************************************** { if ( contact->getLayer() == Configuration::getGMetalH () ) return true; if ( contact->getLayer() == Configuration::getGMetalV () ) return true; if ( contact->getLayer() == Configuration::getGContact() ) return true; return false; } bool Graph::isAGlobalRoutingSegment ( Segment* segment ) // ***************************************************** { if ( segment->getLayer() == Configuration::getGMetalH () ) return true; if ( segment->getLayer() == Configuration::getGMetalV () ) return true; return false; } static void setContactLayer(Contact* contact) // ****************************************** { bool alu2Used = false; bool alu3Used = false; for_each_hook(hook, contact->getBodyHook()->getHooks()) { Component* component = hook->getComponent(); if (dynamic_cast(component) || dynamic_cast(component)) { const Layer* layer = component->getLayer(); if (layer == Configuration::getGMetalH() || layer == Configuration::getPinMetal() ) alu2Used = true; else if (layer == Configuration::getGMetalV() ) alu3Used = true; //else assert(false); // makes non ispd07 benchs failed.... } end_for; } const Layer* layer = NULL; if ( alu2Used ) { if ( alu3Used ) layer = Configuration::getGContact(); else layer = Configuration::getGMetalH(); } else if ( alu3Used ) { layer = Configuration::getGMetalV(); } else assert ( false ); contact->setLayer(layer); } void Graph::MaterializeRouting ( Vertex* vertex ) // ********************************************** { // This function materializes the routing of the connexe component passed as argument countMaterialize++; //if ( debugging ) { // cerr << " Materialize routing" << endl; // CEditor* editor = getCEditor( _nimbus->getCell() ); // editor->Refresh(); // string stopMessage = "MaterializeRouting, starting vertex: "; // stopMessage += getString ( vertex ); // editor->Stop(stopMessage); //} depthMaterialize = 0; //cerr << "INITIAL CALL of materialize routing for net : " << _working_net << endl; Edge* arrivalEdge = NULL; Contact* initContact = NULL; if ( _useSegments ) { initContact = vertex->getContact ( arrivalEdge ); assert ( initContact ); // must be != NULL because the source vertex must have a routingPad ! } MaterializeRouting ( vertex, arrivalEdge, initContact ); } void Graph::MaterializeRouting ( Vertex* vertex, Edge* arrivalEdge, Contact* initialContact ) // ****************************************************************************************** { depthMaterialize++; int vertexConnex = vertex->getConnexID(); assert ( vertexConnex != -1 ); //cerr << "--> check in MaterializeRouting " << endl; //checkGraphConsistency(); //cerr << " MR:" << depthMaterialize << ": vertex " << vertex << endl; //add for test ofnew MaterializeRouting 03/09/2997 d2 if ( _useSegments ) { for ( unsigned i = 0 ; i < 4 ; i++ ) { if ( Edge* edge = vertex->getFirstEdges ( i ) ) { if ( edge == arrivalEdge ) continue; if ( (edge->getNetStamp() == _netStamp) && (edge->getConnexID() == vertexConnex) ) { Vertex* oppositeVertex = edge->getOpposite ( vertex ); Contact* reachedContact = oppositeVertex->getContact(edge); Edge* straightArrivalEdge = edge; vector crossedEdges; crossedEdges.push_back(edge); while ( reachedContact == NULL ) { straightArrivalEdge = oppositeVertex->getFirstEdges(i); if ( straightArrivalEdge == NULL ) throw Error ( "Graph:MaterializeRouting(): Cannot continue straight on." ); oppositeVertex = straightArrivalEdge->getOpposite ( oppositeVertex ); reachedContact = oppositeVertex->getContact ( straightArrivalEdge ); //straightArrivalEdge->incOccupancy(); // put the incOccupancy in insertSegment function crossedEdges.push_back(straightArrivalEdge); } // test pour ne pas recreer le routage preexistant en cas de reroutage bool alreadyExist = false; for_each_component ( component, initialContact->getSlaveComponents() ) { if ( dynamic_cast(component) ) { Segment* seg = static_cast(component); if ( seg->getOppositeAnchor(initialContact) == (Component*)(reachedContact) ) { //cerr << " segment already exists" << endl; alreadyExist = true; } } end_for; } if ( !alreadyExist ) { Segment* segment = createSegment ( initialContact, reachedContact ); assert ( segment ); for ( unsigned j = 0 ; j < crossedEdges.size(); j++ ) crossedEdges[j]->insertSegment(segment); } MaterializeRouting ( oppositeVertex, straightArrivalEdge, reachedContact ); } } } setContactLayer(initialContact); } //else { // for_each_edge ( edge, vertex->getAdjacentEdges() ) { // //if ( edge == arrivalEdge) // // continue; // //cerr << " MR:" << depthMaterialize<< ": edge " << edge << endl; // if ( (edge->getNetStamp() == _netStamp) && (edge->getConnexID() == vertexConnex) ) { // edge->createSplitter ( _working_net ); // _nbSplitters++; // Hook* hook = edge->getSplitterHook ( vertex ); // assert (hook); // if ( Hook* previousHook = vertex->getLocalRingHook() ) // XXX Attention puisqu'on vire le systeme le localRingHook au profit du contact // hook->attach ( previousHook ); // vertex->setLocalRingHook ( hook ); // if ( edge != arrivalEdge ) { // MaterializeRouting ( edge->getOpposite(vertex), edge); // // cleaning for next routing // edge->setSplitter(NULL); // } // end_for; // } // } //} // cleaning for next routing //vertex->setLocalRingHook(NULL); vertex->setContact(NULL); depthMaterialize--; } void Graph::CleanRoutingState() // **************************** { // Vide la pile clearPriorityQueue(); //// Pour chacun des vertex, on efface le pointeur sur la ronde locale et on reinitialise le connexID, la distance et le predecessor //// le vtuple est aussi mis a NULL, c'est pourquoi il faut que la pile ait été vidée avant ( sinon assert ) //// (XXX mieux vaudrait le faire uniquement pour les vertex touchés par le routage XXX) //for ( unsigned i = 0 ; i < _all_vertexes.size() ; i++ ) { // Vertex* vertex = _all_vertexes[i]; // assert (vertex); // vertex->setLocalRingHook(NULL); // vertex->setConnexID(-1); // vertex->setDistance((float)(HUGE)); // vertex->setPredecessor(NULL); // assert ( vertex->getVTuple() == NULL ); //} //// Pour chacune des edges, on efface le pointeur sur le splitter (potentiel) et on reinitialise le connexID //for ( unsigned i = 0 ; i < _all_edges.size() ; i++ ) { // Edge* edge = _all_edges[i]; // assert ( edge ); // edge->setSplitter(NULL); // edge->setConnexID(-1); //} // On vide le set des _vertexes_to_route _vertexes_to_route.clear(); _working_net = NULL; _searchingArea.makeEmpty(); } void Graph::checkGraphConsistency() // ******************************** { bool checkFailed = false; unsigned nbEdges= 0; for_each_edge ( edge, VectorCollection(_all_edges) ) { nbEdges++; if ( edge->getNetStamp() > _netStamp ) { cerr << " - " << edge << " netStamp mismatch" << endl; checkFailed = true; } if ( edge->getNetStamp() == _netStamp ) { int edgeID = edge->getConnexID(); if ( edgeID != -1 ) { if ( edge->getFrom()->getConnexID() == -1 ) { cerr << " - from : " << edge->getFrom() << " of " << edge << " : connexID mismatch" << endl; checkFailed = true; } if ( edge->getTo()->getConnexID() == -1 ) { cerr << " - to : " << edge->getTo() << " of " << edge << " : connexID mismatch" << endl; checkFailed = true; } if ( (edge->getFrom()->getConnexID() != edgeID) && (edge->getTo()->getConnexID() != edgeID) ) { cerr << " - " << edge << " : connexID mismatch" << endl; checkFailed = true; } } } end_for } if ( checkFailed ) { cerr << " ************************************" << endl << " * GRAPH CHECK CONSISTENCY FAILED *" << endl << " ************************************" << endl; } } void Graph::checkEmptyPriorityQueue() // ********************************** { bool checkFailed = false; // check empty priority queue if ( !_vtuplePriorityQueue.empty() ) { checkFailed = true; cerr << " Priority Queue is not empty !!!!" << endl << " stil in queue :" << endl; VTuplePQIter pqit = _vtuplePriorityQueue.begin(); while ( pqit != _vtuplePriorityQueue.end() ) { cerr << " " << (*pqit)->getVertex() << " : " << (*pqit)->getDistance() << endl; pqit++; } } //check null vtuple foreach vertex unsigned nbVertexes= 0; for_each_vertex ( vertex, VectorCollection(_all_vertexes) ) { nbVertexes++; if ( vertex->getNetStamp() > _netStamp ) { cerr << " - " << vertex << " netStamp mismatch" << endl; checkFailed = true; } if ( vertex->getVTuple() ) { cerr << " - " << vertex << " still have a vtuple : " << vertex->getVTuple() << endl; checkFailed = true; } end_for } if ( checkFailed ) { cerr << " *********************************************" << endl << " * GRAPH CHECK EMPTY PRIORITY QUEUE FAILED *" << endl << " *********************************************" << endl; } } // DensityWindow* Graph::createEstimateOccupancyWindow() // // ************************************************** // { // if ( _estimateOccupancyWindow ) return _estimateOccupancyWindow; // unsigned int max = _ySize > _xSize ? _ySize : _xSize; // unsigned int scale = (unsigned) ceil(500.0/(double)max); // _estimateOccupancyWindow = new DensityWindow ( _xSize, _ySize, 3, "fire", scale ); // _estimateOccupancyWindow->setName ( 0, "Global Estimate Occupancy" ); // _estimateOccupancyWindow->setName ( 1, "Horizontal Estimate Occupancy" ); // _estimateOccupancyWindow->setName ( 2, "Vertical Estimate Occupancy" ); // return _estimateOccupancyWindow; // } // void Graph::UpdateEstimateOccupancyWindow() // // **************************************** // { // if ( !_estimateOccupancyWindow ) // createEstimateOccupancyWindow(); // _estimateOccupancyWindow->setSlice(0); // Vertex* currentVertex = _lowerLeftVertex; // int i = 0; // int j = 0; // while ( currentVertex ) { // Vertex* firstLineVertex = currentVertex; // i = 0; // while ( currentVertex ) { // float xEstimateOccupancy = 0.0; // Edge* hEdgeOut = currentVertex->getHEdgeOut(); // if ( hEdgeOut ) // xEstimateOccupancy += hEdgeOut->getEstimateOccupancy(); // float yEstimateOccupancy = 0.0; // if ( Edge* vEdgeOut = currentVertex->getVEdgeOut() ) // yEstimateOccupancy += vEdgeOut->getEstimateOccupancy(); // int colorValue = _maxEstimateOccupancy != 0 ? (int)(255 * (xEstimateOccupancy + yEstimateOccupancy) / _maxEstimateOccupancy) : 0; // int colorXValue = _maxXEstimateOccupancy != 0 ? (int)(255 * xEstimateOccupancy / _maxXEstimateOccupancy) : 0; // int colorYValue = _maxYEstimateOccupancy != 0 ? (int)(255 * yEstimateOccupancy / _maxYEstimateOccupancy) : 0; // _estimateOccupancyWindow->DrawRectangle(i, j, i, j, colorValue , 0); // _estimateOccupancyWindow->DrawRectangle(i, j, i, j, colorXValue, 1); // _estimateOccupancyWindow->DrawRectangle(i, j, i, j, colorYValue, 2); // i++; // if ( hEdgeOut ) // currentVertex = hEdgeOut->getOpposite ( currentVertex ); // else // break; // } // j++; // Edge* vEdgeOut = firstLineVertex->getVEdgeOut(); // if ( vEdgeOut ) // currentVertex = vEdgeOut->getOpposite ( firstLineVertex ); // else // break; // } // _estimateOccupancyWindow->getWindow()->show(); // return; // } //void Graph::printStats() //// ********************* //{ // Vertex* currentVertex = _lowerLeftVertex; // int i = 0; // int j = 0; // int nbEdgesTotal = 0; // int nbEdgesOver = 0; // // unsigned overflow = 0; // unsigned maxOver = 0; // //float maxOver = 0; // //float averageOver = 0; // while ( currentVertex ) { // Vertex* firstLineVertex = currentVertex; // i = 0; // while ( currentVertex ) { // Edge* hEdgeOut = currentVertex->getHEdgeOut(); // if ( hEdgeOut ) { // nbEdgesTotal++; // int ov = 2*(hEdgeOut->getRealOccupancy() - hEdgeOut->getCapacity()); // 2 = minimum sapcing + minimum width // if ( ov > 0 ) { // nbEdgesOver++; // overflow += ov; // maxOver = ov > maxOver ? ov : maxOver; // for_each_segment ( segment, hEdgeOut->getSegments() ) { // Net* net = segment->getNet(); // map::iterator nuit = _netNbOverEdges.find ( net ); // if ( nuit != _netNbOverEdges.end() ) // (*nuit).second = (*nuit).second + 1; // else // _netNbOverEdges[net] = 1; // end_for; // } // } // //float tempOver = (float)hEdgeOut->getRealOccupancy() / (float)hEdgeOut->getCapacity(); // //if ( tempOver > 0.8 ) { // // nbEdgesOver++; // // averageOver += tempOver; // // if ( tempOver > maxOver ) maxOver = tempOver; // //} // } // if ( Edge* vEdgeOut = currentVertex->getVEdgeOut() ) { // nbEdgesTotal++; // int ov = 2*(vEdgeOut->getRealOccupancy() - vEdgeOut->getCapacity()); // if ( ov > 0 ) { // nbEdgesOver++; // overflow += ov; // maxOver = ov > maxOver ? ov : maxOver; // for_each_segment ( segment, vEdgeOut->getSegments() ) { // Net* net = segment->getNet(); // map::iterator nuit = _netNbOverEdges.find ( net ); // if ( nuit != _netNbOverEdges.end() ) // (*nuit).second = (*nuit).second + 1; // else // _netNbOverEdges[net] = 1; // end_for; // } // } // //float tempOver = (float)vEdgeOut->getRealOccupancy() / (float)vEdgeOut->getCapacity(); // //if ( tempOver > 0.8 ) { // // nbEdgesOver++; // // averageOver += tempOver; // // if ( tempOver > maxOver ) maxOver = tempOver; // //} // } // // i++; // if ( hEdgeOut ) // currentVertex = hEdgeOut->getOpposite ( currentVertex ); // else // break; // } // j++; // Edge* vEdgeOut = firstLineVertex->getVEdgeOut(); // if ( vEdgeOut ) // currentVertex = vEdgeOut->getOpposite ( firstLineVertex ); // else // break; // } // //averageOver = nbEdgesOver == 0 ? 0 : averageOver / (float)nbEdgesOver; // // // // cerr << " - Total number of edges : " << nbEdgesTotal << endl // << " - Number of overcapacity edges : " << nbEdgesOver << endl // << " - Total calls to Dijkstra : " << countDijkstra << endl // << " - Total calls to Monotonic : " << countMonotonic << endl // << " - Total calls to Materialize : " << countMaterialize << endl // << " - Taille du Graphe de routage : " << _xSize << " x " << _ySize << endl // << endl // << " - # of overflow : " << overflow << endl // << " - max of overflow : " << maxOver << endl // << " - # of net with overflow : " << _netNbOverEdges.size() << endl; // return; //} // DensityWindow* Graph::createOccupancyWindow() // // ****************************************** // { // if ( _occupancyWindow ) return _occupancyWindow; // unsigned int max = _ySize > _xSize ? _ySize : _xSize; // unsigned int scale = (unsigned) ceil(500.0/(double)max); // _occupancyWindow = new DensityWindow ( _xSize, _ySize, 3, "fire", scale ); // _occupancyWindow->setName ( 0, "Global Occupancy" ); // _occupancyWindow->setName ( 1, "Horizontal Occupancy" ); // _occupancyWindow->setName ( 2, "Vertical Occupancy" ); // return _occupancyWindow; // } // void Graph::UpdateOccupancyWindow() // // ******************************** // { // if ( !_occupancyWindow ) // createOccupancyWindow(); // _occupancyWindow->setSlice(0); // Vertex* currentVertex = _lowerLeftVertex; // int i = 0; // int j = 0; // while ( currentVertex ) { // Vertex* firstLineVertex = currentVertex; // i = 0; // while ( currentVertex ) { // unsigned xOccupancy = 0; // Edge* hEdgeOut = currentVertex->getHEdgeOut(); // if ( hEdgeOut ) // xOccupancy += hEdgeOut->getRealOccupancy(); // unsigned yOccupancy = 0; // if ( Edge* vEdgeOut = currentVertex->getVEdgeOut() ) // yOccupancy += vEdgeOut->getRealOccupancy(); // assert(_maxOccupancy); // assert(_maxXOccupancy); // assert(_maxYOccupancy); // _occupancyWindow->DrawRectangle(i, j, i, j, (255 * (xOccupancy + yOccupancy) / _maxOccupancy), 0); // _occupancyWindow->DrawRectangle(i, j, i, j, (255 * xOccupancy / _maxXOccupancy), 1); // _occupancyWindow->DrawRectangle(i, j, i, j, (255 * yOccupancy / _maxYOccupancy), 2); // i++; // if ( hEdgeOut ) // currentVertex = hEdgeOut->getOpposite ( currentVertex ); // else // break; // } // j++; // Edge* vEdgeOut = firstLineVertex->getVEdgeOut(); // if ( vEdgeOut ) // currentVertex = vEdgeOut->getOpposite ( firstLineVertex ); // else // break; // } // _occupancyWindow->getWindow()->show(); // return; // } Record* Graph::_getRecord() const // ************************ { Record* record = new Record ( getString ( this ) ); record->add ( getSlot ( "LowerLeftVertex", _lowerLeftVertex ) ); // record->add ( getSlot ( "SlicingTree" , _slicingTree ) ); record->add ( getSlot ( "WorkingNet" , _working_net ) ); record->add ( getSlot ( "SearchingArea" , _searchingArea ) ); record->add ( getSlot ( "xSize" , _xSize ) ); record->add ( getSlot ( "ySize" , _ySize ) ); record->add ( getSlot ( "maxEstimateOccupancy", _maxEstimateOccupancy ) ); record->add ( getSlot ( "maxXEstimateOccupancy", _maxXEstimateOccupancy ) ); record->add ( getSlot ( "maxYEstimateOccupancy", _maxYEstimateOccupancy ) ); return record; } string Graph::_getString() const // ***************************** { return "<" + _TName ( "RoutingGraph" ) //+ ":" + getString ( _slicingTree ) + "," + getString ( _xSize ) + "," + getString ( _ySize ) + ">"; } } // namespace Knik