diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index ab17e433..ed86a7c4 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -1355,7 +1355,7 @@ namespace Anabatic { set connectedLayers; forEach ( Segment*, segment, net->getSegments() ) { - if (segment->getLength()) { + if (segment->getAnchoredLength()) { if (net->isExternal()) { NetExternalComponents::setExternal( *segment ); } diff --git a/anabatic/src/AutoContact.cpp b/anabatic/src/AutoContact.cpp index 2978b941..10a17681 100644 --- a/anabatic/src/AutoContact.cpp +++ b/anabatic/src/AutoContact.cpp @@ -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; diff --git a/anabatic/src/AutoHorizontal.cpp b/anabatic/src/AutoHorizontal.cpp index c91739f7..b9345f2a 100644 --- a/anabatic/src/AutoHorizontal.cpp +++ b/anabatic/src/AutoHorizontal.cpp @@ -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; diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index 2b57f510..1b6e421b 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -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 ; depthgetMinimalArea(); 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()) diff --git a/anabatic/src/AutoVertical.cpp b/anabatic/src/AutoVertical.cpp index bed3c094..2dfa47c3 100644 --- a/anabatic/src/AutoVertical.cpp +++ b/anabatic/src/AutoVertical.cpp @@ -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: " diff --git a/anabatic/src/Constants.cpp b/anabatic/src/Constants.cpp index 9e7af137..d3a72004 100644 --- a/anabatic/src/Constants.cpp +++ b/anabatic/src/Constants.cpp @@ -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 () diff --git a/anabatic/src/LayerAssign.cpp b/anabatic/src/LayerAssign.cpp index 569c1e0d..fd5424d5 100644 --- a/anabatic/src/LayerAssign.cpp +++ b/anabatic/src/LayerAssign.cpp @@ -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; } diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp index bcc0d615..43ea958d 100644 --- a/anabatic/src/NetBuilderHV.cpp +++ b/anabatic/src/NetBuilderHV.cpp @@ -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) { diff --git a/anabatic/src/NetBuilderM2.cpp b/anabatic/src/NetBuilderM2.cpp index 42824e6e..242b007d 100644 --- a/anabatic/src/NetBuilderM2.cpp +++ b/anabatic/src/NetBuilderM2.cpp @@ -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) { diff --git a/anabatic/src/NetBuilderVH.cpp b/anabatic/src/NetBuilderVH.cpp index 51c92749..a7539618 100644 --- a/anabatic/src/NetBuilderVH.cpp +++ b/anabatic/src/NetBuilderVH.cpp @@ -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) { diff --git a/anabatic/src/Session.cpp b/anabatic/src/Session.cpp index 6bc4639b..66e56cc4 100644 --- a/anabatic/src/Session.cpp +++ b/anabatic/src/Session.cpp @@ -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() diff --git a/anabatic/src/anabatic/AutoSegment.h b/anabatic/src/anabatic/AutoSegment.h index 1721e8e2..c058dae4 100644 --- a/anabatic/src/anabatic/AutoSegment.h +++ b/anabatic/src/anabatic/AutoSegment.h @@ -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 { bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; }; + public: + struct CompareByRevalidate : public binary_function { + bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; + }; public: typedef std::set DepthLengthSet; typedef std::set 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 ) diff --git a/anabatic/src/anabatic/Constants.h b/anabatic/src/anabatic/Constants.h index 35e631fe..6a9acdcd 100644 --- a/anabatic/src/anabatic/Constants.h +++ b/anabatic/src/anabatic/Constants.h @@ -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& ); diff --git a/katana/src/KatanaEngine.cpp b/katana/src/KatanaEngine.cpp index a2e9b2f0..0867f3a1 100644 --- a/katana/src/KatanaEngine.cpp +++ b/katana/src/KatanaEngine.cpp @@ -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(); diff --git a/katana/src/Session.cpp b/katana/src/Session.cpp index 3e037011..25344b70 100644 --- a/katana/src/Session.cpp +++ b/katana/src/Session.cpp @@ -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] ); diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 9ac92725..6252f9ac 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -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(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; diff --git a/katana/src/TrackCost.cpp b/katana/src/TrackCost.cpp index 56f775bf..ceb96596 100644 --- a/katana/src/TrackCost.cpp +++ b/katana/src/TrackCost.cpp @@ -57,6 +57,7 @@ namespace Katana { , _axisWeight (0) , _distanceToFixed (2*Session::getSliceHeight()) , _longuestOverlap (0) + , _freeLength (DbU::Max) , _dataState (0) , _ripupCount (0) , _selectFlags (NoFlags) diff --git a/katana/src/katana/Track.h b/katana/src/katana/Track.h index c9c5977f..8a59de55 100644 --- a/katana/src/katana/Track.h +++ b/katana/src/katana/Track.h @@ -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 (); diff --git a/katana/src/katana/TrackCost.h b/katana/src/katana/TrackCost.h index c2fc2bca..46092d1d 100644 --- a/katana/src/katana/TrackCost.h +++ b/katana/src/katana/TrackCost.h @@ -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"; }