diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index b5ab4d0b..15f80dc8 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -18,6 +18,7 @@ #include #include "hurricane/Bug.h" #include "hurricane/Error.h" +#include "hurricane/Warning.h" #include "hurricane/Breakpoint.h" #include "hurricane/RegularLayer.h" #include "hurricane/Horizontal.h" @@ -29,20 +30,108 @@ #include "crlcore/RoutingGauge.h" #include "crlcore/Measures.h" #include "anabatic/GCell.h" +#include "anabatic/AutoContactTerminal.h" #include "anabatic/NetBuilderM2.h" #include "anabatic/NetBuilderHV.h" #include "anabatic/NetBuilderVH.h" #include "anabatic/AnabaticEngine.h" +namespace { + + using namespace Hurricane; + using namespace Anabatic; + + + 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 shear ( AutoSegment* segment ) + { + AutoContact* source = segment->getAutoSource(); + AutoContact* target = segment->getAutoTarget(); + bool useSource = true; + + if (segment->isHorizontal()) { + if (not source->isTurn() and target->isTurn()) useSource = false; + } else { + if (not source->isTurn() and target->isTurn()) useSource = false; + } + + segment->makeDogleg( (useSource ? source->getGCell() : target->getGCell()) ); + Session::getDoglegs()[ Session::getDoglegs().size()-2 ]->unsetFlags( AutoSegment::SegAxisSet ); + +#if BAD_RESULTS + AutoContact* source = segment->getAutoSource(); + AutoContact* target = segment->getAutoTarget(); + AutoSegment* perpandicular = NULL; + bool useSource = true; + + if (segment->isHorizontal()) { + if (source->isTurn()) perpandicular = source->getPerpandicular( segment ); + else { + if (target->isTurn()) { perpandicular = target->getPerpandicular( segment ); useSource = false; } + else { + if (source->isHTee()) perpandicular = source->getPerpandicular( segment ); + else { + if (target->isHTee()) { perpandicular = target->getPerpandicular( segment ); useSource = false; } + else + perpandicular = segment; + } + } + } + } else { + if (source->isTurn()) perpandicular = source->getPerpandicular( segment ); + else { + if (target->isTurn()) { perpandicular = target->getPerpandicular( segment ); useSource = false; } + else { + if (source->isVTee()) perpandicular = source->getPerpandicular( segment ); + else { + if (target->isVTee()) { perpandicular = target->getPerpandicular( segment ); useSource = false; } + else + perpandicular = segment; + } + } + } + } + + perpandicular->makeDogleg( (useSource ? source->getGCell() : target->getGCell()) ); +#endif + } + + +} // Anonymous namespace. + + namespace Anabatic { using std::cerr; using std::cout; using std::endl; + using std::multiset; using std::ostringstream; using Hurricane::Bug; using Hurricane::Error; + using Hurricane::Warning; using Hurricane::Breakpoint; using Hurricane::RegularLayer; using Hurricane::Component; @@ -416,6 +505,7 @@ namespace Anabatic { for ( GCell* gcell : _gcells ) _updateLookup( gcell ); } + size_t AnabaticEngine::getNetsFromEdge ( const Edge* edge, NetSet& nets ) { size_t count = 0; @@ -719,11 +809,136 @@ namespace Anabatic { throw Error( badMethod, "Anabatic::loadGlobalRouting()", method, getString(_cell).c_str() ); } cleanupGlobal(); + relaxOverConstraineds(); _state = EngineActive; } + void AnabaticEngine::relaxOverConstraineds () + { + openSession(); + + DbU::Unit pitch3 = Session::getPitch( 2 ); + AutoSegment::IdSet constraineds; + AutoSegment::IdSet processeds; + + for ( GCell* gcell : _gcells ) { + //cerr << "@ " << gcell << endl; + + 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 ) { + //cerr << "@ " << north << endl; + if (south) { + if ( south->canDrag() + and north->canDrag() + and (south->getNet() != north->getNet()) + 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 ); + constraineds.insert( segment ); + //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 ); + constraineds.insert( segment ); + //cerr << "Apply " << constraints << " to " << segment << endl; + } + } + + //if (south->getConstraintBox().getHeight() < pitch3*2) metal2protect( south ); + //if (north->getConstraintBox().getHeight() < pitch3*2) metal2protect( north ); + } + south = north; + } + } + + Session::revalidate(); + + for ( AutoSegment* constrained : constraineds ) { + if (processeds.find(constrained) != processeds.end()) continue; + processeds.insert( constrained ); + + Interval userConstraints ( false ); + vector aligneds; + + aligneds.push_back( constrained ); + + for ( AutoSegment* aligned : constrained->getAligneds() ) { + aligneds.push_back( aligned ); + processeds.insert( aligned ); + } + + sort( aligneds.begin(), aligneds.end(), AutoSegment::CompareBySourceU() ); + + AutoSegment* previous = NULL; + for ( AutoSegment* aligned : aligneds ) { + Interval constraints = userConstraints.getIntersection( aligned->getUserConstraints() ); + cerr << "aligned: " << aligned << " " << aligned->getUserConstraints() << endl; + + if (constraints.getSize() < Session::getPitch(1)) { + if (not previous) { + cerr << Warning( "protectAlignedAccesses(): Shearing constraints between S/T on\n" + " %s\n" + " S:%s\n" + " T:%s\n" + " Combined user constraints are too tight [%s : %s]." + , getString(aligned ).c_str() + , getString(aligned->getAutoSource()->getConstraintBox()).c_str() + , getString(aligned->getAutoTarget()->getConstraintBox()).c_str() + , DbU::getValueString(constraints.getVMin()).c_str() + , DbU::getValueString(constraints.getVMax()).c_str() + ) << endl; + } else { + cerr << Warning( "protectAlignedAccesses(): Shearing constraints between\n" + " %s\n" + " %s\n" + " Combined user constraints are too tight [%s : %s]." + , getString(previous).c_str() + , getString(aligned ).c_str() + , DbU::getValueString(constraints.getVMin()).c_str() + , DbU::getValueString(constraints.getVMax()).c_str() + ) << endl; + } + //if (previous) { + // if (previous->getAutoTarget() == aligned->getAutoSource()) { + // cerr << "Found a shared contact: " << aligned->getAutoSource() << endl; + shear( aligned ); + // } + //} + + userConstraints = aligned->getUserConstraints(); + } else { + userConstraints = constraints; + } + + previous = aligned; + } + + cerr << "Final user constraints:" << userConstraints << endl; + } + + Session::close(); + } + + void AnabaticEngine::_loadGrByNet () { cmess1 << " o Building detailed routing from global. " << endl; diff --git a/anabatic/src/AutoContactHTee.cpp b/anabatic/src/AutoContactHTee.cpp index bcdd16bd..936a0b81 100644 --- a/anabatic/src/AutoContactHTee.cpp +++ b/anabatic/src/AutoContactHTee.cpp @@ -91,8 +91,11 @@ namespace Anabatic { } - AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const - { return NULL; } + AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const + { + if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1; + return NULL; + } AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const diff --git a/anabatic/src/AutoContactTerminal.cpp b/anabatic/src/AutoContactTerminal.cpp index d72275df..ce4ddb0c 100644 --- a/anabatic/src/AutoContactTerminal.cpp +++ b/anabatic/src/AutoContactTerminal.cpp @@ -172,9 +172,36 @@ namespace Anabatic { if (component == NULL) { cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl; cdebug_tabw(145,-1); - return _gcell->getBoundingBox (); + return _gcell->getBoundingBox(); } - + + RoutingLayerGauge* lg = Session::getLayerGauge( Session::getLayerDepth(component->getLayer()) ); + DbU::Unit xborder = 0; + DbU::Unit yborder = 0; + const Layer* viaLayer = Session::getContactLayer( lg->getDepth() ); + + if (viaLayer) { + if (lg->isHorizontal() and (lg->getDepth() != 0)) { + xborder = Session::getViaWidth( lg->getDepth() )/2 + + viaLayer->getBottomEnclosure( Layer::EnclosureH ); + } else { + yborder = Session::getViaWidth( lg->getDepth() )/2 + + viaLayer->getBottomEnclosure( Layer::EnclosureV ); + xborder = Session::getViaWidth( lg->getDepth() )/2 + + viaLayer->getBottomEnclosure( Layer::EnclosureH ); + + if (Session::getRoutingGauge()->isSymbolic()) { + // SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on + // their extremities. Should modificate all the standard cells layout... + // HARDCODED. + if (Session::getRoutingGauge()->getName() == "msxlib") + yborder -= DbU::fromLambda( 1.0 ); + else + yborder -= DbU::fromLambda( 0.5 ); + } + } + } + DbU::Unit xMin; DbU::Unit xMax; DbU::Unit yMin; @@ -211,6 +238,17 @@ namespace Anabatic { if (vertical) { bb = vertical ->getBoundingBox(); const_cast(this)->setFlags( CntOnVertical ); } transformation.applyOn( bb ); + cdebug_log(145,0) << "Shrink border x:" << DbU::getValueString(xborder) + << " y:" << DbU::getValueString(yborder) + << endl; + + // HARDCODED. + if ( (Session::getRoutingGauge()->getName() == "sxlib") + and (bb.getWidth() == DbU::fromLambda(1.0)) ) { + bb.inflate( DbU::fromLambda(0.5), 0 ); + } + + bb.inflate( -xborder, -yborder ); xMin = bb.getXMin(); yMin = bb.getYMin(); xMax = bb.getXMax(); @@ -298,6 +336,7 @@ namespace Anabatic { void AutoContactTerminal::cacheDetach ( AutoSegment* segment ) { if (_segment == segment) { + _segment->unsetFlags( AutoSegment::SegAxisSet ); _segment = NULL; setFlags( CntInvalidatedCache ); unsetFlags( CntDrag ); @@ -325,7 +364,7 @@ namespace Anabatic { if ( (dynamic_cast(_segment) and (getFlags() & CntOnHorizontal)) or (dynamic_cast (_segment) and (getFlags() & CntOnVertical )) ) { - _segment->setFlags( AutoSegment::SegDrag ); + _segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegAxisSet ); setFlags( CntDrag ); cdebug_log(145,0) << "Drag Contact/Segment set" << endl; @@ -364,13 +403,13 @@ namespace Anabatic { _segment = Session::lookup( horizontals[0] ); if (getFlags() & CntOnHorizontal) { setFlags( CntDrag ); - _segment->setFlags( AutoSegment::SegDrag ); + _segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis ); } } else { _segment = Session::lookup( verticals[0] ); if (getFlags() & CntOnVertical) { setFlags( CntDrag ); - _segment->setFlags( AutoSegment::SegDrag ); + _segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis ); } } if (_segment == NULL) { diff --git a/anabatic/src/AutoContactVTee.cpp b/anabatic/src/AutoContactVTee.cpp index 96e5231a..c85c0993 100644 --- a/anabatic/src/AutoContactVTee.cpp +++ b/anabatic/src/AutoContactVTee.cpp @@ -91,8 +91,11 @@ namespace Anabatic { } - AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const - { return NULL; } + AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* from ) const + { + if ( (from == _vertical1) or (from == _vertical2) ) return _horizontal1; + return NULL; + } AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const diff --git a/anabatic/src/AutoHorizontal.cpp b/anabatic/src/AutoHorizontal.cpp index 747db712..36a55ba0 100644 --- a/anabatic/src/AutoHorizontal.cpp +++ b/anabatic/src/AutoHorizontal.cpp @@ -18,6 +18,7 @@ #include "hurricane/Bug.h" #include "hurricane/Error.h" #include "hurricane/DebugSession.h" +#include "hurricane/ViaLayer.h" #include "hurricane/RoutingPad.h" #include "crlcore/RoutingGauge.h" #include "anabatic/Configuration.h" @@ -35,6 +36,7 @@ namespace Anabatic { using Hurricane::Error; using Hurricane::Bug; using Hurricane::DebugSession; + using Hurricane::ViaLayer; using Hurricane::RoutingPad; @@ -330,7 +332,7 @@ namespace Anabatic { const vector& doglegs = Session::getDoglegs(); if (sourceSlackened and (doglegs.size() >= 2)) { - cdebug_log(149,0) << "AutoHorizontal::_slacken(): Source @" << DbU::getValueString(getSourcePosition()) << endl; + cdebug_log(149,0) << "Slackened from source @" << DbU::getValueString(getSourcePosition()) << endl; doglegs[doglegs.size()-2]->setAxis( getSourcePosition() ); success = true; @@ -459,8 +461,8 @@ namespace Anabatic { void AutoHorizontal::updatePositions () { - _sourcePosition = _horizontal->getSourceX() - getExtensionCap(); - _targetPosition = _horizontal->getTargetX() + getExtensionCap(); + _sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source); + _targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target); } @@ -480,11 +482,11 @@ namespace Anabatic { bool AutoHorizontal::checkPositions () const { bool coherency = true; - DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(); - DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(); + DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source); + DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target); if ( _sourcePosition != sourcePosition ) { - cerr << "extensionCap: " << DbU::getValueString(getExtensionCap()) << endl; + cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl; cerr << "ppitch: " << DbU::getValueString(getPPitch()) << endl; cerr << "via width: " << DbU::getValueString(Session::getViaWidth(getLayer())) << endl; cerr << Error ( "%s\n Source position incoherency: " @@ -791,8 +793,17 @@ namespace Anabatic { } while ( gcell and (gcell != end) ); } - size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() ); - bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() ); + bool upLayer = true; + + if (Session::getRoutingGauge()->isTwoMetals()) { + upLayer = (depth == 0); + } else if (Session::getRoutingGauge()->isVH()) { + upLayer = (depth < 2); + } else { + upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + } + Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) ); const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) ); @@ -859,7 +870,7 @@ namespace Anabatic { updateNativeConstraints(); segment2->updateNativeConstraints(); - if (autoTarget->canDrag()) { + if (autoTarget->canDrag() and not autoSource->canDrag()) { Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal); segment1->mergeUserConstraints( dragConstraints ); diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index 244c85d3..fe1c8b0c 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -18,6 +18,7 @@ #include "hurricane/Bug.h" #include "hurricane/DataBase.h" #include "hurricane/Technology.h" +#include "hurricane/ViaLayer.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "crlcore/RoutingGauge.h" @@ -370,19 +371,76 @@ namespace Anabatic { } +// ------------------------------------------------------------------- +// Class : "Anabatic::AutoSegment::CompareBySourceU". + + + bool AutoSegment::CompareBySourceU::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const + { + DbU::Unit deltaUnit = lhs->getSourceU() - rhs->getSourceU(); + if (deltaUnit < 0) return true; // Smallest source first. + if (deltaUnit > 0) return false; + + return lhs->getId() < rhs->getId(); // Smallest Id first. + } + + // ------------------------------------------------------------------- // Class : "Anabatic::AutoSegment". - size_t AutoSegment::_allocateds = 0; - size_t AutoSegment::_globalsCount = 0; - bool AutoSegment::_analogMode = false; + size_t AutoSegment::_allocateds = 0; + size_t AutoSegment::_globalsCount = 0; + bool AutoSegment::_analogMode = false; + bool AutoSegment::_initialized = false; + vector< array > AutoSegment::_extensionCaps; void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; } bool AutoSegment::getAnalogMode () { return _analogMode; } + void AutoSegment::_initialize () + { + cerr << "AutoSegment::_initialize()" << endl; + + _initialized = true; + for ( size_t depth=0 ; depthisVertical()); + uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ; + + cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName() + << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl; + + *viaToSameCap = Session::getWireWidth(depth)/2; + + // Bottom metal of the VIA going *up*. + const Layer* viaLayer = dynamic_cast( Session::getContactLayer(depth) ); + if (viaLayer) + *viaToTopCap = Session::getViaWidth(depth)/2 + viaLayer->getBottomEnclosure( flags ); + + // Top metal of the VIA going *down*. + if (depth > 0) { + viaLayer = dynamic_cast( Session::getContactLayer(depth-1) ); + if (viaLayer) + *viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags ); + } + + cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl; + cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl; + if (depth > 0) + cerr << " viaToBottom width:" << DbU::getValueString( Session::getViaWidth(depth-1)/2 ) << endl; + cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl; + cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl; + + _extensionCaps.push_back( std::array( { viaToTopCap, viaToBottomCap, viaToSameCap } ) ); + } + } + + AutoSegment::AutoSegment ( Segment* segment ) : _id (segment->getId()) , _gcell (NULL) @@ -398,14 +456,16 @@ namespace Anabatic { , _parent (NULL) , _observers () { + if (not _initialized) _initialize(); + _allocateds++; if (dynamic_cast(segment)) setFlags( SegHorizontal ); _globalsCount += isGlobal() ? 1 : 0; - AutoContact* source = Session::lookup(dynamic_cast(segment->getSource())); - AutoContact* target = Session::lookup(dynamic_cast(segment->getTarget())); + AutoContact* source = Session::lookup(dynamic_cast(segment->getSource())); + AutoContact* target = Session::lookup(dynamic_cast(segment->getTarget())); if (source->isTerminal()) setFlags( SegSourceTerminal ); if (target->isTerminal()) setFlags( SegTargetTerminal ); @@ -544,8 +604,7 @@ namespace Anabatic { cdebug_tabw(149,1); - updateOrient (); - updatePositions(); + updateOrient(); uint64_t oldSpinFlags = _flags & SegDepthSpin; @@ -575,6 +634,8 @@ namespace Anabatic { incReduceds(); } + updatePositions(); + unsigned int observerFlags = Revalidate; if ( (_flags & SegCreated) or (oldSpinFlags != (_flags & SegDepthSpin)) ) observerFlags |= RevalidatePPitch; @@ -616,15 +677,29 @@ namespace Anabatic { } - DbU::Unit AutoSegment::getExtensionCap () const + DbU::Unit AutoSegment::getExtensionCap ( Flags flags ) const { - DbU::Unit mWidth = std::max( Session::getWireWidth(getLayer()), Session::getViaWidth(getLayer()) ); - if (getWidth() <= mWidth) return Session::getExtensionCap( getLayer() ); - return getWidth() / 2; -#if NEW_WAY - if (getWidth() <= mWidth) return mWidth/2 + getPitch()/2; - return getWidth()/2 + getPitch()/2; -#endif + size_t depth = Session::getLayerDepth( getLayer() ); + DbU::Unit cap = 0; + + if (flags & Flags::Source) { + if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth); + else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth); + else cap = getViaToSameCap (depth); + cdebug_log(159,0) << "getExtensionCap(): flags:" << getFlags() + << " VIA cap:" << DbU::getValueString(cap) + << " " << (getFlags() & SegSourceBottom) + << endl; + } + + if (flags & Flags::Target) { + if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth); + else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth); + else cap = getViaToSameCap (depth); + } + + if (cap < getWidth()/2) cap = getWidth()/2; + return cap + getLayer()->getMinimalSpacing()/2;; } @@ -702,6 +777,22 @@ namespace Anabatic { } + void AutoSegment::getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const + { + cdebug_log(145,0) << "AutoSegment::getEndAxes() - " << this << endl; + + sourceAxis = getSourceU(); + targetAxis = getTargetU(); + + if (not isNotAligned()) { + for( AutoSegment* aligned : const_cast(this)->getAligneds() ) { + sourceAxis = std::min( sourceAxis, aligned->getSourceU() ); + targetAxis = std::min( targetAxis, aligned->getTargetU() ); + } + } + } + + AutoSegments AutoSegment::getOnSourceContact ( Flags direction ) { return AutoSegments_OnContact @@ -1029,6 +1120,43 @@ namespace Anabatic { cdebug_log(145,0) << "Constraints: [" << DbU::getValueString(constraintMin) << " " << DbU::getValueString(constraintMax) << "]" << endl; + AutoContact* source = getAutoSource(); + AutoContact* target = getAutoTarget(); + + if (isLocal() and source->isTurn() and target->isTurn() and not isUserDefined()) { + AutoSegment* sourcePerpand = source->getPerpandicular(this); + AutoSegment* targetPerpand = target->getPerpandicular(this); + + sourcePerpand->updateOrient(); + targetPerpand->updateOrient(); + + if (not ( (sourcePerpand->getAutoSource() == source) + xor (targetPerpand->getAutoSource() == target) ) ) { + // This is a U-Turn. + DbU::Unit optimal = 0; + + if (sourcePerpand->getAutoSource() == source) { + optimal = std::min( sourcePerpand->getTargetU(), targetPerpand->getTargetU() ); + optimal = std::min( optimal, constraintMax ); + } else { + optimal = std::max( sourcePerpand->getSourceU(), targetPerpand->getSourceU() ); + optimal = std::max( optimal, constraintMin ); + } + + cdebug_log(145,0) << "| Source perpandicular: " << sourcePerpand << endl; + cdebug_log(145,0) << "| Target perpandicular: " << targetPerpand << endl; + cdebug_log(145,0) << "Applying constraint (U-Turn) on: " << this << endl; + cdebug_log(145,0) << "optimal: " << DbU::getValueString(optimal) << endl; + + setOptimalMin( optimal ); + setOptimalMax( optimal ); + processeds.insert( this ); + + cdebug_tabw(145,-1); + return; + } + } + if (isUserDefined()) { optimalMin = optimalMax = getAxis(); aligneds.push_back( this ); @@ -1368,7 +1496,7 @@ namespace Anabatic { bool AutoSegment::canReduce () const { - if (isGlobal()) return false; + if (isGlobal() or isDrag()) return false; if (not isSpinTopOrBottom()) return false; if (_reduceds) return false; @@ -1442,8 +1570,9 @@ namespace Anabatic { _changeDepth( depth, flags & ~Flags::Propagate ); if ((flags & Flags::Propagate) and not isNotAligned()) { - forEach ( AutoSegment*, isegment, getAligneds(Flags::NoCheckLayer) ) { - (*isegment)->_changeDepth( depth, flags & ~Flags::Propagate ); + cdebug_log(149,0) << "Propagate to aligneds." << endl; + for ( AutoSegment* segment : getAligneds(Flags::NoCheckLayer) ) { + segment->_changeDepth( depth, flags & ~Flags::Propagate ); } } @@ -1525,8 +1654,8 @@ namespace Anabatic { success = success or _slacken( flags ); if ((flags & Flags::Propagate) and not isNotAligned()) { - forEach ( AutoSegment*, isegment, getAligneds() ) { - success = success or (*isegment)->_slacken( flags ); + for ( AutoSegment* segment : getAligneds() ) { + success = success or segment->_slacken( flags ); } } @@ -2135,6 +2264,7 @@ namespace Anabatic { { string state; state += isFixed () ?" F":" -"; + state += isFixedAxis () ? "X": "-"; state += isUnsetAxis () ? "u": "-"; state += isStrap () ? "S": "-"; state += isCanonical () ? "C": "-"; @@ -2175,6 +2305,7 @@ namespace Anabatic { Record* AutoSegment::_getRecord () const { Record* record = base()->_getRecord (); + record->add ( getSlot ( "_extensionCaps" , &_extensionCaps ) ); record->add ( getSlot ( "_gcell" , _gcell ) ); record->add ( getSlot ( "_id" , &_id ) ); record->add ( getSlot ( "_flags" , &_flags ) ); diff --git a/anabatic/src/AutoVertical.cpp b/anabatic/src/AutoVertical.cpp index b157ae0a..ea7d5a6d 100644 --- a/anabatic/src/AutoVertical.cpp +++ b/anabatic/src/AutoVertical.cpp @@ -16,6 +16,7 @@ #include #include "hurricane/Bug.h" +#include "hurricane/ViaLayer.h" #include "hurricane/Vertical.h" #include "crlcore/RoutingGauge.h" #include "anabatic/Configuration.h" @@ -30,6 +31,7 @@ namespace Anabatic { using std::max; using Hurricane::Error; using Hurricane::Bug; + using Hurricane::ViaLayer; // ------------------------------------------------------------------- @@ -258,9 +260,11 @@ namespace Anabatic { { cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl; - if ( not isStrongTerminal() - or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) ) - { cdebug_tabw(149,-1); return false; } + if (not isDrag()) { + if ( not isStrongTerminal() + or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < 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; @@ -395,8 +399,8 @@ namespace Anabatic { void AutoVertical::updatePositions () { - _sourcePosition = _vertical->getSourceY() - getExtensionCap(); - _targetPosition = _vertical->getTargetY() + getExtensionCap(); + _sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source); + _targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target); } @@ -416,8 +420,8 @@ namespace Anabatic { bool AutoVertical::checkPositions () const { bool coherency = true; - DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(); - DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(); + DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source); + DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target); if ( _sourcePosition != sourcePosition ) { cerr << Error ( "%s\n Source position incoherency: " @@ -697,8 +701,17 @@ namespace Anabatic { } while ( gcell and (gcell != end) ); } - size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() ); - bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() ); + bool upLayer = true; + + if (Session::getRoutingGauge()->isTwoMetals()) { + upLayer = (depth == 0); + } else if (Session::getRoutingGauge()->isVH()) { + upLayer = (depth < 2); + } else { + upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + } + Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) ); const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) ); @@ -767,7 +780,7 @@ namespace Anabatic { updateNativeConstraints(); segment2->updateNativeConstraints(); - if (autoTarget->canDrag()) { + if (autoTarget->canDrag() and not autoSource->canDrag()) { Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical); segment1->mergeUserConstraints( dragConstraints ); diff --git a/anabatic/src/Configuration.cpp b/anabatic/src/Configuration.cpp index abe3579d..35fcc903 100644 --- a/anabatic/src/Configuration.cpp +++ b/anabatic/src/Configuration.cpp @@ -398,8 +398,14 @@ namespace Anabatic { bool Configuration::selectRpComponent ( RoutingPad* rp ) const { cdebug_log(112,1) << "selectRpComponent(): " << rp << endl; + + if (rp->isAtTopLevel()) { + cdebug_log(112,0) << "> RP is at top level, must not change it." << endl; + cdebug_tabw(112,-1); + return true; + } - Box ab = rp->getCell()->getBoundingBox(); + Box ab = rp->getCell()->getAbutmentBox(); const Layer* metal1 = getLayerGauge( 0 )->getLayer(); RoutingLayerGauge* gauge = getLayerGauge( 1 ); Occurrence occurrence = rp->getPlugOccurrence(); @@ -407,8 +413,8 @@ namespace Anabatic { Net* masterNet = plug->getMasterNet(); Path path = Path( occurrence.getPath(), plug->getInstance() ); Transformation transformation = path.getTransformation(); - Segment* current = dynamic_cast( rp->getOccurrence().getEntity() ); + if (current and (current->getLayer()->getMask() != metal1->getMask())) { cdebug_log(112,0) << "> using default non-metal1 segment." << endl; cdebug_tabw(112,-1); @@ -439,6 +445,11 @@ namespace Anabatic { , Constant::Nearest ); minPos = bb.getXMin(); maxPos = bb.getXMax(); + + cdebug_log(112,0) << "Vertical gauge: " << gauge << endl; + cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(ab.getXMin()) << endl; + cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(ab.getXMax()) << endl; + cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl; } else { trackPos = gauge->getTrackPosition( ab.getYMin() , ab.getYMax() @@ -446,6 +457,11 @@ namespace Anabatic { , Constant::Nearest ); minPos = bb.getYMin(); maxPos = bb.getYMax(); + + cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl; + cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(ab.getYMin()) << endl; + cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(ab.getYMax()) << endl; + cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl; } cdebug_log(112,0) << "| " << occurrence.getPath() << endl; diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index f67fbdcf..b3d8990c 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -1476,10 +1476,8 @@ namespace Anabatic { if (_densities[i] >= 1.0) _flags |= Flags::Saturated; } - if (ccapacity) - _cDensity = ( (float)_contacts.size() ) / ccapacity; - else - _cDensity = 0; + if (ccapacity) _cDensity = ( (float)_contacts.size() ) / ccapacity; + else _cDensity = 0; _flags.reset( Flags::Invalidated ); checkDensity(); diff --git a/anabatic/src/NetBuilderVH.cpp b/anabatic/src/NetBuilderVH.cpp index 8a13e67d..67fc1628 100644 --- a/anabatic/src/NetBuilderVH.cpp +++ b/anabatic/src/NetBuilderVH.cpp @@ -311,6 +311,8 @@ namespace Anabatic { bool NetBuilderVH::_do_xG_xM1_xM3 () { + // Implicit hypothesis : we have at least two globals and at least one terminal. + cdebug_log(145,1) << getTypeName() << "::_do_xG_" << (int)getConnexity().fields.M1 << "M1_" << (int)getConnexity().fields.M3 @@ -352,8 +354,12 @@ namespace Anabatic { } if (north() or east()) { - rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccessEW|VSmall ); - AutoSegment::create( leftContact, rightContact, Flags::Horizontal ); + if (getRoutingPads().size() > 1) { + rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccessEW|VSmall ); + AutoSegment::create( leftContact, rightContact, Flags::Horizontal ); + } else { + rightContact = leftContact; + } if (north() and east()) { setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) ); @@ -517,6 +523,7 @@ namespace Anabatic { cdebug_tabw(145,-1); } + string NetBuilderVH::getTypeName () const { return "NetBuilderVH"; } diff --git a/anabatic/src/NetConstraints.cpp b/anabatic/src/NetConstraints.cpp index 2ea1e7ca..bf94f88a 100644 --- a/anabatic/src/NetConstraints.cpp +++ b/anabatic/src/NetConstraints.cpp @@ -67,7 +67,10 @@ namespace { cdebug_log(145,0) << "slave component: " << component << endl; AutoContact* sourceContact = Session::lookup( dynamic_cast(component) ); if (sourceContact) { + Box constraintBox = sourceContact->getConstraintBox(); + cdebug_log(145,0) << "Start slave: " << sourceContact << endl; + cdebug_log(145,0) << "Constraint: " << constraintBox << endl; set verticalSegments; set horizontalSegments; @@ -87,9 +90,6 @@ namespace { } } - Box constraintBox = sourceContact->getConstraintBox(); - cdebug_log(145,0) << "Contraint: " << constraintBox << endl; - // Propagate constraint through horizontally aligned segments. cdebug_log(145,0) << "Propagate constraint on horizontal segments" << endl; diff --git a/anabatic/src/Session.cpp b/anabatic/src/Session.cpp index 95d536d2..9bffc00c 100644 --- a/anabatic/src/Session.cpp +++ b/anabatic/src/Session.cpp @@ -17,6 +17,7 @@ #include #include #include "hurricane/Error.h" +#include "hurricane/Warning.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Cell.h" @@ -47,6 +48,7 @@ namespace Anabatic { using namespace std; using Hurricane::tab; using Hurricane::Error; + using Hurricane::Warning; using Hurricane::ForEachIterator; using Hurricane::UpdateSession; using Hurricane::Horizontal; @@ -158,6 +160,7 @@ namespace Anabatic { canonical->setFlags( AutoSegment::SegCanonical ); cdebug_log(145,0) << "Canonical: " << canonical << endl; + Interval userConstraints = canonical->getUserConstraints(); for ( size_t j=0 ; jisGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal ); @@ -171,10 +174,23 @@ namespace Anabatic { } aligneds[j]->unsetFlags( AutoSegment::SegCanonical ); cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl; + + userConstraints.intersection( aligneds[j]->getUserConstraints() ); } if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned ); + if (not getRoutingGauge()->isSymbolic() + and (userConstraints.getSize() < Session::getPitch(1)*2) ) { + cerr << Warning( "Session::_canonize(): On %s\n" + " Combined user constraints are too tight [%s : %s]." + , getString(canonical).c_str() + , DbU::getValueString(userConstraints.getVMin()).c_str() + , DbU::getValueString(userConstraints.getVMax()).c_str() + ) << endl; + } + cdebug_log(149,0) << "Align on canonical:" << canonical << endl; + cdebug_log(145,0) << "Combined user constraints: " << userConstraints << endl; //canonical->setAxis( canonical->getAxis(), Flags::Realignate ); if (canonical->isUnsetAxis() and not canonical->isFixed()) @@ -194,21 +210,19 @@ namespace Anabatic { { cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl; - set::iterator inet = _netInvalidateds.begin(); - - for ( ; inet != _netInvalidateds.end() ; inet++ ) { - cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl; - _anabatic->updateNetTopology ( *inet ); - _anabatic->computeNetConstraints( *inet ); - _anabatic->_computeNetOptimals ( *inet ); - _anabatic->_computeNetTerminals ( *inet ); + for ( Net* net : _netInvalidateds ) { + cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << net << endl; + _anabatic->updateNetTopology ( net ); + _anabatic->computeNetConstraints( net ); + _anabatic->_computeNetOptimals ( net ); + _anabatic->_computeNetTerminals ( net ); } _canonize (); - for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) { - if (_segmentInvalidateds[i]->isCanonical()) { - if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis(); - else _segmentInvalidateds[i]->toConstraintAxis(); + for ( AutoSegment* segment : _segmentInvalidateds ) { + if (segment->isCanonical()) { + if (segment->isUnsetAxis()) segment->toOptimalAxis(); + else segment->toConstraintAxis(); } } diff --git a/anabatic/src/anabatic/: b/anabatic/src/anabatic/: new file mode 100644 index 00000000..e4c512cc --- /dev/null +++ b/anabatic/src/anabatic/: @@ -0,0 +1,646 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2008-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | A n a b a t i c - Routing Toolbox | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./anabatic/AutoSegment.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ANABATIC_AUTOSEGMENT_H +#define ANABATIC_AUTOSEGMENT_H + +#include +#include +#include +#include "hurricane/Interval.h" +#include "hurricane/Segment.h" +#include "hurricane/Components.h" +#include "hurricane/Contact.h" +namespace Hurricane { + class Layer; + class Horizontal; + class Vertical; + class Cell; +} +#include "crlcore/RoutingGauge.h" +#include "anabatic/Constants.h" +#include "anabatic/GCell.h" +#include "anabatic/AutoSegments.h" +#include "anabatic/Session.h" + + +namespace Anabatic { + + using std::array; + using std::set; + using std::cerr; + using std::endl; + using std::binary_function; + using Hurricane::StaticObservable; + using Hurricane::BaseObserver; + using Hurricane::tab; + using Hurricane::Interval; + using Hurricane::Layer; + using Hurricane::Components; + using Hurricane::Horizontal; + using Hurricane::Vertical; + using Hurricane::Cell; + using CRL::RoutingGauge; + + class AutoHorizontal; + class AutoVertical; + +// ------------------------------------------------------------------- +// Class : "AutoSegment". + + + + class AutoSegment { + friend class AutoHorizontal; + friend class AutoVertical; + + public: + static const uint64_t SegNoFlags = 0L; + static const uint64_t SegHorizontal = (1L<< 0); + static const uint64_t SegFixed = (1L<< 1); + static const uint64_t SegFixedAxis = (1L<< 2); + static const uint64_t SegGlobal = (1L<< 3); + static const uint64_t SegWeakGlobal = (1L<< 4); + static const uint64_t SegLongLocal = (1L<< 5); + static const uint64_t SegCanonical = (1L<< 6); + static const uint64_t SegBipoint = (1L<< 7); + static const uint64_t SegDogleg = (1L<< 8); + static const uint64_t SegStrap = (1L<< 9); + static const uint64_t SegSourceTop = (1L<<10); + static const uint64_t SegSourceBottom = (1L<<11); + static const uint64_t SegTargetTop = (1L<<12); + static const uint64_t SegTargetBottom = (1L<<13); + static const uint64_t SegIsReduced = (1L<<14); + static const uint64_t SegDrag = (1L<<15); + static const uint64_t SegLayerChange = (1L<<16); + static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal. + static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal. + static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal; + static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd. + static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd. + static const uint64_t SegNotSourceAligned = (1L<<21); + static const uint64_t SegNotTargetAligned = (1L<<22); + static const uint64_t SegUnbound = (1L<<23); + static const uint64_t SegHalfSlackened = (1L<<24); + static const uint64_t SegSlackened = (1L<<25); + static const uint64_t SegAxisSet = (1L<<26); + static const uint64_t SegInvalidated = (1L<<27); + static const uint64_t SegInvalidatedSource = (1L<<28); + static const uint64_t SegInvalidatedTarget = (1L<<29); + static const uint64_t SegInvalidatedLayer = (1L<<30); + static const uint64_t SegCreated = (1L<<31); + static const uint64_t SegUserDefined = (1L<<32); + static const uint64_t SegAnalog = (1L<<33); + static const uint64_t SegWide = (1L<<34); + // Masks. + static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; + static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; + static const uint64_t SegSpinTop = SegSourceTop |SegTargetTop; + static const uint64_t SegSpinBottom = SegSourceBottom |SegTargetBottom; + static const uint64_t SegDepthSpin = SegSpinTop |SegSpinBottom; + + public: + class Observable : public StaticObservable<1> { + public: + enum Indexes { TrackSegment = 0 + }; + public: + inline Observable (); + private: + Observable ( const StaticObservable& ); + Observable& operator= ( const StaticObservable& ); + }; + public: + enum ObserverFlag { Create = (1 << 0) + , Destroy = (1 << 1) + , Invalidate = (1 << 2) + , Revalidate = (1 << 3) + , RevalidatePPitch = (1 << 4) + }; + public: + typedef std::function< void(AutoSegment*) > RevalidateCb_t; + public: + static void setAnalogMode ( bool ); + static bool getAnalogMode (); + inline static DbU::Unit getViaToTopCap ( size_t depth ); + inline static DbU::Unit getViaToBottomCap ( size_t depth ); + inline static DbU::Unit getViaToSameCap ( size_t depth ); + static AutoSegment* create ( AutoContact* source + , AutoContact* target + , Segment* hurricaneSegment + ); + static AutoSegment* create ( AutoContact* source + , AutoContact* target + , Flags dir + , size_t depth=RoutingGauge::nlayerdepth + ); + void destroy (); + // Wrapped Segment Functions. + virtual Segment* base () const = 0; + virtual Segment* base () = 0; + virtual Horizontal* getHorizontal () { return NULL; }; + virtual Vertical* getVertical () { return NULL; }; + inline Cell* getCell () const; + inline Net* getNet () const; + inline const Layer* getLayer () const; + inline Box getBoundingBox () const; + inline Hook* getSourceHook (); + inline Hook* getTargetHook (); + inline Contact* getSource () const; + inline Contact* getTarget () const; + inline Component* getOppositeAnchor ( Component* ) const; + inline Components getAnchors () const; + virtual DbU::Unit getX () const; + virtual DbU::Unit getY () const; + inline DbU::Unit getWidth () const; + inline DbU::Unit getContactWidth () const; + inline DbU::Unit getLength () const; + inline DbU::Unit getSourcePosition () const; + inline DbU::Unit getTargetPosition () const; + inline DbU::Unit getSourceX () const; + inline DbU::Unit getSourceY () const; + inline DbU::Unit getTargetX () const; + inline DbU::Unit getTargetY () const; + inline void invert (); + inline void setLayer ( const Layer* ); + // Predicates. + inline bool isHorizontal () const; + inline bool isVertical () const; + inline bool isGlobal () const; + inline bool isWeakGlobal () const; + inline bool isLongLocal () const; + inline bool isLocal () const; + inline bool isFixed () const; + inline bool isFixedAxis () const; + inline bool isBipoint () const; + inline bool isWeakTerminal () const; + 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; + bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; + inline bool isSourceTerminal () const; + inline bool isTargetTerminal () const; + inline bool isLayerChange () const; + inline bool isSpinTop () const; + inline bool isSpinBottom () const; + inline bool isSpinTopOrBottom () const; + inline bool isReduced () const; + inline bool isStrap () const; + inline bool isDogleg () const; + inline bool isUnbound () const; + inline bool isInvalidated () const; + inline bool isInvalidatedLayer () const; + inline bool isCreated () const; + inline bool isCanonical () const; + inline bool isUnsetAxis () const; + inline bool isSlackened () const; + inline bool isUserDefined () const; + bool isReduceCandidate () const; + bool isUTurn () const; + inline bool isAnalog () const; + inline bool isWide () const; + virtual bool _canSlacken () const = 0; + bool canReduce () const; + bool mustRaise () const; + Flags canDogleg ( Interval ); + virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; + virtual bool canMoveURight ( float reserve=0.0 ) const = 0; + bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canSlacken ( Flags flags=Flags::NoFlags ) const; + virtual bool checkPositions () const = 0; + virtual bool checkConstraints () const = 0; + bool checkDepthSpin () const; + // Accessors. + inline unsigned long getId () const; + inline uint64_t getFlags () const; + virtual Flags getDirection () const = 0; + inline GCell* getGCell () const; + virtual bool getGCells ( vector& ) const = 0; + inline AutoContact* getAutoSource () const; + inline AutoContact* getAutoTarget () const; + AutoContact* getOppositeAnchor ( AutoContact* ) const; + size_t getPerpandicularsBound ( set& ); + inline AutoSegment* getParent () const; + inline unsigned int getDepth () const; + inline DbU::Unit getPitch () const; + DbU::Unit getPPitch () const; +#if DISABLED + DbU::Unit getExtensionCap () const; +#endif + DbU::Unit getExtensionCap ( Flags ) const; + inline DbU::Unit getAxis () const; + void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const; + virtual DbU::Unit getSourceU () const = 0; + virtual DbU::Unit getTargetU () const = 0; + virtual DbU::Unit getDuSource () const = 0; + virtual DbU::Unit getDuTarget () const = 0; + inline DbU::Unit getOrigin () const; + inline DbU::Unit getExtremity () const; + virtual Interval getSpanU () const = 0; + Interval getMinSpanU () const; + virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0; + virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0; + virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0; + inline bool getConstraints ( Interval& i ) const; + inline const Interval& getUserConstraints () const; + inline const Interval& getNativeConstraints () const; + virtual DbU::Unit getSlack () const; + inline DbU::Unit getOptimalMin () const; + inline DbU::Unit getOptimalMax () const; + inline DbU::Unit getNativeMin () const; + inline DbU::Unit getNativeMax () const; + Interval& getOptimal ( Interval& i ) const; + virtual DbU::Unit getCost ( DbU::Unit axis ) const; + virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max ); + inline AutoSegment* getCanonical ( Interval& i ); + float getMaxUnderDensity ( Flags flags ); + // Modifiers. + inline void unsetFlags ( uint64_t ); + inline void setFlags ( uint64_t ); + void setFlagsOnAligneds ( uint64_t ); + inline void incReduceds (); + inline void decReduceds (); + virtual void setDuSource ( DbU::Unit du ) = 0; + virtual void setDuTarget ( DbU::Unit du ) = 0; + void computeTerminal (); + virtual void updateOrient () = 0; + virtual void updatePositions () = 0; + virtual void updateNativeConstraints () = 0; + void updateSourceSpin (); + void updateTargetSpin (); + void sourceDetach (); + void targetDetach (); + void sourceAttach ( AutoContact* ); + void targetAttach ( AutoContact* ); + //inline void mergeUserConstraints ( const Interval& ); + void mergeUserConstraints ( const Interval& ); + inline void resetUserConstraints (); + inline void setOptimalMin ( DbU::Unit min ); + inline void setOptimalMax ( DbU::Unit max ); + inline void mergeNativeMin ( DbU::Unit min ); + inline void mergeNativeMax ( DbU::Unit max ); + inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max ); + bool checkNotInvalidated () const; + inline void setParent ( AutoSegment* ); + void revalidate (); + AutoSegment* makeDogleg ( AutoContact* ); + Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags ); + Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags ); + virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0; + virtual bool moveULeft () = 0; + virtual bool moveURight () = 0; + bool slacken ( Flags flags ); + virtual bool _slacken ( Flags flags ) = 0; + void _changeDepth ( unsigned int depth, Flags flags ); + void changeDepth ( unsigned int depth, Flags flags ); + bool moveUp ( Flags flags=Flags::NoFlags ); + bool moveDown ( Flags flags=Flags::NoFlags ); + bool reduceDoglegLayer (); + bool reduce (); + bool raise (); + // Canonical Modifiers. + AutoSegment* canonize ( Flags flags=Flags::NoFlags ); + virtual void invalidate ( Flags flags=Flags::Propagate ); + void invalidate ( AutoContact* ); + void computeOptimal ( set& processeds ); + void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags ); + bool toConstraintAxis ( Flags flags=Flags::Realignate ); + bool toOptimalAxis ( Flags flags=Flags::Realignate ); + // Collections & Filters. + AutoSegments getOnSourceContact ( Flags direction ); + AutoSegments getOnTargetContact ( Flags direction ); + AutoSegments getCachedOnSourceContact ( Flags direction ); + AutoSegments getCachedOnTargetContact ( Flags direction ); + AutoSegments getAligneds ( Flags flags=Flags::NoFlags ); + AutoSegments getConnecteds ( Flags flags=Flags::NoFlags ); + AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags ); + size_t getAlignedContacts ( map& ) const ; + // Observers. + template< typename OwnerT > + inline OwnerT* getObserver ( size_t slot ); + inline void setObserver ( size_t slot, BaseObserver* ); + inline void notify ( unsigned int flags ); + // Inspector Management. + virtual Record* _getRecord () const = 0; + virtual string _getString () const = 0; + virtual string _getTypeName () const = 0; + // Non-reviewed atomic modifiers. + bool _check () const; +#if THIS_IS_DISABLED + virtual void desalignate ( AutoContact* ) = 0; + bool shearUp ( GCell* + , AutoSegment*& movedUp + , float reserve + , Flags flags ); +#endif + + protected: + // Internal: Static Attributes. + static size_t _allocateds; + static size_t _globalsCount; + static bool _analogMode; + static bool _initialized; + static vector< array > _extensionCaps; + // Internal: Attributes. + const unsigned long _id; + GCell* _gcell; + uint64_t _flags; + unsigned int _depth : 8; + unsigned int _optimalMin :16; + unsigned int _optimalMax :16; + unsigned int _reduceds : 2; + DbU::Unit _sourcePosition; + DbU::Unit _targetPosition; + Interval _userConstraints; + Interval _nativeConstraints; + AutoSegment* _parent; + Observable _observers; + + // Internal: Constructors & Destructors. + protected: + AutoSegment ( Segment* segment ); + virtual ~AutoSegment (); + static void _preCreate ( AutoContact* source, AutoContact* target ); + virtual void _postCreate (); + virtual void _preDestroy (); + static void _initialize (); + private: + AutoSegment ( const AutoSegment& ); + AutoSegment& operator= ( const AutoSegment& ); + protected: + void _invalidate (); + inline uint64_t _getFlags () const; + std::string _getStringFlags () const; + virtual void _setAxis ( DbU::Unit ) = 0; + + public: + struct CompareId : public binary_function { + inline bool operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const; + }; + public: + struct CompareByDepthLength : public binary_function { + bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; + }; + public: + struct CompareByDepthAxis : public binary_function { + bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; + }; + public: + typedef std::set DepthLengthSet; + typedef std::set IdSet; + + // Static Utilities. + public: + static inline uint64_t swapSourceTargetFlags ( AutoSegment* ); + static inline bool areAlignedsAndDiffLayer ( AutoSegment*, AutoSegment* ); + static AutoSegment* getGlobalThroughDogleg ( AutoSegment* dogleg, AutoContact* from ); + static bool isTopologicalBound ( AutoSegment* seed, Flags flags ); + static inline bool arePerpandiculars ( AutoSegment* a, AutoSegment* b ); + static inline bool arePerpandiculars ( bool isHorizontalA, AutoSegment* b ); + static inline bool areAligneds ( AutoSegment* a, AutoSegment* b ); + static Flags getPerpandicularState ( AutoContact* contact + , AutoSegment* source + , AutoSegment* current + , bool isHorizontalMaster + , const Layer* masterLayer=NULL + ); + static inline Flags getPerpandicularState ( AutoContact* contact + , AutoSegment* source + , AutoSegment* current + , AutoSegment* master + ); + static void getTopologicalInfos ( AutoSegment* seed + , vector& collapseds + , vector& perpandiculars + , DbU::Unit& leftBound + , DbU::Unit& rightBound + ); + static int getTerminalCount ( AutoSegment* seed + , vector& collapseds + ); + static inline int getTerminalCount ( AutoSegment* seed ); + static inline size_t getGlobalsCount (); + static inline size_t getAllocateds (); + static inline unsigned long getMaxId (); + }; + + +// Inline Functions. + inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; } + inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; } + inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; } + inline unsigned long AutoSegment::getId () const { return _id; } + inline Cell* AutoSegment::getCell () const { return base()->getCell(); } + inline Net* AutoSegment::getNet () const { return base()->getNet(); } + inline const Layer* AutoSegment::getLayer () const { return base()->getLayer(); } + inline Box AutoSegment::getBoundingBox () const { return base()->getBoundingBox(); } + inline Hook* AutoSegment::getSourceHook () { return base()->getSourceHook(); } + inline Hook* AutoSegment::getTargetHook () { return base()->getTargetHook(); } + inline Contact* AutoSegment::getSource () const { return static_cast(base()->getSource()); } + inline Contact* AutoSegment::getTarget () const { return static_cast(base()->getTarget()); } + inline Component* AutoSegment::getOppositeAnchor ( Component* anchor ) const { return base()->getOppositeAnchor(anchor); }; + inline AutoSegment* AutoSegment::getParent () const { return _parent; } + inline DbU::Unit AutoSegment::getSourcePosition () const { return _sourcePosition; } + inline DbU::Unit AutoSegment::getTargetPosition () const { return _targetPosition; } + inline DbU::Unit AutoSegment::getSourceX () const { return base()->getSourceX(); } + inline DbU::Unit AutoSegment::getSourceY () const { return base()->getSourceY(); } + inline DbU::Unit AutoSegment::getTargetX () const { return base()->getTargetX(); } + inline DbU::Unit AutoSegment::getTargetY () const { return base()->getTargetY(); } + inline DbU::Unit AutoSegment::getWidth () const { return base()->getWidth(); } + inline DbU::Unit AutoSegment::getLength () const { return base()->getLength(); } + inline void AutoSegment::invert () { base()->invert(); } + inline GCell* AutoSegment::getGCell () const { return _gcell; } + inline AutoContact* AutoSegment::getAutoSource () const { return Session::lookup(getSource()); } + inline AutoContact* AutoSegment::getAutoTarget () const { return Session::lookup(getTarget()); } + inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); } + inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); } + inline unsigned int AutoSegment::getDepth () const { return _depth; } + inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); } + inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); } + inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); } + inline DbU::Unit AutoSegment::getExtremity () const { return isHorizontal()?_gcell->getYMax():_gcell->getXMax(); } + inline DbU::Unit AutoSegment::getOptimalMin () const { return DbU::lambda(_optimalMin) + getOrigin(); } + inline DbU::Unit AutoSegment::getOptimalMax () const { return DbU::lambda(_optimalMax) + getOrigin(); } + inline DbU::Unit AutoSegment::getNativeMin () const { return _nativeConstraints.getVMin(); } + inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); } + inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; } + inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; } + + inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; } + inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); } + inline bool AutoSegment::isFixed () const { return _flags & SegFixed; } + inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; } + inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; } + inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; } + inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; } + inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); } + inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; } + inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; } + inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; } + inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; } + 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; } + inline bool AutoSegment::isDogleg () const { return _flags & SegDogleg ; } + inline bool AutoSegment::isUnbound () const { return _flags & SegUnbound ; } + inline bool AutoSegment::isStrap () const { return _flags & SegStrap; } + inline bool AutoSegment::isLayerChange () const { return _flags & SegLayerChange; } + inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); } + inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); } + inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); } + inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; } + inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; } + inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; } + inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); } + inline bool AutoSegment::isInvalidated () const { return _flags & SegInvalidated; } + inline bool AutoSegment::isInvalidatedLayer () const { return _flags & SegInvalidatedLayer; } + inline bool AutoSegment::isCreated () const { return _flags & SegCreated; } + inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; } + inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; } + inline bool AutoSegment::isWide () const { return _flags & SegWide; } + inline void AutoSegment::setFlags ( uint64_t flags ) { _flags |= flags; } + inline void AutoSegment::unsetFlags ( uint64_t flags ) { _flags &= ~flags; } + + inline uint64_t AutoSegment::getFlags () const { return _flags; } + inline uint64_t AutoSegment::_getFlags () const { return _flags; } + inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; } + inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; } + inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; } + inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); } + inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); } + inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); } + inline void AutoSegment::mergeNativeMax ( DbU::Unit max ) { _nativeConstraints.getVMax() = std::min( max, _nativeConstraints.getVMax() ); } + 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::getContactWidth () const + { return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); } + + + inline void AutoSegment::setParent ( AutoSegment* parent ) + { + if ( parent == this ) { + cerr << "Parentage Looping: " << parent->_getString() << endl; + } + _parent = parent; + } + + inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const + { return lhs->getId() < rhs->getId(); } + + inline uint64_t AutoSegment::swapSourceTargetFlags ( AutoSegment* segment ) + { + uint64_t segFlags = segment->getFlags(); + uint64_t swapFlags = segment->getFlags() & ~(SegSourceTop |SegTargetTop + |SegSourceBottom |SegTargetBottom + |SegSourceTerminal |SegTargetTerminal + |SegNotSourceAligned |SegNotTargetAligned + |SegInvalidatedSource|SegInvalidatedTarget + ); + + swapFlags |= (segFlags & SegSourceTop ) ? SegTargetTop : SegNoFlags; + swapFlags |= (segFlags & SegSourceBottom ) ? SegTargetBottom : SegNoFlags; + swapFlags |= (segFlags & SegSourceTerminal ) ? SegTargetTerminal : SegNoFlags; + swapFlags |= (segFlags & SegNotSourceAligned ) ? SegNotTargetAligned : SegNoFlags; + swapFlags |= (segFlags & SegInvalidatedSource) ? SegInvalidatedTarget : SegNoFlags; + + swapFlags |= (segFlags & SegTargetTop ) ? SegSourceTop : SegNoFlags; + swapFlags |= (segFlags & SegTargetBottom ) ? SegSourceBottom : SegNoFlags; + swapFlags |= (segFlags & SegTargetTerminal ) ? SegSourceTerminal : SegNoFlags; + swapFlags |= (segFlags & SegNotTargetAligned ) ? SegNotSourceAligned : SegNoFlags; + swapFlags |= (segFlags & SegInvalidatedTarget) ? SegInvalidatedSource : SegNoFlags; + return swapFlags; + } + + inline bool AutoSegment::areAlignedsAndDiffLayer ( AutoSegment* s1, AutoSegment* s2 ) + { return s1 and s2 + and (s1->isHorizontal() == s2->isHorizontal()) + and (s1->getLayer() != s2->getLayer()); } + + inline bool AutoSegment::arePerpandiculars ( AutoSegment* a, AutoSegment* b ) + { return a and b and (a->isHorizontal() != b->isHorizontal()); } + + inline bool AutoSegment::arePerpandiculars ( bool isHorizontalA, AutoSegment* b ) + { return b and (isHorizontalA != b->isHorizontal()); } + + inline bool AutoSegment::areAligneds ( AutoSegment* a, AutoSegment* b ) + { return a and b and (a->isHorizontal() == b->isHorizontal()); } + + inline Flags AutoSegment::getPerpandicularState ( AutoContact* contact + , AutoSegment* source + , AutoSegment* current + , AutoSegment* master ) + { + return getPerpandicularState ( contact, source, current, master->isHorizontal(), master->getLayer() ); + } + + + inline int AutoSegment::getTerminalCount ( AutoSegment* seed ) + { + cdebug_log(145,0) << "getTerminalCount() - " << seed << endl; + + vector collapseds; + vector perpandiculars; + DbU::Unit leftBound; + DbU::Unit rightBound; + + getTopologicalInfos ( seed + , collapseds + , perpandiculars + , leftBound + , rightBound + ); + + return getTerminalCount ( seed, collapseds ); + } + + + inline size_t AutoSegment::getGlobalsCount () { return _globalsCount; } + inline size_t AutoSegment::getAllocateds () { return _allocateds; } + + + inline void AutoSegment::setObserver ( size_t slot, BaseObserver* observer ) + { _observers.setObserver( slot, observer ); } + + template + inline OwnerT* AutoSegment::getObserver ( size_t slot ) + { return _observers.getObserver(slot); } + + inline void AutoSegment::notify ( unsigned int flags ) + { _observers.notify( flags ); } + + inline AutoSegment::Observable::Observable () : StaticObservable<1>() { } + + +} // End of Anabatic namespace. + + +INSPECTOR_P_SUPPORT(Anabatic::AutoSegment); + + +# endif // ANABATIC_AUTOSEGMENT_H diff --git a/anabatic/src/anabatic/AnabaticEngine.h b/anabatic/src/anabatic/AnabaticEngine.h index 6da94e2b..ca794c40 100644 --- a/anabatic/src/anabatic/AnabaticEngine.h +++ b/anabatic/src/anabatic/AnabaticEngine.h @@ -216,6 +216,7 @@ namespace Anabatic { // Global routing related functions. void globalRoute (); void cleanupGlobal (); + void relaxOverConstraineds (); // Detailed routing related functions. inline bool isInDemoMode () const; inline bool isChip () const; diff --git a/anabatic/src/anabatic/AutoSegment.h b/anabatic/src/anabatic/AutoSegment.h index eef0bd1f..ef819c8c 100644 --- a/anabatic/src/anabatic/AutoSegment.h +++ b/anabatic/src/anabatic/AutoSegment.h @@ -39,6 +39,7 @@ namespace Hurricane { namespace Anabatic { + using std::array; using std::set; using std::cerr; using std::endl; @@ -70,39 +71,40 @@ namespace Anabatic { static const uint64_t SegNoFlags = 0L; static const uint64_t SegHorizontal = (1L<< 0); static const uint64_t SegFixed = (1L<< 1); - static const uint64_t SegGlobal = (1L<< 2); - static const uint64_t SegWeakGlobal = (1L<< 3); - static const uint64_t SegLongLocal = (1L<< 4); - static const uint64_t SegCanonical = (1L<< 5); - static const uint64_t SegBipoint = (1L<< 6); - static const uint64_t SegDogleg = (1L<< 7); - static const uint64_t SegStrap = (1L<< 8); - static const uint64_t SegSourceTop = (1L<< 9); - static const uint64_t SegSourceBottom = (1L<<10); - 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 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 SegFixedAxis = (1L<< 2); + static const uint64_t SegGlobal = (1L<< 3); + static const uint64_t SegWeakGlobal = (1L<< 4); + static const uint64_t SegLongLocal = (1L<< 5); + static const uint64_t SegCanonical = (1L<< 6); + static const uint64_t SegBipoint = (1L<< 7); + static const uint64_t SegDogleg = (1L<< 8); + static const uint64_t SegStrap = (1L<< 9); + static const uint64_t SegSourceTop = (1L<<10); + static const uint64_t SegSourceBottom = (1L<<11); + static const uint64_t SegTargetTop = (1L<<12); + static const uint64_t SegTargetBottom = (1L<<13); + static const uint64_t SegIsReduced = (1L<<14); + static const uint64_t SegDrag = (1L<<15); + static const uint64_t SegLayerChange = (1L<<16); + static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal. + static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal. static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal; - 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); + static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd. + static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd. + static const uint64_t SegNotSourceAligned = (1L<<21); + static const uint64_t SegNotTargetAligned = (1L<<22); + static const uint64_t SegUnbound = (1L<<23); + static const uint64_t SegHalfSlackened = (1L<<24); + static const uint64_t SegSlackened = (1L<<25); + static const uint64_t SegAxisSet = (1L<<26); + static const uint64_t SegInvalidated = (1L<<27); + static const uint64_t SegInvalidatedSource = (1L<<28); + static const uint64_t SegInvalidatedTarget = (1L<<29); + static const uint64_t SegInvalidatedLayer = (1L<<30); + static const uint64_t SegCreated = (1L<<31); + static const uint64_t SegUserDefined = (1L<<32); + static const uint64_t SegAnalog = (1L<<33); + static const uint64_t SegWide = (1L<<34); // Masks. static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; @@ -131,253 +133,264 @@ namespace Anabatic { public: typedef std::function< void(AutoSegment*) > RevalidateCb_t; public: - static void setAnalogMode ( bool ); - static bool getAnalogMode (); - static AutoSegment* create ( AutoContact* source - , AutoContact* target - , Segment* hurricaneSegment - ); - static AutoSegment* create ( AutoContact* source - , AutoContact* target - , Flags dir - , size_t depth=RoutingGauge::nlayerdepth - ); - void destroy (); + static void setAnalogMode ( bool ); + static bool getAnalogMode (); + inline static DbU::Unit getViaToTopCap ( size_t depth ); + inline static DbU::Unit getViaToBottomCap ( size_t depth ); + inline static DbU::Unit getViaToSameCap ( size_t depth ); + static AutoSegment* create ( AutoContact* source + , AutoContact* target + , Segment* hurricaneSegment + ); + static AutoSegment* create ( AutoContact* source + , AutoContact* target + , Flags dir + , size_t depth=RoutingGauge::nlayerdepth + ); + void destroy (); // Wrapped Segment Functions. - virtual Segment* base () const = 0; - virtual Segment* base () = 0; - virtual Horizontal* getHorizontal () { return NULL; }; - virtual Vertical* getVertical () { return NULL; }; - inline Cell* getCell () const; - inline Net* getNet () const; - inline const Layer* getLayer () const; - inline Box getBoundingBox () const; - inline Hook* getSourceHook (); - inline Hook* getTargetHook (); - inline Contact* getSource () const; - inline Contact* getTarget () const; - inline Component* getOppositeAnchor ( Component* ) const; - inline Components getAnchors () const; - virtual DbU::Unit getX () const; - virtual DbU::Unit getY () const; - inline DbU::Unit getWidth () const; - inline DbU::Unit getContactWidth () const; - inline DbU::Unit getLength () const; - inline DbU::Unit getSourcePosition () const; - inline DbU::Unit getTargetPosition () const; - inline DbU::Unit getSourceX () const; - inline DbU::Unit getSourceY () const; - inline DbU::Unit getTargetX () const; - inline DbU::Unit getTargetY () const; - inline void invert (); - inline void setLayer ( const Layer* ); + virtual Segment* base () const = 0; + virtual Segment* base () = 0; + virtual Horizontal* getHorizontal () { return NULL; }; + virtual Vertical* getVertical () { return NULL; }; + inline Cell* getCell () const; + inline Net* getNet () const; + inline const Layer* getLayer () const; + inline Box getBoundingBox () const; + inline Hook* getSourceHook (); + inline Hook* getTargetHook (); + inline Contact* getSource () const; + inline Contact* getTarget () const; + inline Component* getOppositeAnchor ( Component* ) const; + inline Components getAnchors () const; + virtual DbU::Unit getX () const; + virtual DbU::Unit getY () const; + inline DbU::Unit getWidth () const; + inline DbU::Unit getContactWidth () const; + inline DbU::Unit getLength () const; + inline DbU::Unit getSourcePosition () const; + inline DbU::Unit getTargetPosition () const; + inline DbU::Unit getSourceX () const; + inline DbU::Unit getSourceY () const; + inline DbU::Unit getTargetX () const; + inline DbU::Unit getTargetY () const; + inline void invert (); + inline void setLayer ( const Layer* ); // Predicates. - inline bool isHorizontal () const; - inline bool isVertical () const; - inline bool isGlobal () const; - inline bool isWeakGlobal () const; - inline bool isLongLocal () const; - inline bool isLocal () const; - inline bool isFixed () const; - inline bool isBipoint () const; - inline bool isWeakTerminal () const; - 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; - bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; - inline bool isSourceTerminal () const; - inline bool isTargetTerminal () const; - inline bool isLayerChange () const; - inline bool isSpinTop () const; - inline bool isSpinBottom () const; - inline bool isSpinTopOrBottom () const; - inline bool isReduced () const; - inline bool isStrap () const; - inline bool isDogleg () const; - inline bool isUnbound () const; - inline bool isInvalidated () const; - inline bool isInvalidatedLayer () const; - inline bool isCreated () const; - inline bool isCanonical () const; - inline bool isUnsetAxis () const; - inline bool isSlackened () const; - inline bool isUserDefined () const; - bool isReduceCandidate () const; - bool isUTurn () const; - inline bool isAnalog () const; - inline bool isWide () const; - virtual bool _canSlacken () const = 0; - bool canReduce () const; - bool mustRaise () const; - Flags canDogleg ( Interval ); - virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; - virtual bool canMoveURight ( float reserve=0.0 ) const = 0; - bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; - bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; - bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; - bool canSlacken ( Flags flags=Flags::NoFlags ) const; - virtual bool checkPositions () const = 0; - virtual bool checkConstraints () const = 0; - bool checkDepthSpin () const; + inline bool isHorizontal () const; + inline bool isVertical () const; + inline bool isGlobal () const; + inline bool isWeakGlobal () const; + inline bool isLongLocal () const; + inline bool isLocal () const; + inline bool isFixed () const; + inline bool isFixedAxis () const; + inline bool isBipoint () const; + inline bool isWeakTerminal () const; + 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; + bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; + inline bool isSourceTerminal () const; + inline bool isTargetTerminal () const; + inline bool isLayerChange () const; + inline bool isSpinTop () const; + inline bool isSpinBottom () const; + inline bool isSpinTopOrBottom () const; + inline bool isReduced () const; + inline bool isStrap () const; + inline bool isDogleg () const; + inline bool isUnbound () const; + inline bool isInvalidated () const; + inline bool isInvalidatedLayer () const; + inline bool isCreated () const; + inline bool isCanonical () const; + inline bool isUnsetAxis () const; + inline bool isSlackened () const; + inline bool isUserDefined () const; + bool isReduceCandidate () const; + bool isUTurn () const; + inline bool isAnalog () const; + inline bool isWide () const; + virtual bool _canSlacken () const = 0; + bool canReduce () const; + bool mustRaise () const; + Flags canDogleg ( Interval ); + virtual bool canMoveULeft ( float reserve=0.0 ) const = 0; + virtual bool canMoveURight ( float reserve=0.0 ) const = 0; + bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const; + bool canSlacken ( Flags flags=Flags::NoFlags ) const; + virtual bool checkPositions () const = 0; + virtual bool checkConstraints () const = 0; + bool checkDepthSpin () const; // Accessors. - inline unsigned long getId () const; - inline uint64_t getFlags () const; - virtual Flags getDirection () const = 0; - inline GCell* getGCell () const; - virtual bool getGCells ( vector& ) const = 0; - inline AutoContact* getAutoSource () const; - inline AutoContact* getAutoTarget () const; - AutoContact* getOppositeAnchor ( AutoContact* ) const; - size_t getPerpandicularsBound ( set& ); - inline AutoSegment* getParent () const; - inline unsigned int getDepth () const; - inline DbU::Unit getPitch () const; - DbU::Unit getPPitch () const; - DbU::Unit getExtensionCap () const; - inline DbU::Unit getAxis () const; - virtual DbU::Unit getSourceU () const = 0; - virtual DbU::Unit getTargetU () const = 0; - virtual DbU::Unit getDuSource () const = 0; - virtual DbU::Unit getDuTarget () const = 0; - inline DbU::Unit getOrigin () const; - inline DbU::Unit getExtremity () const; - virtual Interval getSpanU () const = 0; - Interval getMinSpanU () const; - virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0; - virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0; - virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0; - inline bool getConstraints ( Interval& i ) const; - inline const Interval& getUserConstraints () const; - inline const Interval& getNativeConstraints () const; - virtual DbU::Unit getSlack () const; - inline DbU::Unit getOptimalMin () const; - inline DbU::Unit getOptimalMax () const; - inline DbU::Unit getNativeMin () const; - inline DbU::Unit getNativeMax () const; - Interval& getOptimal ( Interval& i ) const; - virtual DbU::Unit getCost ( DbU::Unit axis ) const; - virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max ); - inline AutoSegment* getCanonical ( Interval& i ); - float getMaxUnderDensity ( Flags flags ); + inline unsigned long getId () const; + inline uint64_t getFlags () const; + virtual Flags getDirection () const = 0; + inline GCell* getGCell () const; + virtual bool getGCells ( vector& ) const = 0; + inline AutoContact* getAutoSource () const; + inline AutoContact* getAutoTarget () const; + AutoContact* getOppositeAnchor ( AutoContact* ) const; + size_t getPerpandicularsBound ( set& ); + inline AutoSegment* getParent () const; + inline unsigned int getDepth () const; + inline DbU::Unit getPitch () const; + DbU::Unit getPPitch () const; +#if DISABLED + DbU::Unit getExtensionCap () const; +#endif + DbU::Unit getExtensionCap ( Flags ) const; + inline DbU::Unit getAxis () const; + void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const; + virtual DbU::Unit getSourceU () const = 0; + virtual DbU::Unit getTargetU () const = 0; + virtual DbU::Unit getDuSource () const = 0; + virtual DbU::Unit getDuTarget () const = 0; + inline DbU::Unit getOrigin () const; + inline DbU::Unit getExtremity () const; + virtual Interval getSpanU () const = 0; + Interval getMinSpanU () const; + virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0; + virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0; + virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0; + inline bool getConstraints ( Interval& i ) const; + inline const Interval& getUserConstraints () const; + inline const Interval& getNativeConstraints () const; + virtual DbU::Unit getSlack () const; + inline DbU::Unit getOptimalMin () const; + inline DbU::Unit getOptimalMax () const; + inline DbU::Unit getNativeMin () const; + inline DbU::Unit getNativeMax () const; + Interval& getOptimal ( Interval& i ) const; + virtual DbU::Unit getCost ( DbU::Unit axis ) const; + virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max ); + inline AutoSegment* getCanonical ( Interval& i ); + float getMaxUnderDensity ( Flags flags ); // Modifiers. - inline void unsetFlags ( uint64_t ); - inline void setFlags ( uint64_t ); - void setFlagsOnAligneds ( uint64_t ); - inline void incReduceds (); - inline void decReduceds (); - virtual void setDuSource ( DbU::Unit du ) = 0; - virtual void setDuTarget ( DbU::Unit du ) = 0; - void computeTerminal (); - virtual void updateOrient () = 0; - virtual void updatePositions () = 0; - virtual void updateNativeConstraints () = 0; - void updateSourceSpin (); - void updateTargetSpin (); - void sourceDetach (); - void targetDetach (); - void sourceAttach ( AutoContact* ); - void targetAttach ( AutoContact* ); - //inline void mergeUserConstraints ( const Interval& ); - void mergeUserConstraints ( const Interval& ); - inline void resetUserConstraints (); - inline void setOptimalMin ( DbU::Unit min ); - inline void setOptimalMax ( DbU::Unit max ); - inline void mergeNativeMin ( DbU::Unit min ); - inline void mergeNativeMax ( DbU::Unit max ); - inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max ); - bool checkNotInvalidated () const; - inline void setParent ( AutoSegment* ); - void revalidate (); - AutoSegment* makeDogleg ( AutoContact* ); - Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags ); - Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags ); - virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0; - virtual bool moveULeft () = 0; - virtual bool moveURight () = 0; - bool slacken ( Flags flags ); - virtual bool _slacken ( Flags flags ) = 0; - void _changeDepth ( unsigned int depth, Flags flags ); - void changeDepth ( unsigned int depth, Flags flags ); - bool moveUp ( Flags flags=Flags::NoFlags ); - bool moveDown ( Flags flags=Flags::NoFlags ); - bool reduceDoglegLayer (); - bool reduce (); - bool raise (); + inline void unsetFlags ( uint64_t ); + inline void setFlags ( uint64_t ); + void setFlagsOnAligneds ( uint64_t ); + inline void incReduceds (); + inline void decReduceds (); + virtual void setDuSource ( DbU::Unit du ) = 0; + virtual void setDuTarget ( DbU::Unit du ) = 0; + void computeTerminal (); + virtual void updateOrient () = 0; + virtual void updatePositions () = 0; + virtual void updateNativeConstraints () = 0; + void updateSourceSpin (); + void updateTargetSpin (); + void sourceDetach (); + void targetDetach (); + void sourceAttach ( AutoContact* ); + void targetAttach ( AutoContact* ); + //inline void mergeUserConstraints ( const Interval& ); + void mergeUserConstraints ( const Interval& ); + inline void resetUserConstraints (); + inline void setOptimalMin ( DbU::Unit min ); + inline void setOptimalMax ( DbU::Unit max ); + inline void mergeNativeMin ( DbU::Unit min ); + inline void mergeNativeMax ( DbU::Unit max ); + inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max ); + bool checkNotInvalidated () const; + inline void setParent ( AutoSegment* ); + void revalidate (); + AutoSegment* makeDogleg ( AutoContact* ); + Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags ); + Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags ); + virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0; + virtual bool moveULeft () = 0; + virtual bool moveURight () = 0; + bool slacken ( Flags flags ); + virtual bool _slacken ( Flags flags ) = 0; + void _changeDepth ( unsigned int depth, Flags flags ); + void changeDepth ( unsigned int depth, Flags flags ); + bool moveUp ( Flags flags=Flags::NoFlags ); + bool moveDown ( Flags flags=Flags::NoFlags ); + bool reduceDoglegLayer (); + bool reduce (); + bool raise (); // Canonical Modifiers. - AutoSegment* canonize ( Flags flags=Flags::NoFlags ); - virtual void invalidate ( Flags flags=Flags::Propagate ); - void invalidate ( AutoContact* ); - void computeOptimal ( set& processeds ); - void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags ); - bool toConstraintAxis ( Flags flags=Flags::Realignate ); - bool toOptimalAxis ( Flags flags=Flags::Realignate ); + AutoSegment* canonize ( Flags flags=Flags::NoFlags ); + virtual void invalidate ( Flags flags=Flags::Propagate ); + void invalidate ( AutoContact* ); + void computeOptimal ( set& processeds ); + void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags ); + bool toConstraintAxis ( Flags flags=Flags::Realignate ); + bool toOptimalAxis ( Flags flags=Flags::Realignate ); // Collections & Filters. - AutoSegments getOnSourceContact ( Flags direction ); - AutoSegments getOnTargetContact ( Flags direction ); - AutoSegments getCachedOnSourceContact ( Flags direction ); - AutoSegments getCachedOnTargetContact ( Flags direction ); - AutoSegments getAligneds ( Flags flags=Flags::NoFlags ); - AutoSegments getConnecteds ( Flags flags=Flags::NoFlags ); - AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags ); - size_t getAlignedContacts ( map& ) const ; + AutoSegments getOnSourceContact ( Flags direction ); + AutoSegments getOnTargetContact ( Flags direction ); + AutoSegments getCachedOnSourceContact ( Flags direction ); + AutoSegments getCachedOnTargetContact ( Flags direction ); + AutoSegments getAligneds ( Flags flags=Flags::NoFlags ); + AutoSegments getConnecteds ( Flags flags=Flags::NoFlags ); + AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags ); + size_t getAlignedContacts ( map& ) const ; // Observers. template< typename OwnerT > - inline OwnerT* getObserver ( size_t slot ); - inline void setObserver ( size_t slot, BaseObserver* ); - inline void notify ( unsigned int flags ); + inline OwnerT* getObserver ( size_t slot ); + inline void setObserver ( size_t slot, BaseObserver* ); + inline void notify ( unsigned int flags ); // Inspector Management. - virtual Record* _getRecord () const = 0; - virtual string _getString () const = 0; - virtual string _getTypeName () const = 0; + virtual Record* _getRecord () const = 0; + virtual string _getString () const = 0; + virtual string _getTypeName () const = 0; // Non-reviewed atomic modifiers. - bool _check () const; + bool _check () const; #if THIS_IS_DISABLED - virtual void desalignate ( AutoContact* ) = 0; - bool shearUp ( GCell* - , AutoSegment*& movedUp - , float reserve - , Flags flags ); + virtual void desalignate ( AutoContact* ) = 0; + bool shearUp ( GCell* + , AutoSegment*& movedUp + , float reserve + , Flags flags ); #endif protected: // Internal: Static Attributes. - static size_t _allocateds; - static size_t _globalsCount; - static bool _analogMode; + static size_t _allocateds; + static size_t _globalsCount; + static bool _analogMode; + static bool _initialized; + static vector< array > _extensionCaps; // Internal: Attributes. - const unsigned long _id; - GCell* _gcell; - uint64_t _flags; - unsigned int _depth : 8; - unsigned int _optimalMin :16; - unsigned int _optimalMax :16; - unsigned int _reduceds : 2; - DbU::Unit _sourcePosition; - DbU::Unit _targetPosition; - Interval _userConstraints; - Interval _nativeConstraints; - AutoSegment* _parent; - Observable _observers; + const unsigned long _id; + GCell* _gcell; + uint64_t _flags; + unsigned int _depth : 8; + unsigned int _optimalMin :16; + unsigned int _optimalMax :16; + unsigned int _reduceds : 2; + DbU::Unit _sourcePosition; + DbU::Unit _targetPosition; + Interval _userConstraints; + Interval _nativeConstraints; + AutoSegment* _parent; + Observable _observers; // Internal: Constructors & Destructors. protected: - AutoSegment ( Segment* segment ); - virtual ~AutoSegment (); - static void _preCreate ( AutoContact* source, AutoContact* target ); - virtual void _postCreate (); - virtual void _preDestroy (); + AutoSegment ( Segment* segment ); + virtual ~AutoSegment (); + static void _preCreate ( AutoContact* source, AutoContact* target ); + virtual void _postCreate (); + virtual void _preDestroy (); + static void _initialize (); private: - AutoSegment ( const AutoSegment& ); - AutoSegment& operator= ( const AutoSegment& ); + AutoSegment ( const AutoSegment& ); + AutoSegment& operator= ( const AutoSegment& ); protected: - void _invalidate (); - inline uint64_t _getFlags () const; - std::string _getStringFlags () const; - virtual void _setAxis ( DbU::Unit ) = 0; + void _invalidate (); + inline uint64_t _getFlags () const; + std::string _getStringFlags () const; + virtual void _setAxis ( DbU::Unit ) = 0; public: struct CompareId : public binary_function { @@ -391,8 +404,13 @@ namespace Anabatic { struct CompareByDepthAxis : public binary_function { bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; }; + public: + struct CompareBySourceU : public binary_function { + bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const; + }; public: typedef std::set DepthLengthSet; + typedef std::set IdSet; // Static Utilities. public: @@ -431,6 +449,9 @@ namespace Anabatic { // Inline Functions. + inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; } + inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; } + inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; } inline unsigned long AutoSegment::getId () const { return _id; } inline Cell* AutoSegment::getCell () const { return base()->getCell(); } inline Net* AutoSegment::getNet () const { return base()->getNet(); } @@ -471,6 +492,7 @@ namespace Anabatic { inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; } inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); } inline bool AutoSegment::isFixed () const { return _flags & SegFixed; } + inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; } inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; } inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; } inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; } @@ -532,7 +554,6 @@ namespace Anabatic { _parent = parent; } - inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const { return lhs->getId() < rhs->getId(); } diff --git a/crlcore/etc/45/freepdk_45/kite.conf b/crlcore/etc/45/freepdk_45/kite.conf index 39e9e6b0..ec519a13 100644 --- a/crlcore/etc/45/freepdk_45/kite.conf +++ b/crlcore/etc/45/freepdk_45/kite.conf @@ -43,7 +43,8 @@ parametersTable = \ routingGaugesTable = {} routingGaugesTable['gscl45'] = \ - ( ( 'metal1' , ( Gauge.Horizontal, Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.065, 7 ) ) + ( ( 'symbolic', False ) + , ( 'metal1' , ( Gauge.Horizontal, Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.065, 7 ) ) , ( 'metal2' , ( Gauge.Vertical , Gauge.Default, 1, 0.0, 0, 0.190, 0.070, 0.070, 8 ) ) , ( 'metal3' , ( Gauge.Horizontal, Gauge.Default, 2, 0.0, 0, 0.190, 0.070, 0.070, 8 ) ) , ( 'metal4' , ( Gauge.Vertical , Gauge.Default, 3, 0.0, 0, 0.285, 0.140, 0.140, 8 ) ) diff --git a/crlcore/etc/45/freepdk_45/technology.conf b/crlcore/etc/45/freepdk_45/technology.conf index fa691884..6c31b144 100644 --- a/crlcore/etc/45/freepdk_45/technology.conf +++ b/crlcore/etc/45/freepdk_45/technology.conf @@ -33,7 +33,18 @@ technoConfig = { 'name' : 'freepdk_45' # must be expressed in microns. layersExtensionsTable = \ - ( ('NWELL.nWell.extention.cap' , 0.0) + ( ('metal1.minimalSpacing' , 0.065) + , ('metal2.minimalSpacing' , 0.075) + , ('metal3.minimalSpacing' , 0.07 ) + , ('metal4.minimalSpacing' , 0.14 ) + , ('metal5.minimalSpacing' , 0.14 ) + , ('metal6.minimalSpacing' , 0.14 ) + , ('metal7.minimalSpacing' , 0.4 ) + , ('metal8.minimalSpacing' , 0.4 ) + , ('metal9.minimalSpacing' , 0.8 ) + , ('metal10.minimalSpacing' , 0.8 ) + + , ('NWELL.nWell.extention.cap' , 0.0) , ('PWELL.pWell.extention.cap' , 0.0) , ('NTIE.minimum.width' , 3.0) @@ -166,13 +177,15 @@ layersExtensionsTable = \ # VIAs (i.e. Metal <--> Metal) (real). , ('via12.minimum.side' , 0.065) - , ('via12.metal1.enclosure' , 0.0 ) - , ('via12.metal2.enclosure' , 0.025) + # This is the rule as defined in LEF, but seems wrong to me. + #, ('via12.metal1.enclosure' , (0.035 , 0.0 ) ) + , ('via12.metal1.enclosure' , (0.0 , 0.035) ) + , ('via12.metal2.enclosure' , (0.0025, 0.035) ) , ('via23.minimum.side' , 0.070) - , ('via23.metal2.enclosure' , 0.0 ) - , ('via23.metal3.enclosure' , 0.035) + , ('via23.metal2.enclosure' , (0.0 , 0.035) ) + , ('via23.metal3.enclosure' , (0.035 , 0.0 ) ) , ('via34.minimum.side' , 0.070) - , ('via34.metal3.enclosure' , 0.0 ) + , ('via34.metal3.enclosure' , (0.035, 0.0 ) ) , ('via34.metal4.enclosure' , 0.035) , ('via45.minimum.side' , 0.140) , ('via45.metal4.enclosure' , 0.0 ) diff --git a/crlcore/etc/symbolic/cmos/technology.conf b/crlcore/etc/symbolic/cmos/technology.conf index b7f10d97..5b7c733c 100644 --- a/crlcore/etc/symbolic/cmos/technology.conf +++ b/crlcore/etc/symbolic/cmos/technology.conf @@ -88,11 +88,11 @@ layersExtensionsTable = \ # Routing Layers. , ('METAL1.minimum.width' , 1.0) , ('METAL1.metal1.extention.cap' , 0.5) - , ('METAL2.minimum.width' , 1.0) + , ('METAL2.minimum.width' , 2.0) , ('METAL2.metal2.extention.cap' , 1.0) - , ('METAL3.minimum.width' , 1.0) + , ('METAL3.minimum.width' , 2.0) , ('METAL3.metal3.extention.cap' , 1.0) - , ('METAL4.minimum.width' , 1.0) + , ('METAL4.minimum.width' , 2.0) , ('METAL4.metal4.extention.cap' , 1.0) , ('METAL5.minimum.width' , 2.0) , ('METAL5.metal5.extention.cap' , 1.0) diff --git a/crlcore/python/helpers/Alliance.py b/crlcore/python/helpers/Alliance.py index 1ceeb227..3942b019 100644 --- a/crlcore/python/helpers/Alliance.py +++ b/crlcore/python/helpers/Alliance.py @@ -147,16 +147,21 @@ def loadRoutingGaugesTable ( routingGaugesTable, fromFile ): try: if len(entry) != 2: - raise ErrorMessage(1,['Malformed entry in .' % gaugeName - ,'Must have exactly two fields ("METAL_LAYER", (parameters_list)).' - ,str(entry) - ]) + raise ErrorMessage(1,['Malformed entry in .' % gaugeName + ,'Must have exactly two fields ("METAL_LAYER", (parameters_list)).' + ,str(entry) + ]) + + if entry[0] == 'symbolic': + gauge.setSymbolic( entry[1] ) + continue + if len(entry[1]) != 9: - raise ErrorMessage(1,['Malformed entry in .' % gaugeName - ,'Parameters list must have exactly nine fields:' - ,' (direction, type, depth, density, offset, pitch, wire_width, via_width, obs_dw)' - ,str(entry) - ]) + raise ErrorMessage(1,['Malformed entry in .' % gaugeName + ,'Parameters list must have exactly nine fields:' + ,' (direction, type, depth, density, offset, pitch, wire_width, via_width, obs_dw)' + ,str(entry) + ]) gauge.addLayerGauge( RoutingLayerGauge.create( technology.getLayer(entry[0]) , Gauge.toRlGauge(entry[1][0]) # Direction. diff --git a/crlcore/python/helpers/Technology.py b/crlcore/python/helpers/Technology.py index 8c57d09c..af8786fd 100644 --- a/crlcore/python/helpers/Technology.py +++ b/crlcore/python/helpers/Technology.py @@ -216,36 +216,59 @@ def loadLayersExtensions ( layersExtensionsTable, confFile ): ,'Must contains exactly two fields: ( rule_path, value ).' ,str(rule) ]) - if not isinstance(rule[1],int) and not isinstance(rule[1],float): + if not isinstance(rule[1],int) \ + and not isinstance(rule[1],float) \ + and not isinstance(rule[1],tuple): raise ErrorMessage(1,['Invalid entry in .' - ,'Rule value must be of integer or float type.' + ,'Rule value must be of integer, float, or pair a of those type.' ,str(rule) ]) elements = rule[0].split('.') - if len(elements) < 3: + if len(elements) == 2: + ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Real|LayersLUT.MissingError ) + subLayer = None + elif len(elements) == 3 or len(elements) == 4: + ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Composite|LayersLUT.MissingError ) + subLayer = layersLUT.lookup( elements[1], LayersLUT.Real ) + else: raise ErrorMessage(1,['Invalid entry in .' - ,'Rule name must contains at least three components: \"LAYER.category.dimension\".' + ,'Rule name must contains two or three components:' + ,' * \"COMP_LAYER.category.dimension\".' + ,' * \"REAL_LAYER.dimension\".' ,str(rule) ]) - ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Composite|LayersLUT.MissingError ) - subLayer = layersLUT.lookup( elements[1], LayersLUT.Real ) - if elements[0].startswith('via'): value = toDbU(rule[1]) - else: value = DbU.fromLambda(rule[1]) + if elements[0].startswith('via') or elements[0].startswith('metal'): + if isinstance(rule[1],tuple): + value = ( toDbU(rule[1][0]), toDbU(rule[1][1]) ) + else: + value = toDbU(rule[1]) + else: + if isinstance(rule[1],tuple): + value = ( DbU.fromLambda(rule[1][0]), DbU.fromLambda(rule[1][1]) ) + else: + value = DbU.fromLambda(rule[1]) if subLayer: ruleTag = string.join(elements[2:],'.') else: ruleTag = string.join(elements[1:],'.') - if ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value ) + if ruleTag == 'minimalSpacing': ruleLayer.setMinimalSpacing( value ) + elif ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value ) elif ruleTag == 'extention.width': ruleLayer.setExtentionWidth( subLayer, value ) - elif ruleTag == 'enclosure': ruleLayer.setEnclosure ( subLayer, value ) elif ruleTag == 'minimum.width': ruleLayer.setMinimalSize ( value ) elif ruleTag == 'minimum.side': ruleLayer.setMinimalSize ( value ) + elif ruleTag == 'enclosure': + if isinstance(value,tuple): + ruleLayer.setEnclosure( subLayer, value[0], Layer.EnclosureH ) + ruleLayer.setEnclosure( subLayer, value[1], Layer.EnclosureV ) + else: + ruleLayer.setEnclosure( subLayer, value, Layer.EnclosureH|Layer.EnclosureV ) else: raise ErrorMessage(1,['Invalid entry in .' ,'Unknown rule kind: \".%s\", should be any of:' % ruleTag + ,' * "RULE_HEAD.minimalSpacing"' ,' * "RULE_HEAD.extention.cap"' ,' * "RULE_HEAD.extention.width"' ,' * "RULE_HEAD.enclosure"' diff --git a/crlcore/src/ccore/RoutingGauge.cpp b/crlcore/src/ccore/RoutingGauge.cpp index 388d02cb..eb3df892 100644 --- a/crlcore/src/ccore/RoutingGauge.cpp +++ b/crlcore/src/ccore/RoutingGauge.cpp @@ -60,6 +60,7 @@ namespace CRL { , _layerGauges() , _viaLayers () , _technology (DataBase::getDB()->getTechnology()) + , _isSymbolic (true) { } @@ -68,6 +69,7 @@ namespace CRL { , _layerGauges() , _viaLayers () , _technology (gauge._technology) + , _isSymbolic (gauge._isSymbolic) { // Make a deep copy of the map. for ( size_t i=0 ; iadd ( getSlot("_name" , _name ) ); - record->add ( getSlot("_gauges" ,&_layerGauges) ); + record->add ( getSlot("_name" , _name ) ); + record->add ( getSlot("_gauges" ,&_layerGauges) ); + record->add ( getSlot("_isSymbolic", _isSymbolic ) ); return ( record ); } diff --git a/crlcore/src/ccore/SymbolicTechnologyParser.cpp b/crlcore/src/ccore/SymbolicTechnologyParser.cpp index dc74c584..4ed85bd6 100644 --- a/crlcore/src/ccore/SymbolicTechnologyParser.cpp +++ b/crlcore/src/ccore/SymbolicTechnologyParser.cpp @@ -383,7 +383,7 @@ namespace CRL { switch ( ruleType ) { case ExtentionCap: ruleLayer->setExtentionCap (basicLayer,DbU::lambda(doubleValue)); break; case ExtentionWidth: ruleLayer->setExtentionWidth(basicLayer,DbU::lambda(doubleValue)); break; - case Enclosure: ruleLayer->setEnclosure (basicLayer,DbU::lambda(doubleValue)); break; + case Enclosure: ruleLayer->setEnclosure (basicLayer,DbU::lambda(doubleValue),Layer::EnclosureH|Layer::EnclosureV); break; case MinimumWidth: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break; case MinimumSide: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break; } diff --git a/crlcore/src/ccore/crlcore/RoutingGauge.h b/crlcore/src/ccore/crlcore/RoutingGauge.h index a4c2d4ee..12fc9b08 100644 --- a/crlcore/src/ccore/crlcore/RoutingGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingGauge.h @@ -54,6 +54,7 @@ namespace CRL { static RoutingGauge* create ( const char* name ); virtual void destroy (); // Predicates. + inline bool isSymbolic () const; inline bool isTwoMetals () const; inline bool isHV () const; inline bool isVH () const; @@ -85,6 +86,7 @@ namespace CRL { // Methods. void addLayerGauge ( RoutingLayerGauge* layerGauge ); void checkConnexity () const; + inline void setSymbolic ( bool ); // Hurricane Managment. void toJson ( JsonWriter* ) const; virtual Record* _getRecord ( Record* record=NULL ) const; @@ -97,6 +99,7 @@ namespace CRL { vector _layerGauges; vector _viaLayers; Technology* _technology; + bool _isSymbolic; // Internal - Constructors & Destructors. RoutingGauge ( const char* name ); @@ -107,6 +110,7 @@ namespace CRL { }; + inline bool RoutingGauge::isSymbolic () const { return _isSymbolic; } inline bool RoutingGauge::isTwoMetals () const { return (getDepth() < 3); } inline bool RoutingGauge::isHV () const { return not isTwoMetals() and (getLayerGauge(1)->isHorizontal()); } inline bool RoutingGauge::isVH () const { return not isTwoMetals() and (getLayerGauge(1)->isVertical()); } @@ -121,6 +125,7 @@ namespace CRL { inline DbU::Unit RoutingGauge::getLayerOffset ( size_t depth ) const { return getLayerGauge(depth)->getOffset(); } inline DbU::Unit RoutingGauge::getLayerWireWidth ( size_t depth ) const { return getLayerGauge(depth)->getWireWidth(); } inline DbU::Unit RoutingGauge::getViaWidth ( size_t depth ) const { return getLayerGauge(depth)->getViaWidth(); } + inline void RoutingGauge::setSymbolic ( bool state ) { _isSymbolic=state; } // ------------------------------------------------------------------- diff --git a/crlcore/src/pyCRL/PyRoutingGauge.cpp b/crlcore/src/pyCRL/PyRoutingGauge.cpp index 8aa93e2b..8cd8a64e 100644 --- a/crlcore/src/pyCRL/PyRoutingGauge.cpp +++ b/crlcore/src/pyCRL/PyRoutingGauge.cpp @@ -358,6 +358,8 @@ extern "C" { // Standard Attributes. GetNameMethod(RoutingGauge,rg) accessorVectorFromVoid(getLayerGauges,PyRoutingGauge,RoutingGauge,RoutingLayerGauge) + DirectGetBoolAttribute(PyRoutingGauge_isSymbolic ,isSymbolic ,PyRoutingGauge,RoutingGauge) + DirectSetBoolAttribute(PyRoutingGauge_setSymbolic,setSymbolic,PyRoutingGauge,RoutingGauge) // Standart Destroy (Attribute). @@ -366,6 +368,8 @@ extern "C" { PyMethodDef PyRoutingGauge_Methods[] = { { "create" , (PyCFunction)PyRoutingGauge_create , METH_VARARGS|METH_STATIC , "Create a new RoutingGauge." } + , { "isSymbolic" , (PyCFunction)PyRoutingGauge_isSymbolic , METH_NOARGS + , "The RoutingGauge is for symbolic technology." } , { "getName" , (PyCFunction)PyRoutingGauge_getName , METH_NOARGS , "Return the maximum depth of the RoutingGauge." } , { "getTechnology" , (PyCFunction)PyRoutingGauge_getTechnology , METH_NOARGS @@ -392,6 +396,8 @@ extern "C" { , "Return the list of RoutingLayerGauge." } , { "addLayerGauge" , (PyCFunction)PyRoutingGauge_addLayerGauge , METH_VARARGS , "Adds a new RoutingLayerGauge to the RoutingGauge." } + , { "setSymbolic" , (PyCFunction)PyRoutingGauge_setSymbolic , METH_VARARGS + , "Set the symbolic technology state." } //, { "destroy" , (PyCFunction)PyRoutingGauge_destroy , METH_VARARGS // , "Destroy the associated hurricane object. The python object remains." } , {NULL, NULL, 0, NULL} /* sentinel */ diff --git a/hurricane/src/hurricane/Contact.cpp b/hurricane/src/hurricane/Contact.cpp index 53a4f057..41690c38 100644 --- a/hurricane/src/hurricane/Contact.cpp +++ b/hurricane/src/hurricane/Contact.cpp @@ -200,19 +200,21 @@ Point Contact::getPosition() const Box Contact::getBoundingBox() const // ******************************** { - DbU::Unit size = getLayer()->getEnclosure(); + DbU::Unit enclosureH = getLayer()->getEnclosure( Layer::EnclosureH ); + DbU::Unit enclosureV = getLayer()->getEnclosure( Layer::EnclosureV ); - return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size); + return Box(getPosition()).inflate(getHalfWidth() + enclosureH, getHalfHeight() + enclosureV); } Box Contact::getBoundingBox(const BasicLayer* basicLayer) const // ****************************************************** { - if (!_layer->contains(basicLayer)) return Box(); + if (not _layer->contains(basicLayer)) return Box(); - DbU::Unit size = getLayer()->getEnclosure(basicLayer); + DbU::Unit enclosureH = getLayer()->getEnclosure( basicLayer, Layer::EnclosureH ); + DbU::Unit enclosureV = getLayer()->getEnclosure( basicLayer, Layer::EnclosureV ); - return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size); + return Box(getPosition()).inflate(getHalfWidth() + enclosureH, getHalfHeight() + enclosureV ); } Component* Contact::getAnchor() const diff --git a/hurricane/src/hurricane/ContactLayer.cpp b/hurricane/src/hurricane/ContactLayer.cpp index ac2868ee..c37a1a19 100644 --- a/hurricane/src/hurricane/ContactLayer.cpp +++ b/hurricane/src/hurricane/ContactLayer.cpp @@ -69,39 +69,37 @@ namespace Hurricane { ,_enclosures() ,_maximalEnclosure(0) { - if ( !metalLayer ) throw Error ( nullLayer, getString(name).c_str(), "Metal" ); - if ( !cutLayer ) throw Error ( nullLayer, getString(name).c_str(), "Cut" ); - if ( !activeLayer ) throw Error ( nullLayer, getString(name).c_str(), "Active" ); - if ( !diffusionLayer ) throw Error ( nullLayer, getString(name).c_str(), "Diffusion" ); + if (not metalLayer ) throw Error ( nullLayer, getString(name).c_str(), "Metal" ); + if (not cutLayer ) throw Error ( nullLayer, getString(name).c_str(), "Cut" ); + if (not activeLayer ) throw Error ( nullLayer, getString(name).c_str(), "Active" ); + if (not diffusionLayer) throw Error ( nullLayer, getString(name).c_str(), "Diffusion" ); - _basicLayers.reserve ( 5 ); - _enclosures .reserve ( 5 ); + _basicLayers.reserve( 5 ); + _enclosures .reserve( 5 ); // Have to check wich one is top layer & cutLayer of type cut. - _basicLayers.push_back ( metalLayer ); - _basicLayers.push_back ( cutLayer ); - _basicLayers.push_back ( activeLayer ); - _basicLayers.push_back ( diffusionLayer ); + _basicLayers.push_back( metalLayer ); + _basicLayers.push_back( cutLayer ); + _basicLayers.push_back( activeLayer ); + _basicLayers.push_back( diffusionLayer ); - for ( size_t i=0 ; i<4 ; i++ ) { - _enclosures.push_back ( 0 ); - } + for ( size_t i=0 ; i<4 ; i++ ) _enclosures.push_back( make_pair(0,0) ); - _setMask ( metalLayer ->getMask() - | cutLayer ->getMask() - | activeLayer ->getMask() - | diffusionLayer->getMask() ); - _setExtractMask ( metalLayer ->getExtractMask() - | cutLayer ->getExtractMask() - | activeLayer ->getExtractMask() - | diffusionLayer->getExtractMask() ); + _setMask ( metalLayer ->getMask() + | cutLayer ->getMask() + | activeLayer ->getMask() + | diffusionLayer->getMask() ); + _setExtractMask( metalLayer ->getExtractMask() + | cutLayer ->getExtractMask() + | activeLayer ->getExtractMask() + | diffusionLayer->getExtractMask() ); - if ( wellLayer ) { - _basicLayers.push_back ( wellLayer ); - _enclosures .push_back ( 0 ); + if (wellLayer) { + _basicLayers.push_back( wellLayer ); + _enclosures .push_back( make_pair(0,0) ); - _setMask ( getMask() | wellLayer->getMask() ); - _setExtractMask ( getMask() | wellLayer->getExtractMask() ); + _setMask ( getMask() | wellLayer->getMask() ); + _setExtractMask( getMask() | wellLayer->getExtractMask() ); } } @@ -134,38 +132,61 @@ namespace Hurricane { { return getCollection(_basicLayers); } - DbU::Unit ContactLayer::getEnclosure () const - { return _maximalEnclosure; } + DbU::Unit ContactLayer::getEnclosure ( uint32_t flags ) const + { + if (flags & (Layer::EnclosureH|Layer::EnclosureV)) return _maximalEnclosure; + + DbU::Unit enclosure = 0; + if (flags & Layer::EnclosureH) { + for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.first ); + } + if (flags & Layer::EnclosureV) { + for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.second ); + } + + return enclosure; + } - DbU::Unit ContactLayer::getEnclosure ( const BasicLayer* layer ) const + DbU::Unit ContactLayer::getEnclosure ( const BasicLayer* layer, uint32_t flags ) const { for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) { - if ( _basicLayers[i] == layer ) - return _enclosures[i]; + if ( _basicLayers[i] == layer ) { + + if (flags & Layer::EnclosureH) { + if (flags & Layer::EnclosureV) return std::max( _enclosures[i].first, _enclosures[i].second ); + return _enclosures[i].first; + } + if (flags & Layer::EnclosureV) return _enclosures[i].second; + } } return 0; } - void ContactLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure ) + void ContactLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags ) { + _maximalEnclosure = 0; for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) { if ( _basicLayers[i] == layer ) { - _enclosures[i] = enclosure; - _maximalEnclosure = max ( _maximalEnclosure, enclosure ); + if (flags & Layer::EnclosureH) _enclosures[i].first = enclosure; + if (flags & Layer::EnclosureV) _enclosures[i].second = enclosure; } + _maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].first ); + _maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].second ); } } void ContactLayer::_onDbuChange ( float scale ) { - Layer::_onDbuChange ( scale ); - for ( size_t i=0 ; i<_enclosures.size() ; i++ ) - _enclosures[i] = (DbU::Unit)( (float)_enclosures[i] * scale ); - _maximalEnclosure = (DbU::Unit)( (float)_maximalEnclosure * scale ); + Layer::_onDbuChange( scale ); + for ( size_t i=0 ; i<_enclosures.size() ; i++ ) { + _enclosures[i].first = (DbU::Unit)( (float)_enclosures[i].first * scale ); + _enclosures[i].second = (DbU::Unit)( (float)_enclosures[i].second * scale ); + } + _maximalEnclosure = (DbU::Unit)( (float)_maximalEnclosure * scale ); } @@ -202,11 +223,16 @@ namespace Hurricane { if (_basicLayers.size() == 5) jsonWrite( w, "_well", _basicLayers[4]->getName() ); else jsonWrite( w, "_well", "no_well_layer" ); - jsonWrite( w, "_enclosure.metal" , _enclosures[0] ); - jsonWrite( w, "_enclosure.cut" , _enclosures[1] ); - jsonWrite( w, "_enclosure.active" , _enclosures[2] ); - jsonWrite( w, "_enclosure.diffusion", _enclosures[3] ); - jsonWrite( w, "_enclosure.well" , (_basicLayers.size() == 5) ? _enclosures[4] : 0 ); + jsonWrite( w, "_enclosureH.metal" , _enclosures[0].first ); + jsonWrite( w, "_enclosureV.metal" , _enclosures[0].second ); + jsonWrite( w, "_enclosureH.cut" , _enclosures[1].first ); + jsonWrite( w, "_enclosureV.cut" , _enclosures[1].second ); + jsonWrite( w, "_enclosureH.active" , _enclosures[2].first ); + jsonWrite( w, "_enclosureV.active" , _enclosures[2].second ); + jsonWrite( w, "_enclosureH.diffusion", _enclosures[3].first ); + jsonWrite( w, "_enclosureV.diffusion", _enclosures[3].second ); + jsonWrite( w, "_enclosureH.well" , (_basicLayers.size() == 5) ? _enclosures[4].first : 0 ); + jsonWrite( w, "_enclosureV.well" , (_basicLayers.size() == 5) ? _enclosures[4].second : 0 ); } @@ -227,16 +253,21 @@ namespace Hurricane { cdebug_log(19,0) << "JsonContactLayer::JsonContactLayer()" << endl; - add( "_metal" , typeid(string) ); - add( "_cut" , typeid(string) ); - add( "_active" , typeid(string) ); - add( "_diffusion" , typeid(string) ); - add( "_well" , typeid(string) ); - add( "_enclosure.metal" , typeid(int64_t) ); - add( "_enclosure.cut" , typeid(int64_t) ); - add( "_enclosure.active" , typeid(int64_t) ); - add( "_enclosure.diffusion", typeid(int64_t) ); - add( "_enclosure.well" , typeid(int64_t) ); + add( "_metal" , typeid(string) ); + add( "_cut" , typeid(string) ); + add( "_active" , typeid(string) ); + add( "_diffusion" , typeid(string) ); + add( "_well" , typeid(string) ); + add( "_enclosureH.metal" , typeid(int64_t) ); + add( "_enclosureV.metal" , typeid(int64_t) ); + add( "_enclosureH.cut" , typeid(int64_t) ); + add( "_enclosureV.cut" , typeid(int64_t) ); + add( "_enclosureH.active" , typeid(int64_t) ); + add( "_enclosureV.active" , typeid(int64_t) ); + add( "_enclosureH.diffusion", typeid(int64_t) ); + add( "_enclosureV.diffusion", typeid(int64_t) ); + add( "_enclosureH.well" , typeid(int64_t) ); + add( "_enclosureV.well" , typeid(int64_t) ); } @@ -273,11 +304,16 @@ namespace Hurricane { BasicLayer* active = techno->getBasicLayer( get(stack,"_active" ) ); BasicLayer* diffusion = techno->getBasicLayer( get(stack,"_diffusion") ); BasicLayer* well = techno->getBasicLayer( get(stack,"_well" ) ); - DbU::Unit metalEncl = get( stack, "_enclosure.metal" ); - DbU::Unit cutEncl = get( stack, "_enclosure.cut" ); - DbU::Unit activeEncl = get( stack, "_enclosure.active" ); - DbU::Unit diffusionEncl = get( stack, "_enclosure.diffusion" ); - DbU::Unit wellEncl = get( stack, "_enclosure.well" ); + DbU::Unit metalEnclH = get( stack, "_enclosureH.metal" ); + DbU::Unit metalEnclV = get( stack, "_enclosureV.metal" ); + DbU::Unit cutEnclH = get( stack, "_enclosureH.cut" ); + DbU::Unit cutEnclV = get( stack, "_enclosureV.cut" ); + DbU::Unit activeEnclH = get( stack, "_enclosureH.active" ); + DbU::Unit activeEnclV = get( stack, "_enclosureV.active" ); + DbU::Unit diffusionEnclH = get( stack, "_enclosureH.diffusion" ); + DbU::Unit diffusionEnclV = get( stack, "_enclosureV.diffusion" ); + DbU::Unit wellEnclH = get( stack, "_enclosureH.well" ); + DbU::Unit wellEnclV = get( stack, "_enclosureV.well" ); Layer::Mask mask = Layer::Mask::fromString( smask ); @@ -292,11 +328,18 @@ namespace Hurricane { , well ); layer->setSymbolic ( isSymbolic ); - layer->setEnclosure( metal , metalEncl ); - layer->setEnclosure( cut , cutEncl ); - layer->setEnclosure( active , activeEncl ); - layer->setEnclosure( diffusion, diffusionEncl ); - if (well) layer->setEnclosure( well, wellEncl ); + layer->setEnclosure( metal , metalEnclH , Layer::EnclosureH ); + layer->setEnclosure( metal , metalEnclV , Layer::EnclosureV ); + layer->setEnclosure( cut , cutEnclH , Layer::EnclosureH ); + layer->setEnclosure( cut , cutEnclV , Layer::EnclosureV ); + layer->setEnclosure( active , activeEnclH , Layer::EnclosureH ); + layer->setEnclosure( active , activeEnclV , Layer::EnclosureV ); + layer->setEnclosure( diffusion, diffusionEnclH, Layer::EnclosureH ); + layer->setEnclosure( diffusion, diffusionEnclV, Layer::EnclosureV ); + if (well) { + layer->setEnclosure( well, wellEnclH, Layer::EnclosureH ); + layer->setEnclosure( well, wellEnclV, Layer::EnclosureV ); + } if (layer->getMask() != mask) { cerr << Error( "JsonContactLayer::toData(): Layer mask re-creation discrepency on \"%s\":\n" diff --git a/hurricane/src/hurricane/DbU.cpp b/hurricane/src/hurricane/DbU.cpp index dc8aec66..b9e89b28 100644 --- a/hurricane/src/hurricane/DbU.cpp +++ b/hurricane/src/hurricane/DbU.cpp @@ -66,21 +66,21 @@ namespace Hurricane { public: // Constructor. - DbUSlot ( const string& name, const DbU::Unit* data ); - DbUSlot ( string& name, const DbU::Unit* data ); + DbUSlot ( const string& name, const DbU::Unit* data ); + DbUSlot ( string& name, const DbU::Unit* data ); // Accessors. - virtual string getDataString () const; - virtual Record* getDataRecord () const; - virtual DbUSlot* getClone () const; + virtual string getDataString () const; + virtual Record* getDataRecord () const; + virtual DbUSlot* getClone () const; protected: // Internal: Attributes. - const DbU::Unit* _unit; + const DbU::Unit* _unit; private: // Internal: Constructors. - DbUSlot ( const DbUSlot& ); - DbUSlot& operator= ( const DbUSlot& ); + DbUSlot ( const DbUSlot& ); + DbUSlot& operator= ( const DbUSlot& ); }; @@ -327,7 +327,7 @@ namespace Hurricane { case Min: os << "MIN:"; break; case Max: os << "MAX:"; break; default: - os << setprecision(3) << toPhysical(u,_stringModeUnitPower); + os << setprecision(4) << toPhysical(u,_stringModeUnitPower); } } else { if (_stringMode != Db) diff --git a/hurricane/src/hurricane/Layer.cpp b/hurricane/src/hurricane/Layer.cpp index 50295007..2bb977e1 100644 --- a/hurricane/src/hurricane/Layer.cpp +++ b/hurricane/src/hurricane/Layer.cpp @@ -100,7 +100,15 @@ namespace Hurricane { { return _technology->getCutBelow(this,useSymbolic); } - DbU::Unit Layer::getEnclosure () const + DbU::Unit Layer::getEnclosure ( uint32_t ) const + { return 0; } + + + DbU::Unit Layer::getTopEnclosure ( uint32_t ) const + { return 0; } + + + DbU::Unit Layer::getBottomEnclosure ( uint32_t ) const { return 0; } @@ -112,15 +120,15 @@ namespace Hurricane { { return 0; } - DbU::Unit Layer::getEnclosure ( const BasicLayer* layer ) const + DbU::Unit Layer::getEnclosure ( const BasicLayer*, uint32_t ) const { return 0; } - DbU::Unit Layer::getExtentionCap ( const BasicLayer* layer ) const + DbU::Unit Layer::getExtentionCap ( const BasicLayer* ) const { return 0; } - DbU::Unit Layer::getExtentionWidth ( const BasicLayer* layer ) const + DbU::Unit Layer::getExtentionWidth ( const BasicLayer* ) const { return 0; } @@ -164,7 +172,7 @@ namespace Hurricane { } - void Layer::setEnclosure ( const BasicLayer* layer, DbU::Unit ) + void Layer::setEnclosure ( const BasicLayer*, DbU::Unit, uint32_t ) { cerr << "[WARNING] Layer::setEnclosure() musn't be called on " << _getTypeName() << ": dummy implementation." << endl; diff --git a/hurricane/src/hurricane/RoutingPad.cpp b/hurricane/src/hurricane/RoutingPad.cpp index c3cbeb1e..bd0e8937 100644 --- a/hurricane/src/hurricane/RoutingPad.cpp +++ b/hurricane/src/hurricane/RoutingPad.cpp @@ -312,15 +312,17 @@ namespace Hurricane { Occurrence RoutingPad::getPlugOccurrence () { - if (dynamic_cast(_occurrence.getEntity())) - return _occurrence; + if (dynamic_cast(_occurrence.getEntity())) return _occurrence; Component* component = static_cast(_occurrence.getEntity()); Net* net = component->getNet(); Path path = _occurrence.getPath(); - if ( path.isEmpty() ) - throw Error("Empty Path => not in an instance"); + if (path.isEmpty()) + throw Error( "RoutingPad::getPlugOccurrence(): Empty Path, *not* in an instance for\n" + " %s" + , getString(this).c_str() + ); Instance* instance = path.getTailInstance(); Plug* plug = instance->getPlug(net); diff --git a/hurricane/src/hurricane/ViaLayer.cpp b/hurricane/src/hurricane/ViaLayer.cpp index 0b5922be..97b52b9d 100644 --- a/hurricane/src/hurricane/ViaLayer.cpp +++ b/hurricane/src/hurricane/ViaLayer.cpp @@ -95,9 +95,9 @@ namespace Hurricane { | cutLayer ->getExtractMask() | topLayer ->getExtractMask() ); - _enclosures.push_back ( 0 ); - _enclosures.push_back ( 0 ); - _enclosures.push_back ( 0 ); + _enclosures.push_back ( make_pair(0,0) ); + _enclosures.push_back ( make_pair(0,0) ); + _enclosures.push_back ( make_pair(0,0) ); } @@ -141,40 +141,82 @@ namespace Hurricane { } - DbU::Unit ViaLayer::getEnclosure () const + DbU::Unit ViaLayer::getEnclosure ( uint32_t flags ) const { - return _maximalEnclosure; + if (flags & (Layer::EnclosureH|Layer::EnclosureV)) return _maximalEnclosure; + + DbU::Unit enclosure = 0; + if (flags & Layer::EnclosureH) { + for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.first ); + } + if (flags & Layer::EnclosureV) { + for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.second ); + } + + return enclosure; } - DbU::Unit ViaLayer::getEnclosure ( const BasicLayer* layer ) const + DbU::Unit ViaLayer::getEnclosure ( const BasicLayer* layer, uint32_t flags ) const { for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) { - if ( layer == _basicLayers[i] ) return _enclosures[i]; + if ( _basicLayers[i] == layer ) { + + if (flags & Layer::EnclosureH) { + if (flags & Layer::EnclosureV) return std::max( _enclosures[i].first, _enclosures[i].second ); + return _enclosures[i].first; + } + if (flags & Layer::EnclosureV) return _enclosures[i].second; + } } return 0; } - void ViaLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure ) + DbU::Unit ViaLayer::getTopEnclosure ( uint32_t flags ) const { + if (flags & Layer::EnclosureH) { + if (flags & Layer::EnclosureV) return std::max( _enclosures[2].first, _enclosures[2].second ); + return _enclosures[2].first; + } + if (flags & Layer::EnclosureV) return _enclosures[2].second; + return 0; + } + + + DbU::Unit ViaLayer::getBottomEnclosure ( uint32_t flags ) const + { + if (flags & Layer::EnclosureH) { + if (flags & Layer::EnclosureV) return std::max( _enclosures[0].first, _enclosures[0].second ); + return _enclosures[0].first; + } + if (flags & Layer::EnclosureV) return _enclosures[0].second; + return 0; + } + + + void ViaLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags ) + { + _maximalEnclosure = 0; for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) { - if ( layer == _basicLayers[i] ) { - _enclosures[i] = enclosure; - _maximalEnclosure = max ( _maximalEnclosure, enclosure ); + if ( _basicLayers[i] == layer ) { + if (flags & Layer::EnclosureH) _enclosures[i].first = enclosure; + if (flags & Layer::EnclosureV) _enclosures[i].second = enclosure; } + _maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].first ); + _maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].second ); } } void ViaLayer::_onDbuChange ( float scale ) { - Layer::_onDbuChange ( scale ); - - for ( size_t i=0 ; i<_enclosures.size() ; i++ ) - _enclosures[i] = (DbU::Unit)( (float)_enclosures[i] * scale ); - + Layer::_onDbuChange( scale ); + for ( size_t i=0 ; i<_enclosures.size() ; i++ ) { + _enclosures[i].first = (DbU::Unit)( (float)_enclosures[i].first * scale ); + _enclosures[i].second = (DbU::Unit)( (float)_enclosures[i].second * scale ); + } _maximalEnclosure = (DbU::Unit)( (float)_maximalEnclosure * scale ); } @@ -209,9 +251,12 @@ namespace Hurricane { jsonWrite( w, "_cut" , _basicLayers[1]->getName() ); jsonWrite( w, "_top" , _basicLayers[2]->getName() ); - jsonWrite( w, "_enclosure.bottom", _enclosures[0] ); - jsonWrite( w, "_enclosure.cut" , _enclosures[1] ); - jsonWrite( w, "_enclosure.top" , _enclosures[2] ); + jsonWrite( w, "_enclosureH.bottom", _enclosures[0].first ); + jsonWrite( w, "_enclosureV.bottom", _enclosures[0].second ); + jsonWrite( w, "_enclosureH.cut" , _enclosures[1].first ); + jsonWrite( w, "_enclosureV.cut" , _enclosures[1].second ); + jsonWrite( w, "_enclosureH.top" , _enclosures[2].first ); + jsonWrite( w, "_enclosureV.top" , _enclosures[2].second ); } @@ -232,12 +277,15 @@ namespace Hurricane { cdebug_log(19,0) << "JsonViaLayer::JsonViaLayer()" << endl; - add( "_bottom" , typeid(string) ); - add( "_cut" , typeid(string) ); - add( "_top" , typeid(string) ); - add( "_enclosure.bottom", typeid(int64_t) ); - add( "_enclosure.cut" , typeid(int64_t) ); - add( "_enclosure.top" , typeid(int64_t) ); + add( "_bottom" , typeid(string) ); + add( "_cut" , typeid(string) ); + add( "_top" , typeid(string) ); + add( "_enclosureH.bottom", typeid(int64_t) ); + add( "_enclosureV.bottom", typeid(int64_t) ); + add( "_enclosureH.cut" , typeid(int64_t) ); + add( "_enclosureV.cut" , typeid(int64_t) ); + add( "_enclosureH.top" , typeid(int64_t) ); + add( "_enclosureV.top" , typeid(int64_t) ); } @@ -272,9 +320,12 @@ namespace Hurricane { BasicLayer* bottom = techno->getBasicLayer( get(stack,"_bottom" ) ); BasicLayer* cut = techno->getBasicLayer( get(stack,"_cut" ) ); BasicLayer* top = techno->getBasicLayer( get(stack,"_top" ) ); - DbU::Unit bottomEncl = get( stack, "_enclosure.bottom" ); - DbU::Unit cutEncl = get( stack, "_enclosure.cut" ); - DbU::Unit topEncl = get( stack, "_enclosure.top" ); + DbU::Unit bottomEnclH = get( stack, "_enclosureH.bottom" ); + DbU::Unit bottomEnclV = get( stack, "_enclosureV.bottom" ); + DbU::Unit cutEnclH = get( stack, "_enclosureH.cut" ); + DbU::Unit cutEnclV = get( stack, "_enclosureV.cut" ); + DbU::Unit topEnclH = get( stack, "_enclosureH.top" ); + DbU::Unit topEnclV = get( stack, "_enclosureV.top" ); Layer::Mask mask = Layer::Mask::fromString( smask ); @@ -287,9 +338,12 @@ namespace Hurricane { , top ); layer->setSymbolic ( isSymbolic ); - layer->setEnclosure( bottom, bottomEncl ); - layer->setEnclosure( cut , cutEncl ); - layer->setEnclosure( top , topEncl ); + layer->setEnclosure( bottom, bottomEnclH , Layer::EnclosureH ); + layer->setEnclosure( bottom, bottomEnclV , Layer::EnclosureV ); + layer->setEnclosure( cut , cutEnclH , Layer::EnclosureH ); + layer->setEnclosure( cut , cutEnclV , Layer::EnclosureV ); + layer->setEnclosure( top , topEnclH , Layer::EnclosureH ); + layer->setEnclosure( top , topEnclV , Layer::EnclosureV ); if (layer->getMask() != mask) { cerr << Error( "JsonViaLayer::toData(): Layer mask re-creation discrepency on \"%s\":\n" diff --git a/hurricane/src/hurricane/hurricane/Commons.h b/hurricane/src/hurricane/hurricane/Commons.h index 3ad283ab..c2f7d4f3 100644 --- a/hurricane/src/hurricane/hurricane/Commons.h +++ b/hurricane/src/hurricane/hurricane/Commons.h @@ -329,6 +329,45 @@ template inline Hurricane::Record* getRecord ( Data data ) { return NULL; } +// ------------------------------------------------------------------- +// Inspector Support for : "[const] std::pair&". + +template +inline std::string getString ( const std::pair& p ) +{ + return "const std::pair"; +} + + +template +inline Hurricane::Record* getRecord ( const std::pair& p ) +{ + Hurricane::Record* record = NULL; + record = new Hurricane::Record ( "const std::pair" ); + record->add( getSlot("first" , &p.first ) ); + record->add( getSlot("second", &p.second) ); + return record; +} + + +template +inline std::string getString ( std::pair& p ) +{ + return "std::pair"; +} + + +template +inline Hurricane::Record* getRecord ( std::pair& p ) +{ + Hurricane::Record* record = NULL; + record = new Hurricane::Record ( "std::pair" ); + record->add( getSlot("first" , &p.first ) ); + record->add( getSlot("second", &p.second) ); + return record; +} + + // ------------------------------------------------------------------- // Inspector Support for : "[const] std::array*". diff --git a/hurricane/src/hurricane/hurricane/ContactLayer.h b/hurricane/src/hurricane/hurricane/ContactLayer.h index 78fff3d7..2e6b3a31 100644 --- a/hurricane/src/hurricane/hurricane/ContactLayer.h +++ b/hurricane/src/hurricane/hurricane/ContactLayer.h @@ -59,10 +59,10 @@ namespace Hurricane { ); // Accessors. virtual BasicLayers getBasicLayers () const; - virtual DbU::Unit getEnclosure () const; - virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const; + virtual DbU::Unit getEnclosure ( uint32_t flags ) const; + virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const; // Updators. - virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure ); + virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags ); // Hurricane Managment. virtual void _toJson ( JsonWriter* ) const; virtual void _onDbuChange ( float scale ); @@ -72,9 +72,9 @@ namespace Hurricane { private: // Internal: Attributes - vector _basicLayers; - vector _enclosures; - DbU::Unit _maximalEnclosure; + vector _basicLayers; + vector< pair > _enclosures; + DbU::Unit _maximalEnclosure; protected: ContactLayer ( Technology* technology diff --git a/hurricane/src/hurricane/hurricane/DbU.h b/hurricane/src/hurricane/hurricane/DbU.h index 0e858432..6da410ab 100644 --- a/hurricane/src/hurricane/hurricane/DbU.h +++ b/hurricane/src/hurricane/hurricane/DbU.h @@ -187,4 +187,43 @@ namespace Hurricane { // { w->key( key ); w->write( value ); } +template<> +inline std::string getString ( const std::pair& p ) +{ + return "const std::pair"; +} + + +template<> +inline Hurricane::Record* getRecord ( const std::pair& p ) +{ + Hurricane::Record* record = NULL; + record = new Hurricane::Record ( "const std::pair" ); + record->add( Hurricane::DbU::getValueSlot("first" , &p.first ) ); + record->add( Hurricane::DbU::getValueSlot("second", &p.second) ); + return record; +} + + +template<> +inline std::string getString ( const std::array& a ) +{ + return "const array"; +} + + +template<> +inline Hurricane::Record* getRecord ( const std::array& a ) +{ + Hurricane::Record* record = NULL; + record = new Hurricane::Record ( "const array" ); + + for ( size_t i=0 ; iadd( Hurricane::DbU::getValueSlot(label, a[i]) ); + } + return record; +} + + #endif // HURRICANE_DBU_H diff --git a/hurricane/src/hurricane/hurricane/Interval.h b/hurricane/src/hurricane/hurricane/Interval.h index fb8adf4a..27c69f5e 100644 --- a/hurricane/src/hurricane/hurricane/Interval.h +++ b/hurricane/src/hurricane/hurricane/Interval.h @@ -63,7 +63,7 @@ class Interval { public: DbU::Unit& getVMin() {return _vMin;}; public: DbU::Unit& getVMax() {return _vMax;}; public: DbU::Unit getCenter() const {return ((_vMin + _vMax) / 2);}; - public: DbU::Unit getSize() const {return (isEmpty() ? 0 : (_vMax - _vMin));}; + public: DbU::Unit getSize() const; public: DbU::Unit getHalfSize() const {return (getSize() / 2);}; public: Interval getUnion(const Interval& interval) const; public: Interval getIntersection(const Interval& interval) const; @@ -72,6 +72,7 @@ class Interval { // ********** public: bool isEmpty() const { return (_vMax < _vMin);}; + public: bool isFull() const { return (_vMin == DbU::Min) and (_vMax == DbU::Max); }; public: bool isPonctual() const { return (_vMax == _vMin);}; public: bool contains(const DbU::Unit& v) const; public: bool contains(const Interval& interval) const; @@ -104,6 +105,14 @@ class Interval { }; + inline DbU::Unit Interval::getSize () const + { + if (isEmpty()) return 0; + if (isFull ()) return DbU::Max; + return _vMax - _vMin; + } + + } // End of Hurricane namespace. diff --git a/hurricane/src/hurricane/hurricane/Layer.h b/hurricane/src/hurricane/hurricane/Layer.h index d609214b..ab3358e5 100644 --- a/hurricane/src/hurricane/hurricane/Layer.h +++ b/hurricane/src/hurricane/hurricane/Layer.h @@ -52,6 +52,13 @@ namespace Hurricane { class Layer : public DBo { public: typedef DBo Super; + public: + static const uint32_t NoFlags = 0; + static const uint32_t EnclosureH = (1 << 0); + static const uint32_t EnclosureV = (1 << 1); + static const uint32_t EnclosureMax = (1 << 2); + static const uint32_t ExtensionCap = (1 << 3); + static const uint32_t ExtensionWidth = (1 << 4); public: // Types. @@ -72,12 +79,14 @@ namespace Hurricane { Layer* getMetalBelow ( bool useSymbolic=true ) const; Layer* getCutAbove ( bool useSymbolic=true ) const; Layer* getCutBelow ( bool useSymbolic=true ) const; - virtual DbU::Unit getEnclosure () const; + virtual DbU::Unit getEnclosure ( uint32_t flags ) const; virtual DbU::Unit getExtentionCap () const; virtual DbU::Unit getExtentionWidth () const; - virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const; + virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const; virtual DbU::Unit getExtentionCap ( const BasicLayer* layer ) const; virtual DbU::Unit getExtentionWidth ( const BasicLayer* layer ) const; + virtual DbU::Unit getTopEnclosure ( uint32_t flags ) const; + virtual DbU::Unit getBottomEnclosure ( uint32_t flags ) const; // Predicates inline bool above ( const Layer* layer ) const; inline bool below ( const Layer* layer ) const; @@ -89,7 +98,7 @@ namespace Hurricane { inline void setSymbolic ( bool ); void setMinimalSize ( const DbU::Unit& minimalSize ); void setMinimalSpacing ( const DbU::Unit& minimalSpacing ); - virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit ); + virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit, uint32_t flags ); virtual void setExtentionCap ( const BasicLayer* layer, DbU::Unit ); virtual void setExtentionWidth ( const BasicLayer* layer, DbU::Unit ); // Hurricane Managment. diff --git a/hurricane/src/hurricane/hurricane/RoutingPad.h b/hurricane/src/hurricane/hurricane/RoutingPad.h index 2f7abd77..10563483 100644 --- a/hurricane/src/hurricane/hurricane/RoutingPad.h +++ b/hurricane/src/hurricane/hurricane/RoutingPad.h @@ -60,7 +60,8 @@ namespace Hurricane { public: // Accessors. bool isPlacedOccurrence ( unsigned int flags ) const; - inline Occurrence getOccurrence () const { return _occurrence; }; + inline bool isAtTopLevel () const; + inline Occurrence getOccurrence () const; Occurrence getPlugOccurrence (); virtual const Layer* getLayer () const; virtual DbU::Unit getX () const; @@ -97,6 +98,10 @@ namespace Hurricane { Occurrence _occurrence; }; + + inline bool RoutingPad::isAtTopLevel () const { return _occurrence.getPath().isEmpty(); } + inline Occurrence RoutingPad::getOccurrence () const { return _occurrence; }; + // ------------------------------------------------------------------- // Class : "JsonRoutingPad". diff --git a/hurricane/src/hurricane/hurricane/ViaLayer.h b/hurricane/src/hurricane/hurricane/ViaLayer.h index d411d553..262e5928 100644 --- a/hurricane/src/hurricane/hurricane/ViaLayer.h +++ b/hurricane/src/hurricane/hurricane/ViaLayer.h @@ -49,33 +49,35 @@ namespace Hurricane { public: // Constructor. - static ViaLayer* create ( Technology* technology - , const Name& name - , BasicLayer* bottomLayer - , BasicLayer* cutLayer - , BasicLayer* topLayer - ); - // Accessors. - virtual BasicLayers getBasicLayers () const; - virtual const Layer* getTop () const; - virtual const Layer* getBottom () const; - virtual const Layer* getOpposite ( const Layer* ) const; - virtual DbU::Unit getEnclosure () const; - virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const; + static ViaLayer* create ( Technology* technology + , const Name& name + , BasicLayer* bottomLayer + , BasicLayer* cutLayer + , BasicLayer* topLayer + ); + // Accessors. + virtual BasicLayers getBasicLayers () const; + virtual const Layer* getTop () const; + virtual const Layer* getBottom () const; + virtual const Layer* getOpposite ( const Layer* ) const; + virtual DbU::Unit getEnclosure ( uint32_t flags ) const; + virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const; + virtual DbU::Unit getTopEnclosure ( uint32_t flags ) const; + virtual DbU::Unit getBottomEnclosure ( uint32_t flags ) const; // Updators. - virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure ); - // Hurricane Managment. - virtual void _toJson ( JsonWriter* ) const; - virtual void _onDbuChange ( float scale ); - virtual string _getTypeName () const; - virtual string _getString () const; - virtual Record* _getRecord () const; + virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags ); + // Hurricane Managment. + virtual void _toJson ( JsonWriter* ) const; + virtual void _onDbuChange ( float scale ); + virtual string _getTypeName () const; + virtual string _getString () const; + virtual Record* _getRecord () const; private: // Internal: Attributes - vector _basicLayers; - vector _enclosures; - DbU::Unit _maximalEnclosure; + vector _basicLayers; + vector< pair > _enclosures; + DbU::Unit _maximalEnclosure; protected: // Internal: Constructors & Destructors. diff --git a/hurricane/src/isobar/PyLayer.cpp b/hurricane/src/isobar/PyLayer.cpp index 1f448faa..7edc4e60 100644 --- a/hurricane/src/isobar/PyLayer.cpp +++ b/hurricane/src/isobar/PyLayer.cpp @@ -51,7 +51,7 @@ extern "C" { # define accessorDbuFromOptBasicLayer(FUNC_NAME,PY_SELF_TYPE,SELF_TYPE) \ static PyObject* PY_SELF_TYPE##_##FUNC_NAME ( PY_SELF_TYPE* self, PyObject* args ) \ { \ - cdebug_log(20,0) << #PY_SELF_TYPE "_" #FUNC_NAME "()" << endl; \ + cdebug_log(20,0) << #PY_SELF_TYPE "_" #FUNC_NAME "()" << endl; \ \ DbU::Unit rvalue = 0; \ \ @@ -240,13 +240,79 @@ extern "C" { } + static PyObject* PyLayer_getEnclosure ( PyLayer* self, PyObject* args ) + { + cdebug_log(20,0) << "PyLayer_getEnclosure()" << endl; + + DbU::Unit rvalue = 0; + + HTRY + METHOD_HEAD("Layer.getEnclosure()") + + PyObject* arg0 = NULL; + PyObject* arg1 = NULL; + + __cs.init( "Layer.getEnclosure()" ); + if (PyArg_ParseTuple( args, "O&|O&:Layer.getEnclosure()" + , Converter, &arg0 + , Converter, &arg1 )) { + if (__cs.getObjectIds() == ":basiclayer:int") + rvalue = layer->getEnclosure( PYBASICLAYER_O(arg0), PyAny_AsLong(arg1) ); + else if ( __cs.getObjectIds() == ":int" ) + rvalue = layer->getEnclosure( PyAny_AsLong(arg1) ); + else { + PyErr_SetString ( ConstructorError + , "invalid parameter type for Layer.getEnclosure()." ); + return NULL; + } + } else { + PyErr_SetString ( ConstructorError + , "Invalid number of parameters passed to Layer.getEnclosure()." ); + return NULL; + } + HCATCH + + return PyLong_FromLong(rvalue); + } + + + static PyObject* PyLayer_setEnclosure ( PyLayer* self, PyObject* args ) + { + cdebug_log(20,0) << "PyLayer_setEnclosure()" << endl; + + HTRY + METHOD_HEAD("PyLayer.setEnclosure()") + + PyObject* pyBasicLayer = NULL; + PyObject* pyDimension = NULL; + uint32_t flags = 0; + + if (PyArg_ParseTuple( args, "OOi:Layer.setEnclosure()" + , &pyBasicLayer, &pyDimension, &flags )) { + BasicLayer* basicLayer = PYBASICLAYER_O(pyBasicLayer); + if (basicLayer == NULL) { + PyErr_SetString( ConstructorError + , "Layer.setEnclosure(): First parameter is not of BasicLayer type" ); + return NULL; + } + layer->setEnclosure( basicLayer, PyAny_AsLong(pyDimension), flags ); + } else { + PyErr_SetString( ConstructorError + , "Layer.setEnclosure(): Bad parameters types or numbers." ); + return NULL; + } + HCATCH + + Py_RETURN_NONE; + } + + GetNameMethod (Layer, layer) predicateFromLayer ( above ,PyLayer,Layer) predicateFromLayer ( below ,PyLayer,Layer) predicateFromLayer ( contains ,PyLayer,Layer) predicateFromLayer ( intersect ,PyLayer,Layer) predicateFromVoid ( isSymbolic ,PyLayer,Layer) - accessorDbuFromOptBasicLayer( getEnclosure ,PyLayer,Layer) accessorDbuFromOptBasicLayer( getExtentionCap ,PyLayer,Layer) accessorDbuFromOptBasicLayer( getExtentionWidth,PyLayer,Layer) accessorCollectionFromVoid ( getBasicLayers ,PyLayer,Layer,BasicLayer) @@ -266,7 +332,6 @@ extern "C" { SetNameMethod(Layer, layer) updatorFromDbu (setMinimalSize ,PyLayer,Layer) updatorFromDbu (setMinimalSpacing,PyLayer,Layer) - updatorFromBasicLayerDbu(setEnclosure ,PyLayer,Layer) updatorFromBasicLayerDbu(setExtentionCap ,PyLayer,Layer) updatorFromBasicLayerDbu(setExtentionWidth,PyLayer,Layer) DirectSetBoolAttribute (PyLayer_setSymbolic,setSymbolic,PyLayer,Layer) @@ -366,6 +431,15 @@ extern "C" { extern void PyLayer_postModuleInit () { PyDict_SetItemString ( PyTypeLayer.tp_dict, "Mask", (PyObject*)&PyTypeLayerMask ); + + PyObject* constant; + + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::NoFlags ,"NoFlags" ); + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureH ,"EnclosureH" ); + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureV ,"EnclosureV" ); + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureMax ,"EnclosureMax" ); + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::ExtensionCap ,"ExtensionCap" ); + LoadObjectConstant(PyTypeLayer.tp_dict,Layer::ExtensionWidth,"ExtensionWidth"); } diff --git a/katana/src/DataNegociate.cpp b/katana/src/DataNegociate.cpp index 635de11d..f66ec78d 100644 --- a/katana/src/DataNegociate.cpp +++ b/katana/src/DataNegociate.cpp @@ -20,7 +20,9 @@ #include "hurricane/DebugSession.h" #include "anabatic/AutoSegment.h" #include "katana/DataNegociate.h" +#include "katana/RoutingPlane.h" #include "katana/RoutingEvent.h" +#include "katana/KatanaEngine.h" namespace Katana { @@ -136,16 +138,38 @@ namespace Katana { //cerr << " " << interval << endl; //interval.inflate( DbU::fromLambda(-0.5) ); - cdebug_log(159,0) << "| perpandicular: " << perpandiculars[i] << endl; - cdebug_log(159,0) << "| canonical: " << perpandicular << endl; - cdebug_log(159,1) << "Canonical // interval: " << interval << endl; + cdebug_log(159,0) << "| perpandicular: " << perpandiculars[i] << endl; + cdebug_log(159,1) << "| canonical: " << perpandicular << endl; + cdebug_log(159,0) << "Canonical // interval: " << interval << endl; _perpandiculars.push_back( perpandicular ); if (perpandicular->getTrack()) { Interval trackFree = perpandicular->getFreeInterval(); cdebug_log(159,0) << "Track Perpandicular Free: " << trackFree << endl; - _perpandicularFree.intersection( trackFree.inflate(-perpandicular->getExtensionCap()) ); + _perpandicularFree.intersection + ( trackFree.inflate ( -perpandicular->getExtensionCap(Flags::Source) + , -perpandicular->getExtensionCap(Flags::Target)) ); + cdebug_log(159,0) << "Source cap:" + << DbU::getValueString(perpandicular->getExtensionCap(Flags::Source)) << endl; + } else if (perpandicular->isFixedAxis()) { + RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(perpandicular->getLayer()); + Track* track = plane->getTrackByPosition( perpandicular->getAxis() ); + if (track and (perpandicular->getAxis() == track->getAxis())) { + Interval trackFree = track->getFreeInterval( perpandicular->getSourceU(), _trackSegment->getNet() ); + cdebug_log(159,0) << "SourceU: " << DbU::getValueString(perpandicular->getSourceU()) << endl; + cdebug_log(159,0) << "Track Perpandicular Free (fixed axis, source): " << trackFree << endl; + + if (trackFree.isEmpty()) { + trackFree = track->getFreeInterval( perpandicular->getTargetU(), _trackSegment->getNet() ); + cdebug_log(159,0) << "TargetU: " << DbU::getValueString(perpandicular->getTargetU()) << endl; + cdebug_log(159,0) << "Track Perpandicular Free (fixed axis, target): " << trackFree << endl; + } + + _perpandicularFree.intersection + ( trackFree.inflate ( -perpandicular->getExtensionCap(Flags::Source) + , -perpandicular->getExtensionCap(Flags::Target)) ); + } } else { cdebug_log(159,0) << "Not in any track " << perpandicular << endl; } @@ -252,10 +276,10 @@ namespace Katana { } - string DataNegociate::getStateString ( DataNegociate* data ) + string DataNegociate::getStateString ( uint32_t state, unsigned int stateCount ) { ostringstream s; - switch ( data->_state ) { + switch ( state ) { case RipupPerpandiculars: s << "RipupPerpandiculars"; break; case Minimize: s << "Minimize"; break; case Dogleg: s << "Dogleg"; break; @@ -266,13 +290,20 @@ namespace Katana { case MoveUp: s << "MoveUp"; break; case MaximumSlack: s << "MaximumSlack"; break; case Unimplemented: s << "Unimplemented"; break; - case Repair: s << "REPAIR"; break; + case Repair: s << "Repair"; break; + case RepairFailed: s << "RepairFailed"; break; default: - s << "Unknown(" << data->_state << ")"; break; + s << "Unknown(" << state << ")"; break; } - s << ":" << data->_stateCount; + s << ":" << stateCount; return s.str(); } + string DataNegociate::getStateString ( DataNegociate* data ) + { + return getStateString( data->_state, data->_stateCount ); + } + + } // Katana namespace. diff --git a/katana/src/Manipulator.cpp b/katana/src/Manipulator.cpp index 0df323cc..5a612033 100644 --- a/katana/src/Manipulator.cpp +++ b/katana/src/Manipulator.cpp @@ -143,21 +143,21 @@ namespace Katana { bool Manipulator::ripup ( uint32_t type, DbU::Unit axisHint ) { - cdebug_log(159,0) << "Manipulator::ripup() " << endl; + cdebug_log(159,1) << "Manipulator::ripup()" << endl; - if (not canRipup()) return false; - - if (_segment->isFixed()) return false; - if (_data == NULL) return true; + if (not canRipup()) { cdebug_tabw(159,-1); return false; } + if (_segment->isFixed()) { cdebug_tabw(159,-1); return false; } + if (_data == NULL) { cdebug_tabw(159,-1); return true; } _fsm.addAction( _segment, type, axisHint ); + cdebug_tabw(159,-1); return true; } bool Manipulator::ripupPerpandiculars ( uint32_t flags ) { - cdebug_log(159,0) << "Manipulator::ripupPerpandiculars() - " << flags << endl; + cdebug_log(159,1) << "Manipulator::ripupPerpandiculars() - " << flags << endl; bool success = true; bool cagedPerpandiculars = false; @@ -183,6 +183,8 @@ namespace Katana { const vector& perpandiculars = _event->getPerpandiculars(); for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) { + cdebug_log(159,0) << "| " << perpandiculars[i] << endl; + track = perpandiculars[i]->getTrack(); if (not track) { // The perpandicular is not placed yet. @@ -202,10 +204,11 @@ namespace Katana { // Try to ripup the perpandicular. DataNegociate* data2 = perpandiculars[i]->getDataNegociate(); - cdebug_log(159,0) << "| " << perpandiculars[i] << endl; - if ( (flags & Manipulator::ToMoveUp) and (data2->getState() < DataNegociate::MoveUp) ) + if ( (flags & Manipulator::ToMoveUp) and (data2->getState() < DataNegociate::MoveUp) ) { + cdebug_log(159,0) << "Force move up of perpandicular." << endl; data2->setState( DataNegociate::MoveUp ); + } if (Manipulator(perpandiculars[i],_fsm).ripup(perpandicularActionFlags)) { if (dislodgeCaged) { @@ -215,6 +218,7 @@ namespace Katana { } // Cannot ripup the perpandicular, try to ripup it's neigbors. + cdebug_log(159,0) << "Try to ripup neighbors." << endl; size_t begin; size_t end; track->getOverlapBounds( constraints, begin, end ); @@ -233,6 +237,7 @@ namespace Katana { _fsm.addAction( other, SegmentAction::OtherRipup ); } else { cdebug_log(159,0) << "Aborted ripup of perpandiculars, fixed or blocked." << endl; + cdebug_tabw(159,-1); return false; } } @@ -241,6 +246,7 @@ namespace Katana { if (cagedPerpandiculars and not placedPerpandiculars) { cdebug_log(159,0) << "Aborted ripup of perpandiculars, constraints are due to fixed/blockage." << endl; _fsm.addAction( _segment, SegmentAction::SelfRipup ); + cdebug_tabw(159,-1); return true; } @@ -250,6 +256,7 @@ namespace Katana { _fsm.addAction( perpandiculars[i], perpandicularActionFlags|SegmentAction::EventLevel4 ); } _fsm.addAction( _segment, parallelActionFlags ); + cdebug_tabw(159,-1); return true; } @@ -265,13 +272,15 @@ namespace Katana { if (_segment->isLocal() and (tracksNb < 2)) success = ripple(); _fsm.addAction( _segment, parallelActionFlags ); + + cdebug_tabw(159,-1); return success; } bool Manipulator::relax ( Interval interval, uint32_t flags ) { - interval.inflate( - Session::getExtensionCap(getLayer()) ); + Session::toAxisInterval( interval, Session::getLayerDepth(_segment->getLayer())+1 ); cdebug_log(159,0) << "Manipulator::relax() of: " << _segment << " " << interval << endl; if (_segment->isFixed()) return false; @@ -784,7 +793,7 @@ 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()) ) { + if ( segment3->getAxis() == segment2->getTargetAxis() ) { //leftIntrication = true; //leftAxisHint = segment3->getAxis(); } @@ -802,7 +811,7 @@ namespace Katana { break; if ( event3->getTracksFree() == 1 ) { cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl; - if ( segment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap(getLayer()) ) { + if ( segment3->getAxis() == segment2->getSourceAxis() ) { //rightIntrication = true; //rightAxisHint = segment3->getAxis(); } @@ -1162,7 +1171,7 @@ namespace Katana { } else { if (not _segment->canMoveUp(0.5,kflags)) return false; } - return _segment->moveUp( kflags ); + return _segment->moveUp( kflags|Flags::Propagate ); } @@ -1463,6 +1472,7 @@ namespace Katana { Track* track = _fsm.getTrack( 0 ); DbU::Unit axisHint = 0; +#if DISABLED if (termConstraints.getSize() < _segment->getPPitch()*2) { cdebug_log(159,0) << "Constraints less than two perpandicular pitches, lock." << endl; @@ -1475,25 +1485,32 @@ namespace Katana { cdebug_tabw(159,-1); return true; } +#endif 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; + if (begin == end) { + axisHint = termConstraints.getCenter(); + cdebug_log(159,0) << "No conflict under canonical interval (?) use terminal center." << endl; + cdebug_log(159,0) << "term: " << termConstraints << " center:" << DbU::getValueString(axisHint) << endl; + } else { + 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; + } } } @@ -1512,6 +1529,8 @@ namespace Katana { _fsm.addAction( perpandiculars[i], SegmentAction::SelfRipupPerpandWithAxisHint, axisHint ); } + //_fsm.addAction( _segment, SegmentAction::SelfRipup|SegmentAction::EventLevel3 ); + _event->setMinimized(); cdebug_tabw(159,-1); @@ -1536,12 +1555,11 @@ namespace Katana { if ( not Manipulator(perpandicular,_fsm).canRipup() or (data->getState() >= DataNegociate::MaximumSlack) ) continue; - // Ugly: ExtensionCap usage. if ( moveLeft ) { - if ( perpandicular->getTargetU()-Session::getExtensionCap(getLayer()) == _event->getAxisHistory() ) + if ( perpandicular->getTargetAxis() == _event->getAxisHistory() ) _fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking ); } else { - if ( perpandicular->getSourceU()+Session::getExtensionCap(getLayer()) == _event->getAxisHistory() ) + if ( perpandicular->getSourceAxis() == _event->getAxisHistory() ) _fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking ); } } @@ -1560,6 +1578,7 @@ namespace Katana { if (perpandicular->isFixed ()) continue; if (perpandicular->isGlobal()) continue; if (not data) continue; + if (data->getState() >= DataNegociate::RepairFailed) continue; if (RoutingEvent::getStage() == RoutingEvent::Repair) { data->setState( DataNegociate::Repair ); diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index 6fd8a356..1a917818 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -115,8 +115,9 @@ namespace { void loadRoutingPads ( NegociateWindow* nw ) { - AllianceFramework* af = AllianceFramework::get (); - RoutingGauge* rg = nw->getKatanaEngine()->getConfiguration()->getRoutingGauge(); + AllianceFramework* af = AllianceFramework::get (); + RoutingGauge* rg = nw->getKatanaEngine()->getConfiguration()->getRoutingGauge(); + bool isVH = rg->isVH(); for( Net* net : nw->getCell()->getNets() ) { if (net->getType() == Net::Type::POWER ) continue; @@ -126,9 +127,13 @@ namespace { for( RoutingPad* rp : net->getRoutingPads() ) { size_t depth = rg->getLayerDepth(rp->getLayer()); - if (depth > 0) continue; - if (depth == 0) + if (depth == 0) { TrackMarker::create( rp, 1 ); + //if (isVH) TrackMarker::create( rp, 2 ); + } + if (depth == 1) { + TrackMarker::create( rp, 1 ); + } } } } @@ -511,9 +516,6 @@ namespace Katana { } } - event->process( _eventQueue, _eventHistory, _eventLoop ); - count++; - if (tty::enabled()) { cmess2 << " process( _eventQueue, _eventHistory, _eventLoop ); + count++; + //if (count and not (count % 500)) { // _pack( count, false ); //} @@ -580,7 +585,7 @@ namespace Katana { event->process( _eventQueue, _eventHistory, _eventLoop ); count++; - if (RoutingEvent::getProcesseds() >= limit ) setInterrupt( true ); + if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true ); } if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl; diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index 537cd052..f833e122 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -383,49 +383,6 @@ namespace { } - 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. @@ -452,8 +409,6 @@ namespace Katana { } } - for ( GCell* gcell : getGCells() ) protectAlignedAccesses( gcell ); - //DebugSession::close(); Session::revalidate (); diff --git a/katana/src/RoutingEvent.cpp b/katana/src/RoutingEvent.cpp index 2a135d58..1064e57d 100644 --- a/katana/src/RoutingEvent.cpp +++ b/katana/src/RoutingEvent.cpp @@ -68,7 +68,14 @@ namespace Katana { bool RoutingEvent::Compare::operator() ( const RoutingEvent* lhs, const RoutingEvent* rhs ) const { if (lhs == rhs) return false; - return RoutingEvent::Key::Compare()( lhs->getKey(), rhs->getKey() ); + bool value = RoutingEvent::Key::Compare()( lhs->getKey(), rhs->getKey() ); + // if ( (lhs->getSegment()->base()->getFlags() & AutoSegment::SegFixedAxis) + // or (lhs->getSegment()->base()->getFlags() & AutoSegment::SegFixedAxis)) { + // cerr << "Compare: lhs < rhs = " << value << endl; + // cerr << " lhs L:" << lhs->getEventLevel() << " " << lhs << endl; + // cerr << " rhs L:" << rhs->getEventLevel() << " " << rhs << endl; + // } + return value; } @@ -87,6 +94,11 @@ namespace Katana { // Process all M2 (terminal access) before any others. //if ((lhs._layerDepth == 1) and (rhs._layerDepth != 1)) return false; //if ((lhs._layerDepth != 1) and (rhs._layerDepth == 1)) return true; + + // For VH gauge, process fixed axis first. + if ( (lhs._segFlags & AutoSegment::SegFixedAxis) and not (rhs._segFlags & AutoSegment::SegFixedAxis)) return false; + if (not (lhs._segFlags & AutoSegment::SegFixedAxis) and (rhs._segFlags & AutoSegment::SegFixedAxis)) return true; + if (lhs._layerDepth > rhs._layerDepth) return true; if (lhs._layerDepth < rhs._layerDepth) return false; @@ -317,6 +329,11 @@ namespace Katana { RoutingEvent* fork = NULL; + if (getState() == DataNegociate::RepairFailed) { + cdebug_log(159,0) << "Reschedule: cancelled (RepairFailed) -> " << fork << endl; + return NULL; + } + if ( (getStage() != Repair) and isUnimplemented() ) { cdebug_log(159,0) << "Reschedule: cancelled (Unimplemented) -> " << fork << endl; return NULL; @@ -332,7 +349,8 @@ namespace Katana { _segment->getDataNegociate()->setRoutingEvent( fork ); - cdebug_log(159,0) << "Reschedule/Fork: -> " << fork << endl; + cdebug_log(159,0) << "Reschedule/Fork: -> " + << eventLevel << ":" << fork << endl; } if (fork->_eventLevel < eventLevel) @@ -364,10 +382,8 @@ namespace Katana { , RoutingEventLoop& loop ) { - loop.update( _segment->getId() ); + loop.update( _segment ); if (loop.isLooping()) { - loop.erase( _segment->getId() ); - setState( DataNegociate::Unimplemented ); #if LOOP_DEBUG if (loop.getMaxCount() > 500) { @@ -391,13 +407,18 @@ namespace Katana { const vector& elements = loop.getElements(); for ( size_t i=0 ; igetNet(), 155, 160 ); + //DebugSession::open( _segment->getNet(), 155, 160 ); + DebugSession::open( _segment->getNet(), 149, 160 ); cdebug_log(9000,0) << "Deter| Event " << getProcesseds() @@ -591,6 +612,7 @@ namespace Katana { break; default: cdebug_log(159,0) << "Repair failed." << endl; + setState( DataNegociate::RepairFailed ); break; } } diff --git a/katana/src/RoutingEventLoop.cpp b/katana/src/RoutingEventLoop.cpp index 8c9a7199..7c01a760 100644 --- a/katana/src/RoutingEventLoop.cpp +++ b/katana/src/RoutingEventLoop.cpp @@ -28,6 +28,10 @@ namespace Katana { using std::stable_sort; + size_t RoutingEventLoop::Element::getId () const + { return _segment->getId(); } + + RoutingEventLoop::RoutingEventLoop ( size_t depth, int countLimit ) : _elements () , _depth (depth) @@ -37,37 +41,37 @@ namespace Katana { { } - void RoutingEventLoop::update ( size_t id ) + void RoutingEventLoop::update ( TrackElement* segment ) { vector::iterator ielement = _elements.begin(); for ( ; ielement != _elements.end() ; ++ielement ) { - if ( (*ielement)._id == id ) { + if ((*ielement).getId() == segment->getId()) { // Increment an already present element. (*ielement)._count += 1; (*ielement)._timestamp = RoutingEvent::getProcesseds(); _maxCount = std::max ( _maxCount, (*ielement)._count ); - if ( _maxCount > _countLimit ) _isLooping = true; + if (_maxCount > _countLimit) _isLooping = true; break; } } // The Event was not found. - if ( ielement == _elements.end() ) { - if ( _elements.size() >= _depth ) _elements.pop_back (); - _elements.push_back ( Element(id,RoutingEvent::getProcesseds()) ); + if (ielement == _elements.end()) { + if (_elements.size() >= _depth) _elements.pop_back(); + _elements.push_back( Element(segment,RoutingEvent::getProcesseds()) ); } - stable_sort ( _elements.begin(), _elements.end(), CompareByTimestamp() ); + stable_sort( _elements.begin(), _elements.end(), CompareByTimestamp() ); } - void RoutingEventLoop::erase ( size_t id ) + void RoutingEventLoop::erase ( TrackElement* segment ) { vector::iterator ielement = _elements.begin(); for ( ; ielement != _elements.end() ; ++ielement ) { - if ( (*ielement)._id == id ) { - _elements.erase ( ielement ); + if ((*ielement).getId() == segment->getId()) { + _elements.erase( ielement ); break; } } @@ -75,7 +79,7 @@ namespace Katana { _maxCount = 0; ielement = _elements.begin(); for ( ; ielement != _elements.end() ; ++ielement ) { - _maxCount = std::max ( _maxCount, (*ielement)._count ); + _maxCount = std::max( _maxCount, (*ielement)._count ); } _isLooping = (_maxCount > _countLimit); diff --git a/katana/src/RoutingPlane.cpp b/katana/src/RoutingPlane.cpp index f116cdb8..92f8bd32 100644 --- a/katana/src/RoutingPlane.cpp +++ b/katana/src/RoutingPlane.cpp @@ -125,7 +125,7 @@ namespace Katana { if (plane->getDirection() == Flags::Horizontal) { plane->_tracks.push_back( HorizontalTrack::create( plane, index ) ); // Ugly: Direct uses of CellGauge (middle tracks 4 & 5 for local use). - if (depth == 1) { + if ( (depth == 1) and not Session::getRoutingGauge()->isVH() ) { switch ( index%10 ) { case 4: case 5: diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index 20d9973d..4d609406 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -445,20 +445,21 @@ namespace Katana { SegmentFsm::SegmentFsm ( RoutingEvent* event1 , RoutingEventQueue& queue , RoutingEventHistory& history ) - : _event1 (event1) - , _event2 (NULL) - , _queue (queue) - , _history (history) - , _state (0) - , _data1 (NULL) - , _data2 (NULL) - , _constraint () - , _optimal () - , _costs () - , _actions () - , _fullBlocked(true) - , _sameAxis (false) - , _useEvent2 (false) + : _event1 (event1) + , _event2 (NULL) + , _queue (queue) + , _history (history) + , _state (0) + , _data1 (NULL) + , _data2 (NULL) + , _constraint () + , _optimal () + , _costs () + , _actions () + , _fullBlocked (true) + , _sameAxis (false) + , _useEvent2 (false) + , _minimizeDrag(false) { DataSymmetric* symData = NULL; TrackElement* segment1 = _event1->getSegment(); @@ -1184,53 +1185,70 @@ namespace Katana { switch (data->getState()) { case DataNegociate::RipupPerpandiculars: - nextState = DataNegociate::Minimize; - success = manipulator.ripupPerpandiculars(); + if (segment->isDrag() and getCost(0)->isInfinite()) { + nextState = DataNegociate::Slacken; + success = manipulator.dragMinimize(); + if (success) _minimizeDrag = true; + } else { + nextState = DataNegociate::Minimize; + success = manipulator.ripupPerpandiculars(); + } if (success) break; case DataNegociate::Minimize: - if (isFullBlocked() and not segment->isTerminal()) { - cdebug_log(159,0) << "Is Fully blocked." << endl; - nextState = DataNegociate::Unimplemented; - break; + if (nextState == DataNegociate::Minimize) { + if (isFullBlocked() and not segment->isTerminal()) { + cdebug_log(159,0) << "Is Fully blocked." << endl; + nextState = DataNegociate::Unimplemented; + break; + } + nextState = DataNegociate::Dogleg; + success = manipulator.minimize(); + if (success) break; } - nextState = DataNegociate::Dogleg; - // if (segment->isDrag()) - // success = manipulator.dragMinimize(); - // else - success = manipulator.minimize(); - if (success) break; case DataNegociate::Dogleg: - nextState = DataNegociate::Slacken; - success = manipulator.makeDogleg(); - if (success) break; + if (nextState == DataNegociate::Dogleg) { + nextState = DataNegociate::Slacken; + success = manipulator.makeDogleg(); + if (success) break; + } case DataNegociate::Slacken: - nextState = DataNegociate::ConflictSolveByPlaceds; - success = manipulator.slacken(); - if (success) break; + if (nextState == DataNegociate::Slacken) { + nextState = DataNegociate::ConflictSolveByPlaceds; + success = manipulator.slacken(); + if (success) break; + } case DataNegociate::ConflictSolveByHistory: case DataNegociate::ConflictSolveByPlaceds: - nextState = DataNegociate::LocalVsGlobal; - success = conflictSolveByHistory(); - break; + if ( (nextState == DataNegociate::ConflictSolveByHistory) + or (nextState == DataNegociate::ConflictSolveByPlaceds) ) { + nextState = DataNegociate::LocalVsGlobal; + success = conflictSolveByHistory(); + break; + } case DataNegociate::LocalVsGlobal: - nextState = DataNegociate::MoveUp; - success = solveTerminalVsGlobal(); - if (success) break; - break; + if (nextState == DataNegociate::LocalVsGlobal) { + nextState = DataNegociate::MoveUp; + success = solveTerminalVsGlobal(); + if (success) break; + } case DataNegociate::MoveUp: - nextState = DataNegociate::MaximumSlack; - success = manipulator.moveUp(); - if (success) break; + if (nextState == DataNegociate::LocalVsGlobal) { + nextState = DataNegociate::MaximumSlack; + success = manipulator.moveUp(); + if (success) break; + } case DataNegociate::MaximumSlack: - if (segment->isStrap()) { - if ( (nextState < DataNegociate::MaximumSlack) or (data->getStateCount() < 2) ) { - nextState = DataNegociate::MaximumSlack; - success = conflictSolveByPlaceds(); - if (success) break; + if (nextState == DataNegociate::MaximumSlack) { + if (segment->isStrap()) { + if ( (nextState < DataNegociate::MaximumSlack) or (data->getStateCount() < 2) ) { + nextState = DataNegociate::MaximumSlack; + success = conflictSolveByPlaceds(); + if (success) break; + } } } case DataNegociate::Unimplemented: - if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl; + //if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl; nextState = DataNegociate::Unimplemented; break; } @@ -1249,7 +1267,8 @@ namespace Katana { if (not (flags&NoTransition)) { data->setState( nextState ); - cdebug_log(159,0) << "Incrementing state (after): " << nextState << " count:" << data->getStateCount() << endl; + cdebug_log(159,0) << "Incrementing state (after): " + << DataNegociate::getStateString(nextState,data->getStateCount()) << endl; } return success; @@ -1384,6 +1403,10 @@ namespace Katana { if (success) { actionFlags |= SegmentAction::ResetRipup; + if (isMinimizeDrag()) { + actionFlags &= ~SegmentAction::EventLevel5; + actionFlags |= SegmentAction::EventLevel3; + } addAction( segment1, actionFlags ); } else { clearActions(); diff --git a/katana/src/Session.cpp b/katana/src/Session.cpp index 69d67948..64101ba4 100644 --- a/katana/src/Session.cpp +++ b/katana/src/Session.cpp @@ -181,6 +181,23 @@ namespace Katana { { return _getKatanaEngine()->getGCellUnder(Point(x,y)); }; + Interval& Session::_toAxisInterval ( Interval& interval, size_t depth ) const + { + RoutingLayerGauge* rg = getLayerGauge(depth); + if (not rg) return interval; + + Box ab = getKatanaEngine()->getCell()->getAbutmentBox(); + DbU::Unit abMin = (rg->isHorizontal()) ? ab.getYMin() : ab.getXMin(); + DbU::Unit abMax = (rg->isHorizontal()) ? ab.getYMax() : ab.getXMax() ; + + DbU::Unit trackMin = rg->getTrackPosition( abMin, abMax, interval.getVMin(), Constant::Superior ); + DbU::Unit trackMax = rg->getTrackPosition( abMin, abMax, interval.getVMax(), Constant::Inferior ); + interval = Interval( trackMin, trackMax ); + + return interval; + } + + void Session::_doRemovalEvents () { set packTracks; diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 2eb443a6..191d83bd 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -308,6 +308,11 @@ namespace Katana { if (_markers[mbegin]->getNet() != cost.getNet()) { cdebug_log(155,0) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl; cost.incTerminals( _markers[mbegin]->getWeight(this) ); + + if ( (_markers[mbegin]->getRefCount() == 1) and (interval.contains(_markers[mbegin]->getSpan())) ) { + cdebug_log(155,0) << " Total overlap of a one track terminal: infinite cost." << endl; + cost.setInfinite(); + } } } @@ -391,8 +396,11 @@ namespace Katana { if (_segments.empty()) return Interval(_min,_max); getBeginIndex( position, begin, state ); - if ( (state == InsideElement) and (_segments[begin]->getNet() != net) ) + if ( (state == InsideElement) and (_segments[begin]->getNet() != net) ) { + cdebug_log(155,0) << "Track::getFreeInterval(): Inside other element @" << begin + << " - " << _segments[begin] << endl; return Interval(); + } end = begin; return expandFreeInterval( begin, end, state, net ); @@ -616,7 +624,6 @@ namespace Katana { return free; } - Interval occupied = getOccupiedInterval( index ); cdebug_log(155,0) << "Previous occupied:" << occupied << endl; Interval free = getFreeInterval( occupied.getVMin()-1, net ); @@ -642,10 +649,10 @@ namespace Katana { while ( --i != npos ) { if (_segments[i]->getNet() != owner) break; - cdebug_log(155,0) << "| merge:" << _segments[i] << endl; - _segments[i]->getCanonical ( segmentInterval ); if (segmentInterval.getVMax() >= mergedInterval.getVMin()) { + cdebug_log(155,0) << "| merge (prev):" << _segments[i] << endl; + mergedInterval.merge( segmentInterval ); begin = i; } @@ -658,6 +665,8 @@ namespace Katana { _segments[i]->getCanonical( segmentInterval ); if (segmentInterval.getVMin() > mergedInterval.getVMax()) break; + cdebug_log(155,0) << "| merge (next):" << _segments[i] << endl; + mergedInterval.merge( segmentInterval ); } diff --git a/katana/src/TrackCost.cpp b/katana/src/TrackCost.cpp index 7314a48b..7c47d91c 100644 --- a/katana/src/TrackCost.cpp +++ b/katana/src/TrackCost.cpp @@ -58,6 +58,9 @@ namespace Katana { , _selectFlags (NoFlags) , _selectIndex (0) { + cdebug_log(159,1) << "TrackCost::TrackCost() - " << refSegment << endl; + cdebug_log(159,0) << " interval1: " << _interval1 << endl; + std::get<0>( _tracks[0] ) = refTrack; _segment1->addOverlapCost( *this ); @@ -68,6 +71,7 @@ namespace Katana { } consolidate(); + cdebug_tabw(159,-1); } diff --git a/katana/src/TrackElement.cpp b/katana/src/TrackElement.cpp index 97503249..6f2edead 100644 --- a/katana/src/TrackElement.cpp +++ b/katana/src/TrackElement.cpp @@ -133,6 +133,7 @@ namespace Katana { // Wrapped AutoSegment Functions. AutoSegment* TrackElement::base () const { return NULL; } bool TrackElement::isFixed () const { return false; } + bool TrackElement::isFixedAxis () const { return false; } bool TrackElement::isLocal () const { return true; } bool TrackElement::isGlobal () const { return not isLocal(); } bool TrackElement::isBipoint () const { return false; } @@ -162,7 +163,7 @@ namespace Katana { uint32_t TrackElement::getTrackCount () const { return 0; } DbU::Unit TrackElement::getPitch () const { return 0; } DbU::Unit TrackElement::getPPitch () const { return 0; } - DbU::Unit TrackElement::getExtensionCap () const { return 0; } + DbU::Unit TrackElement::getExtensionCap ( Flags ) const { return 0; } float TrackElement::getMaxUnderDensity ( Flags ) const { return 0.0; }; uint32_t TrackElement::getDoglegLevel () const { return 0; } TrackElement* TrackElement::getParent () const { return NULL; } diff --git a/katana/src/TrackFixedSegment.cpp b/katana/src/TrackFixedSegment.cpp index 378325ac..3c5452d5 100644 --- a/katana/src/TrackFixedSegment.cpp +++ b/katana/src/TrackFixedSegment.cpp @@ -144,6 +144,30 @@ namespace Katana { size_t TrackFixedSegment::getTrackSpan () const { return 1; } + DbU::Unit TrackFixedSegment::getSourceAxis () const + { + const Horizontal* horizontal = dynamic_cast( _segment ); + if (horizontal) return horizontal->getSourceX(); + + const Vertical* vertical = dynamic_cast( _segment ); + if (vertical) return vertical->getSourceY(); + + return 0; + } + + + DbU::Unit TrackFixedSegment::getTargetAxis () const + { + const Horizontal* horizontal = dynamic_cast( _segment ); + if (horizontal) return horizontal->getTargetX(); + + const Vertical* vertical = dynamic_cast( _segment ); + if (vertical) return vertical->getTargetY(); + + return 0; + } + + unsigned long TrackFixedSegment::getId () const { cerr << Error("::getId() called on %s.",_getString().c_str()) << endl; diff --git a/katana/src/TrackMarker.cpp b/katana/src/TrackMarker.cpp index e3e1ed87..30d30c99 100644 --- a/katana/src/TrackMarker.cpp +++ b/katana/src/TrackMarker.cpp @@ -81,9 +81,9 @@ namespace Katana { } if ( rpDirection xor (uint64_t)rg->getLayerDirection(rg->getLayerDepth(pad->getLayer())) ) { - _weight = (uint32_t)(( pitch / (pitch+DbU::toLambda(trackSpan.getSize())) ) * 100.0) ; + _weight = (uint32_t)(( pitch / (pitch+trackSpan.getSize()) ) * 100.0) ; } else { - _weight = (uint32_t)( (pitch + DbU::toLambda(trackSpan.getSize())) * 20.0 ); + _weight = (uint32_t)( (pitch + trackSpan.getSize()) * 20.0 ); } Track* track = rp->getTrackByPosition ( trackSpan.getVMin() ); diff --git a/katana/src/TrackSegment.cpp b/katana/src/TrackSegment.cpp index 10e20738..c39bd880 100644 --- a/katana/src/TrackSegment.cpp +++ b/katana/src/TrackSegment.cpp @@ -154,6 +154,7 @@ namespace Katana { AutoSegment* TrackSegment::base () const { return _base; } Segment* TrackSegment::getSegment () const { return _base->base(); } bool TrackSegment::isFixed () const { return _base->isFixed(); } + bool TrackSegment::isFixedAxis () const { return _base->isFixedAxis(); } bool TrackSegment::isHorizontal () const { return _base->isHorizontal(); } bool TrackSegment::isVertical () const { return _base->isVertical(); } bool TrackSegment::isLocal () const { return not _base->isWeakGlobal() and not _base->isGlobal(); } @@ -181,7 +182,7 @@ namespace Katana { const Layer* TrackSegment::getLayer () const { return _base->getLayer(); } DbU::Unit TrackSegment::getPitch () const { return _base->getPitch(); } DbU::Unit TrackSegment::getPPitch () const { return _ppitch; } - DbU::Unit TrackSegment::getExtensionCap () const { return _base->getExtensionCap(); } + DbU::Unit TrackSegment::getExtensionCap ( Flags flags ) const { return _base->getExtensionCap(flags); } DbU::Unit TrackSegment::getAxis () const { return _base->getAxis(); } unsigned long TrackSegment::getFreedomDegree () const { return _freedomDegree; } float TrackSegment::getPriority () const { return _priority; } @@ -195,6 +196,24 @@ namespace Katana { void TrackSegment::invalidate () { setFlags( TElemInvalidated ); _base->invalidate(); } + DbU::Unit TrackSegment::getSourceAxis () const + { + DbU::Unit sourceAxis = 0; + DbU::Unit targetAxis = 0; + base()->getEndAxes( sourceAxis, targetAxis ); + return sourceAxis; + } + + + DbU::Unit TrackSegment::getTargetAxis () const + { + DbU::Unit sourceAxis = 0; + DbU::Unit targetAxis = 0; + base()->getEndAxes( sourceAxis, targetAxis ); + return targetAxis; + } + + DataNegociate* TrackSegment::getDataNegociate ( Flags flags ) const { if (flags & Flags::DataSelf) return _data; diff --git a/katana/src/katana/Constants.h b/katana/src/katana/Constants.h index 0926b150..63389dc5 100644 --- a/katana/src/katana/Constants.h +++ b/katana/src/katana/Constants.h @@ -52,4 +52,7 @@ namespace Katana { } // Katana namespace. + +INSPECTOR_PV_SUPPORT(Katana::Flags) + #endif // KATANA_CONSTANTS_H diff --git a/katana/src/katana/DataNegociate.h b/katana/src/katana/DataNegociate.h index c1cd84ef..ee76ffe3 100644 --- a/katana/src/katana/DataNegociate.h +++ b/katana/src/katana/DataNegociate.h @@ -49,17 +49,18 @@ namespace Katana { class DataNegociate { public: - enum SlackState { RipupPerpandiculars = 1 - , Minimize = 2 - , Dogleg = 3 - , Slacken = 4 - , ConflictSolveByHistory = 5 - , ConflictSolveByPlaceds = 6 - , LocalVsGlobal = 7 - , MoveUp = 8 - , MaximumSlack = 9 - , Unimplemented =10 - , Repair =11 + enum SlackState { RipupPerpandiculars = 1 + , Minimize = 2 + , Dogleg = 3 + , Slacken = 4 + , ConflictSolveByHistory = 5 + , ConflictSolveByPlaceds = 6 + , LocalVsGlobal = 7 + , MoveUp = 8 + , MaximumSlack = 9 + , Unimplemented = 10 + , Repair = 11 + , RepairFailed = 12 }; public: DataNegociate ( TrackElement* ); @@ -89,6 +90,7 @@ namespace Katana { inline void resetRipupCount (); inline void resetStateCount (); void update (); + static string getStateString ( uint32_t state, unsigned int stateCount ); static string getStateString ( DataNegociate* ); Record* _getRecord () const; string _getString () const; @@ -141,6 +143,18 @@ namespace Katana { inline void DataNegociate::setState ( uint32_t state, Flags flags ) { + if ( (_state >= Repair) and (state < _state) ) { + std::cerr << "Revert DataNegociate state from Repair/RepairFailed to " << getStateString(state,_stateCount).c_str() << std::endl; + std::cerr << "On " << _getString() << std::endl; + + std::cerr << *((char*)NULL) << std::endl; + + throw Hurricane::Error( "Revert DataNegociate state from Repair/RepairFailed to %s." + " On %s" + , getStateString(state,_stateCount).c_str() + , _getString().c_str() + ); + } if ( (_state != state) or (flags & Flags::ResetCount) ) { //std::cerr << "Changing state to:" << state << std::endl; _state = state; @@ -155,4 +169,7 @@ namespace Katana { } // Katana namespace. + +INSPECTOR_P_SUPPORT(Katana::DataNegociate); + #endif // KATANA_DATA_NEGOCIATE_H diff --git a/katana/src/katana/RoutingEventLoop.h b/katana/src/katana/RoutingEventLoop.h index b97e897f..f41d4786 100644 --- a/katana/src/katana/RoutingEventLoop.h +++ b/katana/src/katana/RoutingEventLoop.h @@ -1,7 +1,7 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2013, All Rights Reserved +// Copyright (c) UPMC 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -10,7 +10,7 @@ // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | -// | C++ Header : "./katana/RoutingEventLoop.h" | +// | C++ Header : "./katana/RoutingEventLoop.h" | // +-----------------------------------------------------------------+ @@ -22,6 +22,7 @@ namespace Katana { + class TrackElement; class RoutingEvent; @@ -33,11 +34,12 @@ namespace Katana { public: class Element { public: - inline Element ( size_t id=0, size_t timestamp=0 ); + inline Element ( TrackElement* segment, size_t timestamp=0 ); + size_t getId () const; public: - size_t _id; - size_t _timestamp; - int _count; + TrackElement* _segment; + size_t _timestamp; + int _count; }; class CompareByTimestamp { public: @@ -48,8 +50,8 @@ namespace Katana { inline bool isLooping () const; inline int getMaxCount () const; inline const std::vector& getElements () const; - void update ( size_t id ); - void erase ( size_t id ); + void update ( TrackElement* ); + void erase ( TrackElement* ); private: std::vector _elements; size_t _depth; @@ -59,8 +61,8 @@ namespace Katana { }; - inline RoutingEventLoop::Element::Element ( size_t id, size_t timestamp ) - : _id(id), _timestamp(timestamp), _count(1) + inline RoutingEventLoop::Element::Element ( TrackElement* segment, size_t timestamp ) + : _segment(segment), _timestamp(timestamp), _count(1) { } diff --git a/katana/src/katana/SegmentFsm.h b/katana/src/katana/SegmentFsm.h index a72f5342..20197e15 100644 --- a/katana/src/katana/SegmentFsm.h +++ b/katana/src/katana/SegmentFsm.h @@ -114,6 +114,7 @@ namespace Katana { ~SegmentFsm (); inline bool isFullBlocked () const; inline bool isSymmetric () const; + inline bool isMinimizeDrag () const; inline RoutingEvent* getEvent () const; inline RoutingEvent* getEvent1 () const; inline RoutingEvent* getEvent2 () const; @@ -187,40 +188,42 @@ namespace Katana { bool _fullBlocked; bool _sameAxis; bool _useEvent2; + bool _minimizeDrag; }; - inline bool SegmentFsm::isSymmetric () const { return _event2 != NULL; } - inline bool SegmentFsm::isFullBlocked () const { return _fullBlocked and _costs.size(); } - inline RoutingEvent* SegmentFsm::getEvent () const { return (_useEvent2) ? _event2 : _event1; } - inline RoutingEvent* SegmentFsm::getEvent1 () const { return _event1; } - inline RoutingEvent* SegmentFsm::getEvent2 () const { return _event2; } - inline RoutingEventQueue& SegmentFsm::getQueue () const { return _queue; } - inline RoutingEventHistory& SegmentFsm::getHistory () const { return _history; } - inline uint32_t SegmentFsm::getState () const { return _state; } - inline TrackElement* SegmentFsm::getSegment1 () const { return _event1->getSegment(); } - inline TrackElement* SegmentFsm::getSegment2 () const { return (_event2) ? _event2->getSegment() : NULL; } - inline DataNegociate* SegmentFsm::getData () { return (_useEvent2) ? _data2 : _data1; } - inline DataNegociate* SegmentFsm::getData1 () { return _data1; } - inline DataNegociate* SegmentFsm::getData2 () { return _data2; } - inline Interval& SegmentFsm::getConstraint () { return _constraint; } - inline Interval& SegmentFsm::getOptimal () { return _optimal; } - inline vector& SegmentFsm::getCosts () { return _costs; } - inline TrackCost* SegmentFsm::getCost ( size_t icost ) { return _costs[icost]; } - inline Track* SegmentFsm::getTrack ( size_t icost, size_t itrack ) { return (_useEvent2) ? getTrack2(icost,itrack) : getTrack1(icost,itrack); } - inline size_t SegmentFsm::getBegin ( size_t icost, size_t itrack ) { return (_useEvent2) ? getBegin2(icost,itrack) : getBegin1(icost,itrack); } - inline size_t SegmentFsm::getEnd ( size_t icost, size_t itrack ) { return (_useEvent2) ? getEnd2 (icost,itrack) : getEnd1 (icost,itrack); } - inline Track* SegmentFsm::getTrack1 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::NoFlags ); } - inline Track* SegmentFsm::getTrack2 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::Symmetric); } - inline size_t SegmentFsm::getBegin1 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::NoFlags ); } - inline size_t SegmentFsm::getBegin2 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::Symmetric); } - inline size_t SegmentFsm::getEnd1 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::NoFlags ); } - inline size_t SegmentFsm::getEnd2 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::Symmetric); } - inline vector& SegmentFsm::getActions () { return _actions; } - inline void SegmentFsm::setState ( uint32_t state ) { _state = state; } - inline void SegmentFsm::clearActions () { _actions.clear(); } - inline SegmentFsm& SegmentFsm::useEvent1 () { _useEvent2 = false; return *this; } - inline SegmentFsm& SegmentFsm::useEvent2 () { _useEvent2 = true ; return *this; } + inline bool SegmentFsm::isMinimizeDrag () const { return _minimizeDrag; } + inline bool SegmentFsm::isSymmetric () const { return _event2 != NULL; } + inline bool SegmentFsm::isFullBlocked () const { return _fullBlocked and _costs.size(); } + inline RoutingEvent* SegmentFsm::getEvent () const { return (_useEvent2) ? _event2 : _event1; } + inline RoutingEvent* SegmentFsm::getEvent1 () const { return _event1; } + inline RoutingEvent* SegmentFsm::getEvent2 () const { return _event2; } + inline RoutingEventQueue& SegmentFsm::getQueue () const { return _queue; } + inline RoutingEventHistory& SegmentFsm::getHistory () const { return _history; } + inline uint32_t SegmentFsm::getState () const { return _state; } + inline TrackElement* SegmentFsm::getSegment1 () const { return _event1->getSegment(); } + inline TrackElement* SegmentFsm::getSegment2 () const { return (_event2) ? _event2->getSegment() : NULL; } + inline DataNegociate* SegmentFsm::getData () { return (_useEvent2) ? _data2 : _data1; } + inline DataNegociate* SegmentFsm::getData1 () { return _data1; } + inline DataNegociate* SegmentFsm::getData2 () { return _data2; } + inline Interval& SegmentFsm::getConstraint () { return _constraint; } + inline Interval& SegmentFsm::getOptimal () { return _optimal; } + inline vector& SegmentFsm::getCosts () { return _costs; } + inline TrackCost* SegmentFsm::getCost ( size_t icost ) { return _costs[icost]; } + inline Track* SegmentFsm::getTrack ( size_t icost, size_t itrack ) { return (_useEvent2) ? getTrack2(icost,itrack) : getTrack1(icost,itrack); } + inline size_t SegmentFsm::getBegin ( size_t icost, size_t itrack ) { return (_useEvent2) ? getBegin2(icost,itrack) : getBegin1(icost,itrack); } + inline size_t SegmentFsm::getEnd ( size_t icost, size_t itrack ) { return (_useEvent2) ? getEnd2 (icost,itrack) : getEnd1 (icost,itrack); } + inline Track* SegmentFsm::getTrack1 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::NoFlags ); } + inline Track* SegmentFsm::getTrack2 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::Symmetric); } + inline size_t SegmentFsm::getBegin1 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::NoFlags ); } + inline size_t SegmentFsm::getBegin2 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::Symmetric); } + inline size_t SegmentFsm::getEnd1 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::NoFlags ); } + inline size_t SegmentFsm::getEnd2 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::Symmetric); } + inline vector& SegmentFsm::getActions () { return _actions; } + inline void SegmentFsm::setState ( uint32_t state ) { _state = state; } + inline void SegmentFsm::clearActions () { _actions.clear(); } + inline SegmentFsm& SegmentFsm::useEvent1 () { _useEvent2 = false; return *this; } + inline SegmentFsm& SegmentFsm::useEvent2 () { _useEvent2 = true ; return *this; } } // Katana namespace. diff --git a/katana/src/katana/Session.h b/katana/src/katana/Session.h index 8f465c9e..b1cde9e9 100644 --- a/katana/src/katana/Session.h +++ b/katana/src/katana/Session.h @@ -46,6 +46,7 @@ namespace Katana { using Hurricane::Contact; using Hurricane::Segment; using Hurricane::DbU; + using Hurricane::Interval; using Anabatic::AutoContact; using Anabatic::AutoSegment; @@ -74,6 +75,7 @@ namespace Katana { inline static uint32_t getRipupCost (); inline static Anabatic::GCell* getGCellUnder ( DbU::Unit, DbU::Unit ); static void setInterrupt ( bool ); + inline static Interval& toAxisInterval ( Interval&, size_t depth ); inline static void addInsertEvent ( TrackMarker* , Track* ); inline static void addInsertEvent ( TrackElement* , Track* ); inline static void addRemoveEvent ( TrackElement* ); @@ -90,6 +92,7 @@ namespace Katana { Net* _getBlockageNet (); uint32_t _getRipupCost (); Anabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit ); + Interval& _toAxisInterval ( Interval&, size_t depth ) const; void _doLockEvents (); void _doRemovalEvents (); virtual size_t _revalidate (); @@ -164,6 +167,9 @@ namespace Katana { inline Anabatic::GCell* Session::getGCellUnder ( DbU::Unit x, DbU::Unit y ) { return get("getGCellUnder()")->_getGCellUnder(x,y); } + inline Interval& Session::toAxisInterval ( Interval& interval, size_t depth ) + { return get("getGCellUnder()")->_toAxisInterval(interval,depth); } + inline void Session::addInsertEvent ( TrackMarker* marker, Track* track ) { get("addInsertEvent(TrackMarker*)")->_addInsertEvent(marker,track); } diff --git a/katana/src/katana/TrackElement.h b/katana/src/katana/TrackElement.h index dde62c62..fbf62ed7 100644 --- a/katana/src/katana/TrackElement.h +++ b/katana/src/katana/TrackElement.h @@ -99,6 +99,7 @@ namespace Katana { virtual Segment* getSegment () const = 0; // Wrapped AutoSegment Functions (when applicable). virtual bool isFixed () const; + virtual bool isFixedAxis () const; virtual bool isHorizontal () const = 0; virtual bool isVertical () const = 0; virtual bool isWide () const; @@ -151,11 +152,13 @@ namespace Katana { inline Box getBoundingBox () const; virtual TrackElement* getNext () const; virtual TrackElement* getPrevious () const; - virtual DbU::Unit getExtensionCap () const; + virtual DbU::Unit getExtensionCap ( Flags ) const; virtual DbU::Unit getAxis () const = 0; inline DbU::Unit getSymmetricAxis ( DbU::Unit ) const; inline DbU::Unit getSourceU () const; inline DbU::Unit getTargetU () const; + virtual DbU::Unit getSourceAxis () const = 0; + virtual DbU::Unit getTargetAxis () const = 0; inline DbU::Unit getLength () const; inline Interval getCanonicalInterval () const; virtual Interval getFreeInterval () const; diff --git a/katana/src/katana/TrackFixedSegment.h b/katana/src/katana/TrackFixedSegment.h index 9c95d668..9ac4fb2a 100644 --- a/katana/src/katana/TrackFixedSegment.h +++ b/katana/src/katana/TrackFixedSegment.h @@ -55,6 +55,8 @@ namespace Katana { virtual TrackElement* getNext () const; virtual TrackElement* getPrevious () const; virtual DbU::Unit getAxis () const; + inline DbU::Unit getSourceAxis () const; + virtual DbU::Unit getTargetAxis () const; virtual Interval getFreeInterval () const; virtual void addOverlapCost ( TrackCost& ) const; virtual float getPriority () const; diff --git a/katana/src/katana/TrackMarker.h b/katana/src/katana/TrackMarker.h index ae7df36e..db4c01f6 100644 --- a/katana/src/katana/TrackMarker.h +++ b/katana/src/katana/TrackMarker.h @@ -2,7 +2,7 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2013, All Rights Reserved +// Copyright (c) UPMC 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -11,7 +11,7 @@ // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | -// | C++ Header : "./katana/TrackMarker.h" | +// | C++ Header : "./katana/TrackMarker.h" | // +-----------------------------------------------------------------+ @@ -31,6 +31,7 @@ namespace Katana { using Hurricane::Record; using Hurricane::DbU; + using Hurricane::Interval; using Hurricane::RoutingPad; using Hurricane::Net; @@ -47,8 +48,10 @@ namespace Katana { void destroy (); public: Net* getNet () const; + inline uint32_t getRefCount () const; inline DbU::Unit getSourceU () const; inline DbU::Unit getTargetU () const; + inline Interval getSpan () const; inline Track* getTrack () const; inline uint32_t getWeight ( const Track* ) const; inline void setTrack ( Track* ); @@ -85,11 +88,13 @@ namespace Katana { // Inline Functions. - inline DbU::Unit TrackMarker::getSourceU () const { return _sourcePosition; } - inline DbU::Unit TrackMarker::getTargetU () const { return _targetPosition; } - inline Track* TrackMarker::getTrack () const { return _track; } - inline uint32_t TrackMarker::getWeight ( const Track* track ) const { return _weight; } - inline void TrackMarker::setTrack ( Track* track ) { _track = track; } + inline uint32_t TrackMarker::getRefCount () const { return _refcount; } + inline DbU::Unit TrackMarker::getSourceU () const { return _sourcePosition; } + inline DbU::Unit TrackMarker::getTargetU () const { return _targetPosition; } + inline Interval TrackMarker::getSpan () const { return Interval(_sourcePosition,_targetPosition); } + inline Track* TrackMarker::getTrack () const { return _track; } + inline uint32_t TrackMarker::getWeight ( const Track* track ) const { return _weight; } + inline void TrackMarker::setTrack ( Track* track ) { _track = track; } inline bool TrackMarker::Compare::operator() ( const TrackMarker* lhs, const TrackMarker* rhs ) const { return markerLess ( lhs->getSourceU(), rhs->getSourceU() ); } diff --git a/katana/src/katana/TrackSegment.h b/katana/src/katana/TrackSegment.h index bb77dbae..6a672dd1 100644 --- a/katana/src/katana/TrackSegment.h +++ b/katana/src/katana/TrackSegment.h @@ -63,6 +63,7 @@ namespace Katana { virtual AutoSegment* base () const; virtual Segment* getSegment () const; virtual bool isFixed () const; + virtual bool isFixedAxis () const; virtual bool isHorizontal () const; virtual bool isVertical () const; virtual bool isLocal () const; @@ -85,11 +86,11 @@ namespace Katana { virtual bool canDogleg (); virtual bool canDogleg ( Interval ); virtual bool canDogleg ( Anabatic::GCell*, Flags flags=0 ); - virtual bool canPivotUp ( float reserve, Flags flags ) const; - virtual bool canPivotDown ( float reserve, Flags flags ) const; - virtual bool canMoveUp ( float reserve, Flags flags ) const; + virtual bool canPivotUp ( float reserve, Flags ) const; + virtual bool canPivotDown ( float reserve, Flags ) const; + virtual bool canMoveUp ( float reserve, Flags ) const; virtual bool canSlacken () const; - virtual float getMaxUnderDensity ( Flags flags ) const; + virtual float getMaxUnderDensity ( Flags ) const; virtual unsigned long getId () const; virtual Flags getDirection () const; virtual Net* getNet () const; @@ -97,7 +98,7 @@ namespace Katana { virtual const Layer* getLayer () const; virtual DbU::Unit getPitch () const; virtual DbU::Unit getPPitch () const; - virtual DbU::Unit getExtensionCap () const; + virtual DbU::Unit getExtensionCap ( Flags ) const; virtual unsigned long getFreedomDegree () const; virtual float getPriority () const; virtual uint32_t getDoglegLevel () const; @@ -105,6 +106,8 @@ namespace Katana { virtual TrackElement* getPrevious () const; virtual TrackElement* getParent () const; virtual DbU::Unit getAxis () const; + virtual DbU::Unit getSourceAxis () const; + virtual DbU::Unit getTargetAxis () const; virtual Interval getFreeInterval () const; virtual Interval getSourceConstraints () const; virtual Interval getTargetConstraints () const; @@ -137,10 +140,10 @@ namespace Katana { virtual TrackElement* makeDogleg ( Anabatic::GCell*, TrackElement*& perpandicular, TrackElement*& parallel ); virtual TrackElement* makeDogleg ( Interval, Flags& flags ); virtual void _postDoglegs ( TrackElement*& perpandicular, TrackElement*& parallel ); - virtual bool moveAside ( Flags flags ); + virtual bool moveAside ( Flags ); virtual bool slacken ( Flags flags=Flags::NoFlags ); - virtual bool moveUp ( Flags flags ); - virtual bool moveDown ( Flags flags ); + virtual bool moveUp ( Flags ); + virtual bool moveDown ( Flags ); #if THIS_IS_DISABLED virtual void desalignate (); #endif