diff --git a/anabatic/src/AutoContact.cpp b/anabatic/src/AutoContact.cpp index 86d6b6f5..48c575b5 100644 --- a/anabatic/src/AutoContact.cpp +++ b/anabatic/src/AutoContact.cpp @@ -628,6 +628,7 @@ namespace Anabatic { //s.insert( 4, getString(_id) ); s.insert( s.size()-1, (isFixed ())?" F":" -" ); s.insert( s.size()-1, (isTerminal ())? "T": "-" ); + s.insert( s.size()-1, (canDrag ())? "D": "-" ); s.insert( s.size()-1, (isHTee ())? "h": "-" ); s.insert( s.size()-1, (isVTee ())? "v": "-" ); s.insert( s.size()-1, (isInvalidated ())? "i": "-" ); diff --git a/anabatic/src/AutoContactTerminal.cpp b/anabatic/src/AutoContactTerminal.cpp index f508d461..d72275df 100644 --- a/anabatic/src/AutoContactTerminal.cpp +++ b/anabatic/src/AutoContactTerminal.cpp @@ -198,13 +198,18 @@ namespace Anabatic { } else if ( (routingPad = dynamic_cast(component)) ) { Occurrence occurrence = routingPad->getOccurrence(); Transformation transformation = occurrence.getPath().getTransformation(); - Segment* segment = dynamic_cast( occurrence.getEntity() ); + Horizontal* horizontal = dynamic_cast( occurrence.getEntity() ); + Vertical* vertical = dynamic_cast( occurrence.getEntity() ); cdebug_log(145,0) << "Anchor: " << occurrence.getEntity() << endl; cdebug_log(145,0) << "transf: " << transformation << endl; - if (segment) { - Box bb = segment->getBoundingBox(); + if (horizontal or vertical) { + Box bb; + // Assume that transformation contains no rotations (for now). + if (horizontal) { bb = horizontal->getBoundingBox(); const_cast(this)->setFlags( CntOnHorizontal ); } + if (vertical) { bb = vertical ->getBoundingBox(); const_cast(this)->setFlags( CntOnVertical ); } + transformation.applyOn( bb ); xMin = bb.getXMin(); yMin = bb.getYMin(); @@ -295,21 +300,40 @@ namespace Anabatic { if (_segment == segment) { _segment = NULL; setFlags( CntInvalidatedCache ); + unsetFlags( CntDrag ); } } void AutoContactTerminal::cacheAttach ( AutoSegment* segment ) { + DebugSession::open( getNet(), 140, 150 ); + + cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl; + if (_segment) { cerr << Bug( "%s::cacheAttach() On %s,\n" " cache has not been cleared first, cancelled." , _getTypeName().c_str(), getString(this).c_str() ) << endl; + cdebug_tabw(145,-1); + DebugSession::close(); return; } _segment = segment; unsetFlags( CntInvalidatedCache ); + + if ( (dynamic_cast(_segment) and (getFlags() & CntOnHorizontal)) + or (dynamic_cast (_segment) and (getFlags() & CntOnVertical )) ) { + _segment->setFlags( AutoSegment::SegDrag ); + setFlags( CntDrag ); + + cdebug_log(145,0) << "Drag Contact/Segment set" << endl; + } + + cdebug_log(145,0) << "Cached:" << _segment << endl; + cdebug_tabw(145,-1); + DebugSession::close(); } @@ -338,8 +362,16 @@ namespace Anabatic { } if (horizontals[0] != NULL ) { _segment = Session::lookup( horizontals[0] ); + if (getFlags() & CntOnHorizontal) { + setFlags( CntDrag ); + _segment->setFlags( AutoSegment::SegDrag ); + } } else { _segment = Session::lookup( verticals[0] ); + if (getFlags() & CntOnVertical) { + setFlags( CntDrag ); + _segment->setFlags( AutoSegment::SegDrag ); + } } if (_segment == NULL) { ostringstream os; @@ -418,6 +450,18 @@ namespace Anabatic { cdebug_log(145,0) << "Contact for wide segment." << endl; } + if (canDrag()) { + AutoContact* opposite = _segment->getOppositeAnchor(this); + AutoSegment* perpandicular = opposite->getPerpandicular( _segment ); + if (perpandicular) { + DbU::Unit y = perpandicular->getAxis(); + y = std::min( y, getCBYMax() ); + y = std::max( y, getCBYMin() ); + setY( y ); + cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y) << endl; + } + } + if (not getUConstraints(Flags::Horizontal).contains(axis)) { cdebug_log(145,0) << "Cached: " << _segment << endl; message << "Terminal vertical segment X " << DbU::getValueString(axis) diff --git a/anabatic/src/AutoHorizontal.cpp b/anabatic/src/AutoHorizontal.cpp index c067f47f..747db712 100644 --- a/anabatic/src/AutoHorizontal.cpp +++ b/anabatic/src/AutoHorizontal.cpp @@ -142,40 +142,58 @@ namespace Anabatic { bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const { + cdebug_log(155,1) << "getConstraints() " << this << endl; + constraintMin = getNativeMin(); constraintMax = getNativeMax(); - cdebug_log(144,0) << "Native constraints: [" + cdebug_log(155,0) << "Native constraints: [" << DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMax) << "]" << endl; constraintMin = std::max ( constraintMin, getAutoSource()->getCBYMin() ); constraintMax = std::min ( constraintMax, getAutoSource()->getCBYMax() ); - cdebug_log(144,0) << "Merge with source constraints: [" + cdebug_log(155,0) << "Merge with source constraints: [" << DbU::getValueString(getAutoSource()->getCBYMin()) << ":" << DbU::getValueString(getAutoSource()->getCBYMax()) << "]" << endl; constraintMin = std::max ( constraintMin, getAutoTarget()->getCBYMin() ); constraintMax = std::min ( constraintMax, getAutoTarget()->getCBYMax() ); - cdebug_log(144,0) << "Merge with target constraints: [" + cdebug_log(155,0) << "Merge with target constraints: [" << DbU::getValueString(getAutoTarget()->getCBYMin()) << ":" << DbU::getValueString(getAutoTarget()->getCBYMax()) << "]" << endl; - constraintMin = std::max ( constraintMin, getUserConstraints().getVMin() ); - constraintMax = std::min ( constraintMax, getUserConstraints().getVMax() ); - cdebug_log(144,0) << "Merge with user constraints: [" - << DbU::getValueString(getUserConstraints().getVMin()) << ":" - << DbU::getValueString(getUserConstraints().getVMax()) << "]" - << endl; + Interval userConstraints = getUserConstraints(); + if (not userConstraints.isEmpty()) { + constraintMin = std::max ( constraintMin, userConstraints.getVMin() ); + constraintMax = std::min ( constraintMax, userConstraints.getVMax() ); - cdebug_log(145,0) << "Resulting constraints: " << " [" + cdebug_log(155,0) << "Merge with user constraints: [" + << DbU::getValueString(userConstraints.getVMin()) << ":" + << DbU::getValueString(userConstraints.getVMax()) << "]" + << endl; + } else + cdebug_log(155,0) << "Empty user constraints" << endl; + + cdebug_log(155,0) << "Resulting constraints: [" << DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMax) << "]" << endl; + + if (constraintMin > constraintMax) + cerr << Error( "AutoHorizontal::getConstraints(): Invalid interval [%s : %s] -> [%d : %d]\n" + " on %s" + , DbU::getValueString(constraintMin).c_str() + , DbU::getValueString(constraintMax).c_str() + , constraintMin + , constraintMax + , getString(this).c_str() + ) << endl; + cdebug_tabw(155,-1); return true; } @@ -753,6 +771,8 @@ namespace Anabatic { GCell* begin = autoSource->getGCell(); GCell* end = autoTarget->getGCell(); + if (not autoSource->canDrag()) unsetFlags( SegDrag ); + DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2; if (isLocal()) doglegAxis = (getSourceX() + getTargetX()) / 2; @@ -839,6 +859,13 @@ namespace Anabatic { updateNativeConstraints(); segment2->updateNativeConstraints(); + if (autoTarget->canDrag()) { + Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal); + segment1->mergeUserConstraints( dragConstraints ); + + cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl; + } + cdebug_tabw(149,-1); DebugSession::close(); diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index 34aa3941..244c85d3 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -491,13 +491,21 @@ namespace Anabatic { void AutoSegment::invalidate ( Flags flags ) { if (Session::doDestroyTool()) return; - if (flags & Flags::Source) setFlags( SegInvalidatedSource ); - if (flags & Flags::Target) setFlags( SegInvalidatedTarget ); - if (isInvalidated()) return; cdebug_log(149,0) << "AutoSegment::invalidate() " << flags << " " << this << endl; cdebug_tabw(149,1); + if (flags & Flags::Source) setFlags( SegInvalidatedSource ); + if (flags & Flags::Target) setFlags( SegInvalidatedTarget ); + + if ( (getFlags() & SegSourceTerminal) and getAutoSource() and getAutoSource()->canDrag() ) + getAutoSource()->invalidate(); + + if ( (getFlags() & SegTargetTerminal) and getAutoTarget() and getAutoTarget()->canDrag() ) + getAutoTarget()->invalidate(); + + if (isInvalidated()) { cdebug_tabw(149,-1); return; } + _invalidate(); if ((flags & Flags::Propagate) and not isNotAligned()) { @@ -2108,6 +2116,17 @@ namespace Anabatic { coherency = checkConstraints() and coherency; coherency = checkDepthSpin() and coherency; + if (isDrag() xor (getAutoSource()->canDrag() or getAutoTarget()->canDrag())) { + cerr << Error( "%s\n" + " Discrepency between segment \"drag\" state and it's contacts.\n" + " source:%s\n" + " target:%s" + , getString(this).c_str() + , getString(getAutoSource()).c_str() + , getString(getAutoTarget()).c_str() + ) << endl; + coherency = false; + } return coherency; } @@ -2123,6 +2142,7 @@ namespace Anabatic { state += isWeakGlobal () ? "g": "-"; state += isLongLocal () ? "L": "-"; state += isStrongTerminal () ? "T": "-"; + state += isDrag () ? "D": "-"; state += isWeakTerminal1 () ? "W": "-"; state += isWeakTerminal2 () ? "w": "-"; state += isNotAligned () ? "A": "-"; @@ -2293,6 +2313,7 @@ namespace Anabatic { } if (wPitch > 1) segment->setFlags( SegWide ); + if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag ); return segment; } @@ -2383,6 +2404,7 @@ namespace Anabatic { throw Error( badSegment, getString(source).c_str(), getString(target).c_str() ); if (wPitch > 1) segment->setFlags( SegWide ); + if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag ); return segment; } diff --git a/anabatic/src/AutoSegments.cpp b/anabatic/src/AutoSegments.cpp index 71b9dcb8..5bc9c4f2 100644 --- a/anabatic/src/AutoSegments.cpp +++ b/anabatic/src/AutoSegments.cpp @@ -93,14 +93,12 @@ namespace Anabatic { bool AutoSegments_OnContact::Locator::isValid () const - { return !_hook; } + { return _hook; } void AutoSegments_OnContact::Locator::progress () { - cdebug_log(145,0) << "AutoSegments_OnContact::Locator::progress()" << endl; - - while (_hook and not _hook->isMaster()) { + while (_hook) { _hook = _hook->getNextHook(); _element = NULL; @@ -108,7 +106,6 @@ namespace Anabatic { Segment* segment = dynamic_cast( _hook->getComponent() ); if (segment) _element = Session::lookup( segment ); - if (not _element or (_element == _master)) continue; break; diff --git a/anabatic/src/AutoVertical.cpp b/anabatic/src/AutoVertical.cpp index 8117cbd5..b157ae0a 100644 --- a/anabatic/src/AutoVertical.cpp +++ b/anabatic/src/AutoVertical.cpp @@ -137,6 +137,8 @@ namespace Anabatic { bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const { + cdebug_log(149,1) << "getConstraints() " << this << endl; + constraintMin = getNativeMin(); constraintMax = getNativeMax(); @@ -159,19 +161,32 @@ namespace Anabatic { << DbU::getValueString(getAutoTarget()->getCBXMax()) << "]" << endl; - constraintMin = max ( constraintMin, getUserConstraints().getVMin() ); - constraintMax = min ( constraintMax, getUserConstraints().getVMax() ); + Interval userConstraints = getUserConstraints(); + if (not userConstraints.isEmpty()) { + constraintMin = max ( constraintMin, userConstraints.getVMin() ); + constraintMax = min ( constraintMax, userConstraints.getVMax() ); - cdebug_log(149,0) << "Merge with user constraints: [" - << DbU::getValueString(getUserConstraints().getVMin()) << ":" - << DbU::getValueString(getUserConstraints().getVMax()) << "]" - << endl; + cdebug_log(149,0) << "Merge with user constraints: [" + << DbU::getValueString(userConstraints.getVMin()) << ":" + << DbU::getValueString(userConstraints.getVMax()) << "]" + << endl; + } else + cdebug_log(155,0) << "Empty user constraints" << endl; - cdebug_log(149,0) << "Resulting constraints: " << " [" + cdebug_log(149,0) << "Resulting constraints: [" << DbU::getValueString(constraintMin) << ":" << DbU::getValueString(constraintMax) << "]" << endl; + + if (constraintMin > constraintMax) + cerr << Error( "AutoVertical::getConstraints(): Invalid interval [%s : %s]\n" + " on %s" + , DbU::getValueString(constraintMin).c_str() + , DbU::getValueString(constraintMax).c_str() + , getString(this).c_str() + ) << endl; + cdebug_tabw(149,-1); return true; } @@ -659,12 +674,14 @@ namespace Anabatic { { cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl; + //Session::doglegReset(); + AutoContact* autoSource = getAutoSource(); AutoContact* autoTarget = getAutoTarget(); GCell* begin = autoSource->getGCell(); GCell* end = autoTarget->getGCell(); - //Session::doglegReset(); + if (not autoSource->canDrag()) unsetFlags( SegDrag ); DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2; if (isLocal()) @@ -750,6 +767,13 @@ namespace Anabatic { updateNativeConstraints(); segment2->updateNativeConstraints(); + if (autoTarget->canDrag()) { + Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical); + segment1->mergeUserConstraints( dragConstraints ); + + cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl; + } + return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer; } diff --git a/anabatic/src/NetBuilderVH.cpp b/anabatic/src/NetBuilderVH.cpp index 55d39d8e..8a13e67d 100644 --- a/anabatic/src/NetBuilderVH.cpp +++ b/anabatic/src/NetBuilderVH.cpp @@ -79,6 +79,7 @@ namespace Anabatic { Point sourcePosition; Point targetPosition; + Net* net = rp->getNet(); const Layer* rpLayer = rp->getLayer(); size_t rpDepth = Session::getLayerDepth( rp->getLayer() ); Flags direction = Session::getDirection ( rpDepth ); @@ -112,6 +113,54 @@ namespace Anabatic { } } +#if 0 + // Quasi-punctual M1 terminal. + if (flags & VSmall) { + Box ab = rp->getCell()->getBoundingBox(); + RoutingLayerGauge* gaugeMetal3 = Session::getLayerGauge( 2 ); + DbU::Unit metal3axis = gaugeMetal3->getTrackPosition( ab.getYMin() + , ab.getYMax() + , sourcePosition.getY() + , Constant::Nearest ); + DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0); + + AutoContact* sourceVia12 = AutoContactTerminal::create( sourceGCell + , rp + , Session::getContactLayer(0) + , sourcePosition + , viaSideProtect, viaSideProtect + ); + AutoContact* targetVia12 = AutoContactTerminal::create( targetGCell + , rp + , Session::getContactLayer(0) + , targetPosition + , viaSideProtect, viaSideProtect + ); + AutoContact* sourceVia23 = AutoContactTurn::create( sourceGCell, net, Session::getContactLayer(1) ); + AutoContact* targetVia23 = AutoContactTurn::create( targetGCell, net, Session::getContactLayer(1) ); + sourceVia23->setY( metal3axis ); + targetVia23->setY( metal3axis ); + sourceVia23->setX( sourcePosition.getX() ); + targetVia23->setX( targetPosition.getX() ); + + AutoSegment* segmentS = AutoSegment::create( sourceVia12, sourceVia23, Flags::Vertical ); + AutoSegment* segmentT = AutoSegment::create( targetVia12, targetVia23, Flags::Vertical ); + AutoSegment* segmentM = AutoSegment::create( sourceVia23, targetVia23, Flags::Horizontal ); + + sourceVia12->setFlags( CntFixed ); + sourceVia23->setFlags( CntFixed ); + targetVia12->setFlags( CntFixed ); + targetVia23->setFlags( CntFixed ); + segmentS->setFlags( AutoSegment::SegFixed ); + segmentT->setFlags( AutoSegment::SegFixed ); + segmentM->setFlags( AutoSegment::SegFixed ); + + cdebug_log(145,0) << "Hard protect: " << rp << endl; + cdebug_log(145,0) << "X:" << DbU::getValueString(sourcePosition.getX()) + << " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl; + } +#endif + // Non-M1 terminal or punctual M1 protections. if ( (rpDepth != 0) or ((sourcePosition == targetPosition) and (gridPosition == 0)) ) { map::iterator irp = getRpLookup().find( rp ); diff --git a/anabatic/src/Session.cpp b/anabatic/src/Session.cpp index fe81614f..95d536d2 100644 --- a/anabatic/src/Session.cpp +++ b/anabatic/src/Session.cpp @@ -177,8 +177,10 @@ namespace Anabatic { cdebug_log(149,0) << "Align on canonical:" << canonical << endl; //canonical->setAxis( canonical->getAxis(), Flags::Realignate ); - if (canonical->isUnsetAxis()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate ); - else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate ); + if (canonical->isUnsetAxis() and not canonical->isFixed()) + canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate ); + else + canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate ); aligneds.clear(); cdebug_tabw(145,-1); } diff --git a/anabatic/src/anabatic/AutoContact.h b/anabatic/src/anabatic/AutoContact.h index 5b3b30fe..cc958b67 100644 --- a/anabatic/src/anabatic/AutoContact.h +++ b/anabatic/src/anabatic/AutoContact.h @@ -67,6 +67,9 @@ namespace Anabatic { , CntIgnoreAnchor = (1 << 11) , CntWeakTerminal = (1 << 12) , CntUserNativeConstraints = (1 << 13) + , CntOnVertical = (1 << 14) + , CntOnHorizontal = (1 << 15) + , CntDrag = (1 << 16) }; class AutoContact { @@ -118,12 +121,14 @@ namespace Anabatic { inline bool hasBadTopology () const; bool canDestroy ( Flags flags=Flags::NoFlags ) const; bool canMoveUp ( const AutoSegment* moved ) const; + inline bool canDrag () const; // Accessors. inline Contact* base () const; static size_t getAllocateds (); static const Name& getStaticName (); virtual const Name& getName () const; inline size_t getId () const; + inline Flags getFlags () const; virtual Box getBoundingBox () const; inline GCell* getGCell () const; virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0; @@ -253,7 +258,9 @@ namespace Anabatic { inline bool AutoContact::isHTee () const { return _flags&CntHTee; } inline bool AutoContact::isVTee () const { return _flags&CntVTee; } inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; } + inline bool AutoContact::canDrag () const { return _flags&CntDrag; } inline size_t AutoContact::getId () const { return _id; } + inline Flags AutoContact::getFlags () const { return _flags; } inline Contact* AutoContact::base () const { return _contact; } inline GCell* AutoContact::getGCell () const { return _gcell; } inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); } diff --git a/anabatic/src/anabatic/AutoSegment.h b/anabatic/src/anabatic/AutoSegment.h index 56b10620..eef0bd1f 100644 --- a/anabatic/src/anabatic/AutoSegment.h +++ b/anabatic/src/anabatic/AutoSegment.h @@ -82,26 +82,27 @@ namespace Anabatic { static const uint64_t SegTargetTop = (1L<<11); static const uint64_t SegTargetBottom = (1L<<12); static const uint64_t SegIsReduced = (1L<<13); - static const uint64_t SegLayerChange = (1L<<14); - static const uint64_t SegSourceTerminal = (1L<<15); // Replace Terminal. - static const uint64_t SegTargetTerminal = (1L<<16); // Replace Terminal. + static const uint64_t SegDrag = (1L<<14); + static const uint64_t SegLayerChange = (1L<<15); + static const uint64_t SegSourceTerminal = (1L<<16); // Replace Terminal. + static const uint64_t SegTargetTerminal = (1L<<17); // Replace Terminal. static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal; - static const uint64_t SegWeakTerminal1 = (1L<<17); // Replace TopologicalEnd. - static const uint64_t SegWeakTerminal2 = (1L<<18); // Replace TopologicalEnd. - static const uint64_t SegNotSourceAligned = (1L<<19); - static const uint64_t SegNotTargetAligned = (1L<<20); - static const uint64_t SegUnbound = (1L<<21); - static const uint64_t SegHalfSlackened = (1L<<22); - static const uint64_t SegSlackened = (1L<<23); - static const uint64_t SegAxisSet = (1L<<24); - static const uint64_t SegInvalidated = (1L<<25); - static const uint64_t SegInvalidatedSource = (1L<<26); - static const uint64_t SegInvalidatedTarget = (1L<<27); - static const uint64_t SegInvalidatedLayer = (1L<<28); - static const uint64_t SegCreated = (1L<<29); - static const uint64_t SegUserDefined = (1L<<30); - static const uint64_t SegAnalog = (1L<<31); - static const uint64_t SegWide = (1L<<32); + static const uint64_t SegWeakTerminal1 = (1L<<18); // Replace TopologicalEnd. + static const uint64_t SegWeakTerminal2 = (1L<<19); // Replace TopologicalEnd. + static const uint64_t SegNotSourceAligned = (1L<<20); + static const uint64_t SegNotTargetAligned = (1L<<21); + static const uint64_t SegUnbound = (1L<<22); + static const uint64_t SegHalfSlackened = (1L<<23); + static const uint64_t SegSlackened = (1L<<24); + static const uint64_t SegAxisSet = (1L<<25); + static const uint64_t SegInvalidated = (1L<<26); + static const uint64_t SegInvalidatedSource = (1L<<27); + static const uint64_t SegInvalidatedTarget = (1L<<28); + static const uint64_t SegInvalidatedLayer = (1L<<29); + static const uint64_t SegCreated = (1L<<30); + static const uint64_t SegUserDefined = (1L<<31); + static const uint64_t SegAnalog = (1L<<32); + static const uint64_t SegWide = (1L<<33); // Masks. static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; @@ -183,6 +184,7 @@ namespace Anabatic { inline bool isWeakTerminal1 () const; inline bool isWeakTerminal2 () const; inline bool isTerminal () const; + inline bool isDrag () const; inline bool isNotSourceAligned () const; inline bool isNotTargetAligned () const; inline bool isNotAligned () const; @@ -480,6 +482,7 @@ namespace Anabatic { inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; } inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; } inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; } + inline bool AutoSegment::isDrag () const { return _flags & SegDrag; } 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; } diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp index c758b13a..55ae22dc 100644 --- a/crlcore/src/ccore/lefdef/LefImport.cpp +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -445,7 +445,7 @@ namespace { parser->clearPinSegments(); cerr << " - " << cellName - << " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << "\n" << endl; + << " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << endl; parser->setCell( NULL ); return 0; diff --git a/katana/src/Manipulator.cpp b/katana/src/Manipulator.cpp index fa30e39f..0df323cc 100644 --- a/katana/src/Manipulator.cpp +++ b/katana/src/Manipulator.cpp @@ -671,10 +671,10 @@ namespace Katana { Interval toFree (_segment->getCanonicalInterval()); //Net* ripupNet = NULL; set canonicals; - DbU::Unit rightAxisHint = 0; - DbU::Unit leftAxisHint = 0; - bool leftIntrication = false; - bool rightIntrication = false; + //DbU::Unit rightAxisHint = 0; + //DbU::Unit leftAxisHint = 0; + //bool leftIntrication = false; + //bool rightIntrication = false; bool success = true; cdebug_log(159,1) << "Manipulator::_insertInTrack(size_t) - " << toFree << endl; @@ -785,8 +785,8 @@ namespace Katana { if ( event3->getTracksFree() == 1 ) { cdebug_log(159,0) << "Potential left intrication with other perpandicular." << endl; if ( segment3->getAxis() == segment2->getTargetU() - Session::getExtensionCap(getLayer()) ) { - leftIntrication = true; - leftAxisHint = segment3->getAxis(); + //leftIntrication = true; + //leftAxisHint = segment3->getAxis(); } } } @@ -803,8 +803,8 @@ namespace Katana { if ( event3->getTracksFree() == 1 ) { cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl; if ( segment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap(getLayer()) ) { - rightIntrication = true; - rightAxisHint = segment3->getAxis(); + //rightIntrication = true; + //rightAxisHint = segment3->getAxis(); } } } @@ -1422,6 +1422,103 @@ namespace Katana { } + bool Manipulator::dragMinimize () + { + cdebug_log(159,1) << "Manipulator::dragMinimize() " << _segment << endl; + + if (_segment->isFixed()) { cdebug_tabw(159,-1); return false; } + if (not _segment->isDrag()) { cdebug_tabw(159,-1); return false; } + + Interval termConstraints; + + if (_segment->base()->getAutoSource()->canDrag()) { + cdebug_log(159,0) << _segment->base()->getAutoSource() << endl; + termConstraints = _segment->base()->getAutoSource()->getUConstraints( _segment->getDirection() ); + cdebug_log(159,0) << "Terminal Constraints (source): " << termConstraints << endl; + } + if (_segment->base()->getAutoTarget()->canDrag()) { + cdebug_log(159,0) << _segment->base()->getAutoTarget() << endl; + termConstraints = _segment->base()->getAutoTarget()->getUConstraints( _segment->getDirection() ); + cdebug_log(159,0) << "Terminal Constraints (target): " << termConstraints << endl; + } + + if (_fsm.getCosts().size() == 0) { + cerr << Error( "Manipulator::dragMinimize(): The segment cannot be put in any track.\n" + " On: %s" + , getString(_segment).c_str() + ) << endl; + cdebug_tabw(159,-1); + return false; + } + + if (_fsm.getCosts().size() > 1) + cerr << Error( "Manipulator::dragMinimize(): The segment can be put in more than one track (%d).\n" + " On: %s" + , _fsm.getCosts().size() + , getString(_segment).c_str() + ) << endl; + + size_t begin = _fsm.getBegin( 0 ); + size_t end = _fsm.getEnd ( 0 ); + Track* track = _fsm.getTrack( 0 ); + DbU::Unit axisHint = 0; + + if (termConstraints.getSize() < _segment->getPPitch()*2) { + cdebug_log(159,0) << "Constraints less than two perpandicular pitches, lock." << endl; + + for ( ; begin < end ; ++begin ) { + cdebug_log(159,0) << "| Ripup:" << track->getSegment(begin) << endl; + _fsm.addAction( track->getSegment(begin), SegmentAction::OtherRipup ); + } + _fsm.addAction( _segment, SegmentAction::SelfLock ); + + cdebug_tabw(159,-1); + return true; + } + + for ( ; begin < end ; ++begin ) { + TrackElement* conflict = track->getSegment(begin); + if (conflict->getCanonicalInterval().intersect( _segment->getCanonicalInterval() )) break; + } + + Interval previousFree = track->getPreviousFree( begin, _segment->getNet() ); + if (previousFree.intersect(termConstraints)) + axisHint = previousFree.getCenter(); + else { + Interval nextFree = track->getNextFree( end, _segment->getNet() ); + if (nextFree.intersect(termConstraints)) { + axisHint = nextFree.getCenter(); + } else { + cdebug_log(159,0) << "Neither previous free nor next free can be used." << endl; + cdebug_log(159,0) << "| previous:" << previousFree << endl; + cdebug_log(159,0) << "| next: " << nextFree << endl; + cdebug_tabw(159,-1); + return false; + } + } + + cdebug_log(159,0) << "Axis Hint: " << DbU::getValueString(axisHint) << endl; + + const vector& perpandiculars = _event->getPerpandiculars(); + for ( size_t i=0 ; igetDataNegociate(); + if (not data2) continue; + + cdebug_log(159,0) << " | " << perpandiculars[i] << endl; + + RoutingEvent* event2 = data2->getRoutingEvent(); + if (not event2) continue; + + _fsm.addAction( perpandiculars[i], SegmentAction::SelfRipupPerpandWithAxisHint, axisHint ); + } + + _event->setMinimized(); + + cdebug_tabw(159,-1); + return true; + } + + void Manipulator::reprocessPerpandiculars () { if ( _event->getAxisHistory() == _event->getAxisHint() ) return; diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index 222aef16..537cd052 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -41,6 +41,30 @@ namespace { using Anabatic::perpandicularTo; using Anabatic::AutoSegment; using Anabatic::AutoContactTerminal; + using Anabatic::AutoSegments_OnContact; + using Anabatic::AutoSegments; + + + class SortAcByXY { + public: + inline bool operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 ); + }; + + + inline bool SortAcByXY::operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 ) + { + DbU::Unit x1 = contact1->getX(); + DbU::Unit x2 = contact2->getX(); + + if (x1 == x2) { + DbU::Unit y1 = contact1->getY(); + DbU::Unit y2 = contact2->getY(); + + if (y1 == y2) return false; + return (y1 < y2); + } + return (x1 < x2); + } void getPerpandiculars ( TrackElement* segment @@ -323,6 +347,85 @@ namespace { } + void metal2protect ( AutoContactTerminal* contact ) + { + const Layer* metal2 = Session::getRoutingLayer(1); + RoutingPlane* metal3plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( 2 ); + DbU::Unit metal3axis = metal3plane->getTrackByPosition( contact->getY() )->getAxis(); + RoutingPad* rp = dynamic_cast( contact->getAnchor() ); + DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0); + Point position ( contact->getX(), metal3axis ); + + AutoContact* sourceVia12 = AutoContactTerminal::create( contact->getGCell() + , rp + , metal2 + , position + , viaSideProtect, viaSideProtect + ); + AutoContact* targetVia12 = AutoContactTerminal::create( contact->getGCell() + , rp + , metal2 + , position + , viaSideProtect, viaSideProtect + ); + + AutoSegment* segment = AutoSegment::create( sourceVia12, targetVia12, Flags::Vertical ); + + sourceVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor ); + targetVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor ); + segment->setFlags( AutoSegment::SegFixed ); + + Session::getNegociateWindow()->createTrackSegment( segment, Flags::LoadingStage ); + + cdebug_log(145,0) << "Hard protect: " << contact << endl; + cdebug_log(145,0) << "X:" << DbU::getValueString(position.getX()) + << " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl; + } + + + void protectAlignedAccesses ( GCell* gcell ) + { + DbU::Unit pitch3 = Session::getPitch( 2 ); + + multiset acTerminals; + for ( AutoContact* contact : gcell->getContacts() ) { + if (contact->isTerminal() and (Session::getViaDepth(contact->getLayer()) == 0) ) + acTerminals.insert( dynamic_cast(contact) ); + } + + AutoContactTerminal* south = NULL; + for ( AutoContactTerminal* north : acTerminals ) { + if (south) { + if (south->canDrag() and north->canDrag() and (south->getX() == north->getX())) { + //Interval constraints ( north->getCBYMax() - pitch3, gcell->getYMin() ); + Interval constraints ( north->getCBYMin() - pitch3, gcell->getYMin() ); + AutoSegment* terminal = south->getSegment(); + AutoContact* opposite = terminal->getOppositeAnchor( south ); + + for ( AutoSegment* segment : AutoSegments_OnContact(terminal,opposite->base()) ) { + segment->mergeUserConstraints( constraints ); + cerr << "Apply " << constraints << " to " << segment << endl; + } + + //constraints = Interval( south->getCBYMin() + pitch3, gcell->getYMax() ); + constraints = Interval( south->getCBYMax() + pitch3, gcell->getYMax() ); + terminal = north->getSegment(); + opposite = terminal->getOppositeAnchor( north ); + + for ( AutoSegment* segment : AutoSegments_OnContact(terminal,opposite->base()) ) { + segment->mergeUserConstraints( constraints ); + cerr << "Apply " << constraints << " to " << segment << endl; + } + } + + //if (south->getConstraintBox().getHeight() < pitch3*2) metal2protect( south ); + //if (north->getConstraintBox().getHeight() < pitch3*2) metal2protect( north ); + } + south = north; + } + } + + } // End of local namespace. @@ -337,6 +440,8 @@ namespace Katana { void KatanaEngine::preProcess () { + //DebugSession::open( 145, 150 ); + for ( size_t i=0 ; i<_routingPlanes.size() ; ++i ) { RoutingPlane* plane = _routingPlanes[i]; @@ -346,6 +451,11 @@ namespace Katana { track = track->getNextTrack(); } } + + for ( GCell* gcell : getGCells() ) protectAlignedAccesses( gcell ); + + //DebugSession::close(); + Session::revalidate (); } diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index cac6d9ac..20d9973d 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -365,7 +365,9 @@ namespace Katana { DebugSession::open( _segment->getNet(), 156, 160 ); - if (_type & Perpandicular) { + if (_type & Lock) { + cdebug_log(159,0) << "* Lock // " << _segment << endl; + } else if (_type & Perpandicular) { cdebug_log(159,0) << "* Riping Pp " << _segment << endl; } else { cdebug_log(159,0) << "* Riping // " << _segment << endl; @@ -393,6 +395,8 @@ namespace Katana { return true; } + if (_type&Lock) Session::addLockEvent( _segment ); + if ( (_type & AxisHint) /*and not _segment->isSlackenDogleg()*/ ) { cdebug_log(159,0) << "Setting Axis Hint: @" << DbU::getValueString(_axisHint) << endl; event->setAxisHint( _axisHint ); @@ -1177,6 +1181,7 @@ namespace Katana { uint32_t nextState = data->getState(); Manipulator manipulator ( segment, *this ); + switch (data->getState()) { case DataNegociate::RipupPerpandiculars: nextState = DataNegociate::Minimize; @@ -1189,7 +1194,10 @@ namespace Katana { break; } nextState = DataNegociate::Dogleg; - success = manipulator.minimize(); + // if (segment->isDrag()) + // success = manipulator.dragMinimize(); + // else + success = manipulator.minimize(); if (success) break; case DataNegociate::Dogleg: nextState = DataNegociate::Slacken; @@ -1222,6 +1230,7 @@ namespace Katana { } } case DataNegociate::Unimplemented: + if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl; nextState = DataNegociate::Unimplemented; break; } diff --git a/katana/src/Session.cpp b/katana/src/Session.cpp index 04450bfe..69d67948 100644 --- a/katana/src/Session.cpp +++ b/katana/src/Session.cpp @@ -17,21 +17,68 @@ #include "hurricane/Bug.h" #include "hurricane/Point.h" #include "hurricane/Error.h" +#include "hurricane/RoutingPad.h" +#include "anabatic/AutoContactTerminal.h" #include "katana/Session.h" #include "katana/Track.h" #include "katana/TrackElement.h" #include "katana/KatanaEngine.h" #include "katana/RoutingPlane.h" +#include "katana/NegociateWindow.h" namespace { + using namespace std; + using namespace Hurricane; + using namespace CRL; using namespace Katana; + using Anabatic::perpandicularTo; + using Anabatic::AutoSegment; + using Anabatic::AutoContactTerminal; + using Anabatic::AutoSegments_OnContact; + using Anabatic::AutoSegments; const char* reopenSession = "Katana::Session::_open(): Session already open for %s (internal error)."; + void metal2protect ( AutoContactTerminal* contact ) + { + const Layer* metal2 = Session::getRoutingLayer(1); + RoutingPlane* metal3plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( 2 ); + DbU::Unit metal3axis = metal3plane->getTrackByPosition( contact->getY() )->getAxis(); + RoutingPad* rp = dynamic_cast( contact->getAnchor() ); + DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0); + Point position ( contact->getX(), metal3axis ); + + AutoContact* sourceVia12 = AutoContactTerminal::create( contact->getGCell() + , rp + , metal2 + , position + , viaSideProtect, viaSideProtect + ); + AutoContact* targetVia12 = AutoContactTerminal::create( contact->getGCell() + , rp + , metal2 + , position + , viaSideProtect, viaSideProtect + ); + + AutoSegment* segment = AutoSegment::create( sourceVia12, targetVia12, Flags::Vertical ); + + sourceVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor ); + targetVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor ); + segment->setFlags( AutoSegment::SegFixed ); + + Session::getNegociateWindow()->createTrackSegment( segment, Flags::NoFlags ); + + cdebug_log(145,0) << "Hard protect: " << contact << endl; + cdebug_log(145,0) << "X:" << DbU::getValueString(position.getX()) + << " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl; + } + + } // Anonymous namespace. @@ -149,10 +196,23 @@ namespace Katana { } + void Session::_doLockEvents () + { + for ( size_t i=0 ; i<_lockEvents.size() ; ++i ) { + AutoContactTerminal* source = dynamic_cast( _lockEvents[i]._segment->base()->getAutoSource() ); + AutoContactTerminal* target = dynamic_cast( _lockEvents[i]._segment->base()->getAutoTarget() ); + if (source and source->canDrag()) metal2protect( source ); + if (target and target->canDrag()) metal2protect( target ); + } + _lockEvents.clear(); + } + + size_t Session::_revalidate () { cdebug_log(159,1) << "Katana::Session::_revalidate()" << endl; + _doLockEvents(); _doRemovalEvents(); for ( const Event& event : _insertEvents ) { @@ -302,6 +362,19 @@ namespace Katana { } + void Session::_addLockEvent ( TrackElement* segment ) + { + if (not segment->isTerminal()) { + cerr << Bug( " Katana::Session::addLockEvent() : %s is not connected to a terminal." + , getString(segment).c_str() ) << endl; + return; + } + + cdebug_log(159,0) << "Lock: @" << DbU::getValueString(segment->getAxis()) << " " << segment << endl; + _lockEvents.push_back( Event(segment,NULL) ); + } + + void Session::_addMoveEvent ( TrackElement* segment, Track* track ) { if (not segment->getTrack()) { diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 8feeb29b..2eb443a6 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -589,6 +589,42 @@ namespace Katana { } + Interval Track::getNextFree ( size_t index, Net* net ) + { + if (_segments.empty()) return Interval( _min, _max ); + + if (index >= _segments.size()) { + size_t last = _segments.size()-1; + return Interval( getOccupiedInterval(last).getVMax(), _max ); + } + + Interval occupied = getOccupiedInterval( index ); + return getFreeInterval( occupied.getVMax()+1, net ); + } + + + Interval Track::getPreviousFree ( size_t index, Net* net ) + { + cdebug_log(155,1) << "Track::getPreviousFree() index:" << index << " " << net << endl; + + if (_segments.empty()) { cdebug_tabw(155,-1); return Interval( _min, _max ); } + + if (index == 0) { + size_t first = 0; + Interval free = Interval( _min, getOccupiedInterval(first).getVMin() ); + cdebug_tabw(155,-1); + return free; + } + + + Interval occupied = getOccupiedInterval( index ); + cdebug_log(155,0) << "Previous occupied:" << occupied << endl; + Interval free = getFreeInterval( occupied.getVMin()-1, net ); + cdebug_tabw(155,-1); + return free; + } + + Interval Track::getOccupiedInterval ( size_t& begin ) const { if (begin == npos) return Interval(); diff --git a/katana/src/TrackElement.cpp b/katana/src/TrackElement.cpp index 572f24f1..97503249 100644 --- a/katana/src/TrackElement.cpp +++ b/katana/src/TrackElement.cpp @@ -137,6 +137,7 @@ namespace Katana { bool TrackElement::isGlobal () const { return not isLocal(); } bool TrackElement::isBipoint () const { return false; } bool TrackElement::isTerminal () const { return false; } + bool TrackElement::isDrag () const { return false; } bool TrackElement::isStrongTerminal ( Flags ) const { return false; } bool TrackElement::isStrap () const { return false; } bool TrackElement::isSlackened () const { return false; } diff --git a/katana/src/TrackSegment.cpp b/katana/src/TrackSegment.cpp index 903e0f2e..10e20738 100644 --- a/katana/src/TrackSegment.cpp +++ b/katana/src/TrackSegment.cpp @@ -160,6 +160,7 @@ namespace Katana { bool TrackSegment::isGlobal () const { return _base->isWeakGlobal() or _base->isGlobal(); } bool TrackSegment::isBipoint () const { return _base->isBipoint(); } bool TrackSegment::isTerminal () const { return _base->isTerminal(); } + bool TrackSegment::isDrag () const { return _base->isDrag(); } bool TrackSegment::isStrongTerminal ( Flags flags ) const { return _base->isStrongTerminal(flags); } bool TrackSegment::isStrap () const { return _base->isStrap(); } bool TrackSegment::isSlackened () const { return _base->isSlackened(); } diff --git a/katana/src/katana/Manipulator.h b/katana/src/katana/Manipulator.h index 345f5b5f..16de03ad 100644 --- a/katana/src/katana/Manipulator.h +++ b/katana/src/katana/Manipulator.h @@ -67,6 +67,7 @@ namespace Katana { void reprocessPerpandiculars (); bool ripple (); bool minimize (); + bool dragMinimize (); bool slacken ( Flags flags=Flags::NoFlags ); bool pivotUp (); bool pivotDown (); diff --git a/katana/src/katana/SegmentFsm.h b/katana/src/katana/SegmentFsm.h index 508c635a..a72f5342 100644 --- a/katana/src/katana/SegmentFsm.h +++ b/katana/src/katana/SegmentFsm.h @@ -43,13 +43,15 @@ namespace Katana { , ToRipupLimit = (1<< 7) , MoveToAxis = (1<< 8) , AxisHint = (1<< 9) - , PackingMode = (1<<10) - , ToState = (1<<11) - , EventLevel1 = (1<<12) - , EventLevel2 = (1<<13) - , EventLevel3 = (1<<14) - , EventLevel4 = (1<<15) - , EventLevel5 = (1<<16) + , Lock = (1<<10) + , PackingMode = (1<<11) + , ToState = (1<<12) + , EventLevel1 = (1<<13) + , EventLevel2 = (1<<14) + , EventLevel3 = (1<<15) + , EventLevel4 = (1<<16) + , EventLevel5 = (1<<17) + , SelfLock = Self |Lock , SelfInsert = Self |Insert , SelfRipup = Self |Ripup , SelfRipupPerpand = Self |Ripup|Perpandicular diff --git a/katana/src/katana/Session.h b/katana/src/katana/Session.h index ff2769d1..8f465c9e 100644 --- a/katana/src/katana/Session.h +++ b/katana/src/katana/Session.h @@ -79,6 +79,7 @@ namespace Katana { inline static void addRemoveEvent ( TrackElement* ); inline static void addMoveEvent ( TrackElement* , Track* ); inline static void addSortEvent ( Track*, bool forced=false ); + inline static void addLockEvent ( TrackElement* ); inline static size_t revalidate (); static AutoContact* lookup ( Contact* ); static TrackElement* lookup ( Segment* ); @@ -89,6 +90,7 @@ namespace Katana { Net* _getBlockageNet (); uint32_t _getRipupCost (); Anabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit ); + void _doLockEvents (); void _doRemovalEvents (); virtual size_t _revalidate (); bool _isEmpty () const; @@ -98,6 +100,7 @@ namespace Katana { void _addRemoveEvent ( TrackElement* ); void _addMoveEvent ( TrackElement* , Track* ); void _addSortEvent ( Track*, bool forced ); + void _addLockEvent ( TrackElement* ); virtual Record* _getRecord () const; virtual string _getTypeName () const; protected: @@ -115,6 +118,7 @@ namespace Katana { // Attributes. vector _insertEvents; vector _removeEvents; + vector _lockEvents; set _sortEvents; protected: // Constructors & Destructors. @@ -172,6 +176,9 @@ namespace Katana { inline void Session::addMoveEvent ( TrackElement* segment, Track* track ) { get("addMoveEvent()")->_addMoveEvent(segment,track); } + inline void Session::addLockEvent ( TrackElement* segment ) + { get("addLockEvent()")->_addLockEvent(segment); } + inline void Session::addSortEvent ( Track* track, bool forced ) { get("addSortEvent()")->_addSortEvent(track,forced); } diff --git a/katana/src/katana/Track.h b/katana/src/katana/Track.h index 60b3f412..2f607041 100644 --- a/katana/src/katana/Track.h +++ b/katana/src/katana/Track.h @@ -91,6 +91,8 @@ namespace Katana { DbU::Unit getMinimalPosition ( size_t index, uint32_t state ) const; DbU::Unit getMaximalPosition ( size_t index, uint32_t state ) const; Interval getFreeInterval ( DbU::Unit position, Net* net=NULL ) const; + Interval getNextFree ( size_t index, Net* net ); + Interval getPreviousFree ( size_t index, Net* net ); Interval getOccupiedInterval ( size_t& begin ) const; Interval expandFreeInterval ( size_t& begin, size_t& end, uint32_t state, Net* ) const; void getBeginIndex ( DbU::Unit position, size_t& begin, uint32_t& state ) const; diff --git a/katana/src/katana/TrackElement.h b/katana/src/katana/TrackElement.h index 9fb7f575..dde62c62 100644 --- a/katana/src/katana/TrackElement.h +++ b/katana/src/katana/TrackElement.h @@ -106,6 +106,7 @@ namespace Katana { virtual bool isGlobal () const; virtual bool isBipoint () const; virtual bool isTerminal () const; + virtual bool isDrag () const; virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; virtual bool isStrap () const; virtual bool isSlackened () const; diff --git a/katana/src/katana/TrackSegment.h b/katana/src/katana/TrackSegment.h index 874f5535..bb77dbae 100644 --- a/katana/src/katana/TrackSegment.h +++ b/katana/src/katana/TrackSegment.h @@ -69,6 +69,7 @@ namespace Katana { virtual bool isGlobal () const; virtual bool isBipoint () const; virtual bool isTerminal () const; + virtual bool isDrag () const; virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; virtual bool isStrap () const; virtual bool isSlackened () const;