408 lines
14 KiB
C++
408 lines
14 KiB
C++
|
|
#include <cmath>
|
|
#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 )
|
|
ltrace(300) << 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<Segment*>::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
|