#include #include "crlcore/Utilities.h" #include "hurricane/Breakpoint.h" #include "hurricane/Warning.h" #include "knik/Edge.h" #include "knik/Vertex.h" #include "knik/Graph.h" namespace Knik { extern unsigned __congestion__; extern unsigned __precongestion__; extern bool __ripupMode__; extern float __edge_cost__; const Name Edge::_extensionName = "Knik::Edge"; Edge::Edge ( Vertex* from, Vertex* to ) // ************************************ : Inherit (from->getCell()) , _from (from) , _nextFrom (NULL) , _to (to) , _nextTo (NULL) , _connexID (-1) , _cost (0.0) , _capacity (0) , _realOccupancy (0) , _estimateOccupancy (0.0) , _netStamp (0) , _segments() { /*_cost = v1->getGCell()->getCenter().ManhattanDistance (v2->getGCell()->getCenter());*/ } Edge::Edge ( Vertex* from, Vertex* to, unsigned capacity ) // ******************************************************* : Inherit (from->getCell()) , _boundingBox() , _from (from) , _nextFrom (NULL) , _to (to) , _nextTo (NULL) , _connexID (-1) , _cost (0.0) , _capacity (capacity) , _realOccupancy (0) , _estimateOccupancy (0.0) , _netStamp (0) , _isCongested (false) , _segments() { //cerr << " Edge::Edge() capacity:" << _capacity << endl; } void Edge::_postCreate () // ********************** { Inherit::_postCreate(); _segments.reserve(_capacity); } Edge::~Edge() // ********** { } void Edge::destroy() // **************** { _preDestroy(); delete this; } void Edge::_preDestroy() // ******************** { Inherit::_preDestroy(); } void Edge::setCapacity ( unsigned int capacity ) // ***************************************** { _capacity = capacity; //cerr << "Setting capacity to " << _capacity << " on " << this << endl; } void Edge::increaseCapacity ( int capacity ) // ***************************************** { if ( (int)_capacity + capacity < 0 ) _capacity = 0; else _capacity += capacity; //if ( _capacity < 2 ) _capacity = 0; // cerr << "Increase Edge Capacity " << _from->getPosition() // << " to " << _to->getPosition() << ":" << _capacity << endl; //cerr << "Increasing capacity to " << _capacity << " on " << this << endl; if ( _capacity == 0 ) cdebug_log(139,0) << Warning("%s has reached NULL capacity.",getString(this).c_str()) << endl; } void Edge::incOccupancy () // *********************** { _realOccupancy++; if ( !_isCongested ) { if ( _realOccupancy > _capacity ) { _boundingBox = computeBoundingBox(); _isCongested = true; // reste a mettre les segments traversant l'edge dans la pile ou s'ils y sont deja a les mettre a jour } } } void Edge::decOccupancy () // ************************ { if ( _realOccupancy > 0 ) _realOccupancy--; if ( _isCongested && (_realOccupancy <= _capacity) ) { _boundingBox = computeBoundingBox(); _isCongested = false; } } void Edge::removeSegment ( Segment* segment ) // ****************************************** { assert(segment); decOccupancy(); vector::iterator vsit = find(_segments.begin(),_segments.end(),segment); if ( vsit != _segments.end() ) _segments.erase ( vsit ); else { cerr << segment << " " << this << endl; Breakpoint::stop(0, "Shootdown -h now"); throw Error ( "Edge::removeSegment(): I cannot believe this segment is not in _segments!" ); } } void Edge::addSubEstimateOccupancy ( float increment, bool add ) // ************************************************************* { if ( add ) _estimateOccupancy += increment; else _estimateOccupancy -= increment; return; } DbU::Unit Edge::getXTo() const // *************************** { return _to->getX(); } DbU::Unit Edge::getYTo() const // *************************** { return _to->getY(); } DbU::Unit Edge::getXFrom() const // ***************************** { return _from->getX(); } DbU::Unit Edge::getYFrom() const // ***************************** { return _from->getY(); } void Edge::translate ( const DbU::Unit& dx, const DbU::Unit& dy ) // ************************************************************** { _from->translate ( dx, dy ); _to->translate ( dx, dy ); } Cell* Edge::getCell() const // ************************ { return _from->getCell(); } float Edge::getCost ( Edge* arrivalEdge ) // ************************************** { // 20/10/2010: Check for null capacity, which may occurs after back-annotation // by Kite. if ( _capacity == 0.0 ) return (float)(HUGE_VAL); //#ifdef __USE_CONGESTION__ if ( __congestion__ ) { // definition de la fonction de cout : // on ramene l'occupation de l'edge à un pourcentage de la capacité : float edge_capacity = (float)1.0; float edge_occupancy; //float h = 9.0; //float k = 30.0; // environ 3*h pour etre sur d'avoir cost(0) = 1 !! //now defined as edge's attributes for ripup & reroute if ( !__ripupMode__ ) { //#if defined ( __USE_STATIC_PRECONGESTION__ ) || defined ( __USE_DYNAMIC_PRECONGESTION__ ) if ( __precongestion__ ) edge_occupancy = ((float)getRealOccupancy() + getEstimateOccupancy()) / (float)_capacity; //#else else edge_occupancy = (float)getRealOccupancy() / (float)_capacity; //#endif _cost = 1.0 + (9.0 / (1.0 + exp(-30.0 * (edge_occupancy - edge_capacity)))); // plutot que 1.0 on devrait avoir un getLength renvoyant la longueur de l'arete en unités normalisées (pas de grille) } else { // dans ce mode l'estimation de congestion est utilisé comme historique de congestion edge_occupancy = (float)getRealOccupancy() / (float)_capacity; float historicCost; if ( edge_occupancy < 1 ) historicCost = getEstimateOccupancy() * edge_occupancy; else historicCost = getEstimateOccupancy() * exp(log(8)*(edge_occupancy - edge_capacity)); _cost = 1.0 + (19.0 / (1.0 + exp(-60.0 * (edge_occupancy - edge_capacity)))) + historicCost; } } //#else else _cost = 1.0; //#endif // Prise en compte des vias ! if ( arrivalEdge ) { if ( arrivalEdge->isVertical() && isHorizontal() ) _cost += __edge_cost__; if ( arrivalEdge->isHorizontal() && isVertical() ) _cost += __edge_cost__; } //if ( _from->getRoutingGraph()->getRipupMode() ) // if ( _isCongested ) // _cost += 1000; return _cost; } unsigned Edge::getRealOccupancy() const // ************************************ { // pour debug plus facile : // Attention ce n'est plus vrai lorsque l'edge gère elle même son occupation! //assert ( _realOccupancy == _fence->getOccupancy() ); return _realOccupancy; } Segment* Edge::getSegmentFor ( Net* net ) // ************************************** { for_each_segment ( segment, getCollection ( _segments ) ) { if ( segment->getNet() == net ) return segment; end_for; } return NULL; } bool Edge::hasInfo() const // *********************** { return (_netStamp == _from->getRoutingGraph()->getNetStamp())&&(_connexID != -1); } // void Edge::_Draw ( View* view, BasicLayer* basicLayer, const Box& updateArea, const Transformation& transformation ) // //****************************************************************************************************************** // { // Point fromPos = transformation.getPoint ( _from->getPosition() ); // Point toPos = transformation.getPoint ( _to->getPosition() ); // //view->DrawLine ( fromPos, toPos ); // // new version to represent occupation // DbU::Unit halfWidth = _from->getHalfWidth() < _to->getHalfWidth() ? _from->getHalfWidth() : _to->getHalfWidth(); // DbU::Unit halfHeight = _from->getHalfHeight() < _to->getHalfHeight() ? _from->getHalfHeight() : _to->getHalfHeight(); // bool overCap = false; // float relOccupancy = 0.0; // if ( _realOccupancy > _capacity ) { // overCap = true; // relOccupancy = 1.0; // } // else // relOccupancy = (float)_realOccupancy / (float)_capacity; // if ( fromPos.getY() == toPos.getY() ) { // DbU::Unit medFromX = fromPos.getX() + halfWidth; // DbU::Unit medFromY = fromPos.getY() - halfHeight; // DbU::Unit medToX = fromPos.getX() + halfWidth; // DbU::Unit medToY = fromPos.getY() + halfHeight; // view->DrawLine ( medFromX, medFromY, medToX, medToY ); // DbU::Unit cover = DbU::lambda ( getValue(medToY - medFromY) * relOccupancy ); // view->FillRectangle ( medFromX - 100, medFromY , medFromX + 100, medFromY + (cover/2) ); // view->FillRectangle ( medToX - 100 , medToY - (cover/2), medToX + 100 , medToY ); // if (overCap) // view->FillRectangle ( medFromX-150, medFromY+halfHeight-150, medFromX+150, medFromY+halfHeight+150 ); // } // else { // DbU::Unit medFromX = fromPos.getX() - halfWidth; // DbU::Unit medFromY = fromPos.getY() + halfHeight; // DbU::Unit medToX = fromPos.getX() + halfWidth; // DbU::Unit medToY = fromPos.getY() + halfHeight; // view->DrawLine ( medFromX, medFromY, medToX, medToY ); // DbU::Unit cover = DbU::lambda ( getValue(medToX - medFromX) * relOccupancy ); // view->FillRectangle ( medFromX , medFromY - 100, medFromX + (cover/2), medFromY + 100 ); // view->FillRectangle ( medToX - (cover/2), medToY - 100 , medToX , medToY + 100 ); // if (overCap) // view->FillRectangle ( medFromX+halfWidth-150, medFromY-150, medFromX+halfWidth+150, medFromY+150 ); // } // // old version // //if ( _estimateOccupancy > 0 ) // // view->DrawString ( getString(_estimateOccupancy), (fromPos.getX()+toPos.getX())/2 , (fromPos.getY()+toPos.getY())/2 ); // if ( (_netStamp == _from->getRoutingGraph()->getNetStamp()) && (_connexID != -1) ) { // view->DrawString ( getString(_connexID), (fromPos.getX()+toPos.getX())/2 , (fromPos.getY()+toPos.getY())/2+10 ); // } // //if ( _nextTo ) { // // Point nextToFromPos = transformation.getPoint ( _nextTo->getFrom()->getPosition() ); // // Point nextToToPos = transformation.getPoint ( _nextTo->getTo()->getPosition() ); // // DbU::Unit origX = fromPos.getX() + (toPos.getX() - fromPos.getX())/3; // // DbU::Unit origY = fromPos.getY() + (toPos.getY() - fromPos.getY())/3; // // DbU::Unit destX = nextToFromPos.getX() + (nextToToPos.getX() - nextToFromPos.getX())/3; // // DbU::Unit destY = nextToFromPos.getY() + (nextToToPos.getY() - nextToFromPos.getY())/3; // // view->DrawLine ( origX, origY, destX, destY ); // // view->DrawCircle ( destX, destY, DbU::lambda ( 3 ) ); // //} // //if ( _nextFrom ) { // // Point nextFromFromPos = transformation.getPoint ( _nextFrom->getFrom()->getPosition() ); // // Point nextFromToPos = transformation.getPoint ( _nextFrom->getTo()->getPosition() ); // // DbU::Unit origX = fromPos.getX() + (toPos.getX() - fromPos.getX())*2/3; // // DbU::Unit origY = fromPos.getY() + (toPos.getY() - fromPos.getY())*2/3; // // DbU::Unit destX = nextFromFromPos.getX() + (nextFromToPos.getX() - nextFromFromPos.getX())*2/3; // // DbU::Unit destY = nextFromFromPos.getY() + (nextFromToPos.getY() - nextFromFromPos.getY())*2/3; // // view->DrawLine ( origX, origY, destX, destY ); // // view->FillCircle ( destX, destY, DbU::lambda ( 3 ) ); // //} // } // void Edge::_Highlight ( View* view, const Box& updateArea, const Transformation& transformation ) // // ********************************************************************************************** // { // view->DrawLine ( transformation.getPoint ( _from->getPosition() ) // , transformation.getPoint ( _to->getPosition() ) ); // } // bool Edge::_IsInterceptedBy ( View* view, const Point& point, const DbU::Unit& aperture ) const // // *************************************************************************************** // { // Box area ( point ); // area.inflate(aperture); // return getBoundingBox().intersect ( area ); // } void Edge::invalidate ( bool propagateFlag ) // ***************************************** { Inherit::invalidate ( false ); } string Edge::_getString() const // **************************** { return "<" + _TName ( "Edge" ) + " id:" + getString( _connexID ) + " s:" + getString( _netStamp ) + " " + getString( _realOccupancy ) + "/" + getString( _capacity ) + " " + getString( _from ) + " " + getString( _to ) + ">"; } Record* Edge::_getRecord() const // *********************** { Record* record = Inherit::_getRecord(); if ( !record ) record = new Record ( getString ( this ) ); record->add ( getSlot ( "from" , _from ) ); record->add ( getSlot ( "to" , _to ) ); record->add ( getSlot ( "nextFrom" , _nextFrom ) ); record->add ( getSlot ( "nextTo" , _nextTo ) ); record->add ( getSlot ( "connexID" , _connexID ) ); record->add ( getSlot ( "cost" , _cost ) ); record->add ( getSlot ( "netStamp" , _netStamp ) ); record->add ( getSlot ( "capacity" , _capacity ) ); record->add ( getSlot ( "occupancy", _realOccupancy ) ); record->add ( getSlot ( "estimate occupancy", _estimateOccupancy ) ); record->add ( getSlot ( "segments" , &_segments ) ); return record; } } // end namespace