Rewrite support for minimum area metal wires (stacked VIAs).
We use the segments extensions (dxTarget & dyTarget) to enlarge if needed the segments. This new implementation is completely at Anabatic level and should not be seen (i.e. managed) at Katana level. * Change: In AutoHorizontal & AutoVertical, change the semantic of getSourceU() and getTargetU(). formerly they where the end position of the segment (with extension included), now they gives the position of the anchor contacts, that is the axis of the perpandiculars. * New: AutoSegment::getLength() is still a proxy toward the Segment::getLength() which returns the length of segment with dxSource & dxTarget. We introduce a getAnchoredlength() which returns the length between the centers of the S/T anchors. That is axis to axis. This is this length which is now used througout Anabatic. * New: In AutoSegment::_extentionCaps, add a fourth item to hold the segment minimal length (to respect minimal area given the wire width). * New: In AutoSegment::getExtensionCap(), if the segment has a non-zero S/T extension, returns it instead of the S/T contact extension *if it is greated*. The check of the extension can be disabled by the Flag::NoSegExt flag. * Change: In AutoSegment::isMiddleStack(), security check on the presence of source and targets. More accurate detection of perpandicular in "same layer" with a non-zero length, So the area is OK, even with a short segment. * New: AutoSegment::expandToMinLength(), check if a segment is under the minimal length and expand it if need be by playing with the dxTarget & dxSource. Tag minimal segments with the AutoSegment::SegAtMinArea flag. Also try to keep the segment *inside* it's former (supposedly wider) interval. * New: AutoSegment::unexpandToMinLength(), to be called on a formerly minimal sized segment which as grown up. Reset it's S/T extensions to zero and unset the flag SegAtMinArea. * Change: In AutoHorizontal::updateOrient(), when the extension are non-zero, also swap them if needed, to keep the exact footprint of the segment. * New: In AutoSegment::revalidate(), check that the segment respect the minimal length (area), and expand it if needed. Conversely, if the segment has grown up from a minimal length state, reset it's extensions to zero. * Change: In Anabatic::Session::revalidate(), invalidateds segments are now sorted in such a way that the "middle stack" ones are revalidateds last. Not recall 100% why... * New: In Katana::TrackCost, add a computation of the free interval length we are into (if any). Not used yet, keep it for future use. * Change: In KatanaEngine::finalizeLayout(), remove the call to segments minimum area protection. It is now obsoleted by the new implementation in Anabatic. * Change: In Track::check(), call the minimum size/area checker Track::checkMinArea().
This commit is contained in:
parent
0326d513bd
commit
08d1db5dd6
|
@ -1355,7 +1355,7 @@ namespace Anabatic {
|
|||
set<const Layer*> connectedLayers;
|
||||
|
||||
forEach ( Segment*, segment, net->getSegments() ) {
|
||||
if (segment->getLength()) {
|
||||
if (segment->getAnchoredLength()) {
|
||||
if (net->isExternal()) {
|
||||
NetExternalComponents::setExternal( *segment );
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace Anabatic {
|
|||
size_t depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
|
||||
DbU::Unit length;
|
||||
if (segment->isLocal()) {
|
||||
length = segment->getLength();
|
||||
length = segment->getAnchoredLength();
|
||||
lengths[depth] += length;
|
||||
|
||||
DbU::Unit sideLength = (segment->isHorizontal()) ? hSideLength : vSideLength;
|
||||
|
|
|
@ -47,8 +47,8 @@ namespace Anabatic {
|
|||
Segment* AutoHorizontal::base () { return _horizontal; }
|
||||
Segment* AutoHorizontal::base () const { return _horizontal; }
|
||||
Horizontal* AutoHorizontal::getHorizontal () { return _horizontal; }
|
||||
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSourceX(); }
|
||||
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTargetX(); }
|
||||
DbU::Unit AutoHorizontal::getSourceU () const { return _horizontal->getSource()->getX(); }
|
||||
DbU::Unit AutoHorizontal::getTargetU () const { return _horizontal->getTarget()->getX(); }
|
||||
DbU::Unit AutoHorizontal::getDuSource () const { return _horizontal->getDxSource(); }
|
||||
DbU::Unit AutoHorizontal::getDuTarget () const { return _horizontal->getDxTarget(); }
|
||||
Interval AutoHorizontal::getSpanU () const { return Interval(_horizontal->getSourceX(),_horizontal->getTargetX()); }
|
||||
|
@ -335,11 +335,11 @@ namespace Anabatic {
|
|||
|
||||
cdebug_tabw(149,1);
|
||||
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
|
||||
cdebug_log(149,0) << "test:" << (getLength() < 5*getPitch()) << endl;
|
||||
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
|
||||
cdebug_log(149,0) << "test:" << (getAnchoredLength() < 5*getPitch()) << endl;
|
||||
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
|
||||
|
||||
if (height >= 4*getPitch()) {
|
||||
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 5*getPitch())) {
|
||||
if (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < 5*getPitch())) {
|
||||
cdebug_log(149,0) << "Too short terminal segment to slacken." << endl;
|
||||
cdebug_tabw(149,-1);
|
||||
return false;
|
||||
|
@ -486,9 +486,18 @@ namespace Anabatic {
|
|||
|
||||
void AutoHorizontal::updateOrient ()
|
||||
{
|
||||
if (_horizontal->getTargetX() < _horizontal->getSourceX()) {
|
||||
if (_horizontal->getTarget()->getX() < _horizontal->getSource()->getX()) {
|
||||
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
|
||||
_horizontal->invert();
|
||||
if (isAtMinArea()) {
|
||||
DbU::Unit sourceX = _horizontal->getSourceX();
|
||||
DbU::Unit targetX = _horizontal->getTargetX();
|
||||
_horizontal->invert();
|
||||
setDuSource( sourceX - getSourceU() );
|
||||
setDuTarget( targetX - getTargetU() );
|
||||
} else {
|
||||
_horizontal->invert();
|
||||
}
|
||||
cdebug_log(145,0) << "updateOrient() " << this << " (after S/T swap)" << endl;
|
||||
|
||||
uint64_t spinFlags = _flags & SegDepthSpin;
|
||||
unsetFlags( SegDepthSpin );
|
||||
|
@ -512,8 +521,8 @@ namespace Anabatic {
|
|||
|
||||
void AutoHorizontal::updatePositions ()
|
||||
{
|
||||
_sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
|
||||
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
|
||||
}
|
||||
|
||||
|
||||
|
@ -533,8 +542,8 @@ namespace Anabatic {
|
|||
bool AutoHorizontal::checkPositions () const
|
||||
{
|
||||
bool coherency = true;
|
||||
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
|
||||
DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target);
|
||||
|
||||
if ( _sourcePosition != sourcePosition ) {
|
||||
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl;
|
||||
|
|
|
@ -348,7 +348,7 @@ namespace Anabatic {
|
|||
if ( deltaUnit < 0 ) return true; // Smallest source first.
|
||||
if ( deltaUnit > 0 ) return false;
|
||||
|
||||
deltaUnit = lhs->getLength() - rhs->getLength();
|
||||
deltaUnit = lhs->getAnchoredLength() - rhs->getAnchoredLength();
|
||||
if ( deltaUnit > 0 ) return true; // Longest first.
|
||||
if ( deltaUnit < 0 ) return false;
|
||||
|
||||
|
@ -409,6 +409,22 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::AutoSegment::CompareByRevalidate".
|
||||
|
||||
|
||||
bool AutoSegment::CompareByRevalidate::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
|
||||
{
|
||||
if (lhs->isNonPref() xor rhs->isNonPref() ) return lhs->isNonPref();
|
||||
|
||||
DbU::Unit deltaLength = lhs->getAnchoredLength() - rhs->getAnchoredLength();
|
||||
if (deltaLength > 0) return true; // Longest length first.
|
||||
if (deltaLength < 0) return false;
|
||||
|
||||
return lhs->getId() < rhs->getId(); // Smallest Id first.
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::AutoSegment".
|
||||
|
||||
|
@ -431,6 +447,7 @@ namespace Anabatic {
|
|||
//cerr << "AutoSegment::_initialize()" << endl;
|
||||
|
||||
_initialized = true;
|
||||
DbU::Unit twoGrid = DbU::fromGrid( 2 );
|
||||
for ( size_t depth=0 ; depth<Session::getDepth() ; ++depth ) {
|
||||
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
|
||||
DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 );
|
||||
|
@ -460,6 +477,9 @@ namespace Anabatic {
|
|||
double minimalArea = routingLayer->getMinimalArea();
|
||||
if (minimalArea != 0.0) {
|
||||
*minimalLength = DbU::fromMicrons( minimalArea / DbU::toMicrons( Session::getWireWidth(depth) ) );
|
||||
DbU::Unit modulo = *minimalLength % twoGrid;
|
||||
if (modulo)
|
||||
*minimalLength += twoGrid - modulo;
|
||||
}
|
||||
|
||||
//cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
|
||||
|
@ -684,6 +704,10 @@ namespace Anabatic {
|
|||
incReduceds();
|
||||
}
|
||||
|
||||
Interval oldSpan = Interval( _sourcePosition, _targetPosition );
|
||||
if (not expandToMinLength(oldSpan)) {
|
||||
unexpandToMinLength();
|
||||
}
|
||||
updatePositions();
|
||||
|
||||
unsigned int observerFlags = Revalidate;
|
||||
|
@ -736,25 +760,50 @@ namespace Anabatic {
|
|||
if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth);
|
||||
else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth);
|
||||
else cap = getViaToSameCap (depth);
|
||||
cdebug_log(150,0) << "getExtensionCap(): flags:" << getFlags()
|
||||
cdebug_log(150,0) << "getExtensionCap(): (source) flags:" << getFlags()
|
||||
<< " VIA cap:" << DbU::getValueString(cap)
|
||||
<< " t:" << (getFlags() & SegSourceBottom)
|
||||
<< " b:" << (getFlags() & SegSourceTop)
|
||||
<< endl;
|
||||
if (not (flags & Flags::NoSegExt)) {
|
||||
cdebug_log(150,0) << "duSource=" << DbU::getValueString(getDuSource()) << endl;
|
||||
if (-getDuSource() > cap) {
|
||||
cap = -getDuSource();
|
||||
cdebug_log(150,0) << "-> Custom cap (-duSource):" << DbU::getValueString(cap) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & Flags::Target) {
|
||||
if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth);
|
||||
else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth);
|
||||
else cap = getViaToSameCap (depth);
|
||||
}
|
||||
|
||||
if (not isCreated() and (getMinimalLength(depth) != 0.0) and isMiddleStack()) {
|
||||
if (getLength() < getMinimalLength(depth)) {
|
||||
cap = std::max( cap, getMinimalLength(depth)/2 );
|
||||
cdebug_log(150,0) << "getExtensionCap(): (target) flags:" << getFlags()
|
||||
<< " VIA cap:" << DbU::getValueString(cap)
|
||||
<< " t:" << (getFlags() & SegSourceBottom)
|
||||
<< " b:" << (getFlags() & SegSourceTop)
|
||||
<< endl;
|
||||
if (not (flags & Flags::NoSegExt)) {
|
||||
cdebug_log(150,0) << "duTarget=" << DbU::getValueString(getDuTarget()) << endl;
|
||||
if (getDuTarget() > cap) {
|
||||
cap = getDuTarget();
|
||||
cdebug_log(150,0) << "-> Custom cap (+duTarget):" << DbU::getValueString(cap) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if ( not isCreated()
|
||||
// and not (flags & Flags::NoMinLength)
|
||||
// and (flags & Flags::Target)
|
||||
// and (getMinimalLength(depth) != 0.0)
|
||||
// and isMiddleStack() ) {
|
||||
// DbU::Unit realLength = getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
|
||||
// + getAnchoredLength();
|
||||
// if (realLength + cap < getMinimalLength(depth)) {
|
||||
// cap = getMinimalLength(depth) - realLength;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (getLayer()->isSymbolic() and (cap < getWidth()/2)) cap = getWidth()/2;
|
||||
if (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2;
|
||||
return cap;
|
||||
|
@ -1329,7 +1378,7 @@ namespace Anabatic {
|
|||
if (terminalMin != terminalMax)
|
||||
attractors.addAttractor( terminalMax );
|
||||
}
|
||||
} else if (autoSegment->isLongLocal() or (autoSegment->getLength() > getPPitch()*20)) {
|
||||
} else if (autoSegment->isLongLocal() or (autoSegment->getAnchoredLength() > getPPitch()*20)) {
|
||||
cdebug_log(145,0) << "Used as long global attractor." << endl;
|
||||
|
||||
DbU::Unit perpandMin = autoSegment->getSourceU();
|
||||
|
@ -1555,16 +1604,95 @@ namespace Anabatic {
|
|||
|
||||
bool AutoSegment::isMiddleStack () const
|
||||
{
|
||||
if (isGlobal()) return false;
|
||||
if (isSpinTopOrBottom()) return false;
|
||||
|
||||
cdebug_log(149,0) << "AutoSegment::isMiddleStack() - " << this << endl;
|
||||
if (isGlobal() or isNonPref()) return false;
|
||||
AutoContact* source = getAutoSource();
|
||||
AutoContact* target = getAutoTarget();
|
||||
if (not source or not target) return false;
|
||||
if (isSpinTopOrBottom()) return false;
|
||||
if (not source->isTurn() and not source->isTerminal()) return false;
|
||||
if (not target->isTurn() and not target->isTerminal()) return false;
|
||||
if (source->isTurn()) {
|
||||
AutoSegment* perpandicular = source->getPerpandicular( this );
|
||||
if (perpandicular->isNonPref() and (perpandicular->getAnchoredLength() != 0)) {
|
||||
cdebug_log(149,0) << "| false, perpandicular is non-pref and non-zero. " << this << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (target->isTurn()) {
|
||||
AutoSegment* perpandicular = target->getPerpandicular( this );
|
||||
if (perpandicular->isNonPref() and (perpandicular->getAnchoredLength() != 0)) {
|
||||
cdebug_log(149,0) << "| false, perpandicular is non-pref and non-zero. " << this << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cdebug_log(149,0) << " Middle stack or terminal bound." << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (not source->isTurn() or not target->isTurn()) return false;
|
||||
if (source->getPerpandicular(this)->isNonPref()) return false;
|
||||
if (target->getPerpandicular(this)->isNonPref()) return false;
|
||||
|
||||
bool AutoSegment::isUnderMinLength () const
|
||||
{
|
||||
return false;
|
||||
// cdebug_log(149,0) << "AutoSegment::isUnderMinLength() - " << this << endl;
|
||||
// if (not isMiddleStack()) return false;
|
||||
// DbU::Unit spanLength = getSpanLength();
|
||||
// DbU::Unit minimalLength = getMinimalLength( Session::getLayerDepth( getLayer() ));
|
||||
// cdebug_log(149,0) << " span=" << DbU::getValueString(spanLength)
|
||||
// << " < min=" << DbU::getValueString(minimalLength)<< endl;
|
||||
// return spanLength < minimalLength;
|
||||
}
|
||||
|
||||
|
||||
bool AutoSegment::expandToMinLength ( Interval span )
|
||||
{
|
||||
if (not isMiddleStack()) return false;
|
||||
cdebug_log(149,1) << "AutoSegment::expandToMinLength() " << this << endl;
|
||||
cdebug_log(149,0) << "In span=" << span << endl;
|
||||
cdebug_log(149,0) << "Before: [" << DbU::getValueString(getSourceU() - getExtensionCap( Flags::Source|Flags::LayerCapOnly ))
|
||||
<< " " << DbU::getValueString(getTargetU() + getExtensionCap( Flags::Target|Flags::LayerCapOnly ))
|
||||
<< "]" << endl;
|
||||
|
||||
DbU::Unit sourceCap = getExtensionCap( Flags::Source|Flags::NoSegExt|Flags::LayerCapOnly );
|
||||
DbU::Unit targetCap = getExtensionCap( Flags::Target|Flags::NoSegExt|Flags::LayerCapOnly );
|
||||
DbU::Unit segMinLength = getAnchoredLength() + sourceCap + targetCap;
|
||||
DbU::Unit techMinLength = getMinimalLength( Session::getLayerDepth( getLayer() ));
|
||||
if (techMinLength <= segMinLength) {
|
||||
cdebug_log(149,0) << "Above minimal length (" << DbU::getValueString(segMinLength)
|
||||
<< " >= " << DbU::getValueString(techMinLength) << ")" << endl;
|
||||
cdebug_tabw(149,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
DbU::Unit targetExpand = (techMinLength - segMinLength) / 2 + targetCap;
|
||||
DbU::Unit sourceExpand = - (techMinLength - segMinLength) / 2 - sourceCap;
|
||||
if (not span.isEmpty()) {
|
||||
DbU::Unit shiftLeft = span.getVMax() - (getTargetU() + targetExpand);
|
||||
if (shiftLeft < 0) {
|
||||
targetExpand += shiftLeft;
|
||||
sourceExpand += shiftLeft;
|
||||
}
|
||||
}
|
||||
setDuSource( sourceExpand );
|
||||
setDuTarget( targetExpand );
|
||||
cdebug_log(149,0) << "sourceExpand=" << DbU::getValueString(sourceExpand)
|
||||
<< " targetExpand=" << DbU::getValueString(targetExpand) << endl;
|
||||
cdebug_log(149,0) << "After: [" << DbU::getValueString(getSourceU() - getExtensionCap( Flags::Source|Flags::LayerCapOnly ))
|
||||
<< " " << DbU::getValueString(getTargetU() + getExtensionCap( Flags::Target|Flags::LayerCapOnly ))
|
||||
<< "] expand:" << DbU::getValueString(techMinLength - segMinLength)<< endl;
|
||||
setFlags( SegAtMinArea );
|
||||
cdebug_tabw(149,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AutoSegment::unexpandToMinLength ()
|
||||
{
|
||||
if (not isAtMinArea()) return false;
|
||||
cdebug_log(149,0) << "AutoSegment::unexpandToMinLength() " << this << endl;
|
||||
setDuSource( 0 );
|
||||
setDuTarget( 0 );
|
||||
unsetFlags( SegAtMinArea );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1614,8 +1742,8 @@ namespace Anabatic {
|
|||
} else
|
||||
return false;
|
||||
|
||||
cdebug_log(159,0) << " length:" << DbU::getValueString(getLength()) << endl;
|
||||
if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false;
|
||||
cdebug_log(159,0) << " length:" << DbU::getValueString(getAnchoredLength()) << endl;
|
||||
if (getAnchoredLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1653,7 +1781,7 @@ namespace Anabatic {
|
|||
else if (isSpinTop ()) ++perpandicularDepth;
|
||||
else return true;
|
||||
|
||||
return (getLength() >= (Session::getPitch(perpandicularDepth) * 2));
|
||||
return (getAnchoredLength() >= (Session::getPitch(perpandicularDepth) * 2));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2846,7 +2974,7 @@ namespace Anabatic {
|
|||
exploreds.insert( seed->getAutoSource() );
|
||||
exploreds.insert( seed->getAutoTarget() );
|
||||
|
||||
if (seed->getLength()) {
|
||||
if (seed->getAnchoredLength()) {
|
||||
if (flags & Flags::Superior) stack.push_back( seed->getAutoTarget() );
|
||||
else stack.push_back( seed->getAutoSource() );
|
||||
} else {
|
||||
|
@ -2871,7 +2999,7 @@ namespace Anabatic {
|
|||
AutoSegment* autoSegment = Session::lookup( segment );
|
||||
if (not autoSegment) continue;
|
||||
|
||||
if (not autoSegment->getLength()) {
|
||||
if (not autoSegment->getAnchoredLength()) {
|
||||
AutoContact* contact = autoSegment->getAutoSource();
|
||||
if (contact and (contact != currentContact)) {
|
||||
if (exploreds.find(contact) == exploreds.end())
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace Anabatic {
|
|||
Segment* AutoVertical::base () { return _vertical; }
|
||||
Segment* AutoVertical::base () const { return _vertical; }
|
||||
Vertical* AutoVertical::getVertical () { return _vertical; }
|
||||
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSourceY(); }
|
||||
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTargetY(); }
|
||||
DbU::Unit AutoVertical::getSourceU () const { return _vertical->getSource()->getY(); }
|
||||
DbU::Unit AutoVertical::getTargetU () const { return _vertical->getTarget()->getY(); }
|
||||
DbU::Unit AutoVertical::getDuSource () const { return _vertical->getDySource(); }
|
||||
DbU::Unit AutoVertical::getDuTarget () const { return _vertical->getDyTarget(); }
|
||||
Interval AutoVertical::getSpanU () const { return Interval(_vertical->getSourceY(),_vertical->getTargetY()); }
|
||||
|
@ -268,13 +268,13 @@ namespace Anabatic {
|
|||
|
||||
if (not isDrag()) {
|
||||
if ( not isStrongTerminal()
|
||||
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) )
|
||||
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getAnchoredLength() < getPitch()*5)) )
|
||||
{ cdebug_tabw(149,-1); return false; }
|
||||
}
|
||||
|
||||
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
|
||||
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl;
|
||||
cdebug_log(149,0) << "length:" << DbU::getValueString(getLength()) << endl;
|
||||
cdebug_log(149,0) << "test:" << (getAnchoredLength() < getPitch()*5) << endl;
|
||||
cdebug_log(149,0) << "length:" << DbU::getValueString(getAnchoredLength()) << endl;
|
||||
|
||||
bool success = false;
|
||||
bool sourceSlackened = false;
|
||||
|
@ -382,6 +382,10 @@ namespace Anabatic {
|
|||
if (_vertical->getTargetY() < _vertical->getSourceY()) {
|
||||
cdebug_log(145,0) << "updateOrient() " << this << " (before S/T swap)" << endl;
|
||||
_vertical->invert();
|
||||
DbU::Unit duSource = getDuSource();
|
||||
DbU::Unit duTarget = getDuTarget();
|
||||
setDuSource( -duTarget );
|
||||
setDuTarget( -duSource );
|
||||
|
||||
unsigned int spinFlags = _flags & SegDepthSpin;
|
||||
unsetFlags( SegDepthSpin );
|
||||
|
@ -405,8 +409,8 @@ namespace Anabatic {
|
|||
|
||||
void AutoVertical::updatePositions ()
|
||||
{
|
||||
_sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
|
||||
_sourcePosition = getSourceU() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = getTargetU() + getExtensionCap(Flags::Target);
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,8 +430,8 @@ namespace Anabatic {
|
|||
bool AutoVertical::checkPositions () const
|
||||
{
|
||||
bool coherency = true;
|
||||
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
|
||||
DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target);
|
||||
|
||||
if ( _sourcePosition != sourcePosition ) {
|
||||
cerr << Error ( "%s\n Source position incoherency: "
|
||||
|
|
|
@ -122,6 +122,8 @@ namespace Anabatic {
|
|||
const BaseFlags Flags::UseNonPref = (1L << 34);
|
||||
const BaseFlags Flags::Force = (1L << 35);
|
||||
const BaseFlags Flags::LayerCapOnly = (1L << 36);
|
||||
const BaseFlags Flags::NoMinLength = (1L << 37);
|
||||
const BaseFlags Flags::NoSegExt = (1L << 38);
|
||||
|
||||
|
||||
Flags::~Flags ()
|
||||
|
|
|
@ -754,7 +754,7 @@ namespace Anabatic {
|
|||
if (not segment->isStrongTerminal()) locals.push_back( segment );
|
||||
continue;
|
||||
}
|
||||
if ( (segment->getLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
|
||||
if ( (segment->getAnchoredLength() < 3*Session::getSliceHeight()) and (segment != seed) ) {
|
||||
locals.push_back( segment );
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1737,7 +1737,7 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
|
||||
|
||||
// HARDCODED VALUE.
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) )
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
|
||||
addToFixSegments( globalSegment );
|
||||
|
||||
if (getConnexity().fields.globals < 2) {
|
||||
|
|
|
@ -318,7 +318,7 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
|
||||
|
||||
// HARDCODED VALUE.
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) )
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
|
||||
addToFixSegments( globalSegment );
|
||||
|
||||
if (getConnexity().fields.globals < 2) {
|
||||
|
|
|
@ -577,7 +577,7 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "Create global segment: " << globalSegment << endl;
|
||||
|
||||
// HARDCODED VALUE.
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getLength() < 2*Session::getSliceHeight()) )
|
||||
if ( (getTopology() & Global_Fixed) and (globalSegment->getAnchoredLength() < 2*Session::getSliceHeight()) )
|
||||
addToFixSegments( globalSegment );
|
||||
|
||||
if (getConnexity().fields.globals < 2) {
|
||||
|
|
|
@ -259,6 +259,8 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "_segmentInvalidateds.size(): " << _segmentInvalidateds.size() << endl;
|
||||
|
||||
_segmentRevalidateds.clear();
|
||||
std::sort( _segmentInvalidateds.begin(), _segmentInvalidateds.end()
|
||||
, AutoSegment::CompareByRevalidate() );
|
||||
for ( size_t i=0 ; i < _segmentInvalidateds.size() ; ++i, ++count ) {
|
||||
_segmentInvalidateds[i]->revalidate();
|
||||
if ( not _destroyedSegments.empty()
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace Anabatic {
|
|||
static const uint64_t SegShortNet = (1L<<35);
|
||||
static const uint64_t SegUnbreakable = (1L<<36);
|
||||
static const uint64_t SegNonPref = (1L<<37);
|
||||
static const uint64_t SegAtMinArea = (1L<<38);
|
||||
// Masks.
|
||||
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
|
||||
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
|
||||
|
@ -173,6 +174,7 @@ namespace Anabatic {
|
|||
inline DbU::Unit getContactWidth () const;
|
||||
inline DbU::Unit getLength () const;
|
||||
inline DbU::Unit getSpanLength () const;
|
||||
inline DbU::Unit getAnchoredLength () const;
|
||||
inline DbU::Unit getSourcePosition () const;
|
||||
inline DbU::Unit getTargetPosition () const;
|
||||
inline DbU::Unit getSourceX () const;
|
||||
|
@ -200,6 +202,7 @@ namespace Anabatic {
|
|||
inline bool isUnbreakable () const;
|
||||
inline bool isNonPref () const;
|
||||
inline bool isDrag () const;
|
||||
inline bool isAtMinArea () const;
|
||||
inline bool isNotSourceAligned () const;
|
||||
inline bool isNotTargetAligned () const;
|
||||
inline bool isNotAligned () const;
|
||||
|
@ -212,6 +215,7 @@ namespace Anabatic {
|
|||
inline bool isSpinBottom () const;
|
||||
inline bool isSpinTopOrBottom () const;
|
||||
inline bool isReduced () const;
|
||||
bool isUnderMinLength () const;
|
||||
inline bool isStrap () const;
|
||||
inline bool isDogleg () const;
|
||||
inline bool isUnbound () const;
|
||||
|
@ -332,6 +336,8 @@ namespace Anabatic {
|
|||
bool bloatStackedStrap ();
|
||||
bool reduce ();
|
||||
bool raise ();
|
||||
bool expandToMinLength ( Interval );
|
||||
bool unexpandToMinLength ();
|
||||
// Canonical Modifiers.
|
||||
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
|
||||
virtual void invalidate ( Flags flags=Flags::Propagate );
|
||||
|
@ -425,6 +431,10 @@ namespace Anabatic {
|
|||
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
struct CompareByRevalidate : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
|
||||
typedef std::set<AutoSegment*,CompareId> IdSet;
|
||||
|
@ -526,6 +536,7 @@ namespace Anabatic {
|
|||
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
|
||||
inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
|
||||
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
|
||||
inline bool AutoSegment::isAtMinArea () const { return _flags & SegAtMinArea; }
|
||||
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
|
||||
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
|
||||
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
|
||||
|
@ -564,6 +575,7 @@ namespace Anabatic {
|
|||
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
|
||||
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
|
||||
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
|
||||
inline DbU::Unit AutoSegment::getAnchoredLength () const { return std::abs(getTargetU() - getSourceU()); }
|
||||
|
||||
inline void AutoSegment::setLayer ( size_t depth )
|
||||
{
|
||||
|
@ -579,8 +591,8 @@ namespace Anabatic {
|
|||
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
|
||||
|
||||
inline DbU::Unit AutoSegment::getSpanLength () const
|
||||
{ return getLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly )
|
||||
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly );
|
||||
{ return getAnchoredLength() + getExtensionCap( Flags::Source|Flags::LayerCapOnly|Flags::NoMinLength )
|
||||
+ getExtensionCap( Flags::Target|Flags::LayerCapOnly|Flags::NoMinLength );
|
||||
}
|
||||
|
||||
inline void AutoSegment::setParent ( AutoSegment* parent )
|
||||
|
|
|
@ -103,6 +103,8 @@ namespace Anabatic {
|
|||
static const BaseFlags UseNonPref ;
|
||||
static const BaseFlags Force ;
|
||||
static const BaseFlags LayerCapOnly ;
|
||||
static const BaseFlags NoMinLength ;
|
||||
static const BaseFlags NoSegExt ;
|
||||
public:
|
||||
inline Flags ( uint64_t flags = NoFlags );
|
||||
inline Flags ( const Hurricane::BaseFlags& );
|
||||
|
|
|
@ -844,13 +844,13 @@ namespace Katana {
|
|||
|
||||
cdebug_tabw(155,1);
|
||||
|
||||
openSession();
|
||||
for ( RoutingPlane* plane : _routingPlanes ) {
|
||||
for ( Track* track : plane->getTracks() ) {
|
||||
track->expandMinArea();
|
||||
}
|
||||
}
|
||||
Session::close();
|
||||
// openSession();
|
||||
// for ( RoutingPlane* plane : _routingPlanes ) {
|
||||
// for ( Track* track : plane->getTracks() ) {
|
||||
// track->expandMinArea();
|
||||
// }
|
||||
// }
|
||||
// Session::close();
|
||||
|
||||
setState( Anabatic::EngineDriving );
|
||||
_gutKatana();
|
||||
|
|
|
@ -324,6 +324,25 @@ namespace Katana {
|
|||
TrackElement* trackSegment = lookup( revalidateds[i] );
|
||||
if (trackSegment) trackSegment->reschedule( 0 );
|
||||
}
|
||||
// if (revalidateds[i]->isUnderMinLength()) {
|
||||
// cdebug_log(159,0) << "Session: under min length:" << revalidateds[i] << endl;
|
||||
// revalidateds[i]->expandToMinLength();
|
||||
// TrackElement* trackSegment = lookup( revalidateds[i] );
|
||||
// if (trackSegment) {
|
||||
// trackSegment->invalidate();
|
||||
// trackSegment->reschedule( 0 );
|
||||
// }
|
||||
// } else {
|
||||
// if (revalidateds[i]->isAtMinArea()) {
|
||||
// if (revalidateds[i]->unexpandToMinLength()) {
|
||||
// TrackElement* trackSegment = lookup( revalidateds[i] );
|
||||
// if (trackSegment) {
|
||||
// trackSegment->invalidate();
|
||||
// trackSegment->reschedule( 0 );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (revalidateds[i]->canReduce()) {
|
||||
revalidateds[i]->reduce();
|
||||
TrackElement* trackSegment = lookup( revalidateds[i] );
|
||||
|
|
|
@ -373,8 +373,12 @@ namespace Katana {
|
|||
const Interval& interval = cost.getInterval();
|
||||
Interval freeInterval = getFreeInterval( interval.getCenter(), cost.getNet() );
|
||||
|
||||
if (not freeInterval.contains(interval))
|
||||
if (not freeInterval.contains(interval)) {
|
||||
getOverlapBounds( cost.getInterval(), begin, end );
|
||||
cost.setFreeLength( 0 );
|
||||
} else {
|
||||
cost.setFreeLength( freeInterval.getSize() );
|
||||
}
|
||||
cost.setTrack( const_cast<Track*>(this), begin, end );
|
||||
|
||||
cdebug_log(155,1) << "addOverlapCost() @" << DbU::getValueString(_axis)
|
||||
|
@ -658,6 +662,8 @@ namespace Katana {
|
|||
if (not holes)
|
||||
coherency = (checkOverlap(overlaps) == 0) and coherency;
|
||||
|
||||
coherency = (checkMinArea() == 0) and coherency;
|
||||
|
||||
return coherency;
|
||||
}
|
||||
|
||||
|
@ -867,6 +873,30 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
uint32_t Track::checkMinArea () const
|
||||
{
|
||||
if (_segments.empty()) return 0;
|
||||
|
||||
uint32_t nonMinArea = 0;
|
||||
DbU::Unit techMinLength = AutoSegment::getMinimalLength( Session::getLayerDepth( getLayer() ));
|
||||
for ( size_t j=0 ; j<_segments.size() ; ++j ) {
|
||||
if (not _segments[j]->base() or not (_segments[j]->getDirection() & getDirection())) {
|
||||
++j;
|
||||
continue;
|
||||
}
|
||||
if (not _segments[j]->base()->isMiddleStack()) continue;
|
||||
if (_segments[j]->base()->getSpanLength() < techMinLength) {
|
||||
cerr << Error( "Below minimal length/area for %s:\n length:%s, minimal length:%s"
|
||||
, getString(_segments[j]).c_str()
|
||||
, DbU::getValueString(_segments[j]->base()->getSpanLength()).c_str()
|
||||
, DbU::getValueString(techMinLength).c_str() ) << endl;
|
||||
++nonMinArea;
|
||||
}
|
||||
}
|
||||
return nonMinArea;
|
||||
}
|
||||
|
||||
|
||||
void Track::expandMinArea ()
|
||||
{
|
||||
if (_segments.empty()) return;
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace Katana {
|
|||
, _axisWeight (0)
|
||||
, _distanceToFixed (2*Session::getSliceHeight())
|
||||
, _longuestOverlap (0)
|
||||
, _freeLength (DbU::Max)
|
||||
, _dataState (0)
|
||||
, _ripupCount (0)
|
||||
, _selectFlags (NoFlags)
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace Katana {
|
|||
DbU::Unit getSourcePosition ( size_t index ) const;
|
||||
bool check ( uint32_t& overlaps, const char* message=NULL ) const;
|
||||
uint32_t checkOverlap ( uint32_t& overlaps ) const;
|
||||
uint32_t checkMinArea () const;
|
||||
void expandMinArea ();
|
||||
inline void setLocalAssigned ( bool );
|
||||
void invalidate ();
|
||||
|
|
|
@ -131,6 +131,7 @@ namespace Katana {
|
|||
inline DbU::Unit getDeltaPerpand () const;
|
||||
inline DbU::Unit getLongestOverlap () const;
|
||||
inline DbU::Unit getAxisWeight () const;
|
||||
inline DbU::Unit getFreeLength () const;
|
||||
inline int getRipupCount () const;
|
||||
inline uint32_t getDataState () const;
|
||||
inline uint32_t setFlags ( uint32_t );
|
||||
|
@ -152,6 +153,7 @@ namespace Katana {
|
|||
inline void incDeltaShared ( DbU::Unit );
|
||||
inline void incAxisWeight ( DbU::Unit );
|
||||
inline void setLonguestOverlap ( DbU::Unit );
|
||||
inline void setFreeLength ( DbU::Unit );
|
||||
inline void mergeRipupCount ( int );
|
||||
inline void mergeDataState ( uint32_t );
|
||||
inline bool selectNextTrack ();
|
||||
|
@ -183,6 +185,7 @@ namespace Katana {
|
|||
DbU::Unit _axisWeight;
|
||||
DbU::Unit _distanceToFixed;
|
||||
DbU::Unit _longuestOverlap;
|
||||
DbU::Unit _freeLength;
|
||||
uint32_t _dataState;
|
||||
int _ripupCount;
|
||||
uint32_t _selectFlags;
|
||||
|
@ -223,6 +226,7 @@ namespace Katana {
|
|||
inline const Interval& TrackCost::getInterval2 () const { return _interval2; }
|
||||
inline uint32_t TrackCost::getTerminals () const { return _terminals; }
|
||||
inline DbU::Unit TrackCost::getLongestOverlap () const { return _longuestOverlap; }
|
||||
inline DbU::Unit TrackCost::getFreeLength () const { return _freeLength; }
|
||||
inline DbU::Unit TrackCost::getDelta () const { return _delta; }
|
||||
inline DbU::Unit TrackCost::getAxisWeight () const { return _axisWeight; }
|
||||
inline int TrackCost::getRipupCount () const { return _ripupCount; }
|
||||
|
@ -245,6 +249,7 @@ namespace Katana {
|
|||
inline void TrackCost::incDeltaShared ( DbU::Unit delta ) { _deltaShared += delta; }
|
||||
inline void TrackCost::incAxisWeight ( DbU::Unit weight ) { _axisWeight += weight; }
|
||||
inline void TrackCost::setLonguestOverlap ( DbU::Unit overlap ) { _longuestOverlap = std::max( overlap, _longuestOverlap ); }
|
||||
inline void TrackCost::setFreeLength ( DbU::Unit length ) { _freeLength = std::min( length , _freeLength ); }
|
||||
inline void TrackCost::mergeRipupCount ( int count ) { _ripupCount = std::max( count , _ripupCount ); }
|
||||
inline void TrackCost::mergeDataState ( uint32_t state ) { _dataState = std::max( state , _dataState ); }
|
||||
inline string TrackCost::_getTypeName () const { return "TrackCost"; }
|
||||
|
|
Loading…
Reference in New Issue