Corrections in the Dijkstra global routing (ripup) mechanism.

* Bug: In Anabatic::Dijkstra, the degree of a vertex (the number of neighbors
    belonging to the same net) was miscalculated. This was leading, in the
    materialize step to some feed-through vertexes not being broken.
    Leading in turn to incomplete transformation of the detailed routing.
      Also in _trackback(), the degree of the first vertex we were backtracking
    from was not incremented.
* Bug: In Anabatic::Dijkstra::materialize(), systematically use
    GCell::breakGoThrough() on both source and target. This is needed when
    we are in the ripup phase as both source and target can be go-through.
      This was also leading to incomplete detailed routing transformation.
* Change: In Anabatic::Edge::ripup(), ripup one third of the segments instead
    of thoses exeeding the global length threshold. This way we are sure to
    desaturate an edge. Needs to be further calibrated.
* Change: In Aanabatic::GCell::breakGoThrough(), no longer return NULL.
    Return existing gcontact if any. Break if it is a go-through and create
    a new gcontact in last resort. Maybe rename this function.
* New: In Anabatic::Configuration, new parameters:
    - anabatic.edgeHScaling, to adjust the length of the horizontal edges
        relative to the vertical ones (this is a ratio).
    - anabatic.globalIterations, set the maximum number of ripup passes
        of the global router.
* New: In CRL/etc/*/kite.conf, added new parameters anabatic.edgeHScaling
    and anabatic.globalIterations.
* New: In Katana::GlobalRoute::DigitalDistance, take into account the new
    edgeHScaling factor. Must be used when the capacity of V-edges differs
    greatly for H-edges (case of AMS 350nm c35b4 for instance).
* Bug: In Katana::GlobalRoute::DigitalDistance, the historic cost is
    computed for an edge length of "1". Must be multiplicated by the
    current edge length to have any measurable effect.
      This bug is finally explaining why the ripup was producing the
    same solutions over and over, the historical cost was negligible!
This commit is contained in:
Jean-Paul Chaput 2018-04-16 12:10:48 +02:00
parent 80dcd264bb
commit 1a338f620c
13 changed files with 190 additions and 83 deletions

View File

@ -627,6 +627,15 @@ namespace Anabatic {
cdebug_log(112,1) << "AnabaticEngine::unify(): " << (void*)contact << endl;
cdebug_log(112,0) << contact << endl;
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( hook->getComponent() );
if (rp) {
cdebug_log(112,0) << "Cannot unify, there is a RoutingPad in this GCell." << endl;
cdebug_tabw(112,-1);
return false;
}
}
for ( Component* slave : contact->getSlaveComponents() ) {
Horizontal* h = dynamic_cast<Horizontal*>( slave );
if (h) {

View File

@ -69,23 +69,25 @@ namespace Anabatic {
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt())
, _globalThreshold(0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH", 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK",-10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
: _gdepthv (ndepth)
, _gdepthh (ndepth)
, _ddepthv (ndepth)
, _ddepthh (ndepth)
, _ddepthc (ndepth)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps ()
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble())
, _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt())
, _globalThreshold (0)
, _allowedDepth (0)
, _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt()))
, _edgeWidth (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeWidth" , 4)->asInt()))
, _edgeCostH (Cfg::getParamDouble("anabatic.edgeCostH" , 9.0)->asDouble())
, _edgeCostK (Cfg::getParamDouble("anabatic.edgeCostK" ,-10.0)->asDouble())
, _edgeHInc (Cfg::getParamDouble("anabatic.edgeHInc" , 1.5)->asDouble())
, _edgeHScaling (Cfg::getParamDouble("anabatic.edgeHScaling" , 1.0)->asDouble())
, _globalIterations(Cfg::getParamInt ("anabatic.globalIterations", 10 )->asInt())
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -152,23 +154,25 @@ namespace Anabatic {
Configuration::Configuration ( const Configuration& other )
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold(other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
: _gmetalh (other._gmetalh)
, _gmetalv (other._gmetalv)
, _gcontact (other._gcontact)
, _gdepthv (other._gdepthv)
, _gdepthh (other._gdepthh)
, _ddepthv (other._ddepthv)
, _ddepthh (other._ddepthh)
, _ddepthc (other._ddepthc)
, _cg (NULL)
, _rg (NULL)
, _extensionCaps (other._extensionCaps)
, _saturateRatio (other._saturateRatio)
, _globalThreshold (other._globalThreshold)
, _allowedDepth (other._allowedDepth)
, _edgeCostH (other._edgeCostH)
, _edgeCostK (other._edgeCostK)
, _edgeHInc (other._edgeHInc)
, _edgeHScaling (other._edgeHScaling)
, _globalIterations(other._globalIterations)
{
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
@ -188,15 +192,19 @@ namespace Anabatic {
Configuration* Configuration::clone () const
{ return new Configuration(*this); }
bool Configuration::isTwoMetals () const
{ return _rg->isTwoMetals(); }
bool Configuration::isHV () const
{ return _rg->isHV(); }
bool Configuration::isVH () const
{ return _rg->isVH(); }
bool Configuration::isGMetal ( const Layer* layer ) const
{ return (layer and ((layer == _gmetalh) or (layer == _gmetalv))); }
@ -204,15 +212,19 @@ namespace Anabatic {
bool Configuration::isGContact ( const Layer* layer ) const
{ return (layer and (layer == _gcontact)); }
const Layer* Configuration::getGContactLayer () const
{ return _gcontact; }
const Layer* Configuration::getGHorizontalLayer () const
{ return _gmetalh; }
const Layer* Configuration::getGVerticalLayer () const
{ return _gmetalv; }
size_t Configuration::getDepth () const
{ return _rg->getDepth(); }
@ -379,6 +391,14 @@ namespace Anabatic {
{ return _edgeHInc; }
float Configuration::getEdgeHScaling () const
{ return _edgeHScaling; }
int Configuration::getGlobalIterations () const
{ return _globalIterations; }
DbU::Unit Configuration::isOnRoutingGrid ( RoutingPad* rp ) const
{
Box ab = rp->getCell()->getBoundingBox();

View File

@ -1308,7 +1308,7 @@ namespace Anabatic {
+ " " + DbU::getValueString(_gcell->getXMax())
+ " " + DbU::getValueString(_gcell->getYMax()) + "]"
//+ " rps:" + getString(_rpCount)
//+ " deg:" + getString(_degree)
+ " deg:" + getString(_degree)
+ " connexId:" + ((_connexId >= 0) ? getString(_connexId) : "None")
+ " d:" + ((_distance == unreached) ? "unreached"
: ((_distance == unreachable) ? "unreachable"
@ -1515,7 +1515,7 @@ namespace Anabatic {
vertex->setStamp ( _stamp );
vertex->setConnexId ( _connectedsId );
vertex->setBranchId ( 0 );
vertex->setDegree ( 1 );
vertex->setDegree ( 0 );
vertex->setRpCount ( 0 );
vertex->setFrom ( NULL );
@ -1524,6 +1524,15 @@ namespace Anabatic {
vertex->clearRestriction();
_targets.insert( vertex );
}
for ( Vertex* vertex : connecteds ) {
int degree = 0;
for ( Edge* edge : vertex->getGCell()->getEdges() ) {
Vertex* neighbor = vertex->getNeighbor( edge );
if (vertex->hasValidStamp() and neighbor->hasValidStamp()) ++degree;
}
vertex->setDegree( degree );
cdebug_log(112,0) << "| Add: " << vertex << endl;
}
}
@ -1960,6 +1969,7 @@ namespace Anabatic {
void Dijkstra::_traceback ( Vertex* current )
{
cdebug_log(112,1) << "Dijkstra::_traceback() " << _net << " branchId:" << _sources.size() << endl;
cdebug_log(112,0) << "From: " << current << endl;
int branchId = _sources.size();
_toSources( current, _connectedsId );
@ -1970,6 +1980,7 @@ namespace Anabatic {
if (current->isAnalog()) {
_initiateUpdateIntervals( current );
} else {
current->incDegree();
current = current->getPredecessor();
isfirst = false;
}
@ -2023,12 +2034,20 @@ namespace Anabatic {
//cerr << "state: " << state << endl;
for ( Vertex* startVertex : _sources ) {
if (not startVertex->getFrom()) continue;
cdebug_log(112,0) << "@ " << startVertex << endl;
if (not startVertex->getFrom()) {
cdebug_log(112,0) << "> skip: no getFrom()." << endl;
continue;
}
if ( not startVertex->hasGContact(_net)
and not startVertex->getRpCount()
and (startVertex->getDegree() < 3)
and not startVertex->isAxisTarget() ) continue;
and not startVertex->isAxisTarget() ) {
cdebug_log(112,0) << "> skip: not a good starting point." << endl;
continue;
}
Vertex* source = startVertex;
while ( source ) {
@ -2048,7 +2067,7 @@ namespace Anabatic {
cdebug_log(112,0) << "| " << target << endl;
if (target->getConnexId() < 0) {
cdebug_log(112,0) << "> " << "break (abort: false start)." << endl;
cdebug_log(112,0) << "> break (abort: false start)." << endl;
break;
}
@ -2080,15 +2099,10 @@ namespace Anabatic {
cdebug_log(112,0) << "| " << target << endl;
}
Contact* sourceContact = source->getGContact( _net );
Contact* targetContact = target->hasGContact( _net );
Contact* sourceContact = source->breakGoThrough( _net );
Contact* targetContact = target->breakGoThrough( _net );
Segment* segment = NULL;
if (not targetContact) {
if (target->getFrom()) targetContact = target->getGContact( _net );
else targetContact = target->breakGoThrough( _net );
}
cdebug_log(112,0) << "> aligneds.front():" << aligneds.front()
<< " isHorizontal():" << aligneds.front()->isHorizontal() << endl;

View File

@ -17,6 +17,7 @@
#include <iostream>
#include "hurricane/Error.h"
#include "hurricane/Segment.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "anabatic/Edge.h"
@ -53,6 +54,7 @@ namespace Anabatic {
using std::cerr;
using std::endl;
using Hurricane::Error;
using Hurricane::RoutingPad;
Name Edge::_extensionName = "Anabatic::Edge";
@ -233,19 +235,50 @@ namespace Anabatic {
cdebug_log(112,0) << "| Tbb " << _target->getBoundingBox() << endl;
cdebug_log(112,0) << "| " << segment << endl;
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
if (Session::getRoutingGauge()->isTwoMetals()) {
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
if ( (_source->isStdCellRow() and _source->getBoundingBox().contains(contact->getCenter()))
or (_target->isStdCellRow() and _target->getBoundingBox().contains(contact->getCenter())) )
return true;
}
} else {
// This part is not used (yet). We don't call isEnding() when running
// in over-the-cell mode.
Contact* contact = dynamic_cast<Contact*>( segment->getSource() );
cdebug_log(112,0) << "| source" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
contact = dynamic_cast<Contact*>( segment->getTarget() );
cdebug_log(112,0) << "| target" << contact << endl;
if (contact) {
for ( Hook* hook : contact->getBodyHook()->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
if ( _source->getBoundingBox().contains(contact->getCenter())
or _target->getBoundingBox().contains(contact->getCenter()) )
return true;
break;
}
}
}
}
return false;
}
@ -328,8 +361,8 @@ namespace Anabatic {
sort( _segments.begin(), _segments.end(), SortSegmentByLength() );
for ( size_t i=0 ; i<_segments.size() ; ) {
if (Session::getRoutingGauge()->isTwoMetals()) {
if (Session::getRoutingGauge()->isTwoMetals()) {
for ( size_t i=0 ; i<_segments.size() ; ) {
if (not isEnding(_segments[i])) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalRouted()) ++netCount;
@ -337,16 +370,26 @@ namespace Anabatic {
continue;
}
++i;
} else {
if (_segments[i]->getLength() >= globalThreshold) {
NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[i], Flags::Propagate );
} else {
++i;
}
}
} else {
size_t truncate = (size_t)( (getCapacity()*2) / 3 );
while ( _segments.size() > truncate ) {
NetData* netData = anabatic->getNetData( _segments[truncate]->getNet() );
if (netData->isGlobalRouted()) ++netCount;
anabatic->ripup( _segments[truncate], Flags::Propagate );
}
// for ( size_t i=0 ; i<_segments.size() ; ) {
// if (_segments[i]->getLength() >= globalThreshold) {
// NetData* netData = anabatic->getNetData( _segments[i]->getNet() );
// if (netData->isGlobalRouted()) ++netCount;
// anabatic->ripup( _segments[i], Flags::Propagate );
// } else {
// ++i;
// }
// }
}
return netCount;
}

View File

@ -475,6 +475,9 @@ namespace Anabatic {
Contact* GCell::breakGoThrough ( Net* net )
{
Contact* gcontact = hasGContact( net );
if (gcontact) return gcontact;
for ( Edge* edge : _eastEdges ) {
for ( Segment* segment : edge->getSegments() ) {
if (segment->getNet() == net)
@ -489,7 +492,7 @@ namespace Anabatic {
}
}
return NULL;
return getGContact( net );
}

View File

@ -381,8 +381,9 @@ namespace Anabatic {
inline void AnabaticEngine::removeOv ( Edge* edge )
{
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge )
if (*iedge == edge) { _ovEdges.erase(iedge); break; }
for ( auto iedge = _ovEdges.begin() ; iedge != _ovEdges.end() ; ++iedge ) {
if (*iedge == edge) { _ovEdges.erase(iedge); return; }
}
}

View File

@ -120,6 +120,8 @@ namespace Anabatic {
float getEdgeCostH () const;
float getEdgeCostK () const;
float getEdgeHInc () const;
float getEdgeHScaling () const;
int getGlobalIterations () const;
DbU::Unit isOnRoutingGrid ( RoutingPad* ) const;
bool selectRpComponent ( RoutingPad* ) const;
virtual void print ( Cell* ) const;
@ -148,6 +150,8 @@ namespace Anabatic {
float _edgeCostH;
float _edgeCostK;
float _edgeHInc;
float _edgeHScaling;
int _globalIterations;
private:
Configuration& operator= ( const Configuration& ) = delete;
void _setTopRoutingLayer ( Name name );

View File

@ -27,6 +27,8 @@ parametersTable = \
, ("anabatic.edgeWidth" ,TypeInt ,4 )
, ("anabatic.edgeCostH" ,TypeDouble ,9.0 )
, ("anabatic.edgeCostK" ,TypeDouble ,-10.0 )
, ("anabatic.edgeHScaling" ,TypeDouble ,1.0 )
, ("anabatic.globalIterations" ,TypeInt ,10 , { 'min':1, 'max':100 } )
, ("anabatic.gcell.displayMode" ,TypeEnumerate ,1
, { 'values':( ("Boundary" , 1)
, ("Density" , 2) ) }

View File

@ -31,6 +31,8 @@ parametersTable = \
, ("anabatic.edgeWidth" ,TypeInt ,4 )
, ("anabatic.edgeCostH" ,TypeDouble ,9.0 )
, ("anabatic.edgeCostK" ,TypeDouble ,-10.0 )
, ("anabatic.edgeHScaling" ,TypeDouble ,1.0 )
, ("anabatic.globalIterations" ,TypeInt ,10 , { 'min':1, 'max':100 } )
, ("anabatic.gcell.displayMode" ,TypeEnumerate ,1
, { 'values':( ("Boundary" , 1)
, ("Density" , 2) ) }

View File

@ -27,6 +27,8 @@ parametersTable = \
, ("anabatic.edgeWidth" ,TypeInt ,4 )
, ("anabatic.edgeCostH" ,TypeDouble ,9.0 )
, ("anabatic.edgeCostK" ,TypeDouble ,-10.0 )
, ("anabatic.edgeHScaling" ,TypeDouble ,1.0 )
, ("anabatic.globalIterations" ,TypeInt ,10 , { 'min':1, 'max':100 } )
, ("anabatic.gcell.displayMode" ,TypeEnumerate ,1
, { 'values':( ("Boundary" , 1)
, ("Density" , 2) ) }

View File

@ -21,6 +21,8 @@ parametersTable = \
, ("kite.localRipupLimit" ,TypeInt ,9 , { 'min':1 } )
, ("kite.globalRipupLimit" ,TypeInt ,5 , { 'min':1 } )
, ("kite.longGlobalRipupLimit" ,TypeInt ,5 , { 'min':1 } )
, ("anabatic.edgeHScaling" ,TypeDouble ,1.0 )
, ("anabatic.globalIterations" ,TypeInt ,10 , { 'min':1, 'max':100 } )
)

View File

@ -21,6 +21,8 @@ parametersTable = \
, ("kite.localRipupLimit" ,TypeInt ,9 , { 'min':1 } )
, ("kite.globalRipupLimit" ,TypeInt ,5 , { 'min':1 } )
, ("kite.longGlobalRipupLimit" ,TypeInt ,5 , { 'min':1 } )
, ("anabatic.edgeHScaling" ,TypeDouble ,1.0 )
, ("anabatic.globalIterations" ,TypeInt ,10 , { 'min':1, 'max':100 } )
)

View File

@ -41,7 +41,7 @@ namespace {
class DigitalDistance {
public:
inline DigitalDistance ( float h, float k );
inline DigitalDistance ( float h, float k, float hScaling );
inline void setNet ( Net* );
DbU::Unit operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const;
private:
@ -49,11 +49,12 @@ namespace {
// "KNIK, routeur global pour la plateforme Coriolis", p. 52.
float _h;
float _k;
float _hScaling;
Net* _net;
};
inline DigitalDistance::DigitalDistance ( float h, float k ) : _h(h), _k(k), _net(NULL) { }
inline DigitalDistance::DigitalDistance ( float h, float k, float hScaling ) : _h(h), _k(k), _hScaling(hScaling), _net(NULL) { }
inline void DigitalDistance::setNet ( Net* net ) { _net = net; }
@ -92,10 +93,10 @@ namespace {
or (source->getGCell()->isStdCellRow() and target->getGCell()->isChannelRow()) )
edgeDistance *= 10.0;
float hvDistort = (edge->isHorizontal()) ? 1.0 : 1.0 ;
float distance = (float)source->getDistance()
+ (congestionCost + viaCost) * edgeDistance * hvDistort
+ edge->getHistoricCost();
float hvScaling = (edge->isHorizontal()) ? _hScaling : 1.0 ;
float distance
= (float)source->getDistance()
+ (congestionCost + viaCost + edge->getHistoricCost()) * edgeDistance * hvScaling;
// Edge* sourceFrom = source->getFrom();
// if (sourceFrom) {
@ -198,13 +199,15 @@ namespace Katana {
startMeasures();
cmess1 << " o Running global routing." << endl;
float edgeHInc = getConfiguration()->getEdgeHInc();
float edgeHInc = getConfiguration()->getEdgeHInc();
size_t globalIterations = getConfiguration()->getGlobalIterations();;
openSession();
Dijkstra* dijkstra = new Dijkstra ( this );
DigitalDistance* distance =
dijkstra->setDistance( DigitalDistance( getConfiguration()->getEdgeCostH()
, getConfiguration()->getEdgeCostK() ));
, getConfiguration()->getEdgeCostK()
, getConfiguration()->getEdgeHScaling() ));
const vector<Edge*>& ovEdges = getOvEdges();
if (isChannelMode())
@ -234,13 +237,13 @@ namespace Katana {
// openSession();
netCount = 0;
if (iteration < 10 - 1) {
if (iteration < globalIterations - 1) {
size_t iEdge = 0;
while ( iEdge < ovEdges.size() ) {
Edge* edge = ovEdges[iEdge];
netCount += edge->ripup();
if (ovEdges.empty()) break;
if (iEdge >= ovEdges.size()) break;
if (ovEdges[iEdge] == edge) {
cerr << Error( "AnabaticEngine::globalRoute(): Unable to ripup enough segments of edge:\n"
" %s"
@ -260,7 +263,7 @@ namespace Katana {
resumeMeasures();
++iteration;
} while ( (netCount > 0) and (iteration < 10) );
} while ( (netCount > 0) and (iteration < globalIterations) );
stopMeasures();
printMeasures( "Dijkstra" );