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:
Jean-Paul Chaput 2021-04-05 00:01:54 +02:00
parent 0326d513bd
commit 08d1db5dd6
19 changed files with 270 additions and 55 deletions

View File

@ -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 );
}

View File

@ -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;

View File

@ -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;

View File

@ -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())

View File

@ -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: "

View File

@ -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 ()

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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()

View File

@ -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 )

View File

@ -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& );

View File

@ -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();

View File

@ -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] );

View File

@ -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;

View File

@ -57,6 +57,7 @@ namespace Katana {
, _axisWeight (0)
, _distanceToFixed (2*Session::getSliceHeight())
, _longuestOverlap (0)
, _freeLength (DbU::Max)
, _dataState (0)
, _ripupCount (0)
, _selectFlags (NoFlags)

View File

@ -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 ();

View File

@ -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"; }