More clever way of taking into account constraints on caged terminals.
* Change: In vlsispad, in Dots, add an enable/disable flag because when printing into a cmess, it is only the base class ostream which is took into account as none of it's methods are virtuals (silly me). * Bug: In Etesian, print into cmess instead of cout and make use of the Dots enabling feature. * New: In Katabatic, added AutoContact::migrateConstraintBox() to transfert constraint from one contact to another. New flag for AutoContact, CntWeakTerminal for AutoContact which are at the other of a segment directly connected to a terminal. They may hold special constraints in case of caged terminals (computed in Kite). In AutoHorizontal & AutoVertical, in ::_makeDogleg(), transfert flags and constraints when breaking a segment directly connected to a terminal. * New: In Kite, in protectCagedTerminals(), uses cross constraint on the AutoContact opposite to the ContactTerminal (CntWeakTerminal) instead of moving up one terminal over two consecutives. This is simpler without degrading the routing quality.
This commit is contained in:
parent
ed557d9027
commit
9db97608cb
|
@ -91,14 +91,14 @@ namespace Etesian {
|
||||||
|
|
||||||
void Configuration::print ( Cell* cell ) const
|
void Configuration::print ( Cell* cell ) const
|
||||||
{
|
{
|
||||||
cout << " o Configuration of ToolEngine<Etesian> for Cell <" << cell->getName() << ">" << endl;
|
cmess1 << " o Configuration of ToolEngine<Etesian> for Cell <" << cell->getName() << ">" << endl;
|
||||||
cout << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
|
cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
|
||||||
cout << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
|
cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
|
||||||
cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
|
cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
|
||||||
cout << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl;
|
cmess1 << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl;
|
||||||
cout << Dots::asBool (" - Routing driven",_routingDriven) << endl;
|
cmess1 << Dots::asBool (" - Routing driven",_routingDriven) << endl;
|
||||||
cout << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
|
cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
|
||||||
cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
|
cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -404,6 +404,7 @@ namespace Etesian {
|
||||||
_flatDesign = true;
|
_flatDesign = true;
|
||||||
|
|
||||||
Dots dots ( cmess2, " ", 80, 1000 );
|
Dots dots ( cmess2, " ", 80, 1000 );
|
||||||
|
if (not cmess2.enabled()) dots.disable();
|
||||||
|
|
||||||
cmess1 << " o Erasing previous placement of <" << getCell()->getName() << ">" << endl;
|
cmess1 << " o Erasing previous placement of <" << getCell()->getName() << ">" << endl;
|
||||||
|
|
||||||
|
@ -450,6 +451,8 @@ namespace Etesian {
|
||||||
AllianceFramework* af = AllianceFramework::get();
|
AllianceFramework* af = AllianceFramework::get();
|
||||||
DbU::Unit pitch = getPitch();
|
DbU::Unit pitch = getPitch();
|
||||||
|
|
||||||
|
if (not cmess2.enabled()) dots.disable();
|
||||||
|
|
||||||
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
|
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
|
||||||
//getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten );
|
//getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten );
|
||||||
getCell()->flattenNets( Cell::Flags::NoClockFlatten );
|
getCell()->flattenNets( Cell::Flags::NoClockFlatten );
|
||||||
|
|
|
@ -380,6 +380,12 @@
|
||||||
//! will not lead to an empty interval, in that case, do nothing and
|
//! will not lead to an empty interval, in that case, do nothing and
|
||||||
//! return \false.
|
//! return \false.
|
||||||
|
|
||||||
|
//! \function void AutoContact::migrateConstraintBox ( AutoContact* other );
|
||||||
|
//! Transfer the user constraint box from \c other to the current
|
||||||
|
//! object \c this. The constraints of \c other are restored to their
|
||||||
|
//! native values. The two contacts must belong to the same GCell for
|
||||||
|
//! this method to take effect.
|
||||||
|
|
||||||
|
|
||||||
/*! \class LocatorHelper
|
/*! \class LocatorHelper
|
||||||
*
|
*
|
||||||
|
|
|
@ -500,6 +500,23 @@ namespace Katabatic {
|
||||||
{ return box = box.getIntersection ( getConstraintBox() ); }
|
{ return box = box.getIntersection ( getConstraintBox() ); }
|
||||||
|
|
||||||
|
|
||||||
|
void AutoContact::migrateConstraintBox ( AutoContact* other )
|
||||||
|
{
|
||||||
|
if (_gcell != other->_gcell) {
|
||||||
|
cerr << Error( "AutoContact::migrateConstraintBox(): AutoContacts do not belongs to the same GCell:\n"
|
||||||
|
" from: %s\n"
|
||||||
|
" to: %s"
|
||||||
|
, getString(other).c_str()
|
||||||
|
, getString(this ).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setConstraintBox( other->getConstraintBox() );
|
||||||
|
other->restoreNativeConstraintBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Box AutoContact::getBoundingBox () const
|
Box AutoContact::getBoundingBox () const
|
||||||
{ return _gcell->getBoundingBox (); }
|
{ return _gcell->getBoundingBox (); }
|
||||||
|
|
||||||
|
|
|
@ -294,6 +294,8 @@ namespace Katabatic {
|
||||||
|
|
||||||
ltrace(110) << "delta:" << delta << endl;
|
ltrace(110) << "delta:" << delta << endl;
|
||||||
|
|
||||||
|
unsetFlags( CntWeakTerminal );
|
||||||
|
|
||||||
if (maxDepth - minDepth > 3) {
|
if (maxDepth - minDepth > 3) {
|
||||||
showTopologyError( "Sheared HTee, layer delta exceed 3." );
|
showTopologyError( "Sheared HTee, layer delta exceed 3." );
|
||||||
setFlags( CntBadTopology );
|
setFlags( CntBadTopology );
|
||||||
|
|
|
@ -239,6 +239,7 @@ namespace Katabatic {
|
||||||
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
|
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
|
||||||
size_t delta = abssub ( depthH1, depthV1 );
|
size_t delta = abssub ( depthH1, depthV1 );
|
||||||
|
|
||||||
|
unsetFlags( CntWeakTerminal );
|
||||||
if (delta > 3) {
|
if (delta > 3) {
|
||||||
showTopologyError( "Sheared Turn, layer delta exceed 3." );
|
showTopologyError( "Sheared Turn, layer delta exceed 3." );
|
||||||
setFlags( CntBadTopology );
|
setFlags( CntBadTopology );
|
||||||
|
|
|
@ -262,6 +262,8 @@ namespace Katabatic {
|
||||||
ltrace(110) << "maxDepth:" << maxDepth << endl;
|
ltrace(110) << "maxDepth:" << maxDepth << endl;
|
||||||
ltrace(110) << "delta:" << delta << endl;
|
ltrace(110) << "delta:" << delta << endl;
|
||||||
|
|
||||||
|
unsetFlags( CntWeakTerminal );
|
||||||
|
|
||||||
if ( maxDepth - minDepth > 3 ) {
|
if ( maxDepth - minDepth > 3 ) {
|
||||||
showTopologyError( "Sheared VTee, layer delta exceed 3." );
|
showTopologyError( "Sheared VTee, layer delta exceed 3." );
|
||||||
setFlags( CntBadTopology );
|
setFlags( CntBadTopology );
|
||||||
|
|
|
@ -747,11 +747,19 @@ namespace Katabatic {
|
||||||
if (isSourceTerminal()) {
|
if (isSourceTerminal()) {
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegWeakTerminal1 );
|
segment2->setFlags( SegWeakTerminal1 );
|
||||||
|
autoTarget->unsetFlags( CntWeakTerminal );
|
||||||
|
dlContact1->setFlags ( CntWeakTerminal );
|
||||||
|
if (autoTarget->getGCell() == doglegGCell)
|
||||||
|
dlContact1->migrateConstraintBox( autoTarget );
|
||||||
} else if (isTargetTerminal()) {
|
} else if (isTargetTerminal()) {
|
||||||
unsetFlags( SegTargetTerminal );
|
unsetFlags( SegTargetTerminal );
|
||||||
setFlags( SegWeakTerminal1 );
|
setFlags( SegWeakTerminal1 );
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegTargetTerminal );
|
segment2->setFlags( SegTargetTerminal );
|
||||||
|
autoSource->unsetFlags( CntWeakTerminal );
|
||||||
|
dlContact2->setFlags ( CntWeakTerminal );
|
||||||
|
if (autoSource->getGCell() == doglegGCell)
|
||||||
|
dlContact2->migrateConstraintBox( autoSource );
|
||||||
} else if (isWeakTerminal()) {
|
} else if (isWeakTerminal()) {
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegWeakTerminal1 );
|
segment2->setFlags( SegWeakTerminal1 );
|
||||||
|
|
|
@ -873,9 +873,13 @@ namespace Katabatic {
|
||||||
if (source->isTerminal()) {
|
if (source->isTerminal()) {
|
||||||
unsetFlags( SegWeakTerminal );
|
unsetFlags( SegWeakTerminal );
|
||||||
setFlags ( SegSourceTerminal );
|
setFlags ( SegSourceTerminal );
|
||||||
|
if (not target->isTerminal())
|
||||||
|
target->setFlags( CntWeakTerminal );
|
||||||
} else if (target->isTerminal()) {
|
} else if (target->isTerminal()) {
|
||||||
unsetFlags( SegWeakTerminal );
|
unsetFlags( SegWeakTerminal );
|
||||||
setFlags ( SegTargetTerminal );
|
setFlags ( SegTargetTerminal );
|
||||||
|
if (not source->isTerminal())
|
||||||
|
source->setFlags( CntWeakTerminal );
|
||||||
} else {
|
} else {
|
||||||
unsigned int terminalFlag = 0;
|
unsigned int terminalFlag = 0;
|
||||||
switch ( _getFlags() & SegWeakTerminal ) {
|
switch ( _getFlags() & SegWeakTerminal ) {
|
||||||
|
|
|
@ -668,11 +668,19 @@ namespace Katabatic {
|
||||||
if (isSourceTerminal()) {
|
if (isSourceTerminal()) {
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegWeakTerminal1 );
|
segment2->setFlags( SegWeakTerminal1 );
|
||||||
|
autoTarget->unsetFlags( CntWeakTerminal );
|
||||||
|
dlContact1->setFlags ( CntWeakTerminal );
|
||||||
|
if (autoTarget->getGCell() == doglegGCell)
|
||||||
|
dlContact1->migrateConstraintBox( autoTarget );
|
||||||
} else if (isTargetTerminal()) {
|
} else if (isTargetTerminal()) {
|
||||||
unsetFlags( SegTargetTerminal );
|
unsetFlags( SegTargetTerminal );
|
||||||
setFlags( SegWeakTerminal1 );
|
setFlags( SegWeakTerminal1 );
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegTargetTerminal );
|
segment2->setFlags( SegTargetTerminal );
|
||||||
|
autoSource->unsetFlags( CntWeakTerminal );
|
||||||
|
dlContact2->setFlags ( CntWeakTerminal );
|
||||||
|
if (autoSource->getGCell() == doglegGCell)
|
||||||
|
dlContact2->migrateConstraintBox( autoSource );
|
||||||
} else if (isWeakTerminal()) {
|
} else if (isWeakTerminal()) {
|
||||||
segment1->setFlags( SegWeakTerminal1 );
|
segment1->setFlags( SegWeakTerminal1 );
|
||||||
segment2->setFlags( SegWeakTerminal1 );
|
segment2->setFlags( SegWeakTerminal1 );
|
||||||
|
|
|
@ -66,6 +66,7 @@ namespace Katabatic {
|
||||||
, CntInCreationStage = 0x00000080
|
, CntInCreationStage = 0x00000080
|
||||||
, CntBadTopology = 0x00000100
|
, CntBadTopology = 0x00000100
|
||||||
, CntIgnoreAnchor = 0x00000200
|
, CntIgnoreAnchor = 0x00000200
|
||||||
|
, CntWeakTerminal = 0x00000400
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoContact {
|
class AutoContact {
|
||||||
|
@ -161,6 +162,7 @@ namespace Katabatic {
|
||||||
, DbU::Unit constraintMax
|
, DbU::Unit constraintMax
|
||||||
, unsigned int flags=KbWarnOnError );
|
, unsigned int flags=KbWarnOnError );
|
||||||
void restoreNativeConstraintBox ();
|
void restoreNativeConstraintBox ();
|
||||||
|
void migrateConstraintBox ( AutoContact* other );
|
||||||
void destroy ();
|
void destroy ();
|
||||||
// Inspector Management.
|
// Inspector Management.
|
||||||
Record* _getRecord () const;
|
Record* _getRecord () const;
|
||||||
|
|
|
@ -226,8 +226,8 @@ namespace {
|
||||||
ltrace(150) << "protectCagedTerminals() " << track << endl;
|
ltrace(150) << "protectCagedTerminals() " << track << endl;
|
||||||
ltracein(150);
|
ltracein(150);
|
||||||
|
|
||||||
DbU::Unit lastMovedUp = track->getMin();
|
DbU::Unit lastMovedUp = track->getMin();
|
||||||
unsigned int moveUpCount = 0;
|
unsigned int moveUpCount = 0;
|
||||||
|
|
||||||
Configuration* configuration = Session::getConfiguration();
|
Configuration* configuration = Session::getConfiguration();
|
||||||
const Layer* metal2 = configuration->getRoutingLayer( 1 );
|
const Layer* metal2 = configuration->getRoutingLayer( 1 );
|
||||||
|
@ -258,9 +258,22 @@ namespace {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Katabatic::AutoContact* support = segment->base()->getAutoSource();
|
Katabatic::AutoContact* support = NULL;
|
||||||
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
|
Katabatic::AutoContact* turn = NULL;
|
||||||
Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() );
|
if (segment->base()->isSourceTerminal()) {
|
||||||
|
support = segment->base()->getAutoSource();
|
||||||
|
turn = segment->base()->getAutoTarget();
|
||||||
|
} else {
|
||||||
|
support = segment->base()->getAutoTarget();
|
||||||
|
turn = segment->base()->getAutoSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
|
||||||
|
Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() );
|
||||||
|
|
||||||
|
turn->restrictConstraintBox( freeInterval.getVMin()
|
||||||
|
, freeInterval.getVMax()
|
||||||
|
, KbVertical );
|
||||||
|
|
||||||
if (metal3track->getFreeInterval(segment->getAxis(),segment->getNet()).isEmpty()) {
|
if (metal3track->getFreeInterval(segment->getAxis(),segment->getNet()).isEmpty()) {
|
||||||
cparanoid << "[INFO] Cannot protect caged terminal because top layer (metal3) is obstructed." << endl;
|
cparanoid << "[INFO] Cannot protect caged terminal because top layer (metal3) is obstructed." << endl;
|
||||||
|
@ -270,7 +283,7 @@ namespace {
|
||||||
if (segment->getSourceU() - lastMovedUp < ppitch*4) {
|
if (segment->getSourceU() - lastMovedUp < ppitch*4) {
|
||||||
++moveUpCount;
|
++moveUpCount;
|
||||||
if (moveUpCount % 2 == 0) {
|
if (moveUpCount % 2 == 0) {
|
||||||
moveUpCaged( segment );
|
//moveUpCaged( segment );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
moveUpCount = 0;
|
moveUpCount = 0;
|
||||||
|
|
|
@ -170,12 +170,12 @@ void Graph::_postCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lowerLeftVertex->getHEdgeOut())
|
if (_lowerLeftVertex->getHEdgeOut())
|
||||||
cout << Dots::asUInt (" - Global router H edges capacity" ,_lowerLeftVertex->getHEdgeOut()->getCapacity()) << endl;
|
cmess1 << Dots::asUInt (" - Global router H edges capacity" ,_lowerLeftVertex->getHEdgeOut()->getCapacity()) << endl;
|
||||||
else
|
else
|
||||||
cerr << Warning( "Knik::Graph: Design has only one column, H edge capacity is zero." ) << endl;
|
cerr << Warning( "Knik::Graph: Design has only one column, H edge capacity is zero." ) << endl;
|
||||||
|
|
||||||
if (_lowerLeftVertex->getVEdgeOut())
|
if (_lowerLeftVertex->getVEdgeOut())
|
||||||
cout << Dots::asUInt (" - Global router V edges capacity" ,_lowerLeftVertex->getVEdgeOut()->getCapacity()) << endl;
|
cmess1 << Dots::asUInt (" - Global router V edges capacity" ,_lowerLeftVertex->getVEdgeOut()->getCapacity()) << endl;
|
||||||
else
|
else
|
||||||
cerr << Warning( "Knik::Graph: Design has only one row, V edge capacity is zero." ) << endl;
|
cerr << Warning( "Knik::Graph: Design has only one row, V edge capacity is zero." ) << endl;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace Utilities {
|
||||||
CR();
|
CR();
|
||||||
else
|
else
|
||||||
_flags &= ~FirstDot;
|
_flags &= ~FirstDot;
|
||||||
_ostream << _indent;
|
if (enabled())
|
||||||
|
_ostream << _indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
_flush( '.' );
|
_flush( '.' );
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Utilities {
|
||||||
|
|
||||||
class Dots {
|
class Dots {
|
||||||
public:
|
public:
|
||||||
enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02 };
|
enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02, Disabled=0x04 };
|
||||||
public:
|
public:
|
||||||
inline Dots ( std::ostream&
|
inline Dots ( std::ostream&
|
||||||
, const std::string& indent
|
, const std::string& indent
|
||||||
|
@ -38,6 +38,9 @@ namespace Utilities {
|
||||||
inline void CR ();
|
inline void CR ();
|
||||||
void dot ();
|
void dot ();
|
||||||
void finish ( unsigned int flags );
|
void finish ( unsigned int flags );
|
||||||
|
inline bool enabled ();
|
||||||
|
inline void enable ();
|
||||||
|
inline void disable ();
|
||||||
private:
|
private:
|
||||||
inline void _flush ( char );
|
inline void _flush ( char );
|
||||||
private:
|
private:
|
||||||
|
@ -61,9 +64,14 @@ namespace Utilities {
|
||||||
|
|
||||||
inline void Dots::setWidth ( unsigned int w ) { _width=w; }
|
inline void Dots::setWidth ( unsigned int w ) { _width=w; }
|
||||||
inline void Dots::setDivider ( unsigned int d ) { _divider=d; }
|
inline void Dots::setDivider ( unsigned int d ) { _divider=d; }
|
||||||
|
inline bool Dots::enabled () { return not (_flags & Disabled); }
|
||||||
|
inline void Dots::enable () { _flags &= ~Disabled; }
|
||||||
|
inline void Dots::disable () { _flags |= Disabled; }
|
||||||
|
|
||||||
inline void Dots::_flush ( char c )
|
inline void Dots::_flush ( char c )
|
||||||
{
|
{
|
||||||
|
if (not enabled()) return;
|
||||||
|
|
||||||
_ostream << c;
|
_ostream << c;
|
||||||
_ostream.flush();
|
_ostream.flush();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +83,7 @@ namespace Utilities {
|
||||||
|
|
||||||
inline void Dots::reset ( unsigned int flags )
|
inline void Dots::reset ( unsigned int flags )
|
||||||
{
|
{
|
||||||
_flags = flags;
|
_flags = flags | ((not enabled()) ? Disabled : NoFlags);
|
||||||
_count = 0;
|
_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue