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:
Jean-Paul Chaput 2015-08-18 15:42:28 +02:00
parent ed557d9027
commit 9db97608cb
15 changed files with 94 additions and 19 deletions

View File

@ -91,14 +91,14 @@ namespace Etesian {
void Configuration::print ( Cell* cell ) const
{
cout << " o Configuration of ToolEngine<Etesian> for Cell <" << cell->getName() << ">" << endl;
cout << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
cout << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
cout << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl;
cout << Dots::asBool (" - Routing driven",_routingDriven) << endl;
cout << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
cmess1 << " o Configuration of ToolEngine<Etesian> for Cell <" << cell->getName() << ">" << endl;
cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl;
cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl;
cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
cmess1 << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl;
cmess1 << Dots::asBool (" - Routing driven",_routingDriven) << endl;
cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
}

View File

@ -404,6 +404,7 @@ namespace Etesian {
_flatDesign = true;
Dots dots ( cmess2, " ", 80, 1000 );
if (not cmess2.enabled()) dots.disable();
cmess1 << " o Erasing previous placement of <" << getCell()->getName() << ">" << endl;
@ -450,6 +451,8 @@ namespace Etesian {
AllianceFramework* af = AllianceFramework::get();
DbU::Unit pitch = getPitch();
if (not cmess2.enabled()) dots.disable();
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
//getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten );
getCell()->flattenNets( Cell::Flags::NoClockFlatten );

View File

@ -380,6 +380,12 @@
//! will not lead to an empty interval, in that case, do nothing and
//! 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
*

View File

@ -500,6 +500,23 @@ namespace Katabatic {
{ 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
{ return _gcell->getBoundingBox (); }

View File

@ -294,6 +294,8 @@ namespace Katabatic {
ltrace(110) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if (maxDepth - minDepth > 3) {
showTopologyError( "Sheared HTee, layer delta exceed 3." );
setFlags( CntBadTopology );

View File

@ -239,6 +239,7 @@ namespace Katabatic {
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
size_t delta = abssub ( depthH1, depthV1 );
unsetFlags( CntWeakTerminal );
if (delta > 3) {
showTopologyError( "Sheared Turn, layer delta exceed 3." );
setFlags( CntBadTopology );

View File

@ -262,6 +262,8 @@ namespace Katabatic {
ltrace(110) << "maxDepth:" << maxDepth << endl;
ltrace(110) << "delta:" << delta << endl;
unsetFlags( CntWeakTerminal );
if ( maxDepth - minDepth > 3 ) {
showTopologyError( "Sheared VTee, layer delta exceed 3." );
setFlags( CntBadTopology );

View File

@ -747,11 +747,19 @@ namespace Katabatic {
if (isSourceTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
} else if (isTargetTerminal()) {
unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell)
dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );

View File

@ -873,9 +873,13 @@ namespace Katabatic {
if (source->isTerminal()) {
unsetFlags( SegWeakTerminal );
setFlags ( SegSourceTerminal );
if (not target->isTerminal())
target->setFlags( CntWeakTerminal );
} else if (target->isTerminal()) {
unsetFlags( SegWeakTerminal );
setFlags ( SegTargetTerminal );
if (not source->isTerminal())
source->setFlags( CntWeakTerminal );
} else {
unsigned int terminalFlag = 0;
switch ( _getFlags() & SegWeakTerminal ) {

View File

@ -668,11 +668,19 @@ namespace Katabatic {
if (isSourceTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );
autoTarget->unsetFlags( CntWeakTerminal );
dlContact1->setFlags ( CntWeakTerminal );
if (autoTarget->getGCell() == doglegGCell)
dlContact1->migrateConstraintBox( autoTarget );
} else if (isTargetTerminal()) {
unsetFlags( SegTargetTerminal );
setFlags( SegWeakTerminal1 );
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegTargetTerminal );
autoSource->unsetFlags( CntWeakTerminal );
dlContact2->setFlags ( CntWeakTerminal );
if (autoSource->getGCell() == doglegGCell)
dlContact2->migrateConstraintBox( autoSource );
} else if (isWeakTerminal()) {
segment1->setFlags( SegWeakTerminal1 );
segment2->setFlags( SegWeakTerminal1 );

View File

@ -66,6 +66,7 @@ namespace Katabatic {
, CntInCreationStage = 0x00000080
, CntBadTopology = 0x00000100
, CntIgnoreAnchor = 0x00000200
, CntWeakTerminal = 0x00000400
};
class AutoContact {
@ -161,6 +162,7 @@ namespace Katabatic {
, DbU::Unit constraintMax
, unsigned int flags=KbWarnOnError );
void restoreNativeConstraintBox ();
void migrateConstraintBox ( AutoContact* other );
void destroy ();
// Inspector Management.
Record* _getRecord () const;

View File

@ -226,8 +226,8 @@ namespace {
ltrace(150) << "protectCagedTerminals() " << track << endl;
ltracein(150);
DbU::Unit lastMovedUp = track->getMin();
unsigned int moveUpCount = 0;
DbU::Unit lastMovedUp = track->getMin();
unsigned int moveUpCount = 0;
Configuration* configuration = Session::getConfiguration();
const Layer* metal2 = configuration->getRoutingLayer( 1 );
@ -258,9 +258,22 @@ namespace {
continue;
}
Katabatic::AutoContact* support = segment->base()->getAutoSource();
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() );
Katabatic::AutoContact* support = NULL;
Katabatic::AutoContact* turn = NULL;
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()) {
cparanoid << "[INFO] Cannot protect caged terminal because top layer (metal3) is obstructed." << endl;
@ -270,7 +283,7 @@ namespace {
if (segment->getSourceU() - lastMovedUp < ppitch*4) {
++moveUpCount;
if (moveUpCount % 2 == 0) {
moveUpCaged( segment );
//moveUpCaged( segment );
}
} else {
moveUpCount = 0;

View File

@ -170,12 +170,12 @@ void Graph::_postCreate()
}
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
cerr << Warning( "Knik::Graph: Design has only one column, H edge capacity is zero." ) << endl;
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
cerr << Warning( "Knik::Graph: Design has only one row, V edge capacity is zero." ) << endl;

View File

@ -30,7 +30,8 @@ namespace Utilities {
CR();
else
_flags &= ~FirstDot;
_ostream << _indent;
if (enabled())
_ostream << _indent;
}
_flush( '.' );

View File

@ -26,7 +26,7 @@ namespace Utilities {
class Dots {
public:
enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02 };
enum Flag { NoFlags=0x00, FirstDot=0x01, Reset=0x02, Disabled=0x04 };
public:
inline Dots ( std::ostream&
, const std::string& indent
@ -38,6 +38,9 @@ namespace Utilities {
inline void CR ();
void dot ();
void finish ( unsigned int flags );
inline bool enabled ();
inline void enable ();
inline void disable ();
private:
inline void _flush ( char );
private:
@ -61,9 +64,14 @@ namespace Utilities {
inline void Dots::setWidth ( unsigned int w ) { _width=w; }
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 )
{
if (not enabled()) return;
_ostream << c;
_ostream.flush();
}
@ -75,7 +83,7 @@ namespace Utilities {
inline void Dots::reset ( unsigned int flags )
{
_flags = flags;
_flags = flags | ((not enabled()) ? Disabled : NoFlags);
_count = 0;
}