diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 98e09c975..739fab73a 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -58,7 +58,7 @@ jobs: run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" cd ${{ github.workspace }}/coriolis-2.x/src/coriolis - make -f Makefile.LIP6 install install_alliance + make -f Makefile.LIP6 SRC_DIR=${{ github.workspace }}/coriolis-2.x/src install install_alliance - name: Check for binaries run: ls -1 ${{ github.workspace }}/coriolis-2.x/release/install/bin - name: Run the reference set of designs diff --git a/.gitignore b/.gitignore index 2e3fcedb5..ed9a4ff53 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.pyc *.log *.bak +.#* TAGS GTAGS @@ -24,6 +25,7 @@ build/ venv/ coriolis.egg-info/ .pdm-python +.doit.db bootstrap/coriolis2.spec diff --git a/Makefile.LIP6 b/Makefile.LIP6 index 42c436a9b..f93b15498 100644 --- a/Makefile.LIP6 +++ b/Makefile.LIP6 @@ -63,11 +63,19 @@ $(CORIOLIS_SRC)/.pdm-plugins/bin/pdm: $(HOME)/.local/bin/pdm @$(localpath) pdm install --no-self -d --plugins +wipe: + @$(localpath) pdm run meson setup ${BUILDDIR} --wipe -Dpython.install_env=prefix -Donly-docs=false + + +setup: + @$(localpath) pdm run meson setup ${BUILDDIR} --prefix=$(PREFIX) -Dpython.install_env=prefix -Donly-docs=false + + configure: - @$(localpath) pdm run meson setup ${BUILDDIR} --prefix=$(PREFIX) -Dpython.install_env=prefix + @$(localpath) pdm run meson configure ${BUILDDIR} --prefix=$(PREFIX) -Dpython.install_env=prefix -install: check_dir $(CORIOLIS_SRC)/.pdm-plugins/bin/pdm configure +install: check_dir $(CORIOLIS_SRC)/.pdm-plugins/bin/pdm setup configure @$(localpath) pdm run meson install -C $(BUILDDIR) @echo ""; \ echo "============================================================================"; \ @@ -80,7 +88,6 @@ install: check_dir $(CORIOLIS_SRC)/.pdm-plugins/bin/pdm configure install_docs: check_dir $(CORIOLIS_SRC)/.pdm-plugins/bin/pdm configure @$(localpath) pdm run meson configure ${BUILDDIR} --prefix=$(PREFIX) \ - -Donly-docs=true \ -Ddocs=true @$(localpath) pdm run meson install -C $(BUILDDIR) @@ -92,10 +99,10 @@ install_alliance: sed -i 's,dirs="\\$$newdirs documentation",dirs="$$newdirs",' ./autostuff; \ ./autostuff clean; \ ./autostuff; \ - mkdir -p $(BUILDDIR); \ + mkdir -p $(BUILDDIR); \ cd $(BUILDDIR); \ $(ALLIANCE_SRC)/configure --prefix=$(PREFIX) --enable-alc-shared; \ - make -j1 install + make -j1 install clean_build: check_dir diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index b0bbf16c1..cf78961c3 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -1177,7 +1177,10 @@ namespace Anabatic { } cleanupGlobal(); - if (not _configuration->isTwoMetals()) relaxOverConstraineds(); + if (not _configuration->isTwoMetals()) { + if (_configuration->getDirection((size_t)0) & Flags::Vertical) + relaxOverConstraineds(); + } _state = EngineActive; } @@ -1776,7 +1779,8 @@ namespace Anabatic { UpdateSession::open(); for ( auto rp : rps ) { - if (not _configuration->selectRpComponent(rp)) + bool ongrid = _configuration->selectRpComponent(rp); + if (not ongrid and not _configuration->isM1Offgrid()) cerr << Warning( "AnabaticEngine::computeEdgeCapacities(): %s has no components on grid.", getString(rp).c_str() ) << endl; Point center = rp->getBoundingBox().getCenter(); diff --git a/anabatic/src/AutoContact.cpp b/anabatic/src/AutoContact.cpp index c81eaa461..dbc7a99b8 100644 --- a/anabatic/src/AutoContact.cpp +++ b/anabatic/src/AutoContact.cpp @@ -392,38 +392,39 @@ namespace Anabatic { void AutoContact::showTopologyError ( const std::string& message, Flags flags ) { - Component* anchor = NULL; - Horizontal** horizontals = new Horizontal* [10]; - Vertical** verticals = new Vertical* [10]; - - if (not (flags & Flags::CParanoid)) cparanoid.setStreamMask( mstream::PassThrough ); + Component* anchor = NULL; + Horizontal** horizontals = new Horizontal* [10]; + Vertical** verticals = new Vertical* [10]; + ostringstream strError; + strError << "In topology of " << this << "\n"; _getTopology ( base(), anchor, horizontals, verticals, 10 ); - cparanoid << Error("In topology of %s",getString(this).c_str()) << endl; - if (anchor) cparanoid << " A: " << anchor << endl; + if (anchor) strError << " A: " << anchor << "\n"; for ( size_t i=0 ; (i<10) and (horizontals[i] != NULL); ++i ) { AutoSegment* autoSegment = Session::lookup ( horizontals[i] ); if (autoSegment != NULL) - cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl; + strError << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << "\n"; else - cparanoid << " ?: " << horizontals[i] << endl; + strError << " ?: " << horizontals[i] << "\n"; } for ( size_t i=0 ; (i<10) and (verticals[i] != NULL); ++i ) { AutoSegment* autoSegment = Session::lookup ( verticals[i] ); if (autoSegment != NULL) - cparanoid << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << endl; + strError << " " << (autoSegment->isGlobal()?'G':'L') << ": " << autoSegment << "\n"; else - cparanoid << " ?: " << verticals[i] << endl; + strError << " ?: " << verticals[i] << "\n"; } - cparanoid << " " << message << endl; - if (not (flags & Flags::CParanoid)) cparanoid.unsetStreamMask( mstream::PassThrough ); - + strError << " " << message << "\n"; + Error error ( strError.str().c_str() ); + delete [] horizontals; delete [] verticals; + + throw error; } diff --git a/anabatic/src/AutoContactTerminal.cpp b/anabatic/src/AutoContactTerminal.cpp index c3a96fc46..f1a05932b 100644 --- a/anabatic/src/AutoContactTerminal.cpp +++ b/anabatic/src/AutoContactTerminal.cpp @@ -464,6 +464,8 @@ namespace Anabatic { ostringstream message; if (not hasBadTopology()) { + if (getAnchor()->getLayer() == getLayer()) setFlags ( CntMetalOnly ); + else unsetFlags( CntMetalOnly ); Box anchorBb = getAnchor()->getBoundingBox(); anchorBb.inflate( Session::getViaWidth (getAnchor()->getLayer()) - Session::getWireWidth(getAnchor()->getLayer()) ); @@ -475,6 +477,25 @@ namespace Anabatic { setHeight( _segment->getContactWidth() ); } + if (canDrag()) { + AutoContact* opposite = _segment->getOppositeAnchor(this); + AutoSegment* perpandicular = opposite->getPerpandicular( _segment ); + if (perpandicular) { + cdebug_log(145,0) << "Draging H interval [" + << DbU::getValueString(getCBXMin()) << " " + << DbU::getValueString(getCBXMax()) << "]" << endl; + Point onGrid = Session::getNearestGridPoint( Point(perpandicular->getAxis(),getY()) + , getConstraintBox() ); + DbU::Unit x = onGrid.getX(); + x = std::min( x, getCBXMax() ); + x = std::max( x, getCBXMin() ); + setX( x ); + cdebug_log(145,0) << "Dragging to X @" << DbU::getValueString(x) + << " pitched:" << DbU::getValueString(onGrid.getX()) + << " " << getConstraintBox() << endl; + } + } + if (not getUConstraints(Flags::Vertical).contains(axis)) { cdebug_log(145,0) << "Cached: " << _segment << endl; message << "Terminal horizontal segment Y " << DbU::getValueString(axis) @@ -503,7 +524,7 @@ namespace Anabatic { AutoContact* opposite = _segment->getOppositeAnchor(this); AutoSegment* perpandicular = opposite->getPerpandicular( _segment ); if (perpandicular) { - cdebug_log(145,0) << "Draging V interval [" + cdebug_log(145,0) << "Dragging V interval [" << DbU::getValueString(getCBYMin()) << " " << DbU::getValueString(getCBYMax()) << "]" << endl; DbU::Unit y = perpandicular->getAxis(); diff --git a/anabatic/src/AutoHorizontal.cpp b/anabatic/src/AutoHorizontal.cpp index 3746a6981..734d89fcd 100644 --- a/anabatic/src/AutoHorizontal.cpp +++ b/anabatic/src/AutoHorizontal.cpp @@ -386,13 +386,13 @@ namespace Anabatic { int nativeSlack = nativeConstraints.getSize() / getPitch(); cdebug_log(149,0) << "Source constraint: " << constraints - << " slack:" << slack - << " native slack:" << nativeSlack << endl; + << " slack:" << slack + << " native slack:" << nativeSlack << endl; cdebug_log(149,0) << "Perpand constraints on target: " << perpandConstraints << endl; // Ugly: GCell's track number is hardwired. if (isNonPrefSource or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { cdebug_log(149,0) << "Slackening from Source: " << source << endl; - _makeDogleg( source->getGCell(), Flags::NoFlags ); + _makeDogleg( source->getGCell(), Flags::DoglegDown ); sourceSlackened = true; } else if (slack < 10) { halfSlackened = true; @@ -430,7 +430,7 @@ namespace Anabatic { << " native slack:" << nativeSlack << endl; if (isNonPrefTarget or (nativeSlack < lowSlack) or (nativeSlack - slack < 3)) { cdebug_log(149,0) << "Slackening from Target: " << target << endl; - parallel->_makeDogleg( target->getGCell(), Flags::NoFlags ); + parallel->_makeDogleg( target->getGCell(), Flags::DoglegDown ); targetSlackened = true; } else if (slack < 10) { halfSlackened = true; @@ -541,6 +541,11 @@ namespace Anabatic { { _sourcePosition = getSourceU() - getExtensionCap(Flags::Source); _targetPosition = getTargetU() + getExtensionCap(Flags::Target); + if (isNonPref()) { + DbU::Unit halfCap = getExtensionCap( Flags::NoFlags ) -1; + _sourcePosition -= halfCap; + _targetPosition += halfCap; + } } @@ -562,6 +567,11 @@ namespace Anabatic { bool coherency = true; DbU::Unit sourcePosition = _horizontal->getSource()->getX() - getExtensionCap(Flags::Source); DbU::Unit targetPosition = _horizontal->getTarget()->getX() + getExtensionCap(Flags::Target); + if (isNonPref()) { + DbU::Unit halfCap = getExtensionCap( Flags::NoFlags ) -1; + sourcePosition -= halfCap; + targetPosition += halfCap; + } if ( _sourcePosition != sourcePosition ) { cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl; @@ -879,7 +889,10 @@ namespace Anabatic { } else if (Session::getRoutingGauge()->isVH()) { upLayer = (depth < 2); } else { - upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + if ((depth > 0) and (flags & Flags::DoglegDown)) + upLayer = not (Session::getConfiguration()->isUsable( depth-1 )); + else + upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); } size_t doglegDepth = depth + ((upLayer)?1:-1); diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index ac7d982e5..aaab0e053 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -789,23 +789,29 @@ namespace Anabatic { // cdebug_log(150,0) << "-> Custom cap (-duSource):" << DbU::getValueString(cap) << endl; } } - } - - if (flags & Flags::Target) { - if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth); - else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth); - else cap = getViaToSameCap (depth); - // cdebug_log(150,0) << "getExtensionCap(): (target) flags:" << getFlags() - // << " VIA cap:" << DbU::getValueString(cap) - // << " t:" << (getFlags() & SegSourceBottom) - // << " b:" << (getFlags() & SegSourceTop) - // << endl; - if (not (flags & Flags::NoSegExt)) { - // cdebug_log(150,0) << "duTarget=" << DbU::getValueString(getDuTarget()) << endl; - if (getDuTarget() > cap) { - cap = getDuTarget(); - // cdebug_log(150,0) << "-> Custom cap (+duTarget):" << DbU::getValueString(cap) << endl; + } else { + if (flags & Flags::Target) { + if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth); + else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth); + else cap = getViaToSameCap (depth); + // cdebug_log(150,0) << "getExtensionCap(): (target) flags:" << getFlags() + // << " VIA cap:" << DbU::getValueString(cap) + // << " t:" << (getFlags() & SegSourceBottom) + // << " b:" << (getFlags() & SegSourceTop) + // << endl; + if (not (flags & Flags::NoSegExt)) { + // cdebug_log(150,0) << "duTarget=" << DbU::getValueString(getDuTarget()) << endl; + if (getDuTarget() > cap) { + cap = getDuTarget(); + // cdebug_log(150,0) << "-> Custom cap (+duTarget):" << DbU::getValueString(cap) << endl; + } } + } else { + //cap = getViaToBottomCap( depth ); + cap = getViaToSameCap( depth ); + // cdebug_log(150,0) << "getExtensionCap(): (force bottom) flags:" << getFlags() + // << " VIA cap:" << DbU::getValueString(cap) + // << endl; } } @@ -823,6 +829,7 @@ namespace Anabatic { if (getLayer()->isSymbolic() and (cap < getWidth()/2)) cap = getWidth()/2; if (not (flags & Flags::LayerCapOnly)) cap += getLayer()->getMinimalSpacing()/2; + // cdebug_log(150,0) << "getExtensionCap(): cap=" << DbU::getValueString(cap) << endl; return cap; } @@ -2544,7 +2551,7 @@ namespace Anabatic { cdebug_log(149,0) << "isSource:" << isSource << endl; - makeDogleg( from->getGCell(), Flags::NoCheckLayer ); + makeDogleg( from->getGCell(), Flags::NoCheckLayer|Flags::NoCheckGCell ); if (doglegs.size() == index) { cdebug_tabw(149,-1); return NULL; @@ -2697,7 +2704,7 @@ namespace Anabatic { return 0; } - if (doglegGCell->getSide(getDirection()).intersect(getSpanU())) { + if ((flags & Flags::NoCheckGCell) or doglegGCell->getSide(getDirection()).intersect(getSpanU())) { cdebug_log(149,0) << "Dogleg in " << this << " spanU:" << getSpanU() << endl; rflags = _makeDogleg( doglegGCell, flags ); } else { @@ -2822,7 +2829,7 @@ namespace Anabatic { DbU::Unit verticalWidth = Session::getDVerticalWidth(); if (not Session::getAnabatic()->getConfiguration()->isGMetal(hurricaneSegment->getLayer())) { size_t depth = Session::getAnabatic()->getConfiguration()->getLayerDepth( hurricaneSegment->getLayer() ); - if (depth > 2) { + if ((depth == 0) or (depth > 2)) { horizontalLayer = verticalLayer = hurricaneSegment->getLayer(); horizontalWidth = Session::getAnabatic()->getConfiguration()->getWireWidth( depth ); verticalWidth = Session::getAnabatic()->getConfiguration()->getPWireWidth( depth ); @@ -3066,9 +3073,10 @@ namespace Anabatic { } else throw Error( badSegment, getString(source).c_str(), getString(target).c_str() ); - if (wPitch > 1) segment->setFlags( SegWide ); - if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag ); - if (dir & Flags::UseNonPref) segment->setFlags( SegNonPref ); + if (wPitch > 1) segment->setFlags( SegWide ); + if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag ); + if (dir & Flags::UseNonPref) segment->setFlags( SegNonPref ); + if (dir & Flags::Unbreakable) segment->setFlags( SegUnbreakable ); if (dir.contains(Flags::UseNonPref|Flags::OnVSmall)) segment->setFlags( SegOnVSmall ); return segment; diff --git a/anabatic/src/AutoVertical.cpp b/anabatic/src/AutoVertical.cpp index 790c0438a..68f0f15d9 100644 --- a/anabatic/src/AutoVertical.cpp +++ b/anabatic/src/AutoVertical.cpp @@ -317,7 +317,7 @@ namespace Anabatic { // Ugly: GCell's track number is hardwired. if ((slack < lowSlack) or (nativeSlack - slack < 3)) { - _makeDogleg( source->getGCell(), Flags::NoFlags ); + _makeDogleg( source->getGCell(), Flags::DoglegDown ); sourceSlackened = true; } else if (slack < 10) { halfSlackened = true; @@ -348,7 +348,7 @@ namespace Anabatic { // Ugly: GCell's track number is hardwired. if ((slack < lowSlack) or (nativeSlack - slack < 3)) { - _makeDogleg( target->getGCell(), Flags::NoFlags ); + _makeDogleg( target->getGCell(), Flags::DoglegDown ); targetSlackened = true; } else if (slack < 10) { halfSlackened = true; @@ -432,6 +432,11 @@ namespace Anabatic { { _sourcePosition = getSourceU() - getExtensionCap(Flags::Source); _targetPosition = getTargetU() + getExtensionCap(Flags::Target); + if (isNonPref()) { + DbU::Unit halfCap = getExtensionCap( Flags::NoFlags ) - 1; + _sourcePosition -= halfCap; + _targetPosition += halfCap; + } } @@ -453,6 +458,11 @@ namespace Anabatic { bool coherency = true; DbU::Unit sourcePosition = _vertical->getSource()->getY() - getExtensionCap(Flags::Source); DbU::Unit targetPosition = _vertical->getTarget()->getY() + getExtensionCap(Flags::Target); + if (isNonPref()) { + DbU::Unit halfCap = getExtensionCap( Flags::NoFlags ) - 1; + sourcePosition -= halfCap; + targetPosition += halfCap; + } if ( _sourcePosition != sourcePosition ) { cerr << Error ( "%s\n Source position incoherency: " @@ -740,7 +750,10 @@ namespace Anabatic { } else if (Session::getRoutingGauge()->isVH()) { upLayer = (depth < 2); } else { - upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); + if ((depth > 0) and (flags & Flags::DoglegDown)) + upLayer = not (Session::getConfiguration()->isUsable( depth-1 )); + else + upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth()); } size_t doglegDepth = depth + ((upLayer)?1:-1); diff --git a/anabatic/src/Configuration.cpp b/anabatic/src/Configuration.cpp index 81d10971a..b5d87bf16 100644 --- a/anabatic/src/Configuration.cpp +++ b/anabatic/src/Configuration.cpp @@ -20,6 +20,7 @@ #include "hurricane/configuration/Configuration.h" #include "hurricane/Warning.h" #include "hurricane/Error.h" +#include "hurricane/DebugSession.h" #include "hurricane/Technology.h" #include "hurricane/DataBase.h" #include "hurricane/BasicLayer.h" @@ -51,6 +52,7 @@ namespace Anabatic { using Hurricane::tab; using Hurricane::Warning; using Hurricane::Error; + using Hurricane::DebugSession; using Hurricane::Transformation; using Hurricane::Technology; using Hurricane::DataBase; @@ -225,12 +227,20 @@ namespace Anabatic { { return new Configuration(*this); } + bool Configuration::isSymbolic () const + { return _rg->isSymbolic(); } + + bool Configuration::isTwoMetals () const { return _rg->isTwoMetals(); } bool Configuration::isHybrid () const { return _routingStyle & StyleFlags::Hybrid; } + + + bool Configuration::isM1Offgrid () const + { return _routingStyle & StyleFlags::M1Offgrid; } bool Configuration::isHV () const @@ -239,6 +249,14 @@ namespace Anabatic { bool Configuration::isVH () const { return _rg->isVH(); } + + + bool Configuration::isUsable ( size_t depth ) const + { return _rg->isUsable( depth ); } + + + size_t Configuration::getFirstRoutingLayer () const + { return _rg->getFirstRoutingLayer(); } bool Configuration::isGMetal ( const Layer* layer ) const @@ -460,11 +478,14 @@ namespace Anabatic { bool Configuration::selectRpComponent ( RoutingPad* rp ) const { + DebugSession::open( rp->getNet(), 112, 120 ); cdebug_log(112,1) << "selectRpComponent(): " << rp << endl; + //rp->setFlags( RoutingPad::SelectedComponent ); if (rp->isAtTopLevel()) { cdebug_log(112,0) << "> RP is at top level, must not change it." << endl; cdebug_tabw(112,-1); + DebugSession::close(); return true; } @@ -472,9 +493,17 @@ namespace Anabatic { #if BETTER_FOR_TSMC rp->setOnBestComponent( RoutingPad::BiggestArea ); cdebug_tabw(112,-1); + DebugSession::close(); return true; #else + if (rp->hasSelectedComponent()) { + cdebug_tabw(112,-1); + DebugSession::close(); + return not rp->isM1Offgrid(); + } + Box ab = rp->getCell()->getAbutmentBox(); + const Layer* via12 = getContactLayer( 0 ); const Layer* metal1 = getLayerGauge( 0 )->getLayer(); RoutingLayerGauge* gauge = getLayerGauge( 1 ); Occurrence occurrence = rp->getPlugOccurrence(); @@ -487,11 +516,17 @@ namespace Anabatic { if (current and (current->getLayer()->getMask() != metal1->getMask())) { cdebug_log(112,0) << "> using default non-metal1 segment." << endl; cdebug_tabw(112,-1); + DebugSession::close(); return true; } - DbU::Unit bestSpan = 0; - Component* bestComponent = NULL; + Point ongridCenter; + DbU::Unit bestSpan = 0; + Component* ongridComponent = NULL; + Component* offgridComponent = NULL; + DbU::Unit viaShrink = 0; + if (not isSymbolic()) + viaShrink = _rg->getViaWidth( (size_t)0 )/2 + via12->getBottomEnclosure( Layer::EnclosureH ); cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl; for ( Component* component : masterNet->getComponents() ) { @@ -503,23 +538,23 @@ namespace Anabatic { if (dynamic_cast(component)) { cdebug_log(112,0) << " Pins are always considered best candidates:" << component << endl; - bestComponent = component; + ongridComponent = component; break; } Component* candidate = dynamic_cast( component ); if (not candidate - or (candidate->getLayer()->getMask() != metal1->getMask()) ) - candidate = dynamic_cast(component); - if (not candidate) + or (candidate->getLayer()->getMask() != metal1->getMask()) ) { candidate = dynamic_cast( component ); - if (not candidate) continue; + if (not candidate) continue; + } Box bb = transformation.getBox( candidate->getBoundingBox() ); DbU::Unit trackPos = 0; DbU::Unit minPos = DbU::Max; DbU::Unit maxPos = DbU::Min; + bb.inflate( -viaShrink ); if (gauge->isVertical()) { trackPos = gauge->getTrackPosition( ab.getXMin() , ab.getXMax() @@ -529,8 +564,8 @@ namespace Anabatic { maxPos = bb.getXMax(); cdebug_log(112,0) << "Vertical gauge: " << gauge << endl; - cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(bb.getXMin()) << endl; - cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(bb.getXMax()) << 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() @@ -541,8 +576,8 @@ namespace Anabatic { maxPos = bb.getYMax(); cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl; - cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(bb.getYMin()) << endl; - cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(bb.getYMax()) << 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; } @@ -550,26 +585,109 @@ namespace Anabatic { cdebug_log(112,0) << "| " << transformation << endl; cdebug_log(112,0) << "| " << bb << " of:" << candidate << endl; cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl; + cdebug_log(112,0) << "| " << DbU::getValueString(minPos) << " < trackPos < " + << DbU::getValueString(maxPos) << endl; if ( (trackPos >= minPos) and (trackPos <= maxPos) ) { - if (not bestComponent or (bestSpan < maxPos-minPos)) { - bestComponent = component; - bestSpan = maxPos - minPos; + if (not ongridComponent or (bestSpan < maxPos-minPos)) { + ongridComponent = component; + bestSpan = maxPos - minPos; + if (gauge->isVertical()) + ongridCenter = Point( trackPos, bb.getCenter().getY() ); + else + ongridCenter = Point( bb.getCenter().getX(), trackPos ); } + } else { + cdebug_log(112,0) << "Component is offgrid." << endl; + offgridComponent = candidate; } } - if (bestComponent) { - rp->setExternalComponent( bestComponent ); - cdebug_log(112,0) << "Using best candidate:" << bestComponent << endl; - cdebug_tabw(112,-1); - return true; + bool rvalue = false; + if (ongridComponent) { + rp->setExternalComponent( ongridComponent ); + rp->setUserCenter( ongridCenter ); + cdebug_log(112,0) << "Using best candidate:" << ongridComponent << endl; + rvalue = true; + } else { + if (not offgridComponent) + throw Error( "Configuration::selectRpComponent(): On %s,\n" + " No suitable external component found." + , getString(rp).c_str() + ); + rp->setExternalComponent( offgridComponent ); + rp->setFlags( RoutingPad::M1Offgrid ); + cdebug_log(112,0) << "Using offgrid candidate:" << offgridComponent << endl; } + checkRoutingPadSize( rp ); cdebug_tabw(112,-1); - return false; + DebugSession::close(); + return rvalue; #endif } + + + void Configuration::getPositions ( RoutingPad* rp, Point& source, Point& target ) const + { + source = rp->getSourcePosition(); + target = rp->getTargetPosition(); + + if (source == target) return; + if (source.getX() > target.getX()) std::swap( source, target ); + if (source.getY() > target.getY()) std::swap( source, target ); + + if (not getRoutingGauge()->isSymbolic()) { + size_t rpDepth = getLayerDepth( rp->getLayer() ); + Flags direction = getDirection ( rpDepth ); + DbU::Unit wwidth = getWireWidth ( rpDepth ) / 2; + cdebug_log(145,0) << "Not a symbolic gauge, shrink positions of " << DbU::getValueString(wwidth) << endl; + if (rpDepth == 0) return; + if (direction.contains(Flags::Horizontal)) { + cdebug_log(145,0) << "H shrink" << endl; + source.translate( wwidth, 0 ); + target.translate( -wwidth, 0 ); + } else { + cdebug_log(145,0) << "V shrink" << endl; + source.translate( 0, wwidth ); + target.translate( 0, -wwidth ); + } + } else { + cdebug_log(145,0) << "Symbolic gauge, no shrink" << endl; + } + } + + + void Configuration::checkRoutingPadSize ( RoutingPad* rp ) const + { + Point source; + Point target; + + size_t rpDepth = getLayerDepth( rp->getLayer() ); + if (rpDepth == 0) ++rpDepth; + else return; + + getPositions( rp, source, target ); + + DbU::Unit width = abs( target.getX() - source.getX() ); + DbU::Unit height = abs( target.getY() - source.getY() ); + + uint64_t flags = 0; + flags |= (width < 3*getPitch(rpDepth)) ? RoutingPad::HSmall : 0; + flags |= (height < 3*getPitch(rpDepth)) ? RoutingPad::VSmall : 0; + //flags |= ((width == 0) && (height == 0)) ? RoutingPad::Punctual : 0; + if ((flags & RoutingPad::HSmall) and (flags & RoutingPad::VSmall)) + flags |= RoutingPad::Punctual; + + rp->unsetFlags( RoutingPad::HSmall|RoutingPad::VSmall|RoutingPad::Punctual ); + rp->setFlags ( flags ); + cdebug_log(145,0) << "::checkRoutingPadSize(): pitch[" << rpDepth << "]:" + << DbU::getValueString(getPitch(rpDepth)) << " " + << ((flags & RoutingPad::HSmall ) ? "HSmall " : " ") + << ((flags & RoutingPad::VSmall ) ? "VSmall " : " ") + << ((flags & RoutingPad::Punctual) ? "Punctual " : " ") + << endl; + } void Configuration::print ( Cell* cell ) const diff --git a/anabatic/src/Constants.cpp b/anabatic/src/Constants.cpp index dc4c2beeb..9ced3e3f7 100644 --- a/anabatic/src/Constants.cpp +++ b/anabatic/src/Constants.cpp @@ -117,22 +117,26 @@ namespace Anabatic { const BaseFlags Flags::Superior = (1L << 22); const BaseFlags Flags::DoglegOnLeft = (1L << 23); const BaseFlags Flags::DoglegOnRight = (1L << 24); - const BaseFlags Flags::WithNeighbors = (1L << 25); - const BaseFlags Flags::NoCheckLayer = (1L << 26); - const BaseFlags Flags::HalfSlacken = (1L << 27); - const BaseFlags Flags::NoGCellShrink = (1L << 28); - const BaseFlags Flags::CParanoid = (1L << 29); - const BaseFlags Flags::CheckLowDensity = (1L << 30); - const BaseFlags Flags::CheckLowUpDensity = (1L << 31); - const BaseFlags Flags::NoUpdate = (1L << 32); - const BaseFlags Flags::NorthPath = (1L << 33); - const BaseFlags Flags::UseNonPref = (1L << 34); - const BaseFlags Flags::Force = (1L << 35); - const BaseFlags Flags::LayerCapOnly = (1L << 36); - const BaseFlags Flags::NoMinLength = (1L << 37); - const BaseFlags Flags::NoSegExt = (1L << 38); - const BaseFlags Flags::NullLength = (1L << 39); - const BaseFlags Flags::OnVSmall = (1L << 40); + const BaseFlags Flags::DoglegDown = (1L << 25); + const BaseFlags Flags::WithNeighbors = (1L << 26); + const BaseFlags Flags::NoCheckLayer = (1L << 27); + const BaseFlags Flags::NoCheckGCell = (1L << 28); + const BaseFlags Flags::HalfSlacken = (1L << 29); + const BaseFlags Flags::NoGCellShrink = (1L << 30); + const BaseFlags Flags::CParanoid = (1L << 31); + const BaseFlags Flags::CheckLowDensity = (1L << 32); + const BaseFlags Flags::CheckLowUpDensity = (1L << 33); + const BaseFlags Flags::NoUpdate = (1L << 34); + const BaseFlags Flags::NorthPath = (1L << 35); + const BaseFlags Flags::UseNonPref = (1L << 36); + const BaseFlags Flags::Force = (1L << 37); + const BaseFlags Flags::LayerCapOnly = (1L << 38); + const BaseFlags Flags::NoMinLength = (1L << 39); + const BaseFlags Flags::NoSegExt = (1L << 40); + const BaseFlags Flags::NullLength = (1L << 41); + const BaseFlags Flags::OnVSmall = (1L << 42); + const BaseFlags Flags::Unbreakable = (1L << 43); + const BaseFlags Flags::ForOffgrid = (1L << 44); Flags::~Flags () @@ -222,12 +226,13 @@ namespace Anabatic { // Class : "Anabatic::StyleFlags". - const BaseFlags StyleFlags::NoStyle = 0; - const BaseFlags StyleFlags::HV = (1L << 0); - const BaseFlags StyleFlags::VH = (1L << 1); - const BaseFlags StyleFlags::OTH = (1L << 2); - const BaseFlags StyleFlags::Channel = (1L << 3); - const BaseFlags StyleFlags::Hybrid = (1L << 4); + const BaseFlags StyleFlags::NoStyle = 0; + const BaseFlags StyleFlags::HV = (1L << 0); + const BaseFlags StyleFlags::VH = (1L << 1); + const BaseFlags StyleFlags::OTH = (1L << 2); + const BaseFlags StyleFlags::Channel = (1L << 3); + const BaseFlags StyleFlags::Hybrid = (1L << 4); + const BaseFlags StyleFlags::M1Offgrid = (1L << 5); StyleFlags::~StyleFlags () @@ -236,12 +241,13 @@ namespace Anabatic { StyleFlags StyleFlags::toFlag ( std::string textFlag ) { - if (textFlag == "HV") return HV; - if (textFlag == "VH") return VH; - if (textFlag == "OTH") return OTH; - if (textFlag == "Channel") return Channel; - if (textFlag == "Hybrid") return Hybrid; - if (textFlag == "NoStyle") return NoStyle; + if (textFlag == "HV") return HV; + if (textFlag == "VH") return VH; + if (textFlag == "OTH") return OTH; + if (textFlag == "Channel") return Channel; + if (textFlag == "Hybrid") return Hybrid; + if (textFlag == "NoStyle") return NoStyle; + if (textFlag == "M1Offgrid") return M1Offgrid; std::cerr << Error( "StyleFlags::toFlag(): Unknown flag value \"%s\"", textFlag.c_str() ) << std::endl; return NoStyle; } @@ -265,11 +271,12 @@ namespace Anabatic { { ostringstream s; - if (_flags & (uint64_t)HV) { s << (s.tellp() ? "|" : "") << "HV"; } - if (_flags & (uint64_t)VH) { s << (s.tellp() ? "|" : "") << "VH"; } - if (_flags & (uint64_t)OTH) { s << (s.tellp() ? "|" : "") << "OTH"; } - if (_flags & (uint64_t)Channel) { s << (s.tellp() ? "|" : "") << "Channel"; } - if (_flags & (uint64_t)Hybrid ) { s << (s.tellp() ? "|" : "") << "Hybrid"; } + if (_flags & (uint64_t)HV) { s << (s.tellp() ? "|" : "") << "HV"; } + if (_flags & (uint64_t)VH) { s << (s.tellp() ? "|" : "") << "VH"; } + if (_flags & (uint64_t)OTH) { s << (s.tellp() ? "|" : "") << "OTH"; } + if (_flags & (uint64_t)Channel) { s << (s.tellp() ? "|" : "") << "Channel"; } + if (_flags & (uint64_t)Hybrid ) { s << (s.tellp() ? "|" : "") << "Hybrid"; } + if (_flags & (uint64_t)M1Offgrid) { s << (s.tellp() ? "|" : "") << "M1Offgrid"; } s << " (0x" << hex << _flags << ")"; return s.str(); } diff --git a/anabatic/src/Dijkstra.cpp b/anabatic/src/Dijkstra.cpp index fda73355a..2ec28cd48 100644 --- a/anabatic/src/Dijkstra.cpp +++ b/anabatic/src/Dijkstra.cpp @@ -1563,11 +1563,13 @@ namespace Anabatic { uint32_t driverCount = 0; for ( auto rp : rps ) { - if (not _anabatic->getConfiguration()->selectRpComponent(rp)) - cerr << Warning( "Dijktra::load(): %s has no components on grid.", getString(rp).c_str() ) << endl; + if (not _anabatic->getConfiguration()->selectRpComponent(rp)) { + if (not _anabatic->getConfiguration()->isM1Offgrid()) + cerr << Warning( "Dijktra::load(): %s has no components on grid.", getString(rp).c_str() ) << endl; + } - cdebug_log(112,0) << "@ rp: " << rp << ", getCenter(): " << rp->getBoundingBox().getCenter() << endl; - Point center = rp->getBoundingBox().getCenter(); + cdebug_log(112,0) << "@ rp: " << rp << ", getUserCenter(): " << rp->getUserCenter() << endl; + Point center = rp->getUserCenter(); GCell* gcell = _anabatic->getGCellUnder( center ); Box bb = rp->getBoundingBox(); bool isDriver = false; diff --git a/anabatic/src/EdgeCapacity.cpp b/anabatic/src/EdgeCapacity.cpp index 84e944ddd..1d48a1906 100644 --- a/anabatic/src/EdgeCapacity.cpp +++ b/anabatic/src/EdgeCapacity.cpp @@ -54,14 +54,14 @@ namespace Anabatic { if (layerGauges[depth]->getDirection() != Constant::Horizontal) continue; _capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getYMin() , span.getVMax() - ab.getYMin() ); - //cdebug_log(110,0) << "Horizontal edge capacity:" << capacity << endl; + //cdebug_log(110,0) << "Horizontal edge capacity:" << _capacities[depth] << endl; } if (_flags & Flags::Vertical) { if (layerGauges[depth]->getDirection() != Constant::Vertical) continue; _capacities[depth] = layerGauges[depth]->getTrackNumber( span.getVMin() - ab.getXMin() , span.getVMax() - ab.getXMin() ); - //cdebug_log(110,0) << "Vertical edge capacity:" << capacity << endl; + //cdebug_log(110,0) << "Vertical edge capacity:" << _capacities[depth] << endl; } } } diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index beeedea02..f52039ddd 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -324,7 +324,7 @@ namespace Anabatic { _fragmentations[i] = 0.0; _globalsCount [i] = 0.0; - if (Session::getRoutingGauge()->getLayerGauge(i)->getType() == Constant::PinOnly) + if (not Session::getRoutingGauge()->getLayerGauge(i)->isUsable()) ++_pinDepth; } @@ -1349,7 +1349,7 @@ namespace Anabatic { for ( size_t depth=0 ; depth<_depth ; ++depth ) { RoutingLayerGauge* rlg = Session::getLayerGauge( depth ); - if (rlg->getType() & Constant::PinOnly) continue; + if (not rlg->isUsable()) continue; if (_densities[depth] >= 0.9) { if (depth+2 < _depth) { Edge* edge = (rlg->getDirection() == Constant::Vertical) ? getNorthEdge() @@ -1557,6 +1557,8 @@ namespace Anabatic { int contiguousNonSaturated = 0; for ( size_t i=0 ; i<_depth ; i++ ) { uLengths2[i] += _blockages[i]; + if (Session::getLayerGauge(i)->getType() & Constant::LocalOnly) + continue; if (Session::getLayerGauge(i)->getType() & Constant::PinOnly) continue; if (Session::getLayerGauge(i)->getType() & Constant::PowerSupply) @@ -1927,6 +1929,73 @@ namespace Anabatic { } + bool GCell::getHGCellsUnder ( vector& gcells + , GCell* gcell + , GCell* end + , DbU::Unit yprobe + ) + { + vector().swap( gcells ); + + cdebug_log(144,0) << "yprobe: " << DbU::getValueString(yprobe) << endl; + + bool success = true; + if (gcell->getXMin() > end->getXMin()) std::swap( gcell, end ); + if (yprobe == gcell->getConstraintYMax()) yprobe--; + + gcells.push_back( gcell ); + while ( gcell != end ) { + gcell = gcell->getEast( yprobe ); + if (not gcell) { + success = false; + cerr << Error( "GCell::getHGCellsUnder() : NULL GCell under\n" + " begin:%s\n" + " end: %s" + , getString(gcell).c_str() + , getString(end ).c_str() + ) << endl; + break; + } + gcells.push_back( gcell ); + } + return success; + } + + + bool GCell::getVGCellsUnder ( vector& gcells + , GCell* gcell + , GCell* end + , DbU::Unit xprobe + ) + { + vector().swap( gcells ); + + cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl; + + bool success = true; + if (gcell->getYMin() > end->getYMin()) std::swap( gcell, end ); + if (xprobe == gcell->getConstraintXMax()) xprobe--; + + gcells.push_back( gcell ); + while ( gcell != end ) { + gcell = gcell->getNorth( xprobe ); + + if (not gcell) { + success = false; + cerr << Error( "GCell::getVGCellsUnder() : NULL GCell under\n" + " begin:%s\n" + " end: %s" + , getString(gcell).c_str() + , getString(end ).c_str() + ) << endl; + break; + } + gcells.push_back( gcell ); + } + return success; + } + + // ------------------------------------------------------------------- // Class : "Anabatic::GCellDensitySet". diff --git a/anabatic/src/NetBuilder.cpp b/anabatic/src/NetBuilder.cpp index b9b858c25..1fcb5be86 100644 --- a/anabatic/src/NetBuilder.cpp +++ b/anabatic/src/NetBuilder.cpp @@ -228,73 +228,19 @@ namespace Anabatic { // Class : "NetBuilder". - void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target ) + uint64_t NetBuilder::checkRoutingPadSize ( RoutingPad* rp ) { - Segment* segment = dynamic_cast( anchor ); - if (segment) { - source = segment->getSourcePosition(); - target = segment->getTargetPosition(); - } else { - RoutingPad* rp = dynamic_cast( anchor ); - if (rp) { - source = rp->getSourcePosition(); - target = rp->getTargetPosition(); - } else { - source = anchor->getPosition(); - target = anchor->getPosition(); - return; - } - } - - if (source == target) return; - if (source.getX() > target.getX()) swap( source, target ); - if (source.getY() > target.getY()) swap( source, target ); - - if (not Session::getRoutingGauge()->isSymbolic()) { - size_t rpDepth = Session::getLayerDepth( anchor->getLayer() ); - Flags direction = Session::getDirection ( rpDepth ); - DbU::Unit wwidth = Session::getWireWidth (rpDepth) / 2; - cdebug_log(145,0) << "Not a symbolic gauge, shrink positions of " << DbU::getValueString(wwidth) << endl; - if (rpDepth == 0) return; - if (direction.contains(Flags::Horizontal)) { - cdebug_log(145,0) << "H shrink" << endl; - source.translate( wwidth, 0 ); - target.translate( -wwidth, 0 ); - } else { - cdebug_log(145,0) << "V shrink" << endl; - source.translate( 0, wwidth ); - target.translate( 0, -wwidth ); - } - } else { - cdebug_log(145,0) << "Symbolic gauge, no shrink" << endl; - } - } - - - uint64_t NetBuilder::checkRoutingPadSize ( Component* anchor ) - { - Point source; - Point target; - - size_t anchorDepth = Session::getLayerDepth( anchor->getLayer() ); - if (anchorDepth == 0) ++anchorDepth; - - NetBuilder::getPositions( anchor, source, target ); - - DbU::Unit width = abs( target.getX() - source.getX() ); - DbU::Unit height = abs( target.getY() - source.getY() ); - - uint64_t flags = 0; - flags |= (width < 3*Session::getPitch(anchorDepth)) ? NetBuilder::HSmall : 0; - flags |= (height < 3*Session::getPitch(anchorDepth)) ? NetBuilder::VSmall : 0; - flags |= ((width == 0) && (height == 0)) ? NetBuilder::Punctual : 0; - - cdebug_log(145,0) << "::checkRoutingPadSize(): pitch[" << anchorDepth << "]:" - << DbU::getValueString(Session::getPitch(anchorDepth)) << " " - << ((flags & NetBuilder::HSmall) ? "HSmall " : " ") - << ((flags & NetBuilder::VSmall) ? "VSmall " : " ") - << endl; - + uint32_t rpFlags = rp->getFlags(); + uint32_t flags = 0; + flags |= (rpFlags & RoutingPad::VSmall ) ? VSmall : 0; + flags |= (rpFlags & RoutingPad::HSmall ) ? HSmall : 0; + flags |= (rpFlags & RoutingPad::Punctual ) ? Punctual : 0; + flags |= (rpFlags & RoutingPad::M1Offgrid) ? M1Offgrid : 0; + cdebug_log(145,0) << "::checkRoutingPadSize(): " + << ((flags & NetBuilder::HSmall ) ? "HSmall " : " ") + << ((flags & NetBuilder::VSmall ) ? "VSmall " : " ") + << ((flags & NetBuilder::Punctual) ? "Punctual " : " ") + << rp << endl; return flags; } @@ -1045,7 +991,7 @@ namespace Anabatic { } - void NetBuilder::doRp_StairCaseH ( GCell* gcell, Component* rp1, Component* rp2 ) + void NetBuilder::doRp_StairCaseH ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 ) { cdebug_log(145,0) << "doRp_StairCaseH()" << endl; @@ -1079,7 +1025,7 @@ namespace Anabatic { } - void NetBuilder::doRp_StairCaseV ( GCell* gcell, Component* rp1, Component* rp2 ) + void NetBuilder::doRp_StairCaseV ( GCell* gcell, RoutingPad* rp1, RoutingPad* rp2 ) { cdebug_log(145,0) << "doRp_StairCaseV()" << endl; @@ -1250,7 +1196,10 @@ namespace Anabatic { bool NetBuilder::_do_1G_1M1_1PinM3 () { - throw Error ( "%s::_do_1G_1M1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() ); + throw Error ( "%s::_do_1G_1M1_1PinM3() method *not* reimplemented from base class.\n" + " On %s" + , getTypeName().c_str() + , getString(getNet()).c_str() ); return false; } @@ -1302,7 +1251,7 @@ namespace Anabatic { cdebug_log(145,1) << "NetBuilder::singleGCell() " << net << endl; vector rpM1s; - Component* rpM2 = NULL; + RoutingPad* rpM2 = NULL; for ( RoutingPad* rp : net->getRoutingPads() ) { if ( Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp index b81051310..a984c587e 100644 --- a/anabatic/src/NetBuilderHV.cpp +++ b/anabatic/src/NetBuilderHV.cpp @@ -72,7 +72,7 @@ namespace Anabatic { void NetBuilderHV::doRp_AutoContacts ( GCell* gcell - , Component* rp + , RoutingPad* rp , AutoContact*& source , AutoContact*& target , uint64_t flags @@ -97,7 +97,7 @@ namespace Anabatic { Flags direction = Session::getDirection ( rpDepth ); DbU::Unit viaSide = Session::getViaWidth ( rpDepth ); - getPositions( rp, sourcePosition, targetPosition ); + Session::getPositions( rp, sourcePosition, targetPosition ); GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition ); GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition ); @@ -242,9 +242,13 @@ namespace Anabatic { } - AutoContact* NetBuilderHV::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags ) + AutoContact* NetBuilderHV::doRp_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags ) { cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl; + if (rp->isM1Offgrid()) { + cdebug_tabw(145,-1); + return doRp_AccessOffgrid( gcell, rp, flags ); + } size_t rpDepth = Session::getLayerDepth( rp->getLayer() ); AutoContact* rpSourceContact = NULL; @@ -266,6 +270,7 @@ namespace Anabatic { cdebug_log(145,0) << "METAL3 override." << endl; contactLayer = Session::getRoutingLayer( 2 ); wireDepth = 2; + flags &= ~(Punctual|VSmall); } if (flags & HAccess) { @@ -361,6 +366,39 @@ namespace Anabatic { } + AutoContact* NetBuilderHV::doRp_AccessOffgrid ( GCell* gcell, RoutingPad* rp, uint64_t flags ) + { + cdebug_log(145,1) << getTypeName() << "::doRp_AccessOffgrid() - flags:" << flags << endl; + + size_t rpDepth = Session::getLayerDepth( rp->getLayer() ); + AutoContact* rpSourceContact = NULL; + AutoContact* rpContactTarget = NULL; + doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, flags ); + + AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildRoutingLayer(rpDepth+1) ); + AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|Flags::UseNonPref ); + rpSourceContact = subContact1; + + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildContactLayer(rpDepth+1) ); + AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal ); + rpSourceContact = subContact1; + + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildContactLayer(rpDepth+1) ); + AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical ); + rpSourceContact = subContact1; + + if (not (flags & HAccess)) { + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildContactLayer(rpDepth+1) ); + AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal ); + rpSourceContact = subContact1; + } + + cdebug_tabw(145,-1); + + return rpSourceContact; + } + + AutoContact* NetBuilderHV::doRp_AccessNorthSouthPin ( GCell* gcell, RoutingPad* rp ) { cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthSouthPin() " << rp << endl; @@ -471,7 +509,7 @@ namespace Anabatic { AutoSegment::create( leftContact, rightContact, Flags::Horizontal ); } - Component* globalRp = NULL; + RoutingPad* globalRp = NULL; if (east()) globalRp = getRoutingPads()[getRoutingPads().size()-1]; else if (west()) globalRp = getRoutingPads()[0]; else { @@ -1334,16 +1372,19 @@ namespace Anabatic { uint64_t flags = checkRoutingPadSize( getRoutingPads()[0] ); if (flags & VSmall) { - doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + //doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags ); contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 ); AutoSegment::create( contact1, contact2, Flags::Vertical ); setBothCornerContacts( contact2 ); } else { - doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + //doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess ); setSouthWestContact( contact1 ); - doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + //doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags ); + contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess ); setNorthEastContact( contact1 ); } } else { @@ -1366,8 +1407,11 @@ namespace Anabatic { setSouthWestContact( (east()) ? contact2 : contact3 ); setNorthEastContact( (east()) ? contact3 : contact2 ); } else { - AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags ); - AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ); + AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess ); + AutoContact* contact2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 ); + AutoSegment::create( contact1, contact2, Flags::Horizontal ); + contact1 = contact2; + contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ); AutoSegment::create( contact1, contact2, Flags::Vertical ); AutoContact* contact3 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ); AutoSegment::create( contact2, contact3, Flags::Vertical ); @@ -1397,8 +1441,8 @@ namespace Anabatic { { cdebug_log(145,1) << getTypeName() << "::_do_xG_1M1_1M2() [Managed Configuration]" << endl; - Component* rpL1; - Component* rpL2; + RoutingPad* rpL1; + RoutingPad* rpL2; if (getRoutingPads()[0]->getLayer() == Session::getBuildRoutingLayer(0)) { rpL1 = getRoutingPads()[0]; rpL2 = getRoutingPads()[1]; @@ -1471,7 +1515,7 @@ namespace Anabatic { cdebug_log(145,0) << "east: " << east() << endl; cdebug_log(145,0) << "west: " << west() << endl; - Component* rpM3 = NULL; + RoutingPad* rpM3 = NULL; if (getRoutingPads()[0]->getLayer() == Session::getBuildRoutingLayer(2)) rpM3 = getRoutingPads()[0]; @@ -1535,7 +1579,7 @@ namespace Anabatic { } // All RoutingPad are M1. - Component* southWestRp = getRoutingPads()[0]; + RoutingPad* southWestRp = getRoutingPads()[0]; cdebug_log(145,0) << "| Initial S-W Global RP: " << southWestRp << endl; // for ( size_t i=1 ; igetBoundingBox().getHeight() >= 4*Session::getPitch(1)) break; @@ -1557,7 +1601,7 @@ namespace Anabatic { AutoSegment::create( rpContact, getSouthWestContact(), Flags::Horizontal ); } - Component* northEastRp = getRoutingPads()[getRoutingPads().size()-1]; + RoutingPad* northEastRp = getRoutingPads()[getRoutingPads().size()-1]; cdebug_log(145,0) << "| Initial N-E Global RP: " << northEastRp << endl; if (getRoutingPads().size() > 1) { @@ -1593,7 +1637,7 @@ namespace Anabatic { { cdebug_log(145,1) << getTypeName() << "::_do_4G_1M2() [Managed Configuration]" << endl; - Component* rpL2 = getRoutingPads()[0]; + RoutingPad* rpL2 = getRoutingPads()[0]; cdebug_log(145,0) << "rpL2 := " << rpL2 << endl; AutoContact* rpL2ContactSource = NULL; @@ -1620,7 +1664,7 @@ namespace Anabatic { << (int)getConnexity().fields.globals << "G_" << (int)getConnexity().fields.M2 << "M2() [Managed Configuration - x]" << endl; - Component* biggestRp = getRoutingPads()[0]; + RoutingPad* biggestRp = getRoutingPads()[0]; for ( size_t i=1 ; igetBoundingBox().getWidth() > biggestRp->getBoundingBox().getWidth()) @@ -1768,7 +1812,7 @@ namespace Anabatic { } AutoContact* unusedContact = NULL; - Component* rp = getRoutingPads()[0]; + RoutingPad* rp = getRoutingPads()[0]; if (west() and not south()) { setSouthWestContact( doRp_Access( getGCell(), rp, HAccess ) ); @@ -1921,11 +1965,33 @@ namespace Anabatic { Segment* baseSegment = static_cast( getFromHook()->getComponent() ); if ( (getSourceFlags() | getFlags()) & ToUpperRouting) { cdebug_log(145,0) << "Moving up global" << endl; + vector gcells; size_t gdepth = Session::getGHorizontalDepth(); - if (dynamic_cast(baseSegment)) + if (dynamic_cast(baseSegment)) { gdepth = Session::getGVerticalDepth(); - baseSegment->setLayer( Session::getBuildRoutingLayer( gdepth+2 )); - baseSegment->setWidth( Session::getWireWidth( gdepth+2 )); + GCell::getVGCellsUnder( gcells + , getSourceContact()->getGCell() + , targetContact->getGCell() + , baseSegment->getX() ); + } else { + GCell::getHGCellsUnder( gcells + , getSourceContact()->getGCell() + , targetContact->getGCell() + , baseSegment->getY() ); + } + bool canMoveUp = true; + for ( GCell* gcell : gcells ) { + if (not gcell->hasFreeTrack(gdepth+2,2.0)) { + canMoveUp = false; + break; + } + } + if (canMoveUp) { + baseSegment->setLayer( Session::getBuildRoutingLayer( gdepth+2 )); + baseSegment->setWidth( Session::getWireWidth( gdepth+2 )); + } else { + cdebug_log(145,0) << "-> Cancel move up, not enough up free track" << endl; + } } AutoSegment* globalSegment = AutoSegment::create( getSourceContact() @@ -1964,7 +2030,7 @@ namespace Anabatic { cdebug_log(145,1) << "NetBuilderHV::singleGCell() " << net << endl; vector rpM1s; - Component* rpM2 = NULL; + RoutingPad* rpM2 = NULL; RoutingPad* rpPin = NULL; for ( RoutingPad* rp : net->getRoutingPads() ) { @@ -2018,28 +2084,24 @@ namespace Anabatic { AutoContact* target = NULL; for ( size_t irp=1 ; irpgetUConstraints(Flags::Vertical).intersect(target->getUConstraints(Flags::Vertical))) { uint64_t flags = checkRoutingPadSize( rpM1s[irp-1] ); - if ((flags & VSmall) or Session::getConfiguration()->isVH()) { - if (Session::getConfiguration()->isHV()) { - turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); - AutoSegment::create( source, turn1, Flags::Horizontal ); - source = turn1; - } + if (flags & VSmall) { + turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); + AutoSegment::create( source, turn1, Flags::Horizontal ); + source = turn1; turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); AutoSegment::create( source, turn1 , Flags::Vertical ); source = turn1; } flags = checkRoutingPadSize( rpM1s[irp] ); - if ((flags & VSmall) or Session::getConfiguration()->isVH()) { - if (Session::getConfiguration()->isHV()) { - turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); - AutoSegment::create( target, turn1, Flags::Horizontal ); - target = turn1; - } + if (flags & VSmall) { + turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); + AutoSegment::create( target, turn1, Flags::Horizontal ); + target = turn1; turn1 = AutoContactTurn::create( gcell1, rpM1s[irp]->getNet(), Session::getDContactLayer() ); AutoSegment::create( target, turn1 , Flags::Vertical ); target = turn1; @@ -2055,8 +2117,8 @@ namespace Anabatic { } if (rpM2) { - doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact ); - doRp_AutoContacts( gcell1, rpM2 , target, turn1, DoSourceContact ); + source = doRp_Access( gcell1, rpM1s[0], HAccess ); + target = doRp_Access( gcell1, rpM2 , HAccess ); turn1 = AutoContactTurn::create( gcell1, rpM2->getNet(), Session::getBuildContactLayer(1) ); AutoSegment::create( source, turn1 , Flags::Horizontal ); AutoSegment::create( turn1 , target, Flags::Vertical ); @@ -2068,7 +2130,7 @@ namespace Anabatic { if ( (pinDir == Pin::AccessDirection::NORTH) or (pinDir == Pin::AccessDirection::SOUTH) ) { - doRp_AutoContacts( gcell1, rpM1s[0], source, turn1, DoSourceContact ); + source = doRp_Access( gcell1, rpM1s[0], HAccess ); target = doRp_AccessNorthSouthPin( gcell1, rpPin ); turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getBuildContactLayer(1) ); AutoSegment::create( source, turn1 , Flags::Horizontal ); @@ -2079,7 +2141,7 @@ namespace Anabatic { if (pinDir == Pin::AccessDirection::EAST) closest = rpM1s.back(); else closest = rpM1s.front(); - doRp_AutoContacts( gcell1, closest, source, turn1, DoSourceContact ); + source = doRp_Access( gcell1, closest, HAccess ); target = doRp_AccessEastWestPin( gcell1, rpPin ); AutoSegment::create( source, target , Flags::Horizontal ); } diff --git a/anabatic/src/NetBuilderHybridVH.cpp b/anabatic/src/NetBuilderHybridVH.cpp index 5b7b85b46..fff63f2f8 100644 --- a/anabatic/src/NetBuilderHybridVH.cpp +++ b/anabatic/src/NetBuilderHybridVH.cpp @@ -70,7 +70,7 @@ namespace Anabatic { void NetBuilderHybridVH::doRp_AutoContacts ( GCell* gcell - , Component* rp + , RoutingPad* rp , AutoContact*& source , AutoContact*& target , uint64_t flags @@ -80,7 +80,7 @@ namespace Anabatic { } - AutoContact* NetBuilderHybridVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags ) + AutoContact* NetBuilderHybridVH::doRp_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags ) { cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl; cdebug_log(145,0) << rp << endl; diff --git a/anabatic/src/NetBuilderM2.cpp b/anabatic/src/NetBuilderM2.cpp index c3de1875d..e4cb73549 100644 --- a/anabatic/src/NetBuilderM2.cpp +++ b/anabatic/src/NetBuilderM2.cpp @@ -67,7 +67,7 @@ namespace Anabatic { void NetBuilderM2::doRp_AutoContacts ( GCell* gcell - , Component* rp + , RoutingPad* rp , AutoContact*& source , AutoContact*& target , uint64_t flags @@ -85,7 +85,7 @@ namespace Anabatic { Flags direction = Session::getDirection ( rpDepth ); DbU::Unit viaSide = Session::getViaWidth ( rpDepth ); - getPositions( rp, sourcePosition, targetPosition ); + Session::getPositions( rp, sourcePosition, targetPosition ); if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition ); if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition ); @@ -156,7 +156,7 @@ namespace Anabatic { } - AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags ) + AutoContact* NetBuilderM2::doRp_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags ) { cdebug_log(145,1) << getTypeName() << "::doRp_Access()" << endl; cdebug_log(145,0) << rp << endl; @@ -168,7 +168,7 @@ namespace Anabatic { DbU::Unit viaSide = Session::getDContactWidth(); DbU::Unit ypitch = Session::getDVerticalPitch(); - getPositions( rp, sourcePosition, targetPosition ); + Session::getPositions( rp, sourcePosition, targetPosition ); if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition ); if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition ); diff --git a/anabatic/src/NetBuilderVH.cpp b/anabatic/src/NetBuilderVH.cpp index c92063465..29ae2019b 100644 --- a/anabatic/src/NetBuilderVH.cpp +++ b/anabatic/src/NetBuilderVH.cpp @@ -57,6 +57,7 @@ namespace Anabatic { using Hurricane::Warning; using Hurricane::Error; using Hurricane::Pin; + using Constant::LayerGaugeType; NetBuilderVH::NetBuilderVH () @@ -72,7 +73,7 @@ namespace Anabatic { void NetBuilderVH::doRp_AutoContacts ( GCell* gcell - , Component* rp + , RoutingPad* rp , AutoContact*& source , AutoContact*& target , uint64_t flags @@ -90,7 +91,7 @@ namespace Anabatic { Flags direction = Session::getDirection ( rpDepth ); DbU::Unit viaSide = Session::getViaWidth ( rpDepth ); - getPositions( rp, sourcePosition, targetPosition ); + Session::getPositions( rp, sourcePosition, targetPosition ); if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition ); if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition ); @@ -178,47 +179,75 @@ namespace Anabatic { } - AutoContact* NetBuilderVH::doRp_Access ( GCell* gcell, Component* rp, uint64_t flags ) + AutoContact* NetBuilderVH::doRp_Access ( GCell* gcell, RoutingPad* rp, uint64_t flags ) { cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl; - AutoContact* rpContactSource = NULL; - AutoContact* rpContactTarget = NULL; - const Layer* rpLayer = rp->getLayer(); - size_t rpDepth = Session::getLayerDepth( rp->getLayer() ); + AutoSegment* segment = nullptr; + AutoContact* rpContactSource = nullptr; + AutoContact* rpContactTarget = nullptr; + const Layer* rpLayer = rp->getLayer(); + size_t rpDepth = Session::getLayerDepth( rpLayer ); + RoutingLayerGauge* rlg = Session::getLayerGauge( rpLayer ); + uint64_t offgridFlag = 0; flags |= checkRoutingPadSize( rp ); - doRp_AutoContacts( gcell, rp, rpContactSource, rpContactTarget, flags ); + const Layer* viaLayer1 = Session::getBuildContactLayer( 1 ); + + if (rp->isM1Offgrid() /*or (flags & HSmall)*/) { + AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildRoutingLayer(rpDepth+1) ); + Flags segFlags = Flags::NoFlags; + size_t segDepth = 1; + offgridFlag |= AutoSegment::SegForOffgrid; + if (rlg->getType() == LayerGaugeType::LocalOnly) { + segDepth = 0; + if (flags & VSmall) { + segment = AutoSegment::create( rpContactSource + , subContact1 + , segFlags|Flags::Vertical|Flags::UseNonPref + , segDepth ); + rpContactSource = subContact1; + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getBuildRoutingLayer(rpDepth+1) ); + segFlags |= Flags::Unbreakable; + } + } + AutoSegment::create( rpContactSource, subContact1, segFlags|Flags::Horizontal, segDepth ); + rpContactSource = subContact1; + } - if (rpDepth % 2 == 0) { // RP should be vertical (M1, M3). + cdebug_log(145,0) << "rpDepth=" << rpDepth << endl; + if (rpDepth % 2 == 0) { // RP should be horizontal (M1, M3). if (not (flags & (HAccess|HAccessEW))) { - AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); - AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); - AutoSegment::create( rpContactSource, subContact1, Flags::Vertical , rpDepth+2 ); - AutoSegment::create( subContact1, subContact2, Flags::Horizontal, rpDepth+1 ); + cdebug_log(145,0) << "case not(HAccess|HAccessEW)" << endl; + AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), viaLayer1 ); + AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), viaLayer1 ); + AutoSegment::create( rpContactSource, subContact1, Flags::Vertical )->setFlags( offgridFlag ); + AutoSegment::create( subContact1, subContact2, Flags::Horizontal); rpContactSource = subContact2; } else { if (flags & VSmall) { + cdebug_log(145,0) << "case VSmall" << endl; AutoContact* subContact1 = NULL; if (flags & HAccessEW) - subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); + subContact1 = AutoContactHTee::create( gcell, rp->getNet(), viaLayer1 ); else - subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), viaLayer1 ); - AutoSegment::create( rpContactSource, subContact1, Flags::Vertical ); + AutoSegment::create( rpContactSource, subContact1, Flags::Vertical )->setFlags( offgridFlag ); rpContactSource = subContact1; } } - } else { // RP should be horizontal (M2). + } else { // RP should be vertical (M2). if (flags & (HAccess|HAccessEW)) { + cdebug_log(145,0) << "case HAccess|HAccessEW" << endl; AutoContact* subContact1 = NULL; if (flags & HAccessEW) - subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); + subContact1 = AutoContactHTee::create( gcell, rp->getNet(), viaLayer1 ); else - subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(rpDepth+1) ); + subContact1 = AutoContactTurn::create( gcell, rp->getNet(), viaLayer1 ); - AutoSegment::create( rpContactSource, subContact1, Flags::Vertical, rpDepth+1 ); + AutoSegment::create( rpContactSource, subContact1, Flags::Vertical ); rpContactSource = subContact1; } } @@ -229,6 +258,80 @@ namespace Anabatic { } + AutoContact* NetBuilderVH::doRp_AccessNorthSouthPin ( GCell* gcell, RoutingPad* rp ) + { + cdebug_log(145,1) << getTypeName() << "::doRp_AccessNorthSouthPin() " << rp << endl; + + AutoContact* rpSourceContact = NULL; + AutoContact* rpContactTarget = NULL; + AutoContact* turn = NULL; + + doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect ); + + Net* net = rp->getNet(); + Pin* pin = dynamic_cast( rp->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + if (pinDir == Pin::AccessDirection::NORTH) { + turn = AutoContactTurn::create( gcell, net, Session::getBuildRoutingLayer(1) ); + AutoSegment* segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical ); + segment->setAxis( rp->getX(), Flags::Force ); + segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + rpSourceContact = turn; + + turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(1) ); + segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + + DbU::Unit axis = gcell->getYMax() - Session::getDHorizontalPitch(); + cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl; + + segment->setAxis( axis, Flags::Force ); + //segment->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + cdebug_log(145,0) << segment << endl; + } else { + turn = rpSourceContact; + } + + cdebug_tabw(145,-1); + return turn; + } + + + AutoContact* NetBuilderVH::doRp_AccessEastWestPin ( GCell* gcell, RoutingPad* rp ) + { + cdebug_log(145,1) << getTypeName() << "::doRp_AccessEastWestPin() " << rp << endl; + + Net* net = rp->getNet(); + Pin* pin = dynamic_cast( rp->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + AutoContact* rpSourceContact = NULL; + AutoContact* rpContactTarget = NULL; + AutoContact* turn = NULL; + AutoSegment* segment = NULL; + + doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, NoProtect ); + + turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(1) ); + segment = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + segment->setAxis( pin->getCenter().getY(), Flags::Force ); + + rpSourceContact = turn; + turn = AutoContactTurn::create( gcell, net, Session::getBuildContactLayer(1) ); + segment = AutoSegment::create( rpSourceContact, turn, Flags::Vertical ); + + DbU::Unit axis = 0; + if (pinDir == Pin::AccessDirection::EAST) + axis = gcell->getXMax() - Session::getDVerticalPitch(); + else + axis = gcell->getXMin() + Session::getDVerticalPitch(); + segment->setAxis( axis ); + + cdebug_tabw(145,-1); + return turn; + } + + + bool NetBuilderVH::_do_1G_1PinM2 () { cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl; @@ -401,21 +504,23 @@ namespace Anabatic { cdebug_log(145,0) << "east: " << east() << endl; cdebug_log(145,0) << "west: " << west() << endl; - AutoContact* tee = NULL; - if (east() and west()) { - tee = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall ); + AutoContact* tee = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall ); + setBothCornerContacts( tee ); + } else if (north() and south()) { + AutoContact* tee = doRp_Access( getGCell(), getRoutingPads()[0], HAccessEW|VSmall ); + AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ); + AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getDContactLayer() ); + AutoSegment::create( turn1, tee, Flags::Horizontal ); + AutoSegment::create( turn2, tee, Flags::Horizontal ); + setSouthWestContact( turn1 ); + setNorthEastContact( turn2 ); } else { AutoContact* turn = doRp_Access( getGCell(), getRoutingPads()[0], HAccess|VSmall ); - - if (east() or west()) - tee = AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ); - else - tee = AutoContactVTee::create( getGCell(), getNet(), Session::getDContactLayer() ); - + AutoContact* tee = AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ); AutoSegment::create( turn, tee, Flags::Horizontal ); + setBothCornerContacts( tee ); } - setBothCornerContacts( tee ); cdebug_tabw(145,-1); return true; @@ -494,6 +599,65 @@ namespace Anabatic { return true; } + bool NetBuilderVH::_do_1G_1M1_1PinM3 () + { + cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1_1PinM3() [Delegated] " << getTopology() << endl; + bool rvalue = false; + rvalue = NetBuilderVH::_do_1G_xM1_1PinM3 (); + cdebug_tabw(145,-1); + return rvalue; + } + + + bool NetBuilderVH::_do_1G_xM1_1PinM3 () + { + cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl; + + sortRpByX( getRoutingPads(), NoFlags ); // increasing X. + + vector rpsM1; + RoutingPad* pinM3 = NULL; + for ( RoutingPad* rp : getRoutingPads() ) { + if (dynamic_cast(rp->getOccurrence().getEntity())) pinM3 = rp; + else rpsM1.push_back( rp ); + } + + for ( size_t i=1 ; i rps; + vector rpM1s; + RoutingPad* rpPin = NULL; for ( RoutingPad* rp : net->getRoutingPads() ) { + if (dynamic_cast(rp->getOccurrence().getEntity())) { + rpPin = rp; + continue; + } if (Session::getRoutingGauge()->getLayerDepth(rp->getLayer()) == 0) { - rps.push_back( rp ); + rpM1s.push_back( rp ); continue; } cerr << Error( "%s::singleGCell(): Non metal1 terminals are not managed yet.\n" @@ -591,16 +760,17 @@ namespace Anabatic { return; } - if (rps.size() < 2) { - cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d)." + if (rpM1s.size() + ((rpPin)?1:0) < 2) { + cerr << Error( "%s::singleGCell(): For %s, less than two Plugs/Pins (%d+%d)." , getTypeName().c_str() , getString(net).c_str() - , rps.size() ) << endl; + , rpM1s.size() + , (rpPin?1:0) ) << endl; cdebug_tabw(145,-1); return; } - if (rps.empty()) { + if (rpM1s.empty()) { cerr << Error( "%s::singleGCell(): No terminals for Net \"%s\"." , getTypeName().c_str() , getString(net->getName()).c_str() ) << endl; @@ -608,22 +778,22 @@ namespace Anabatic { return; } - sortRpByX( rps, NetBuilder::NoFlags ); // increasing X. + sortRpByX( rpM1s, NetBuilder::NoFlags ); // increasing X. - GCell* gcell1 = anbt->getGCellUnder( (*rps.begin ())->getCenter() ); - GCell* gcell2 = anbt->getGCellUnder( (*rps.rbegin())->getCenter() ); + GCell* gcell1 = anbt->getGCellUnder( (*rpM1s.begin ())->getCenter() ); + GCell* gcell2 = anbt->getGCellUnder( (*rpM1s.rbegin())->getCenter() ); if (not gcell1) { cerr << Error( "%s::singleGCell(): No GCell under %s." , getTypeName().c_str() - , getString(*(rps.begin())).c_str() ) << endl; + , getString(*(rpM1s.begin())).c_str() ) << endl; cdebug_tabw(145,-1); return; } if (gcell1 != gcell2) { cerr << Error( "%s::singleGCell(): Not under a single GCell %s." , getTypeName().c_str() - , getString(*(rps.rbegin())).c_str() ) << endl; + , getString(*(rpM1s.rbegin())).c_str() ) << endl; cdebug_tabw(145,-1); return; } @@ -633,12 +803,35 @@ namespace Anabatic { AutoContact* source = NULL; AutoContact* target = NULL; - for ( size_t irp=1 ; irp( rpPin->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + + if ( (pinDir == Pin::AccessDirection::NORTH) + or (pinDir == Pin::AccessDirection::SOUTH) ) { + source = doRp_Access( gcell1, rpM1s[0], HAccess ); + target = doRp_AccessNorthSouthPin( gcell1, rpPin ); + AutoContact* turn1 = AutoContactTurn::create( gcell1, rpPin->getNet(), Session::getBuildContactLayer(1) ); + AutoSegment::create( source, turn1 , Flags::Horizontal ); + AutoSegment::create( turn1 , target, Flags::Vertical ); + } else { + RoutingPad* closest = NULL; + + if (pinDir == Pin::AccessDirection::EAST) closest = rpM1s.back(); + else closest = rpM1s.front(); + + source = doRp_Access( gcell1, closest, HAccess ); + target = doRp_AccessEastWestPin( gcell1, rpPin ); + AutoSegment::create( source, target, Flags::Horizontal ); + } + } + cdebug_tabw(145,-1); } diff --git a/anabatic/src/NetConstraints.cpp b/anabatic/src/NetConstraints.cpp index f78fbf2bf..839bb272e 100644 --- a/anabatic/src/NetConstraints.cpp +++ b/anabatic/src/NetConstraints.cpp @@ -62,6 +62,8 @@ namespace { void propagateConstraintFromRp ( RoutingPad* rp ) { cdebug_log(146,1) << "propagateConstraintFromRp() - " << rp << endl; + RoutingLayerGauge* rlg = Session::getLayerGauge( rp->getLayer() ); + bool allowOffgrid = (rlg->getType() == Constant::LocalOnly); for ( Component* component : rp->getSlaveComponents() ) { cdebug_log(146,0) << "slave component: " << component << endl; @@ -74,19 +76,25 @@ namespace { set verticalSegments; set horizontalSegments; + set offgridSegments; for ( AutoSegment* segment : sourceContact->getAutoSegments() ) { cdebug_log(146,0) << "Examining: " << segment << endl; - AutoContact* targetContact = segment->getOppositeAnchor(sourceContact); + AutoContact* targetContact = segment->getOppositeAnchor( sourceContact ); if (targetContact) { + if (allowOffgrid and (segment->getLayer() == rp->getLayer()) and segment->isNonPref()) { + cdebug_log(146,0) << "On offgrid stack " << segment << endl; + offgridSegments.insert( segment ); + continue; + } if (segment->isHorizontal()) { cdebug_log(146,0) << "On horizontal stack " << segment << endl; horizontalSegments.insert( segment ); - } else { - cdebug_log(146,0) << "On vertical stack " << segment << endl; - verticalSegments.insert( segment ); + continue; } + cdebug_log(146,0) << "On vertical stack " << segment << endl; + verticalSegments.insert( segment ); } } @@ -94,7 +102,7 @@ namespace { cdebug_log(146,0) << "Propagate constraint on horizontal segments" << endl; for ( AutoSegment* horizontal : horizontalSegments ) { - AutoContact* contact = NULL; + AutoContact* contact = nullptr; for ( AutoSegment* aligned : horizontal->getAligneds(Flags::WithSelf) ) { cdebug_log(146,0) << "aligned horizontal: " << aligned << endl; @@ -121,7 +129,7 @@ namespace { cdebug_log(146,0) << "Propagate constraint on vertical segments" << endl; for ( AutoSegment* vertical : verticalSegments ) { - AutoContact* contact = NULL; + AutoContact* contact = nullptr; for ( AutoSegment* aligned : vertical->getAligneds(Flags::WithSelf) ) { cdebug_log(146,0) << "aligned vertical: " << aligned << endl; @@ -141,6 +149,33 @@ namespace { } } } + + // Special case of offgrid segments (usually local M1). + cdebug_log(146,0) << "Propagate constraint on offgrid segments" << endl; + + for ( AutoSegment* perpandicular : offgridSegments ) { + AutoContact* targetContact = perpandicular->getOppositeAnchor( sourceContact ); + Box nonPrefConstraint = constraintBox; + Box ongridConstraint = constraintBox; + if (rlg->isHorizontal()) { + nonPrefConstraint.inflate( 0, rlg->getPitch(), 0, rlg->getPitch() ); + } else { + nonPrefConstraint.inflate( rlg->getPitch(), 0, rlg->getPitch(), 0 ); + } + ongridConstraint.inflate( rlg->getPitch() ); + + cdebug_log(146,0) << "perpandicular offgrid: " << perpandicular << endl; + targetContact->setConstraintBox( nonPrefConstraint ); + cdebug_log(146,0) << "Apply to first turn: " << targetContact << endl; + if (not targetContact->isTurn()) continue; + + AutoSegment* parallel = targetContact->getPerpandicular( perpandicular ); + cdebug_log(146,0) << "parallel offgrid: " << parallel << endl; + targetContact = parallel->getOppositeAnchor( targetContact ); + if (not targetContact) continue; + targetContact->setConstraintBox( ongridConstraint ); + cdebug_log(146,0) << "Apply to second turn: " << targetContact << endl; + } } } diff --git a/anabatic/src/PyStyleFlags.cpp b/anabatic/src/PyStyleFlags.cpp index 1a911ccc8..73105d252 100644 --- a/anabatic/src/PyStyleFlags.cpp +++ b/anabatic/src/PyStyleFlags.cpp @@ -86,12 +86,13 @@ extern "C" { extern void PyStyleFlags_postModuleInit () { PyObject* constant = NULL; - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::NoStyle, "NoStyle" ); - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::HV , "HV" ); - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::VH , "VH" ); - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::OTH , "OTH" ); - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Channel, "Channel" ); - LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Hybrid , "Hybrid" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::NoStyle , "NoStyle" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::HV , "HV" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::VH , "VH" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::OTH , "OTH" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Channel , "Channel" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::Hybrid , "Hybrid" ); + LoadObjectConstant( PyTypeStyleFlags.tp_dict, (uint64_t)StyleFlags::M1Offgrid, "M1Offgrid" ); } @@ -111,7 +112,8 @@ extern "C" { or (value == (uint64_t)StyleFlags::VH) or (value == (uint64_t)StyleFlags::OTH) or (value == (uint64_t)StyleFlags::Channel) - or (value == (uint64_t)StyleFlags::Hybrid)) + or (value == (uint64_t)StyleFlags::Hybrid) + or (value == (uint64_t)StyleFlags::M1Offgrid)) return value; return StyleFlags::NoStyle; } diff --git a/anabatic/src/anabatic/AutoContact.h b/anabatic/src/anabatic/AutoContact.h index 175feb712..62a9bee69 100644 --- a/anabatic/src/anabatic/AutoContact.h +++ b/anabatic/src/anabatic/AutoContact.h @@ -73,6 +73,7 @@ namespace Anabatic { , CntDrag = (1 << 16) , CntHDogleg = (1 << 17) , CntVDogleg = (1 << 18) + , CntMetalOnly = (1 << 19) }; class AutoContact { @@ -123,6 +124,7 @@ namespace Anabatic { inline bool isUserNativeConstraints () const; inline bool isHDogleg () const; inline bool isVDogleg () const; + inline bool isMetalOnly () const; virtual bool isOnPin () const; inline bool hasBadTopology () const; bool canDestroy ( Flags flags=Flags::NoFlags ) const; @@ -267,6 +269,7 @@ namespace Anabatic { inline bool AutoContact::isVTee () const { return _flags&CntVTee; } inline bool AutoContact::isHDogleg () const { return _flags&CntHDogleg; } inline bool AutoContact::isVDogleg () const { return _flags&CntVDogleg; } + inline bool AutoContact::isMetalOnly () const { return _flags&CntMetalOnly; } inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; } inline bool AutoContact::canDrag () const { return _flags&CntDrag; } inline size_t AutoContact::getId () const { return _id; } diff --git a/anabatic/src/anabatic/AutoSegment.h b/anabatic/src/anabatic/AutoSegment.h index 894041606..bdb11cea5 100644 --- a/anabatic/src/anabatic/AutoSegment.h +++ b/anabatic/src/anabatic/AutoSegment.h @@ -110,6 +110,7 @@ namespace Anabatic { static const uint64_t SegAtMinArea = (1L<<38); static const uint64_t SegNoMoveUp = (1L<<39); static const uint64_t SegOnVSmall = (1L<<40); + static const uint64_t SegForOffgrid = (1L<<41); // Masks. static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2; static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned; @@ -204,6 +205,7 @@ namespace Anabatic { inline bool isUnbreakable () const; inline bool isNonPref () const; inline bool isNonPrefOnVSmall () const; + inline bool isForOffgrid () const; inline bool isDrag () const; inline bool isAtMinArea () const; inline bool isNotSourceAligned () const; @@ -539,6 +541,7 @@ namespace Anabatic { inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; } inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; } inline bool AutoSegment::isNonPrefOnVSmall () const { return (_flags & SegNonPref) and (_flags & SegOnVSmall); } + inline bool AutoSegment::isForOffgrid () const { return _flags & SegForOffgrid; } inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; } inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); } inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); } diff --git a/anabatic/src/anabatic/Configuration.h b/anabatic/src/anabatic/Configuration.h index 33e278d6e..bd29c05db 100644 --- a/anabatic/src/anabatic/Configuration.h +++ b/anabatic/src/anabatic/Configuration.h @@ -42,6 +42,7 @@ namespace Anabatic { using Hurricane::Name; using Hurricane::Layer; using Hurricane::DbU; + using Hurricane::Point; using Hurricane::RoutingPad; using Hurricane::Cell; using CRL::CellGauge; @@ -62,13 +63,17 @@ namespace Anabatic { virtual ~Configuration (); virtual Configuration* clone () const; // Methods. - inline bool isGLayer ( const Layer* ) const; - bool isGMetal ( const Layer* ) const; - bool isGContact ( const Layer* ) const; + bool isSymbolic () const; bool isTwoMetals () const; bool isHybrid () const; + bool isM1Offgrid () const; bool isHV () const; bool isVH () const; + inline bool isGLayer ( const Layer* ) const; + bool isGMetal ( const Layer* ) const; + bool isGContact ( const Layer* ) const; + bool isUsable ( size_t depth ) const; + size_t getFirstRoutingLayer () const; inline std::string getNetBuilderStyle () const; inline StyleFlags getRoutingStyle () const; const Layer* getGContactLayer () const; @@ -104,7 +109,7 @@ namespace Anabatic { Layer* getContactLayer ( size_t depth ) const; DbU::Unit getSliceHeight () const; DbU::Unit getSliceStep () const; - DbU::Unit getPitch ( size_t depth, Flags flags ) const; + DbU::Unit getPitch ( size_t depth, Flags flags=Flags::NoFlags ) const; DbU::Unit getOffset ( size_t depth ) const; DbU::Unit getWireWidth ( size_t depth ) const; DbU::Unit getPWireWidth ( size_t depth ) const; @@ -134,6 +139,8 @@ namespace Anabatic { float getEdgeHScaling () const; int getGlobalIterations () const; DbU::Unit isOnRoutingGrid ( RoutingPad* ) const; + void getPositions ( RoutingPad* , Point& source, Point& target ) const; + void checkRoutingPadSize ( RoutingPad* ) const; bool selectRpComponent ( RoutingPad* ) const; inline void setRoutingStyle ( StyleFlags ); inline void resetRoutingStyle ( StyleFlags ); diff --git a/anabatic/src/anabatic/Constants.h b/anabatic/src/anabatic/Constants.h index 92e975644..d5040d1ef 100644 --- a/anabatic/src/anabatic/Constants.h +++ b/anabatic/src/anabatic/Constants.h @@ -95,8 +95,10 @@ namespace Anabatic { static const BaseFlags Superior ; static const BaseFlags DoglegOnLeft ; static const BaseFlags DoglegOnRight ; + static const BaseFlags DoglegDown ; static const BaseFlags WithNeighbors ; static const BaseFlags NoCheckLayer ; + static const BaseFlags NoCheckGCell ; static const BaseFlags HalfSlacken ; static const BaseFlags NoGCellShrink ; static const BaseFlags CParanoid ; @@ -111,6 +113,8 @@ namespace Anabatic { static const BaseFlags NoSegExt ; static const BaseFlags NullLength ; static const BaseFlags OnVSmall ; + static const BaseFlags Unbreakable ; + static const BaseFlags ForOffgrid ; public: inline Flags ( uint64_t flags = NoFlags ); inline Flags ( const Hurricane::BaseFlags& ); @@ -130,12 +134,13 @@ namespace Anabatic { class StyleFlags : public Hurricane::BaseFlags { public: - static const BaseFlags NoStyle; // = 0; - static const BaseFlags HV ; // = (1 << 0); - static const BaseFlags VH ; // = (1 << 1); - static const BaseFlags OTH ; // = (1 << 2); - static const BaseFlags Channel; // = (1 << 3); - static const BaseFlags Hybrid ; // = (1 << 4); + static const BaseFlags NoStyle ; // = 0; + static const BaseFlags HV ; // = (1 << 0); + static const BaseFlags VH ; // = (1 << 1); + static const BaseFlags OTH ; // = (1 << 2); + static const BaseFlags Channel ; // = (1 << 3); + static const BaseFlags Hybrid ; // = (1 << 4); + static const BaseFlags M1Offgrid; // = (1 << 5); public: inline StyleFlags ( std::string ); inline StyleFlags ( uint64_t flags = NoStyle ); diff --git a/anabatic/src/anabatic/GCell.h b/anabatic/src/anabatic/GCell.h index d181161ec..13120e540 100644 --- a/anabatic/src/anabatic/GCell.h +++ b/anabatic/src/anabatic/GCell.h @@ -137,6 +137,14 @@ namespace Anabatic { static Box getBorder ( const GCell*, const GCell* ); static inline DbU::Unit getMatrixHSide (); static inline DbU::Unit getMatrixVSide (); + static bool getHGCellsUnder ( vector& gcells + , GCell* gcell + , GCell* end + , DbU::Unit yprobe ); + static bool getVGCellsUnder ( vector& gcells + , GCell* gcell + , GCell* end + , DbU::Unit xprobe ); public: static GCell* create ( AnabaticEngine* ); public: diff --git a/anabatic/src/anabatic/NetBuilder.h b/anabatic/src/anabatic/NetBuilder.h index 9d08f33fd..5b4d09b9c 100644 --- a/anabatic/src/anabatic/NetBuilder.h +++ b/anabatic/src/anabatic/NetBuilder.h @@ -88,13 +88,14 @@ namespace Anabatic { class NetBuilder { public: - enum FunctionFlags { NoFlags = (1 << 0) - , SortDecreasing = (1 << 1) - , HAccess = (1 << 2) - , HAccessEW = (1 << 3) - , VSmall = (1 << 4) - , HSmall = (1 << 5) - , Punctual = (1 << 6) + enum FunctionFlags { NoFlags = 0 + , SortDecreasing = (1 << 0) + , HAccess = (1 << 1) + , HAccessEW = (1 << 2) + , VSmall = (1 << 3) + , HSmall = (1 << 4) + , Punctual = (1 << 5) + , M1Offgrid = (1 << 6) , HCollapse = (1 << 7) , VCollapse = (1 << 8) , Terminal = (1 << 9) @@ -145,8 +146,7 @@ namespace Anabatic { public: template< typename BuilderT > static void load ( AnabaticEngine*, Net* ); - static void getPositions ( Component* anchor, Point& source, Point& target ); - static uint64_t checkRoutingPadSize ( Component* anchor ); + static uint64_t checkRoutingPadSize ( RoutingPad* rp ); static Hook* getSegmentOppositeHook ( Hook* hook ); static uint64_t getSegmentHookType ( Hook* hook ); static void sortHookByX ( vector& , uint64_t flags=NoFlags ); @@ -209,12 +209,12 @@ namespace Anabatic { inline void addToFixSegments ( AutoSegment* ); bool push ( Hook* to, AutoContact* contact, uint64_t flags=0 ); bool isInsideBlockage ( GCell*, Component* ) const; - virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ) = 0; - virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ) = 0; + virtual void doRp_AutoContacts ( GCell*, RoutingPad*, AutoContact*& source, AutoContact*& target, uint64_t flags ) = 0; + virtual AutoContact* doRp_Access ( GCell*, RoutingPad*, uint64_t flags ) = 0; virtual AutoContact* doRp_AccessPad ( RoutingPad*, uint64_t flags ); virtual AutoContact* doRp_AccessAnalog ( GCell*, RoutingPad*, uint64_t flags ); - void doRp_StairCaseH ( GCell*, Component* rp1, Component* rp2 ); - void doRp_StairCaseV ( GCell*, Component* rp1, Component* rp2 ); + void doRp_StairCaseH ( GCell*, RoutingPad* rp1, RoutingPad* rp2 ); + void doRp_StairCaseV ( GCell*, RoutingPad* rp1, RoutingPad* rp2 ); void _load ( AnabaticEngine*, Net* ); private: virtual bool _do_xG (); diff --git a/anabatic/src/anabatic/NetBuilderHV.h b/anabatic/src/anabatic/NetBuilderHV.h index f25802b75..1f72745cf 100644 --- a/anabatic/src/anabatic/NetBuilderHV.h +++ b/anabatic/src/anabatic/NetBuilderHV.h @@ -29,8 +29,9 @@ namespace Anabatic { NetBuilderHV (); virtual ~NetBuilderHV (); static std::string getStyle (); - virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); - virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); + virtual void doRp_AutoContacts ( GCell*, RoutingPad*, AutoContact*& source, AutoContact*& target, uint64_t flags ); + virtual AutoContact* doRp_Access ( GCell*, RoutingPad*, uint64_t flags ); + AutoContact* doRp_AccessOffgrid ( GCell*, RoutingPad*, uint64_t flags ); AutoContact* doRp_AccessNorthSouthPin ( GCell*, RoutingPad* ); AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* ); private: diff --git a/anabatic/src/anabatic/NetBuilderHybridVH.h b/anabatic/src/anabatic/NetBuilderHybridVH.h index 2b791e5c3..e36902025 100644 --- a/anabatic/src/anabatic/NetBuilderHybridVH.h +++ b/anabatic/src/anabatic/NetBuilderHybridVH.h @@ -28,10 +28,10 @@ namespace Anabatic { NetBuilderHybridVH (); virtual ~NetBuilderHybridVH (); static std::string getStyle (); - virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); - virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); - AutoContact* doRp_AccessEastWestPin ( GCell* , RoutingPad* ); - AutoContact* doRp_AccessNorthSouthPin ( GCell* , RoutingPad* ); + virtual void doRp_AutoContacts ( GCell*, RoutingPad*, AutoContact*& source, AutoContact*& target, uint64_t flags ); + virtual AutoContact* doRp_Access ( GCell*, RoutingPad*, uint64_t flags ); + AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* ); + AutoContact* doRp_AccessNorthSouthPin ( GCell*, RoutingPad* ); private: bool doRp_xG_1M1 ( RoutingPad* ); bool doRp_1G_1PinM2 ( RoutingPad* ); diff --git a/anabatic/src/anabatic/NetBuilderM2.h b/anabatic/src/anabatic/NetBuilderM2.h index 389459f8e..602056a76 100644 --- a/anabatic/src/anabatic/NetBuilderM2.h +++ b/anabatic/src/anabatic/NetBuilderM2.h @@ -28,8 +28,8 @@ namespace Anabatic { NetBuilderM2 (); virtual ~NetBuilderM2 (); static std::string getStyle (); - virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); - virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); + virtual void doRp_AutoContacts ( GCell*, RoutingPad*, AutoContact*& source, AutoContact*& target, uint64_t flags ); + virtual AutoContact* doRp_Access ( GCell*, RoutingPad*, uint64_t flags ); private: virtual bool _do_1G_1M1 (); virtual bool _do_2G_1M1 (); diff --git a/anabatic/src/anabatic/NetBuilderVH.h b/anabatic/src/anabatic/NetBuilderVH.h index c29105181..a7b8d8e53 100644 --- a/anabatic/src/anabatic/NetBuilderVH.h +++ b/anabatic/src/anabatic/NetBuilderVH.h @@ -25,26 +25,30 @@ namespace Anabatic { class NetBuilderVH : public NetBuilder { public: - NetBuilderVH (); - virtual ~NetBuilderVH (); - static std::string getStyle (); - virtual void doRp_AutoContacts ( GCell*, Component*, AutoContact*& source, AutoContact*& target, uint64_t flags ); - virtual AutoContact* doRp_Access ( GCell*, Component*, uint64_t flags ); + NetBuilderVH (); + virtual ~NetBuilderVH (); + static std::string getStyle (); + virtual void doRp_AutoContacts ( GCell*, RoutingPad*, AutoContact*& source, AutoContact*& target, uint64_t flags ); + virtual AutoContact* doRp_Access ( GCell*, RoutingPad*, uint64_t flags ); + AutoContact* doRp_AccessNorthSouthPin ( GCell*, RoutingPad* ); + AutoContact* doRp_AccessEastWestPin ( GCell*, RoutingPad* ); private: - virtual bool _do_1G_1PinM2 (); - virtual bool _do_xG_1PinM2 (); - virtual bool _do_1G_1PinM3 (); - virtual bool _do_xG_1PinM3 (); - virtual bool _do_1G_1M1 (); - virtual bool _do_1G_xM1 (); - virtual bool _do_2G_1M1 (); - virtual bool _do_xG_xM1_xM3 (); - virtual bool _do_xG (); - virtual bool _do_2G (); - virtual bool _do_globalSegment (); - virtual void singleGCell ( AnabaticEngine*, Net* ); - public: - virtual string getTypeName () const; + virtual bool _do_1G_1PinM2 (); + virtual bool _do_xG_1PinM2 (); + virtual bool _do_1G_1PinM3 (); + virtual bool _do_xG_1PinM3 (); + virtual bool _do_1G_1M1 (); + virtual bool _do_1G_xM1 (); + virtual bool _do_2G_1M1 (); + virtual bool _do_xG_xM1_xM3 (); + virtual bool _do_1G_1M1_1PinM3 (); + virtual bool _do_xG (); + virtual bool _do_2G (); + virtual bool _do_globalSegment (); + virtual void singleGCell ( AnabaticEngine*, Net* ); + bool _do_1G_xM1_1PinM3 (); + public: + virtual string getTypeName () const; }; diff --git a/anabatic/src/anabatic/Session.h b/anabatic/src/anabatic/Session.h index c2d438ee5..b83757ed1 100644 --- a/anabatic/src/anabatic/Session.h +++ b/anabatic/src/anabatic/Session.h @@ -138,6 +138,7 @@ namespace Anabatic { static inline DbU::Unit getExtensionCap ( const Layer* ); static inline DbU::Unit getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode ); static inline Point getNearestGridPoint ( Point, Box constraints ); + static inline void getPositions ( RoutingPad*, Point&, Point& ); static inline size_t getSegmentStackSize (); static inline size_t getContactStackSize (); static inline const vector& getInvalidateds (); @@ -286,6 +287,7 @@ namespace Anabatic { inline Flags Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); } inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); } inline DbU::Unit Session::getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode ) { return get("getNearestTrackAxis()")->_getNearestTrackAxis(layer,axis,mode); } + inline void Session::getPositions ( RoutingPad* rp, Point& source, Point& target ) { getConfiguration()->getPositions(rp,source,target); } inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); } inline void Session::_doglegReset () { _doglegs.clear(); } diff --git a/crlcore/python/meson.build b/crlcore/python/meson.build index e5dcfab05..3d1ce67c9 100644 --- a/crlcore/python/meson.build +++ b/crlcore/python/meson.build @@ -36,6 +36,14 @@ py.install_sources( subdir: 'coriolis/technos/node180/gf180mcu', ) +py.install_sources( + 'technos/node180/gf180mcu_c4m/__init__.py', + 'technos/node180/gf180mcu_c4m/techno.py', + 'technos/node180/gf180mcu_c4m/StdCell3V3Lib.py', + 'technos/node180/gf180mcu_c4m/iolib.py', + subdir: 'coriolis/technos/node180/gf180mcu_c4m', +) + py.install_sources( 'technos/node180/scn6m_deep_09/__init__.py', 'technos/node180/scn6m_deep_09/alliance.py', diff --git a/crlcore/python/technos/node180/gf180mcu/mcu9t5v0.py b/crlcore/python/technos/node180/gf180mcu/mcu9t5v0.py index 3b2348fa8..0d9090bfc 100644 --- a/crlcore/python/technos/node180/gf180mcu/mcu9t5v0.py +++ b/crlcore/python/technos/node180/gf180mcu/mcu9t5v0.py @@ -17,7 +17,7 @@ __all__ = [ "setup" ] -def _routing (): +def _routing ( useHV ): """ Define the routing gauge along with the various P&R tool parameters. """ @@ -26,10 +26,20 @@ def _routing (): tech = db.getTechnology() rg = RoutingGauge.create('mcu9t5v0') rg.setSymbolic( False ) + if useHV: + dirM1 = RoutingLayerGauge.Vertical + dirM2 = RoutingLayerGauge.Horizontal + netBuilderStyle = 'HV,3RL+' + routingStyle = StyleFlags.HV|StyleFlags.M1Offgrid + else: + dirM1 = RoutingLayerGauge.Horizontal + dirM2 = RoutingLayerGauge.Vertical + netBuilderStyle = 'VH,3RL+' + routingStyle = StyleFlags.VH|StyleFlags.M1Offgrid rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'Metal1' ) # metal - , RoutingLayerGauge.Horizontal # preferred routing direction - , RoutingLayerGauge.PinOnly # layer usage + , dirM1 # preferred routing direction + , RoutingLayerGauge.LocalOnly # layer usage , 0 # depth , 0.0 # density (deprecated) , u(0.0) # track offset from AB @@ -40,7 +50,7 @@ def _routing (): , u(0.0 ) )) # obstacle dW rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'Metal2' ) # metal - , RoutingLayerGauge.Vertical # preferred routing direction + , dirM2 # preferred routing direction , RoutingLayerGauge.Default # layer usage , 1 # depth , 0.0 # density (deprecated) @@ -52,7 +62,7 @@ def _routing (): , u(0.0 ) )) # obstacle dW rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'Metal3' ) # metal - , RoutingLayerGauge.Horizontal # preferred routing direction + , dirM1 # preferred routing direction , RoutingLayerGauge.Default # layer usage , 2 # depth , 0.0 # density (deprecated) @@ -64,7 +74,7 @@ def _routing (): , u(0.0 ) )) # obstacle dW rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'Metal4' ) # metal - , RoutingLayerGauge.Vertical # preferred routing direction + , dirM2 # preferred routing direction , RoutingLayerGauge.Default # layer usage , 3 # depth , 0.0 # density (deprecated) @@ -76,7 +86,7 @@ def _routing (): , u(0.0 ) )) # obstacle dW rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'Metal5' ) # metal - , RoutingLayerGauge.Horizontal # preferred routing direction + , dirM1 # preferred routing direction , RoutingLayerGauge.Default # layer usage , 4 # depth , 0.0 # density (deprecated) @@ -88,7 +98,7 @@ def _routing (): , u(0.0 ) )) # obstacle dW rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer( 'MetalTop' ) # metal - , RoutingLayerGauge.Vertical # preferred routing direction + , dirM2 # preferred routing direction , RoutingLayerGauge.PowerSupply # layer usage , 5 # depth , 0.0 # density (deprecated) @@ -112,7 +122,7 @@ def _routing (): with CfgCache(priority=Cfg.Parameter.Priority.ConfigurationFile) as cfg: env = af.getEnvironment() - env.setRegister( '.*__dff.*' ) + env.setRegister( '.*_dff.*' ) # Place & Route setup cfg.viewer.minimumSize = 500 cfg.viewer.pixelThreshold = 2 @@ -148,10 +158,10 @@ def _routing (): ) cfg.anabatic.routingGauge = 'mcu9t5v0' cfg.anabatic.cellGauge = 'LEF.GF018hv5v_green_sc9' - cfg.anabatic.globalLengthThreshold = 1450 + cfg.anabatic.globalLengthThreshold = 30*u(5.04) cfg.anabatic.saturateRatio = 0.90 cfg.anabatic.saturateRp = 10 - #cfg.anabatic.topRoutingLayer = 'mt2' + cfg.anabatic.topRoutingLayer = 'Metal5' cfg.anabatic.edgeLength = 192 cfg.anabatic.edgeWidth = 32 cfg.anabatic.edgeCostH = 9.0 @@ -162,8 +172,8 @@ def _routing (): cfg.anabatic.globalIterations = [ 1, 100 ] cfg.anabatic.gcell.displayMode = 1 cfg.anabatic.gcell.displayMode = (("Boundary", 1), ("Density", 2)) - cfg.anabatic.netBuilderStyle = 'VH,3RL+' - cfg.anabatic.routingStyle = StyleFlags.VH + cfg.anabatic.netBuilderStyle = netBuilderStyle + cfg.anabatic.routingStyle = routingStyle cfg.katana.disableStackedVias = False cfg.katana.hTracksReservedLocal = 4 cfg.katana.hTracksReservedLocal = [0, 20] @@ -302,6 +312,8 @@ def _loadStdLib ( cellsTop ): io.vprint( 2, ' (__file__="{}")'.format( os.path.abspath( __file__ ))) LefImport.load( (cellsTop / '..' / 'tech' / 'gf180mcu_6LM_1TM_9K_9t_tech.lef').as_posix() ) LefImport.setMergeLibrary( cellLib ) + #LefImport.setPinFilter( u(0.84), u(0.26), LefImport.PinFilter_WIDEST ) + LefImport.setPinFilter( u(0.26), u(0.26), LefImport.PinFilter_WIDEST ) for cellDir in cellsTop.iterdir(): for lefFile in sorted(cellDir.glob('*.lef')): LefImport.load( lefFile.as_posix() ) @@ -321,7 +333,7 @@ def _loadIoLib (): , Gds.NoGdsPrefix ) -def setup ( cellsTop ): - _routing() +def setup ( cellsTop, useHV ): + _routing( useHV ) _loadStdLib( cellsTop ) #_loadIoLib() diff --git a/crlcore/python/technos/node180/gf180mcu/techno.py b/crlcore/python/technos/node180/gf180mcu/techno.py index 3eb541b1e..9dfee0145 100644 --- a/crlcore/python/technos/node180/gf180mcu/techno.py +++ b/crlcore/python/technos/node180/gf180mcu/techno.py @@ -15,7 +15,52 @@ __all__ = [ 'setup' ] -def _setup_techno(): +class VIAS ( object ): + """ + Create all the VIAs in the technology. The enclosures of the VIAs + are choosen according to the kind of routing gauge : HV or VH. + Be sure to make them coherent. + + The enclosure are given for the HV case. + + * Side : size of the *square* central cut (hole). + * BHE : Bottom Horizontal Enclosure. + * BVE : Bottom Vertical Enclosure. + * THE : Top Horizontal Enclosure. + * TVE : Top Vertical Enclosure. + """ + + # + # Name | BMetal | Cut | TMetal | Side| BHE | BVH | THE | TVE | + # 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + ViaDatas = ( ( 'VIA12', 'Metal1', 'Via1', 'Metal2' , 0.22, 0.06, 0.00, 0.06, 0.01 ) + , ( 'VIA23', 'Metal2', 'Via2', 'Metal3' , 0.26, 0.06, 0.01, 0.01, 0.06 ) + , ( 'VIA34', 'Metal3', 'Via3', 'Metal4' , 0.26, 0.01, 0.06, 0.06, 0.01 ) + , ( 'VIA45', 'Metal4', 'Via4', 'Metal5' , 0.26, 0.06, 0.01, 0.01, 0.06 ) + , ( 'VIA5T', 'Metal5', 'Via5', 'MetalTop', 0.26, 0.01, 0.06, 0.06, 0.01 ) + ) + + def __init__ ( self, useHV ): + self.useHV = useHV + + def setup ( self, tech ): + if self.useHV: + bhindex = 5 + bvindex = 6 + thindex = 7 + tvindex = 8 + else: + bhindex = 6 + bvindex = 5 + thindex = 8 + tvindex = 7 + for datas in VIAS.ViaDatas: + VIA = createVia( tech, datas[0], datas[1], datas[2], datas[3], u(datas[4]) ) + setEnclosures( VIA, tech.getLayer(datas[1]), ( u(datas[bhindex]), u(datas[bvindex]) )) + setEnclosures( VIA, tech.getLayer(datas[3]), ( u(datas[thindex]), u(datas[tvindex]) )) + + +def _setup_techno( useHV ): io.vprint( 1, ' o Setup GF180MCU technology.' ) io.vprint( 2, ' (__file__="{}")'.format( os.path.abspath( __file__ ))) @@ -79,21 +124,22 @@ def _setup_techno(): CONT = createVia( tech, 'CONT_POLY2', 'Poly2', 'Contact', 'Metal1', u(0.22) ) setEnclosures( CONT, Poly2 , u(0.07) ) setEnclosures( CONT, Metal1, u(0.12) ) - VIA12 = createVia( tech, 'VIA12', 'Metal1', 'Via1', 'Metal2', u(0.26) ) - setEnclosures( VIA12, Metal1, (u(0.06), u(0.00)) ) - setEnclosures( VIA12, Metal2, (u(0.06), u(0.01)) ) - VIA23 = createVia( tech, 'VIA23', 'Metal2', 'Via2', 'Metal3', u(0.26) ) - setEnclosures( VIA23, Metal2, (u(0.06), u(0.01)) ) - setEnclosures( VIA23, Metal3, (u(0.01), u(0.06)) ) - VIA34 = createVia( tech, 'VIA34', 'Metal3', 'Via3', 'Metal4', u(0.26) ) - setEnclosures( VIA34, Metal3, (u(0.01), u(0.06)) ) - setEnclosures( VIA34, Metal4, (u(0.06), u(0.01)) ) - VIA45 = createVia( tech, 'VIA45', 'Metal4', 'Via4', 'Metal5', u(0.26) ) - setEnclosures( VIA45, Metal4, (u(0.06), u(0.01)) ) - setEnclosures( VIA45, Metal5, (u(0.01), u(0.06)) ) - VIA5T = createVia( tech, 'VIA5T', 'Metal5', 'Via5', 'MetalTop', u(0.26) ) - setEnclosures( VIA5T, Metal5 , (u(0.01), u(0.06)) ) - setEnclosures( VIA5T, MetalTop, (u(0.06), u(0.01)) ) + VIAS( useHV ).setup( tech ) + #VIA12 = createVia( tech, 'VIA12', 'Metal1', 'Via1', 'Metal2', u(0.26) ) + #setEnclosures( VIA12, Metal1, (u(0.06), u(0.00)) ) + #setEnclosures( VIA12, Metal2, (u(0.06), u(0.01)) ) + #VIA23 = createVia( tech, 'VIA23', 'Metal2', 'Via2', 'Metal3', u(0.26) ) + #setEnclosures( VIA23, Metal2, (u(0.06), u(0.01)) ) + #setEnclosures( VIA23, Metal3, (u(0.01), u(0.06)) ) + #VIA34 = createVia( tech, 'VIA34', 'Metal3', 'Via3', 'Metal4', u(0.26) ) + #setEnclosures( VIA34, Metal3, (u(0.01), u(0.06)) ) + #setEnclosures( VIA34, Metal4, (u(0.06), u(0.01)) ) + #VIA45 = createVia( tech, 'VIA45', 'Metal4', 'Via4', 'Metal5', u(0.26) ) + #setEnclosures( VIA45, Metal4, (u(0.06), u(0.01)) ) + #setEnclosures( VIA45, Metal5, (u(0.01), u(0.06)) ) + #VIA5T = createVia( tech, 'VIA5T', 'Metal5', 'Via5', 'MetalTop', u(0.26) ) + #setEnclosures( VIA5T, Metal5 , (u(0.01), u(0.06)) ) + #setEnclosures( VIA5T, MetalTop, (u(0.06), u(0.01)) ) Border = createBL( tech, 'Border', BasicLayer.Material.other, gds2Layer=63 ) @@ -307,8 +353,8 @@ def _setup_display(): Viewer.Graphics.setStyle( 'Alliance.Classic [black]' ) -def setup(): - _setup_techno() +def setup( useHV ): + _setup_techno( useHV ) _setup_display() try: from .techno_fix import fix diff --git a/crlcore/src/LibraryManager/LibraryManager.cpp b/crlcore/src/LibraryManager/LibraryManager.cpp index ac29980a7..5cf1f8290 100644 --- a/crlcore/src/LibraryManager/LibraryManager.cpp +++ b/crlcore/src/LibraryManager/LibraryManager.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -170,4 +171,24 @@ namespace CRL { { _cellsWidget->updateLibrary(); } + void LibraryManager::readQtSettings () + { + QSettings settings; + QString sizeKey = QString( "LibraryManager/geometry" ); + if (not settings.contains(sizeKey)) return; + settings.beginGroup( QString("LibraryManager") ); + restoreGeometry( settings.value( "geometry" ).toByteArray() ); + settings.endGroup(); + } + + + void LibraryManager::saveQtSettings () + { + QSettings settings; + settings.beginGroup( QString("LibraryManager") ); + settings.setValue( "geometry", saveGeometry() ); + settings.endGroup(); + } + + } // CRL namespace. diff --git a/crlcore/src/LibraryManager/crlcore/LibraryManager.h b/crlcore/src/LibraryManager/crlcore/LibraryManager.h index 285b486c7..884821f06 100644 --- a/crlcore/src/LibraryManager/crlcore/LibraryManager.h +++ b/crlcore/src/LibraryManager/crlcore/LibraryManager.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef CRL_LIBRARY_MANAGER_H -#define CRL_LIBRARY_MANAGER_H - +#pragma once #include #include "hurricane/Observer.h" @@ -54,6 +52,8 @@ namespace CRL { public: LibraryManager ( QWidget* parent=NULL ); ~LibraryManager (); + void readQtSettings (); + void saveQtSettings (); inline void setCellViewer ( CellViewer* ); inline CellViewer* getCellViewer () const; inline LibrariesWidget* getLibrariesWidget () const; @@ -78,5 +78,3 @@ namespace CRL { } // CRL namespace. - -#endif // CRL_LIBRARY_WIDGET_H diff --git a/crlcore/src/ccore/RoutingGauge.cpp b/crlcore/src/ccore/RoutingGauge.cpp index 983e793c8..05ec24b10 100644 --- a/crlcore/src/ccore/RoutingGauge.cpp +++ b/crlcore/src/ccore/RoutingGauge.cpp @@ -161,7 +161,7 @@ namespace CRL { for ( size_t i=_firstRoutingLayer ; i<_layerGauges.size() ; ++i ) { RoutingLayerGauge* gauge = _layerGauges[i]; if (gauge->isHorizontal()) { - if (gauge->getType() != Constant::LayerGaugeType::PinOnly) + if (gauge->isUsable()) return gauge; else if (not pinOnly) pinOnly = gauge; @@ -177,7 +177,7 @@ namespace CRL { for ( size_t i=_firstRoutingLayer ; i<_layerGauges.size() ; ++i ) { RoutingLayerGauge* gauge = _layerGauges[i]; if (gauge->isVertical()) { - if (gauge->getType() != Constant::LayerGaugeType::PinOnly) + if (gauge->isUsable()) return gauge; else if (not pinOnly) pinOnly = gauge; @@ -185,6 +185,16 @@ namespace CRL { } return pinOnly; } + + + bool RoutingGauge::isUsable ( const Layer* layer ) const + { + for ( size_t i=0 ; i < _layerGauges.size() ; i++ ) { + if (_layerGauges[i]->getLayer()->getMask() == layer->getMask()) + return _layerGauges[i]->isUsable(); + } + return false; + } RoutingLayerGauge* RoutingGauge::getLayerGauge ( size_t depth ) const @@ -358,8 +368,8 @@ namespace CRL { ,getString(_layerGauges[i ]->getLayer()).c_str() ,getString(_layerGauges[i+1]->getLayer()).c_str()) << endl; } - if ( _layerGauges[i+1]->getType() == Constant::PinOnly ) { - cerr << Error("In %s: only first layer can be PinOnly.\n" + if ( not _layerGauges[i+1]->isUsable() ) { + cerr << Error("In %s: only first layer can be PinOnly or LocalOnly.\n" " (%s at depth %d)" ,getString(this).c_str() ,getString(_layerGauges[i+1]).c_str() diff --git a/crlcore/src/ccore/crlcore/LefImport.h b/crlcore/src/ccore/crlcore/LefImport.h index d0ecd8441..f94bc91f6 100644 --- a/crlcore/src/ccore/crlcore/LefImport.h +++ b/crlcore/src/ccore/crlcore/LefImport.h @@ -14,11 +14,10 @@ // +-----------------------------------------------------------------+ -#ifndef CRL_LEF_IMPORT_H -#define CRL_LEF_IMPORT_H - +#pragma once #include +#include namespace Hurricane { class Library; } @@ -26,17 +25,22 @@ namespace Hurricane { namespace CRL { + using Hurricane::DbU; + class LefImport { + public: + static const uint32_t PinFilter_NOFLAGS = 0; + static const uint32_t PinFilter_TALLEST = (1<<0); + static const uint32_t PinFilter_WIDEST = (1<<1); + static const uint32_t PinFilter_LARGEST = (1<<2); public: static void reset (); static Hurricane::Library* load ( std::string fileName ); static void setMergeLibrary ( Hurricane::Library* ); static void setGdsForeignDirectory ( std::string path ); + static void setPinFilter ( DbU::Unit xThreshold, DbU::Unit yThreshold, uint32_t flags ); }; } // CRL namespace. - - -#endif // CRL_DEF_IMPORT_H diff --git a/crlcore/src/ccore/crlcore/RoutingGauge.h b/crlcore/src/ccore/crlcore/RoutingGauge.h index 7ca0ed34d..c257bbae2 100644 --- a/crlcore/src/ccore/crlcore/RoutingGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingGauge.h @@ -74,6 +74,7 @@ namespace CRL { RoutingLayerGauge* getVerticalGauge () const; RoutingLayerGauge* getPowerSupplyGauge () const; RoutingLayerGauge* getLayerGauge ( const Layer* ) const; + bool isUsable ( const Layer* ) const; size_t getViaDepth ( const Layer* ) const; size_t getLayerDepth ( const Layer* ) const; unsigned int getLayerType ( const Layer* ) const; @@ -86,8 +87,9 @@ namespace CRL { RoutingLayerGauge* getLayerGauge ( size_t depth ) const; const Layer* getRoutingLayer ( size_t depth ) const; Layer* getContactLayer ( size_t depth ) const; - inline unsigned int getLayerDirection ( size_t depth ) const; + inline bool isUsable ( size_t depth ) const; inline unsigned int getLayerType ( size_t depth ) const; + inline unsigned int getLayerDirection ( size_t depth ) const; inline DbU::Unit getLayerPitch ( size_t depth ) const; inline DbU::Unit getLayerOffset ( size_t depth ) const; inline DbU::Unit getLayerWireWidth ( size_t depth ) const; @@ -140,6 +142,7 @@ namespace CRL { inline DbU::Unit RoutingGauge::getVerticalPitch () const { return getVerticalGauge ()->getPitch(); } inline size_t RoutingGauge::getDepth () const { return _layerGauges.size(); } inline DbU::Unit RoutingGauge::getViaWidth ( size_t depth ) const { return getLayerGauge(depth)->getViaWidth(); } + inline bool RoutingGauge::isUsable ( size_t depth ) const { return getLayerGauge(depth)->isUsable(); } inline unsigned int RoutingGauge::getLayerType ( size_t depth ) const { return getLayerGauge(depth)->getType(); } inline unsigned int RoutingGauge::getLayerDirection ( size_t depth ) const { return getLayerGauge(depth)->getDirection(); } inline DbU::Unit RoutingGauge::getLayerPitch ( size_t depth ) const { return getLayerGauge(depth)->getPitch(); } diff --git a/crlcore/src/ccore/crlcore/RoutingLayerGauge.h b/crlcore/src/ccore/crlcore/RoutingLayerGauge.h index f42172614..b5546f670 100644 --- a/crlcore/src/ccore/crlcore/RoutingLayerGauge.h +++ b/crlcore/src/ccore/crlcore/RoutingLayerGauge.h @@ -38,8 +38,9 @@ namespace Constant { , Unusable = (1 << 4) , PowerSupply = (1 << 5) , PinOnly = (1 << 6) - , Default = (1 << 7) - , BottomPowerSupply = (1 << 8) + , LocalOnly = (1 << 7) + , Default = (1 << 8) + , BottomPowerSupply = (1 << 9) }; enum Round { Superior = (1 << 10) @@ -94,6 +95,7 @@ namespace CRL { // Accessors. inline bool isHorizontal () const; inline bool isVertical () const; + inline bool isUsable () const; inline const Layer* getLayer () const; inline const Layer* getBlockageLayer () const; unsigned int getDepth () const; @@ -178,6 +180,8 @@ namespace CRL { inline bool RoutingLayerGauge::isHorizontal () const { return (_direction == Constant::Direction::Horizontal); } inline bool RoutingLayerGauge::isVertical () const { return (_direction == Constant::Direction::Vertical); } + inline bool RoutingLayerGauge::isUsable () const { return (_type != Constant::LayerGaugeType::PinOnly) + and (_type != Constant::LayerGaugeType::LocalOnly); } inline const Layer* RoutingLayerGauge::getLayer () const { return _layer; } inline unsigned int RoutingLayerGauge::getDepth () const { return _depth; } inline const Layer* RoutingLayerGauge::getBlockageLayer () const { return _blockageLayer; } @@ -270,6 +274,7 @@ inline void from ( Constant::LayerGaugeType& type, const std::string& s ) { if (s == "Unusable" ) type = Constant::Unusable; else if (s == "PinOnly" ) type = Constant::PinOnly; + else if (s == "LocalOnly" ) type = Constant::LocalOnly; else if (s == "PowerSupply" ) type = Constant::PowerSupply; else if (s == "PowerSupply|Bottom") type = Constant::BottomPowerSupply; else { @@ -289,6 +294,7 @@ inline std::string getString case Constant::Bottom: return "Bottom (error)"; case Constant::Unusable: return "Unusable"; case Constant::PinOnly: return "PinOnly"; + case Constant::LocalOnly: return "LocalOnly"; case Constant::Default: return "Default"; case Constant::PowerSupply: return "PowerSupply"; case Constant::BottomPowerSupply: return "PowerSupply|Bottom"; @@ -311,6 +317,7 @@ inline std::string getString case Constant::Bottom: return "Bottom (error)"; case Constant::Unusable: return "Unusable"; case Constant::PinOnly: return "PinOnly"; + case Constant::LocalOnly: return "LocalOnly"; case Constant::Default: return "Default"; case Constant::PowerSupply: return "PowerSupply"; case Constant::BottomPowerSupply: return "PowerSupply|Bottom"; diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp index 2d471bc02..c60af3f17 100644 --- a/crlcore/src/ccore/lefdef/LefImport.cpp +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -37,6 +37,7 @@ #include "hurricane/Cell.h" #include "hurricane/Library.h" #include "hurricane/UpdateSession.h" +#include "hurricane/DebugSession.h" #include "crlcore/Utilities.h" #include "crlcore/ToolBox.h" #include "crlcore/RoutingGauge.h" @@ -69,12 +70,62 @@ namespace { vdd->setType ( Net::Type::POWER ); } #endif + + + class PinRectilinearFilter { + public: + PinRectilinearFilter ( DbU::Unit xThreshold=0 + , DbU::Unit yThreshold=0 + , uint32_t flags=LefImport::PinFilter_NOFLAGS ); + bool match ( const Box& candidate, const Box& best ); + inline DbU::Unit getXThreshold () const; + inline DbU::Unit getYThreshold () const; + inline uint32_t getFlags () const; + inline void setXThreshold ( DbU::Unit ); + inline void setYThreshold ( DbU::Unit ); + inline void setFlags ( uint32_t ); + private: + DbU::Unit _xThreshold; + DbU::Unit _yThreshold; + uint32_t _flags; + }; + + + PinRectilinearFilter::PinRectilinearFilter ( DbU::Unit xThreshold, DbU::Unit yThreshold, uint32_t flags ) + : _xThreshold(xThreshold) + , _yThreshold(yThreshold) + , _flags (flags) + { } + + + inline DbU::Unit PinRectilinearFilter::getXThreshold () const { return _xThreshold; } + inline DbU::Unit PinRectilinearFilter::getYThreshold () const { return _yThreshold; } + inline uint32_t PinRectilinearFilter::getFlags () const { return _flags; } + inline void PinRectilinearFilter::setXThreshold ( DbU::Unit xThreshold ) { _xThreshold=xThreshold; } + inline void PinRectilinearFilter::setYThreshold ( DbU::Unit yThreshold ) { _yThreshold=yThreshold; } + inline void PinRectilinearFilter::setFlags ( uint32_t flags ) { _flags=flags; } + + + bool PinRectilinearFilter::match ( const Box& candidate, const Box& best ) + { + if (candidate.getWidth () < _xThreshold) return false; + if (candidate.getHeight() < _yThreshold) return false; + if (_flags & LefImport::PinFilter_TALLEST) return (candidate.getHeight() > best.getHeight()); + if (_flags & LefImport::PinFilter_WIDEST ) return (candidate.getWidth () > best.getWidth ()); + if (_flags & LefImport::PinFilter_LARGEST) { + float candidateArea = (float)candidate.getWidth() * (float)candidate.getHeight(); + float bestArea = (float)best .getWidth() * (float)best .getHeight(); + return (candidateArea > bestArea); + } + return false; + } class LefParser { public: static void setMergeLibrary ( Library* ); static void setGdsForeignDirectory ( string ); + static void setPinFilter ( DbU::Unit xThreshold, DbU::Unit yThreshold, uint32_t flags ); static DbU::Unit fromLefUnits ( int ); static Layer* getLayer ( string ); static void addLayer ( string, Layer* ); @@ -136,32 +187,33 @@ namespace { void _pinStdPostProcess (); void _pinPadPostProcess (); private: - static string _gdsForeignDirectory; - static Library* _mergeLibrary; - string _file; - string _libraryName; - Library* _library; - string _foreignPath; - Point _foreignPosition; - Net* _gdsPower; - Net* _gdsGround; - Cell* _cell; - Net* _net; - string _busBits; - double _unitsMicrons; - DbU::Unit _oneGrid; + static string _gdsForeignDirectory; + static Library* _mergeLibrary; + static PinRectilinearFilter _pinFilter; + string _file; + string _libraryName; + Library* _library; + string _foreignPath; + Point _foreignPosition; + Net* _gdsPower; + Net* _gdsGround; + Cell* _cell; + Net* _net; + string _busBits; + double _unitsMicrons; + DbU::Unit _oneGrid; map< string, vector > _pinComponents; - static map _layerLut; - vector _unmatchedLayers; - vector _errors; - int _nthMetal; - int _nthCut; - int _nthRouting; - RoutingGauge* _routingGauge; - CellGauge* _cellGauge; - DbU::Unit _minTerminalWidth; - static DbU::Unit _coreSiteX; - static DbU::Unit _coreSiteY; + static map _layerLut; + vector _unmatchedLayers; + vector _errors; + int _nthMetal; + int _nthCut; + int _nthRouting; + RoutingGauge* _routingGauge; + CellGauge* _cellGauge; + DbU::Unit _minTerminalWidth; + static DbU::Unit _coreSiteX; + static DbU::Unit _coreSiteY; }; @@ -215,11 +267,12 @@ namespace { } - string LefParser::_gdsForeignDirectory = ""; - Library* LefParser::_mergeLibrary = nullptr; - map LefParser::_layerLut; - DbU::Unit LefParser::_coreSiteX = 0; - DbU::Unit LefParser::_coreSiteY = 0; + string LefParser::_gdsForeignDirectory = ""; + Library* LefParser::_mergeLibrary = nullptr; + PinRectilinearFilter LefParser::_pinFilter; + map LefParser::_layerLut; + DbU::Unit LefParser::_coreSiteX = 0; + DbU::Unit LefParser::_coreSiteY = 0; void LefParser::setMergeLibrary ( Library* library ) @@ -230,6 +283,14 @@ namespace { { _gdsForeignDirectory = path; } + void LefParser::setPinFilter ( DbU::Unit xThreshold, DbU::Unit yThreshold, uint32_t flags ) + { + _pinFilter.setXThreshold( xThreshold ); + _pinFilter.setYThreshold( yThreshold ); + _pinFilter.setFlags ( flags ); + } + + void LefParser::reset () { _layerLut.clear(); @@ -861,7 +922,9 @@ namespace { const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 ); Box ab = _cell->getAbutmentBox(); - //cerr << " @ _pinStdPostProcess" << endl; + if (_cell->getName() == "gf180mcu_fd_sc_mcu9t5v0__inv_1") + DebugSession::open( 100, 110 ); + cdebug_log(100,1) << "@ _pinStdPostProcess" << endl; for ( auto element : _pinComponents ) { string pinName = element.first; @@ -926,14 +989,13 @@ namespace { } Rectilinear* rectilinear = dynamic_cast( component ); if (rectilinear) { - cerr << " > " << rectilinear << endl; + cdebug_log(100,0) << "+ " << rectilinear << endl; if (rectilinear->getLayer()->getMask() != metal1->getMask()) continue; vector boxes; - rectilinear->getAsRectangles( boxes ); - if (component->getNet()->isSupply()) { + rectilinear->getAsRectangles( boxes ); ongrids.push_back( Horizontal::create( rectilinear->getNet() , rectilinear->getLayer() , boxes.front().getYCenter() @@ -943,21 +1005,77 @@ namespace { ) ); } else { + rectilinear->getAsBiggestRectangles( boxes + , _pinFilter.getXThreshold() + , _pinFilter.getYThreshold() ); + Box best; + for ( const Box& candidate : boxes ) { + if (_pinFilter.match(candidate,best)) + best = candidate; + } + if (not best.isEmpty()) { +#if EXTENDED_COVERAGE + DbU::Unit ymin = gaugeMetal2->getTrackPosition( ab.getYMin() + , ab.getXMax() + , best.getYMin() + gaugeMetal2->getViaWidth()/2 + , Constant::Superior ); + DbU::Unit ymax = gaugeMetal2->getTrackPosition( ab.getYMin() + , ab.getXMax() + , best.getYMax() - gaugeMetal2->getViaWidth()/2 + , Constant::Inferior ); + ongrids.push_back( Vertical::create( rectilinear->getNet() + , rectilinear->getLayer() + , best.getXCenter() + , best.getWidth() + , ymin - gaugeMetal2->getViaWidth()/2 + , ymax + gaugeMetal2->getViaWidth()/2 + ) + ); + cdebug_log(100,0) << "| -> " << ongrids.back() << endl; +#endif + //if (gaugeMetal2->isHorizontal()) { + if (best.getWidth() < best.getHeight()) { + ongrids.push_back( Vertical::create( rectilinear->getNet() + , rectilinear->getLayer() + , best.getXCenter() + , best.getWidth() + , best.getYMin() + , best.getYMax() + ) + ); + } else { + ongrids.push_back( Horizontal::create( rectilinear->getNet() + , rectilinear->getLayer() + , best.getYCenter() + , best.getHeight() + , best.getXMin() + , best.getXMax() + ) + ); + } + cdebug_log(100,0) << "| -> " << ongrids.back() << endl; + } +#if THIS_IS_DISABLED for ( const Box& box : boxes ) { - DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin() - , ab.getXMax() - , box.getXCenter() - , Constant::Nearest ); - DbU::Unit xmin = std::min( box.getXMin(), nearestX - gaugeMetal2->getViaWidth()/2 ); - DbU::Unit xmax = std::max( box.getXMax(), nearestX + gaugeMetal2->getViaWidth()/2 ); + cdebug_log(100,0) << "| " << box << endl; + // Assume M2 is horizontal. + DbU::Unit ymin = gaugeMetal2->getTrackPosition( ab.getYMin() + , ab.getXMax() + , box.getYMin() + gaugeMetal2->getViaWidth()/2 + , Constant::Superior ); + DbU::Unit ymax = gaugeMetal2->getTrackPosition( ab.getYMin() + , ab.getXMax() + , box.getYMax() - gaugeMetal2->getViaWidth()/2 + , Constant::Inferior ); ongrids.push_back( Vertical::create( rectilinear->getNet() , rectilinear->getLayer() - , (xmax+xmin)/2 - , xmax-xmin - , box.getYMin() - , box.getYMax() + , box.getXCenter() + , box.getWidth() + , ymin - gaugeMetal2->getViaWidth()/2 + , ymax + gaugeMetal2->getViaWidth()/2 ) ); + cdebug_log(100,0) << "| -> " << ongrids.back() << endl; // DbU::Unit neighbor = nearestY // + ((nearestY > box.getYCenter()) ? 1 : -1) * gaugeMetal2->getPitch(); @@ -973,6 +1091,7 @@ namespace { // ); // } } +#endif } } } @@ -990,6 +1109,10 @@ namespace { } } } + + cdebug_tabw(100,-1); + if (_cell->getName() == "gf180mcu_fd_sc_mcu9t5v0__inv_1") + DebugSession::close(); } @@ -1214,4 +1337,12 @@ namespace CRL { } -} // End of CRL namespace. + void LefImport::setPinFilter ( DbU::Unit xThreshold, DbU::Unit yThreshold, uint32_t flags ) + { +#if defined(HAVE_LEFDEF) + LefParser::setPinFilter( xThreshold, yThreshold, flags ); +#endif + } + + +} // CRL namespace. diff --git a/crlcore/src/pyCRL/PyCRL.cpp b/crlcore/src/pyCRL/PyCRL.cpp index 6c5ea9bff..f4ac3e4ba 100644 --- a/crlcore/src/pyCRL/PyCRL.cpp +++ b/crlcore/src/pyCRL/PyCRL.cpp @@ -231,6 +231,7 @@ extern "C" { PySpice_postModuleInit (); PyVerilog_postModuleInit (); PyGds_postModuleInit (); + PyLefImport_postModuleInit (); PyDefExport_postModuleInit (); //PyObject* dictionnary = PyModule_GetDict ( module ); diff --git a/crlcore/src/pyCRL/PyConstant.cpp b/crlcore/src/pyCRL/PyConstant.cpp index 100eb4504..faa5a8e0b 100644 --- a/crlcore/src/pyCRL/PyConstant.cpp +++ b/crlcore/src/pyCRL/PyConstant.cpp @@ -62,6 +62,7 @@ extern "C" { LoadObjectConstant( dictionnary, Constant::Vertical , "Vertical" ) LoadObjectConstant( dictionnary, Constant::Default , "Default" ) LoadObjectConstant( dictionnary, Constant::PinOnly , "PinOnly" ) + LoadObjectConstant( dictionnary, Constant::LocalOnly , "LocalOnly" ) LoadObjectConstant( dictionnary, Constant::Superior , "Superior" ) LoadObjectConstant( dictionnary, Constant::Inferior , "Inferior" ) LoadObjectConstant( dictionnary, Constant::Nearest , "Nearest" ) diff --git a/crlcore/src/pyCRL/PyLefImport.cpp b/crlcore/src/pyCRL/PyLefImport.cpp index 0986d5db2..a6fd6bb32 100644 --- a/crlcore/src/pyCRL/PyLefImport.cpp +++ b/crlcore/src/pyCRL/PyLefImport.cpp @@ -38,6 +38,7 @@ namespace CRL { using Isobar::ConstructorError; using Isobar::HurricaneError; using Isobar::HurricaneWarning; + using Isobar::PyAny_AsLong; using Isobar::getPyHash; using Isobar::ParseOneArg; using Isobar::ParseTwoArg; @@ -125,6 +126,24 @@ extern "C" { } + static PyObject* PyLefImport_setPinFilter ( PyObject*, PyObject* args ) + { + cdebug_log(30,0) << "PyLefImport_setPinFilter()" << endl; + HTRY + PyObject* pyXThreshold = NULL; + PyObject* pyYThreshold = NULL; + unsigned int flags = 0; + if (PyArg_ParseTuple( args, "OOI:LefImport.setPinFilter", &pyXThreshold, &pyYThreshold, &flags )) { + LefImport::setPinFilter( PyAny_AsLong(pyXThreshold), PyAny_AsLong(pyXThreshold), flags ); + } else { + PyErr_SetString ( ConstructorError, "LefImport.setPinFilter(): Bad type or bad number of parameters." ); + return NULL; + } + HCATCH + Py_RETURN_NONE; + } + + // Standart Destroy (Attribute). @@ -137,6 +156,8 @@ extern "C" { , "Merge into this library instead of creating a new one." } , { "setGdsForeignDirectory", (PyCFunction)PyLefImport_setGdsForeignDirectory, METH_VARARGS|METH_STATIC , "Set the directory where to find FOREIGN GDS files." } + , { "setPinFilter" , (PyCFunction)PyLefImport_setPinFilter , METH_VARARGS|METH_STATIC + , "Select the way Rectilinear pins are converted to one rectangle." } //, { "destroy" , (PyCFunction)PyLefImport_destroy , METH_VARARGS // , "Destroy the associated hurricane object. The python object remains." } , {NULL, NULL, 0, NULL} /* sentinel */ @@ -158,6 +179,16 @@ extern "C" { PyTypeObjectDefinitionsOfModule(CRL,LefImport) + extern void PyLefImport_postModuleInit () + { + PyObject* constant; + LoadObjectConstant(PyTypeLefImport.tp_dict,LefImport::PinFilter_NOFLAGS,"PinFilter_NOFLAGS"); + LoadObjectConstant(PyTypeLefImport.tp_dict,LefImport::PinFilter_TALLEST,"PinFilter_TALLEST"); + LoadObjectConstant(PyTypeLefImport.tp_dict,LefImport::PinFilter_WIDEST ,"PinFilter_WIDEST" ); + LoadObjectConstant(PyTypeLefImport.tp_dict,LefImport::PinFilter_LARGEST,"PinFilter_LARGEST" ); + } + + #endif // End of Shared Library Code Part. } // extern "C". diff --git a/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp b/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp index 944f376ff..e73617163 100644 --- a/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp +++ b/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp @@ -111,6 +111,7 @@ extern "C" { case Constant::BottomPowerSupply: case Constant::PowerSupply: case Constant::PinOnly: + case Constant::LocalOnly: case Constant::Default: break; default: PyErr_SetString ( ConstructorError, "Bad value for type argument of RoutingLayerGauge.create()." ); @@ -267,6 +268,9 @@ extern "C" { DirectGetUIntAttribute (PyRoutingLayerGauge_getDirection ,getDirection ,PyRoutingLayerGauge,RoutingLayerGauge) DirectGetUIntAttribute (PyRoutingLayerGauge_getType ,getType ,PyRoutingLayerGauge,RoutingLayerGauge) DirectGetDoubleAttribute(PyRoutingLayerGauge_getDensity ,getDensity ,PyRoutingLayerGauge,RoutingLayerGauge) + DirectGetBoolAttribute (PyRoutingLayerGauge_isUsable ,isUsable ,PyRoutingLayerGauge,RoutingLayerGauge) + DirectGetBoolAttribute (PyRoutingLayerGauge_isHorizontal ,isHorizontal ,PyRoutingLayerGauge,RoutingLayerGauge) + DirectGetBoolAttribute (PyRoutingLayerGauge_isVertical ,isVertical ,PyRoutingLayerGauge,RoutingLayerGauge) DirectGetLongAttribute (PyRoutingLayerGauge_getOffset ,getOffset ,PyRoutingLayerGauge,RoutingLayerGauge) DirectGetLongAttribute (PyRoutingLayerGauge_getPitch ,getPitch ,PyRoutingLayerGauge,RoutingLayerGauge) DirectGetLongAttribute (PyRoutingLayerGauge_getHalfPitch ,getHalfPitch ,PyRoutingLayerGauge,RoutingLayerGauge) @@ -286,6 +290,12 @@ extern "C" { PyMethodDef PyRoutingLayerGauge_Methods[] = { { "create" , (PyCFunction)PyRoutingLayerGauge_create , METH_VARARGS|METH_STATIC , "Create a new RoutingLayerGauge." } + , { "isUsable" , (PyCFunction)PyRoutingLayerGauge_isUsable , METH_NOARGS + , "Tells if the layer is usable for standard routing." } + , { "isHorizontal" , (PyCFunction)PyRoutingLayerGauge_isHorizontal , METH_NOARGS + , "Tells if the layer prefered routing direction is horizontal." } + , { "isVertical" , (PyCFunction)PyRoutingLayerGauge_isVertical , METH_NOARGS + , "Tells if the layer prefered routing direction is vertical." } , { "getLayer" , (PyCFunction)PyRoutingLayerGauge_getLayer , METH_NOARGS , "Returns the associated routing layer." } , { "getBlockageLayer" , (PyCFunction)PyRoutingLayerGauge_getBlockageLayer, METH_NOARGS @@ -357,6 +367,7 @@ extern "C" { LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Vertical ,"Vertical" ); LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Unusable ,"Unusable" ); LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::PinOnly ,"PinOnly" ); + LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::LocalOnly ,"LocalOnly" ); LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::PowerSupply ,"PowerSupply" ); LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::BottomPowerSupply,"BottomPowerSupply" ); LoadObjectConstant(PyTypeRoutingLayerGauge.tp_dict,Constant::Default ,"Default" ); diff --git a/crlcore/src/pyCRL/crlcore/PyLefImport.h b/crlcore/src/pyCRL/crlcore/PyLefImport.h index dca57938a..9f1442a20 100644 --- a/crlcore/src/pyCRL/crlcore/PyLefImport.h +++ b/crlcore/src/pyCRL/crlcore/PyLefImport.h @@ -15,9 +15,7 @@ // +-----------------------------------------------------------------+ -#ifndef CRL_PY_LEF_IMPORT_H -#define CRL_PY_LEF_IMPORT_H - +#pragma once #include "hurricane/isobar/PyHurricane.h" #include "crlcore/LefImport.h" @@ -42,6 +40,7 @@ extern "C" { extern PyMethodDef PyLefImport_Methods[]; extern void PyLefImport_LinkPyType(); + extern void PyLefImport_postModuleInit(); #define IsPyLefImport(v) ( (v)->ob_type == &PyTypeLefImport ) @@ -51,5 +50,3 @@ extern "C" { } // extern "C". } // CRL namespace. - -#endif // CRL_PY_LEF_IMPORT_H diff --git a/cumulus/src/designflow/graal.py b/cumulus/src/designflow/graal.py index 6faacf0aa..60d2277e5 100644 --- a/cumulus/src/designflow/graal.py +++ b/cumulus/src/designflow/graal.py @@ -34,7 +34,7 @@ def __repr__ ( self ): return '<{}>'.format( ' '.join(self.command) ) def doTask ( self ): - from helpers.io import ErrorMessage + from ..helpers.io import ErrorMessage shellEnv = ShellEnv() shellEnv[ 'MBK_IN_PH' ] = self.layoutFile.suffix[1:] diff --git a/cumulus/src/designflow/meson.build b/cumulus/src/designflow/meson.build index 0eca0a58e..56aa9db6b 100644 --- a/cumulus/src/designflow/meson.build +++ b/cumulus/src/designflow/meson.build @@ -22,6 +22,9 @@ designflow = files([ 'pnrcheck.py', 'routecheck.py', 's2r.py', + 'surelog.py', + 'sv2v.py', + 'svase.py', 'task.py', 'technos.py', 'vasy.py', diff --git a/cumulus/src/designflow/technos.py b/cumulus/src/designflow/technos.py index f807780d4..b70dd13ac 100644 --- a/cumulus/src/designflow/technos.py +++ b/cumulus/src/designflow/technos.py @@ -73,7 +73,7 @@ def setupCMOS ( checkToolkit=None ): env.addSYSTEM_LIBRARY( library=(Where.checkToolkit / 'cells' / 'niolib').as_posix() , mode =CRL.Environment.Append ) - Yosys.setLiberty( Where.cellsTop / 'sxlib' / 'sxlib.lib' ) + Yosys.setLiberty( Where.allianceTop / 'cells' / 'sxlib' / 'sxlib.lib' ) ShellEnv.RDS_TECHNO_NAME = (Where.allianceTop / 'etc' / 'cmos.rds').as_posix() path = None @@ -186,6 +186,65 @@ def setupCMOS45 ( useNsxlib=False, checkToolkit=None, cellsTop=None ): break +def setupMOSIS ( checkToolkit=None, cellsTop=None ): + from .. import Cfg + from .. import Viewer + from .. import CRL + from ..helpers import overlay, l, u, n + from .yosys import Yosys + import coriolis.technos.node180.scn6m_deep_09 + + Where( checkToolkit ) + if cellsTop is None: + cellsTop = Where.cellsTop + else: + if isinstance(cellsTop,str): + cellsTop = Path( cellsTop ) + + with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg: + cfg.misc.catchCore = False + cfg.misc.info = False + cfg.misc.paranoid = False + cfg.misc.bug = False + cfg.misc.logMode = True + cfg.misc.verboseLevel1 = True + cfg.misc.verboseLevel2 = True + cfg.misc.minTraceLevel = 1900 + cfg.misc.maxTraceLevel = 3000 + cfg.katana.eventsLimit = 1000000 + cfg.etesian.graphics = 3 + cfg.etesian.spaceMargin = 0.05 + cfg.etesian.aspectRatio = 1.0 + cfg.anabatic.edgeLenght = 24 + cfg.anabatic.edgeWidth = 8 + cfg.katana.termSatReservedLocal = 6 + cfg.katana.termSatThreshold = 9 + + Viewer.Graphics.setStyle( 'Alliance.Classic [black]' ) + af = CRL.AllianceFramework.get() + env = af.getEnvironment() + env.setCLOCK( '^ck$|m_clock|^clk$' ) + + sxlib = cellsTop / 'nsxlib' + iolib = cellsTop / 'niolib' + liberty = sxlib / 'nsxlib.lib' + env.addSYSTEM_LIBRARY( library=iolib.as_posix(), mode=CRL.Environment.Prepend ) + env.addSYSTEM_LIBRARY( library=sxlib.as_posix(), mode=CRL.Environment.Prepend ) + if not sxlib.is_dir(): + print( '[ERROR] technos.setupCMOS45(): nsxlib directory do *not* exists:' ) + print( ' "{}"'.format(sxlib.as_posix()) ) + + Yosys.setLiberty( liberty ) + #ShellEnv.RDS_TECHNO_NAME = (Where.checkToolkit / 'etc' / 'FreePDK45.rds').as_posix() + + path = None + for pathVar in [ 'PATH', 'path' ]: + if pathVar in os.environ: + path = os.environ[ pathVar ] + os.environ[ pathVar ] = path + ':' + (Where.allianceTop / 'bin').as_posix() + break + + def setupSky130_c4m ( checkToolkit=None, pdkMasterTop=None ): from .. import Cfg from .. import Viewer @@ -400,7 +459,7 @@ def setupTSMC_c180_c4m ( checkToolkit=None, ndaTop=None ): ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix() -def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ): +def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None, useHV=False ): from .. import Cfg from .. import Viewer from .. import CRL @@ -423,8 +482,8 @@ def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ): from coriolis.technos.node180.gf180mcu import techno from coriolis.technos.node180.gf180mcu import mcu9t5v0 - techno.setup() - mcu9t5v0.setup( cellsTop ) + techno.setup( useHV ) + mcu9t5v0.setup( cellsTop, useHV ) with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg: cfg.misc.catchCore = False @@ -437,7 +496,7 @@ def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ): cfg.misc.verboseLevel1 = False cfg.misc.verboseLevel2 = False cfg.etesian.graphics = 2 - cfg.anabatic.topRoutingLayer = 'm4' + cfg.anabatic.topRoutingLayer = 'Metal5' cfg.katana.eventsLimit = 4000000 af = CRL.AllianceFramework.get() #lg5 = af.getRoutingGauge( 'mcu9t' ).getLayerGauge( 5 ) @@ -447,3 +506,69 @@ def setupGF180MCU_GF ( checkToolkit=None, pdkTop=None ): Yosys.setLiberty( liberty ) ShellEnv.CHECK_TOOLKIT = Where.checkToolkit.as_posix() + + +def setupAMS350 ( checkToolkit=None, ndaTop=None, cellsTop=None ): + from .. import Cfg + from .. import Viewer + from .. import CRL + from ..helpers import setNdaTopDir, overlay, l, u, n + from .yosys import Yosys + + if isinstance(ndaTop,str): + ndaTop = Path( ndaTop ) + setNdaTopDir( ndaTop.as_posix() ) + if not ndaTop.is_dir(): + print( '[ERROR] technos.setupAMS350(): ndaTop directory do *not* exists:' ) + print( ' "{}"'.format(ndaTop.as_posix()) ) + import NDA.node350.c35b4 + + Where( checkToolkit ) + if cellsTop is None: + cellsTop = Where.cellsTop + else: + if isinstance(cellsTop,str): + cellsTop = Path( cellsTop ) + + with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg: + cfg.misc.catchCore = False + cfg.misc.info = False + cfg.misc.paranoid = False + cfg.misc.bug = False + cfg.misc.logMode = True + cfg.misc.verboseLevel1 = True + cfg.misc.verboseLevel2 = True + cfg.misc.minTraceLevel = 1900 + cfg.misc.maxTraceLevel = 3000 + cfg.katana.eventsLimit = 1000000 + cfg.etesian.graphics = 3 + cfg.etesian.spaceMargin = 0.05 + cfg.etesian.aspectRatio = 1.0 + cfg.anabatic.edgeLenght = 24 + cfg.anabatic.edgeWidth = 8 + cfg.katana.termSatReservedLocal = 6 + cfg.katana.termSatThreshold = 9 + + Viewer.Graphics.setStyle( 'Alliance.Classic [black]' ) + af = CRL.AllianceFramework.get() + env = af.getEnvironment() + env.setCLOCK( '^ck$|m_clock|^clk$' ) + + sxlib = cellsTop / 'nsxlib' + iolib = cellsTop / 'niolib' + liberty = sxlib / 'nsxlib.lib' + env.addSYSTEM_LIBRARY( library=iolib.as_posix(), mode=CRL.Environment.Prepend ) + env.addSYSTEM_LIBRARY( library=sxlib.as_posix(), mode=CRL.Environment.Prepend ) + if not sxlib.is_dir(): + print( '[ERROR] technos.setupAMS350(): nsxlib directory do *not* exists:' ) + print( ' "{}"'.format(sxlib.as_posix()) ) + + Yosys.setLiberty( liberty ) + #ShellEnv.RDS_TECHNO_NAME = (Where.checkToolkit / 'etc' / 'FreePDK45.rds').as_posix() + + path = None + for pathVar in [ 'PATH', 'path' ]: + if pathVar in os.environ: + path = os.environ[ pathVar ] + os.environ[ pathVar ] = path + ':' + (Where.allianceTop / 'bin').as_posix() + break diff --git a/cumulus/src/plugins/block/block.py b/cumulus/src/plugins/block/block.py index fd0792efb..c80188470 100644 --- a/cumulus/src/plugins/block/block.py +++ b/cumulus/src/plugins/block/block.py @@ -702,7 +702,7 @@ def placeMacro ( self, ipath, transf ): with UpdateSession(): instance = self.rgetCoreInstance( ipath ) macro = Macro.wrap( instance.getMasterCell() - , self.conf.routingGauge.getName(), 3, 2 ) + , self.conf.routingGauge.getName(), 3, 3 ) instanceAb = instance.getMasterCell().getAbutmentBox() coreTransf = self.conf.icore.getTransformation() if self.conf.isCoreBlock: diff --git a/cumulus/src/plugins/block/configuration.py b/cumulus/src/plugins/block/configuration.py index b010c83e4..e556b2694 100644 --- a/cumulus/src/plugins/block/configuration.py +++ b/cumulus/src/plugins/block/configuration.py @@ -175,6 +175,8 @@ def _loadRoutingGauge ( self ): continue if self._routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.PinOnly: continue + if self._routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.LocalOnly: + continue if self._routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.BottomPowerSupply: continue if self._routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.PowerSupply: diff --git a/cumulus/src/plugins/block/spares.py b/cumulus/src/plugins/block/spares.py index b5b93b373..a2406b2ce 100644 --- a/cumulus/src/plugins/block/spares.py +++ b/cumulus/src/plugins/block/spares.py @@ -21,7 +21,7 @@ from ...Hurricane import Breakpoint, DbU, Box, Transformation, Box, \ Path, Layer, Occurrence, Net, RoutingPad, \ Horizontal, Vertical, Contact, Pin, Plug, \ - Instance + Instance, Point from ...CRL import AllianceFramework, RoutingLayerGauge from ...helpers import trace, dots, l, u, n from ...helpers.io import ErrorMessage, WarningMessage, catch @@ -276,27 +276,54 @@ def create ( spares ): @staticmethod def isUsedArea ( spares, area, rtag, raiseError ): - centerArea = Box( area.getCenter() ) sliceHeight = spares.conf.sliceHeight - centerArea.inflate( 4*sliceHeight, sliceHeight ) - trace( 540, '\tQuadTree.isUnderArea(): {} {} of {}\n'.format(rtag,centerArea,spares.conf.cell) ) + if rtag[-2:] == 'bl': + vWireArea = Box( area.getXCenter(), area.getYCenter() + , area.getXCenter(), area.getYMax () ) + hWireArea = Box( area.getXCenter(), area.getYMax() + , area.getXMax (), area.getYMax() ) + elif rtag[-2:] == 'br': + vWireArea = Box( area.getXCenter(), area.getYCenter() + , area.getXCenter(), area.getYMax () ) + hWireArea = Box( area.getXCenter(), area.getYMax() + , area.getXMin (), area.getYMax() ) + elif rtag[-2:] == 'tl': + vWireArea = Box( area.getXCenter(), area.getYCenter() + , area.getXCenter(), area.getYMin () ) + hWireArea = Box( area.getXCenter(), area.getYMin() + , area.getXMax (), area.getYMin() ) + elif rtag[-2:] == 'tr': + vWireArea = Box( area.getXCenter(), area.getYCenter() + , area.getXCenter(), area.getYMin () ) + hWireArea = Box( area.getXCenter(), area.getYMin() + , area.getXMin (), area.getYMin() ) + else: + vWireArea = Box( area.getXCenter(), area.getYCenter() ) + hWireArea = vWireArea + vWireArea.inflate( 0, sliceHeight ) + hWireArea.inflate( sliceHeight, 0 ) + trace( 540, '\tQuadTree.isUsedArea(): {} {} of {}\n'.format(rtag,hWireArea,vWireArea,spares.conf.cell) ) trace( 540, '\t{}\n'.format( spares.conf.cellPnR )) - for occurrence in spares.conf.cellPnR.getTerminalNetlistInstanceOccurrencesUnder( centerArea ): - if not isinstance(occurrence.getEntity(),Instance): - continue - instance = occurrence.getEntity() - masterCell = instance.getMasterCell() - if not masterCell.isTerminalNetlist(): - continue - trace( 540, '\t| Overlap {}\n'.format(occurrence.getEntity()) ) - if raiseError: - raise Error%essage( 1, [ 'QuadTree.create(): Unable to create QuadTree under area {}' \ - .format(area) - , 'Area center is under fixed block {}' .format() - ] ) - return True + for treeBox in vWireArea, hWireArea: + for occurrence in spares.conf.cellPnR.getTerminalNetlistInstanceOccurrencesUnder( treeBox ): + if not isinstance(occurrence.getEntity(),Instance): + continue + instance = occurrence.getEntity() + masterCell = instance.getMasterCell() + if not masterCell.isTerminalNetlist(): + continue + if instance.getName().startswith('spare_'): + continue + trace( 540, '\t| Overlap {}\n'.format(occurrence.getEntity()) ) + if raiseError: + raise Error%essage( 1, [ 'QuadTree.create(): Unable to create QuadTree under area {}' \ + .format(area) + , 'Area center is under fixed block {}' .format() + ] ) + return True sys.stdout.flush() sys.stderr.flush() + trace( 540, '\t-> Area is clear.\n' ) return False @staticmethod @@ -305,6 +332,7 @@ def _create ( spares, parent, area, tag, raiseError=False ): if QuadTree.isUsedArea( spares, area, childRtag, raiseError ): return None qt = QuadTree( spares, parent, area, childRtag ) + trace( 540, '\tQuadTree._create(): {}\n'.format(qt) ) return qt def __init__ ( self, spares, parent, area, rtag='root' ): diff --git a/cumulus/src/plugins/core2chip/meson.build b/cumulus/src/plugins/core2chip/meson.build index 19b54a45e..5aa301c5f 100644 --- a/cumulus/src/plugins/core2chip/meson.build +++ b/cumulus/src/plugins/core2chip/meson.build @@ -2,6 +2,7 @@ core2chip = files([ '__init__.py', 'cmos.py', 'core2chip.py', + 'gf180mcu.py', 'libresocio.py', 'niolib.py', 'phlib.py', diff --git a/cumulus/src/plugins/macro/macro.py b/cumulus/src/plugins/macro/macro.py index aac97ef64..cc0c5aaee 100644 --- a/cumulus/src/plugins/macro/macro.py +++ b/cumulus/src/plugins/macro/macro.py @@ -124,7 +124,7 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): that are half free and half occluded by the block itself may cause (stupid) deadlock to appear. """ - trace( 550, '\tMacro.__init__() {}\n'.format(macroCell) ) + trace( 550, '+,', '\tMacro.__init__() {}\n'.format(macroCell) ) self.cell = macroCell Macro.LUT[ self.cell ] = self @@ -224,6 +224,7 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): with UpdateSession(): for component in westPins: + trace( 550, '\twestPin {}\n'.format( component )) NetExternalComponents.setInternal( component ) pitch = self.rg.getPitch( component.getLayer() ) ppitch = self.getPPitch( component.getLayer() ) @@ -317,6 +318,7 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): ) NetExternalComponents.setExternal( horizontal ) for component in eastPins: + trace( 550, '\teastPin {}\n'.format( component )) layer = component.getLayer() if layer.getMask() != gaugeMetal2.getLayer().getMask(): useBigVia = True @@ -363,13 +365,23 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): ) NetExternalComponents.setExternal( horizontal ) for component in southPins: + trace( 550, '\tsouthPin {}\n'.format( component )) NetExternalComponents.setInternal( component ) - pitch = self.rg.getPitch( component.getLayer() ) + innerRg = self.rg.getLayerGauge( component.getLayer() ) + outerRg = innerRg + vDepth = innerRg.getDepth() + if innerRg.isHorizontal(): + #if vDepth+1 < self.rg.getAllowedDepth(): vDepth += 1 + #else: vDepth -= 1 + outerRg = self.rg.getLayerGauge( vDepth + 1 ) + if outerRg.getLayer().getMask() != innerRg.getLayer().getMask(): + useBigVia = True + pitch = self.rg.getPitch( outerRg.getLayer() ) ppitch = self.getPPitch( component.getLayer() ) - wwidth = self.getWireWidth( component.getLayer() ) + wwidth = self.getWireWidth( outerRg.getLayer() ) bb = component.getBoundingBox() xAxis = bb.getXCenter() - xOngrid = self.getNearestTrackAxis( component.getLayer(), xAxis ) + xOngrid = self.getNearestTrackAxis( outerRg.getLayer(), xAxis ) yMax = bb.getYMin() yMin = yMax - vMargin*ppitch width = bb.getWidth() @@ -382,22 +394,33 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): else: ppXAxis += width//2 ppXOngrid -= wwidth//2 - horizontal = Horizontal.create( component.getNet() - , component.getLayer() - , bb.getYMin() - , width - , ppXAxis - , ppXOngrid - ) + if useBigVia: + bvia = BigVia( component.getNet() + , innerRg.getDepth() + , xOngrid + , bb.getYMin() + wwidth + , wwidth + , 3*wwidth + , flags=BigVia.AllowAllExpand ) + bvia.mergeDepth( outerRg.getDepth() ) + bvia.doLayout() + else: + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , bb.getYMin() + , width + , ppXAxis + , ppXOngrid + ) vertical = Vertical.create( component.getNet() - , component.getLayer() + , outerRg.getLayer() , xOngrid , wwidth , yMin , yMax ) vertical = Vertical.create( component.getNet() - , component.getLayer() + , outerRg.getLayer() , xOngrid , wwidth , yMin @@ -405,6 +428,7 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): ) NetExternalComponents.setExternal( vertical ) for component in northPins: + trace( 550, '\tnorthPin {}\n'.format( component )) layer = component.getLayer() if layer.getMask() != gaugeMetal3.getLayer().getMask(): useBigVia = True @@ -462,3 +486,4 @@ def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): ) NetExternalComponents.setExternal( vertical ) self.cell.setAbutmentBox( self.outerAb ) + trace( 550, '-' ) diff --git a/documentation/content/images/notes/Katana-Debug_3.png b/documentation/content/images/notes/Katana-Debug_3.png new file mode 100755 index 000000000..51c336cc1 Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_3.png differ diff --git a/documentation/content/images/notes/Katana-Debug_4.png b/documentation/content/images/notes/Katana-Debug_4.png new file mode 100755 index 000000000..9fcb6a811 Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_4.png differ diff --git a/documentation/content/images/notes/Katana-Debug_5.png b/documentation/content/images/notes/Katana-Debug_5.png new file mode 100755 index 000000000..dd6fa7cbc Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_5.png differ diff --git a/documentation/content/images/notes/Katana-Debug_6.png b/documentation/content/images/notes/Katana-Debug_6.png new file mode 100755 index 000000000..179f311a5 Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_6.png differ diff --git a/documentation/content/images/notes/Katana-Debug_7.png b/documentation/content/images/notes/Katana-Debug_7.png new file mode 100755 index 000000000..de6a25984 Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_7.png differ diff --git a/documentation/content/images/notes/Katana-Debug_9.png b/documentation/content/images/notes/Katana-Debug_9.png new file mode 100755 index 000000000..0b4b51160 Binary files /dev/null and b/documentation/content/images/notes/Katana-Debug_9.png differ diff --git a/documentation/content/pages/documentation.rst b/documentation/content/pages/documentation.rst index e43cddbe8..8674f5dae 100644 --- a/documentation/content/pages/documentation.rst +++ b/documentation/content/pages/documentation.rst @@ -104,6 +104,9 @@ Coriolis Documentation `Oroshi Reference <../doc/oroshi/index.html>`_ |br| Analog devices generators + + `Technical Log <{filename}/pages/technical-log/TechnicalLog_HTML.rst>`_ |br| + Technical logs (history of changes & fixes). Third Party Documentation diff --git a/documentation/content/pages/python-tutorial/definitions.rst b/documentation/content/pages/python-tutorial/definitions.rst index 7bd40f2af..17a55e8aa 100644 --- a/documentation/content/pages/python-tutorial/definitions.rst +++ b/documentation/content/pages/python-tutorial/definitions.rst @@ -1,7 +1,7 @@ .. -*- Mode: rst -*- -.. Hurricane doxygen doc links. +.. Hurricane/doxygen doc links. .. _Breakpoint: ../doc/hurricane/classHurricane_1_1Breakpoint.html .. _UpdateSession: ../doc/hurricane/classHurricane_1_1UpdateSession.html .. _Layer: ../doc/hurricane/classHurricane_1_1Layer.html @@ -23,7 +23,6 @@ .. _Contact: ../doc/hurricane/classHurricane_1_1Contact.html .. _Contacts: ../doc/hurricane/classHurricane_1_1Contact.html .. _Pad: ../doc/hurricane/classHurricane_1_1Pad.html -.. _RoutingPad: ../doc/hurricane/classHurricane_1_1RoutingPad.html .. _RoutingPads: ../doc/hurricane/classHurricane_1_1RoutingPad.html .. _Horizontal: ../doc/hurricane/classHurricane_1_1Horizontal.html .. _Vertical: ../doc/hurricane/classHurricane_1_1Vertical.html diff --git a/documentation/content/pages/technical-log/December_2023.rst b/documentation/content/pages/technical-log/December_2023.rst new file mode 100644 index 000000000..14342871c --- /dev/null +++ b/documentation/content/pages/technical-log/December_2023.rst @@ -0,0 +1,197 @@ +.. -*- Mode: rst -*- + + +December 2023 +============= + + +|BUG| Bad Topology in ``NetBuilderHV::_do_xG_1M1()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In case of three globals (one ``M1`` terminal) and *no* south global, +the generated topology was wrong. We were accessing the terminal directly +with a vertical segment. It was creating a layer gap between *that* +vertical, which is ``M3`` and and terminal in ``M1``. This is also +too rigid a configuration. + +Fix: add an horizontal, in ``M2``, to access the terminal. + +Occured on ``benchs/RISC-V/Minerva/sky130_c4m/``. + +.. image:: {static}/images/notes/Katana-Debug_3.png + :alt: Faulty _do_xG_1M3 (no South) configuration. + :align: center + :width: 60% + + +|CHANGE| Reorganization of the size detection of RoutingPad +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of detecting the size characteristics of a RoutingPad_ at a late +stage when calling ``NetBuilder::_doRp_Access()``, do it once when first +loading the net in ``Dijkstra::load()`` with ``Configuration::selectRpcomponent()``. + +Add a new flag attribute on RoutingPad_ in order to store various +additionnal informations. Currently, the size characteristics. + +Add an ``M1Offgrid`` flags for the terminal characteristics set. + +Move ``getPositions()`` and ``checkRoutingPadSize()`` from ``NetBuilder`` to +``Anabatic::Configuration()``. + +In ``Anabatic::Configuration``, add support for the ``M1Offgrid`` options, +that allows fully offgrid terminals. + +The ``Anabatic::Configuration::checkRoutingpadSize()`` now store the +characteristics of the terminal (``HSmall``, ``VSmall``, ...) directly in +the flags of the ``RoutingPad``. + +For the whole function stack, work directly on RoutingPad_ instead of +``Component*`` : + +* ``NetBuilder::_doRp_StairCaseH()`` +* ``NetBuilder::_doRp_StairCaseV()`` +* ``NetBuilderHV::_doRp_Access()`` +* ``NetBuilderHV::_doRp_AutoContacts()`` +* ``NetBuilderHybridHV::_doRp_Access()`` +* ``NetBuilderHybridHV::_doRp_AutoContacts()`` +* ``NetBuilderM2::_doRp_Access()`` +* ``NetBuilderM2::_doRp_AutoContacts()`` + + +|NEW| Implementation of Pin Rectilinear Support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Add a ``PinRectilinearFilter`` to the ``LefImport`` parser in order to select +on which kind of biggest rectangle extracted from the ``Rectilinear`` we want +to create the ``Vertical`` or ``Horizontal`` *only* external component. +We can choose betwen the *tallest*, *widest* or *largest* (area). +There is also a minimum size filtering (to prune too small rectangle +from the start). + +Make use of the new feature in ``gf180mcu/mcu9t5v0.py``. + + +|NEW| Support for offgrid M1 & VH topologies (WIP 1) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Add a flag attribute in RoutingPad_ +--------------------------------------- + +To avoid re-computing informations about the RoutingPad_, namely it's size +characteristics (h-small, v-small, punctual, offgrid), add a ``flag`` attribute +in order to store those informations. They are computed in +``Anabatic::Configuration::selectRpComponent()``. + + +2. Implement horizontal dragging ``AutoContactTerminal::updateGeometry()`` +-------------------------------------------------------------------------- + +Dragging can occurs when an ``AutoContactTerminal`` is anchored on an +horizontal RoutingPad_ **and** the opposite of the connecting segment +is also horizontal. In that case, the connecting segment, which is +*perpandicular* can be *dragged* over the RoutingPad_ as to minimize +the length of the opposite horizontal. + +This feature was until now, only implemenred for verticals. + +.. image:: {static}/images/notes/Katana-Debug_7.png + :alt: Vertical dragging configuration. + :align: center + :width: 60% + + +3. Clarify sourcePosition & targetPosition on AutoSegments +---------------------------------------------------------- + +The ``_sourcePosition`` and ``_targetPosition`` of ``AutoHorizontal`` or +``AutoVertical`` have slighty different meanings whether the segment is +in preferred routing direction or not. + +A. **In preferred routing direction** (fig. a) the position extend from + the segment for *half* the minimum spacing (plus half the size of the + starting or ending VIA). With neighboring segments extentions + computed the same, we ensure that the minimal spacing is always kept. + The complex work of computing the value of the extension of the end + cap of a segment is done by ``AutoSegment::getExtensionCap()``. + +B. **In perpandicular routing direction** (fig. b) the ``_sourcePosition`` + to ``_targetPosition`` interval should cross all the perpandicular + track axis that it has a footprint on. As it may be misaligned and + likely to impinge on the leftmost or rightmost one. In that case, + we must extend by the *minimal spacing* (not it's half). + +.. image:: {static}/images/notes/Katana-Debug_9.png + :alt: Preferred & non-preferred track footprint. + :align: center + :width: 60% + + +The figure below is a simplificated description on how ``AutoSegment::getExtensionCap()`` +compute the extension from the ``sourceU`` coordinate. ``sourceU`` being the +starting or ending coordinate of segment, usually the axis of the perpandicular +it is connected to. + +.. image:: {static}/images/notes/Katana-Debug_6.png + :alt: Preferred & non-preferred track footprint. + :align: center + :width: 60% + + +4. Write topology for NetBuilderVH::_do_2G_1M1() +------------------------------------------------ + +.. image:: {static}/images/notes/Katana-Debug_5.png + :alt: topology of NetBuilderVH::_do_2G_1M1(). + :align: center + :width: 60% + + +4. Allow selection of HV or VH topologies for GF180MCU +------------------------------------------------------ + +In order to ease testing whithout constantly changing the configuration +file, provide a boolean in ``technos.setupGF180MCU_GF()`` to select it. + +In the ``dodo.py``, add: + +.. code-block:: python + + setupGF180MCU_GF( checkToolkit='../../..', pdkTop='../../../../gf180mcu-pdk', useHV=False ) + + +|NEW| Display the "ripup ratio" in Katana::Statistics +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This ratio is an attempt at characterizing the *hardness* of a design +(very elusive concept). It is crudely done for now, as it is just a +ratio between the initial number of events (which is equal to the +number of |TrackElements| to place). It do not take into account the +dogleg creation process that will introduce more primary events +as the net topologie are slackened. + + +|NEW| Support saving & restoring positions and settings of graphic windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The positions of the windows and *some* of the settings of the controller +can be saved and restored. The saving does not occurs at the closing of +the application. You have to take a *snapshot* of the state using the +``File -> Save settings`` menu. This allow to restart the application +in an initial state of your choosing and not at point you left it the +last time it was run. + +Widgets supporting the saving of their configuration gets two more methods: + +.. code:: C++ + + MyWidget::saveQtSettings(); + MyWidget::readQtSettings(); + +Currently we are saving: + +* ``UnicornGui`` +* ``CellViewer`` +* ``LibraryManager`` +* ``ControllerWidget`` and some of it's tabs. +* ``Breakpoint`` diff --git a/documentation/content/pages/technical-log/TechnicalLog_HTML.rst b/documentation/content/pages/technical-log/TechnicalLog_HTML.rst new file mode 100644 index 000000000..edf8a05a6 --- /dev/null +++ b/documentation/content/pages/technical-log/TechnicalLog_HTML.rst @@ -0,0 +1,22 @@ +.. -*- Mode: rst -*- + +====================== +Coriolis Technical Log +====================== + + +:slug: technical-log +:date: 2023-12-05 16:00 +:Authors: Jean-Paul Chaput +:Contact: +:Version: December 5, 2023 (jpc) +:status: hidden + + +.. include:: ../../../etc/definitions.rst + +.. contents:: + :depth: 2 + +.. include:: December_2023.rst + diff --git a/documentation/etc/definitions.rst b/documentation/etc/definitions.rst index 898592b5b..663afca6d 100644 --- a/documentation/etc/definitions.rst +++ b/documentation/etc/definitions.rst @@ -167,6 +167,9 @@ .. |man| replace:: :cb:`man` +.. |BUG| replace:: **BUG** | +.. |NEW| replace:: **NEW** | +.. |CHANGE| replace:: **CHANGE** | .. |KeyUp| replace:: :fboxtt:`Up` .. |KeyDown| replace:: :fboxtt:`Down` .. |KeyLeft| replace:: :fboxtt:`Left` @@ -261,3 +264,11 @@ .. |blif| replace:: :cb:`blif` .. |kgr| replace:: :cb:`kgr` .. |dot_conf| replace:: :cb:`.conf` + +.. Link to Hurricane doc (Doxygen) +.. _RoutingPad: {static}/doc/hurricane/classHurricane_1_1RoutingPad.html +.. |AutoSegment| replace:: :cb:`AutoSegment` +.. |AutoSegments| replace:: :cb:`AutoSegments` +.. |TrackElement| replace:: :cb:`TrackElement` +.. |TrackElements| replace:: :cb:`TrackElements` + diff --git a/documentation/examples/scripts/rectilinear.py b/documentation/examples/scripts/rectilinear.py index a5358ab71..23fa7e560 100644 --- a/documentation/examples/scripts/rectilinear.py +++ b/documentation/examples/scripts/rectilinear.py @@ -1,11 +1,11 @@ #!/usr/bin/python import sys -from Hurricane import DataBase, Net, \ - DbU, Point, Box, Rectilinear -from CRL import AllianceFramework, Catalog, Gds -from helpers import l, u -from helpers.overlay import UpdateSession +from coriolis.Hurricane import DataBase, Net, \ + DbU, Point, Box, Rectilinear +from coriolis.CRL import AllianceFramework, Catalog, Gds +from coriolis.helpers import l, u +from coriolis.helpers.overlay import UpdateSession def buildRectilinear ( editor ): diff --git a/documentation/meson.build b/documentation/meson.build index 73f37dfdc..13f675383 100644 --- a/documentation/meson.build +++ b/documentation/meson.build @@ -10,6 +10,7 @@ pdfcontent = files( rstcontent = files( + 'etc/definitions.rst', 'content/pages/design-flow/DesignFlow_HTML.rst', 'content/pages/design-flow/QuickStart.rst', 'content/pages/documentation.rst', @@ -41,6 +42,8 @@ rstcontent = files( 'content/pages/stratus/Patterns.rst', 'content/pages/stratus/Stratus_HTML.rst', 'content/pages/symbolic-layout.rst', + 'content/pages/technical-log/TechnicalLog_HTML.rst', + 'content/pages/technical-log/December_2023.rst', 'content/pages/users-guide/Configuration.rst', 'content/pages/users-guide/DesignFlow.rst', 'content/pages/users-guide/Installation.rst', diff --git a/documentation/pelicanconf.py.in b/documentation/pelicanconf.py.in index 351a5d222..73be94f31 100644 --- a/documentation/pelicanconf.py.in +++ b/documentation/pelicanconf.py.in @@ -18,6 +18,7 @@ STATIC_PATHS = [ 'pages/users-guide', 'pages/check-toolkit', 'pages/design-flow', 'pages/rds', + 'pages/technical-log', 'images', ] @@ -97,6 +98,8 @@ IGNORE_FILES = [ 'UsersGuide.rst' # For User's Guide. , 'DbU.rst' , 'Name.rst' + , 'December_2023.rst' # For Technical Logs + , 'Stratus.rst' # For Stratus. , 'Developper.rst' , 'DpGen.rst' diff --git a/documentation/themes/nest-coriolis/static/css/coriolis.css b/documentation/themes/nest-coriolis/static/css/coriolis.css index 012cf8c3d..5ded13d0a 100644 --- a/documentation/themes/nest-coriolis/static/css/coriolis.css +++ b/documentation/themes/nest-coriolis/static/css/coriolis.css @@ -63,6 +63,8 @@ div#contents { float: left; top: 260px; left: 20px; + width: 30%; + z-index: -1; } } diff --git a/documentation/themes/nest-coriolis/static/css/nest.css b/documentation/themes/nest-coriolis/static/css/nest.css index 0bf90a22b..dc6d133a1 100644 --- a/documentation/themes/nest-coriolis/static/css/nest.css +++ b/documentation/themes/nest-coriolis/static/css/nest.css @@ -121,7 +121,7 @@ code { padding: 3px 6px; } padding-left: 5px; padding-right: 5px; background:#fcfce1; - font-size: 14px; + font-size: 12px; font-weight: 400; font-family: Consolas, monaco, monospace; color: #000; diff --git a/etesian/src/FlattenPower.cpp b/etesian/src/FlattenPower.cpp index b8483c8d8..44f803c16 100644 --- a/etesian/src/FlattenPower.cpp +++ b/etesian/src/FlattenPower.cpp @@ -856,72 +856,75 @@ namespace { { cdebug_log(159,0) << "addToPowerRail: go=" << go << endl; const Component* component = dynamic_cast( go ); - if (component) { - if ( _framework->isPad(getMasterCell()) - and ( (_routingGauge->getLayerDepth(component->getLayer()) < 2) - or (component->getLayer()->getBasicLayers().getFirst()->getMaterial() - != BasicLayer::Material::blockage) ) ) - return; - - Net* rootNet = _blockageNet; - if (not _isBlockagePlane) { - rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath()); - if (not NetExternalComponents::isExternal(component)) return; - } - if (not rootNet) { - cdebug_log(159,0) << " rootNet is NULL, not taken into account." << endl; - return; - } - cdebug_log(159,0) << " rootNet " << rootNet << " " - << go->getCell() << " (" << go->getCell()->isTerminal() << ")" << endl; + if (not component) return; + + if ( _framework->isPad(getMasterCell()) + and ( (_routingGauge->getLayerDepth(component->getLayer()) < 2) + or (component->getLayer()->getBasicLayers().getFirst()->getMaterial() + != BasicLayer::Material::blockage) ) ) + return; - const Segment* segment = dynamic_cast( component ); - if (segment) { - _goMatchCount++; - cdebug_log(159,0) << " Merging PowerRail element: " << segment << endl; + Net* rootNet = _blockageNet; + if (not _isBlockagePlane) { + rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath()); + if (not NetExternalComponents::isExternal(component)) return; + } + if (not rootNet) { + cdebug_log(159,0) << " rootNet is NULL, not taken into account." << endl; + return; + } + cdebug_log(159,0) << " rootNet " << rootNet << " " + << go->getCell() << " (" << go->getCell()->isTerminal() << ")" << endl; - Box bb = segment->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); - _powerRailsPlanes.merge( bb, rootNet ); - } else { - const Contact* contact = dynamic_cast( component ); - if (contact) { - _goMatchCount++; + const Segment* segment = dynamic_cast( component ); + if (segment) { + _goMatchCount++; + cdebug_log(159,0) << " Merging PowerRail element: " << segment << endl; - Box bb = contact->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); + Box bb = segment->getBoundingBox( basicLayer ); + transformation.applyOn( bb ); + _powerRailsPlanes.merge( bb, rootNet ); + return; + } - cdebug_log(159,0) << " Merging PowerRail element: " << contact << " bb:" << bb - << " " << basicLayer << endl; - - _powerRailsPlanes.merge( bb, rootNet ); - } else { - const Pad* pad = dynamic_cast( component ); - if (pad) { - _goMatchCount++; - - Box bb = pad->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); - - cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb - << " " << basicLayer << endl; - - _powerRailsPlanes.merge( bb, rootNet ); - } else { - const Rectilinear* rectilinear = dynamic_cast( component ); - if (rectilinear and (rectilinear->getPoints().size() == 5)) { - _goMatchCount++; - - Box bb = rectilinear->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); - - cdebug_log(159,0) << " Merging PowerRail element: " << rectilinear << " bb:" << bb - << " " << basicLayer << endl; - - _powerRailsPlanes.merge( bb, rootNet ); - } - } - } + const Contact* contact = dynamic_cast( component ); + if (contact) { + _goMatchCount++; + + Box bb = contact->getBoundingBox( basicLayer ); + transformation.applyOn( bb ); + + cdebug_log(159,0) << " Merging PowerRail element: " << contact << " bb:" << bb + << " " << basicLayer << endl; + + _powerRailsPlanes.merge( bb, rootNet ); + return; + } + + const Pad* pad = dynamic_cast( component ); + if (pad) { + _goMatchCount++; + + Box bb = pad->getBoundingBox( basicLayer ); + transformation.applyOn( bb ); + + cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb + << " " << basicLayer << endl; + + _powerRailsPlanes.merge( bb, rootNet ); + return; + } + + const Rectilinear* rectilinear = dynamic_cast( component ); + if (rectilinear) { + _goMatchCount++; + cdebug_log(159,0) << " Merging PowerRail element: " << rectilinear << " " << basicLayer << endl; + vector boxes; + rectilinear->getAsRectangles( boxes, Rectilinear::HSliced ); + for ( Box bb : boxes ) { + transformation.applyOn( bb ); + cdebug_log(159,0) << " | " << " bb:" << bb << endl; + _powerRailsPlanes.merge( bb, rootNet ); } } } @@ -952,7 +955,7 @@ namespace Etesian { string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString(); RoutingGauge* rg = AllianceFramework::get()->getRoutingGauge( gaugeName ); if (not rg) - throw Error( "EtesianEngine::falttenPower(): No routing gauge named \"%s\"", gaugeName.c_str() ); + throw Error( "EtesianEngine::flattenPower(): No routing gauge named \"%s\"", gaugeName.c_str() ); //DebugSession::open( 150, 160 ); UpdateSession::open(); @@ -962,8 +965,7 @@ namespace Etesian { query.setStopCellFlags( Cell::Flags::AbstractedSupply ); for ( BasicLayer* layer : technology->getBasicLayers() ) { - if ( (layer->getMaterial() != BasicLayer::Material::metal) - and (layer->getMaterial() != BasicLayer::Material::blockage) ) + if (layer->getMaterial() != BasicLayer::Material::metal) continue; if (not query.hasBasicLayer(layer)) continue; diff --git a/hurricane/src/hurricane/Rectilinear.cpp b/hurricane/src/hurricane/Rectilinear.cpp index 63564ed7e..5bc61dba4 100644 --- a/hurricane/src/hurricane/Rectilinear.cpp +++ b/hurricane/src/hurricane/Rectilinear.cpp @@ -38,6 +38,7 @@ #include "hurricane/Cell.h" #include "hurricane/Error.h" #include "hurricane/Warning.h" +#include "hurricane/DebugSession.h" namespace { @@ -48,48 +49,144 @@ namespace { using Hurricane::Box; using Hurricane::Interval; using Hurricane::Rectilinear; + using Hurricane::DebugSession; + +// ------------------------------------------------------------------- +// Class : "SweepInterval". - class SweepInterval : public Interval { + + class SweepInterval { public: - inline SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin ); - inline SweepInterval ( Interval&, DbU::Unit xmin ); - inline SweepInterval& inflate ( DbU::Unit dvMin, DbU::Unit dvMax ); - inline SweepInterval& merge ( DbU::Unit v ); - inline DbU::Unit getXMin () const; - inline void setXMin ( DbU::Unit ); - inline string _getString () const; + inline SweepInterval (); + inline SweepInterval ( const SweepInterval& ); + inline SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin ); + inline SweepInterval ( Interval&, DbU::Unit xmin ); + inline bool isEmpty () const; + inline bool isKeep () const; + inline bool isNewLeft () const; + inline bool isExactMatch () const; + inline bool isSplinter () const; + inline bool isPonctual () const; + inline uint32_t getId () const; + inline DbU::Unit getVMin () const; + inline DbU::Unit getVMax () const; + inline DbU::Unit getSize () const; + inline const Interval& getSpan () const; + inline void inflate ( DbU::Unit dvMin, DbU::Unit dvMax ); + inline void updateSpan ( const Interval& ); + inline void merge ( DbU::Unit v ); + inline DbU::Unit getXMin () const; + inline void setXMin ( DbU::Unit ); + inline void setKeep (); + inline void setNewLeft (); + inline void setExactMatch (); + inline void setSplinter (); + inline void unsetNewLeft (); + inline void unsetSplinter (); + inline void clearUpdateFlags (); + inline string _getString () const; + inline bool operator< ( const SweepInterval& ) const; + private: + const uint32_t NOFLAGS = 0; + const uint32_t UPDATED = (1<<0); + const uint32_t CARVED = (1<<1); + const uint32_t ENLARGED = (1<<2); + const uint32_t EMPTY = (1<<3); + const uint32_t NEW_LEFT = (1<<4); + const uint32_t KEEP = (1<<5); + const uint32_t EXACT_MATCH = (1<<6); + const uint32_t SPLINTER = (1<<7); + static uint32_t _idCounter; private: + uint32_t _id; + Interval _span; + Interval _nextSpan; DbU::Unit _xMin; + uint32_t _flags; }; + + uint32_t SweepInterval::_idCounter = 0; + - inline SweepInterval::SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin ) - : Interval(vmin,vmax) - , _xMin (xmin) + inline SweepInterval::SweepInterval () + : _id (_idCounter++) + , _span () + , _xMin (0) + , _flags(EMPTY|NEW_LEFT) { } + + inline SweepInterval::SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin ) + : _id (_idCounter++) + , _span (vmin,vmax) + , _xMin (xmin) + , _flags(NOFLAGS|NEW_LEFT) + { } + + inline SweepInterval::SweepInterval ( Interval& base, DbU::Unit xmin ) - : Interval(base) - , _xMin (xmin) + : _id (_idCounter++) + , _span (base) + , _xMin (xmin) + , _flags(NEW_LEFT) + { } + + + inline SweepInterval::SweepInterval ( const SweepInterval& other ) + : _id (_idCounter++) + , _span (other._span) + , _xMin (other._xMin) + , _flags(other._flags) { } + + + inline bool SweepInterval::operator< ( const SweepInterval& o ) const + { + if (_span.getVMin() != o._span.getVMin()) return _span.getVMin() < o._span.getVMin(); + if (_span.getVMax() != o._span.getVMax()) return _span.getVMax() < o._span.getVMax(); + if (_xMin != o._xMin) return _xMin < o._xMin; + return _id < o._id; + } + + + inline bool SweepInterval::isEmpty () const { return (_flags & EMPTY); } + inline bool SweepInterval::isKeep () const { return (_flags & KEEP); } + inline bool SweepInterval::isNewLeft () const { return (_flags & NEW_LEFT); } + inline bool SweepInterval::isExactMatch () const { return (_flags & EXACT_MATCH); } + inline bool SweepInterval::isSplinter () const { return (_flags & SPLINTER); } + inline bool SweepInterval::isPonctual () const { return _span.isPonctual(); } + inline uint32_t SweepInterval::getId () const { return _id; } + inline const Interval& SweepInterval::getSpan () const { return _span; } + inline DbU::Unit SweepInterval::getVMin () const { return _span.getVMin(); } + inline DbU::Unit SweepInterval::getVMax () const { return _span.getVMax(); } + inline DbU::Unit SweepInterval::getSize () const { return _span.getSize(); } + inline void SweepInterval::inflate ( DbU::Unit dvMin, DbU::Unit dvMax ) { _span.inflate(dvMin,dvMax); } + inline void SweepInterval::merge ( DbU::Unit v ) { _span.merge(v); } + inline DbU::Unit SweepInterval::getXMin () const { return _xMin; } + inline void SweepInterval::setXMin ( DbU::Unit xmin ) { _xMin=xmin; } + inline void SweepInterval::setKeep () { _flags |= KEEP; } + inline void SweepInterval::setNewLeft () { _flags |= NEW_LEFT; } + inline void SweepInterval::setExactMatch () { _flags |= EXACT_MATCH; } + inline void SweepInterval::setSplinter () { _flags |= SPLINTER; } + inline void SweepInterval::unsetNewLeft () { _flags &= ~NEW_LEFT; } + inline void SweepInterval::unsetSplinter () { _flags &= ~SPLINTER; } + inline void SweepInterval::clearUpdateFlags () { _flags &= ~(KEEP | NEW_LEFT | EXACT_MATCH); } + inline void SweepInterval::updateSpan ( const Interval& v ) { _span.intersection(v); } - inline SweepInterval& SweepInterval::inflate ( DbU::Unit dvMin, DbU::Unit dvMax ) { Interval::inflate(dvMin,dvMax); return *this; } - inline SweepInterval& SweepInterval::merge ( DbU::Unit v ) { Interval::merge(v); return *this; } - inline DbU::Unit SweepInterval::getXMin () const { return _xMin; } - inline void SweepInterval::setXMin ( DbU::Unit xmin ) { _xMin=xmin; } inline string SweepInterval::_getString () const { string s; - s += "@" + DbU::getValueString(_xMin); - s += " [" + DbU::getValueString(getVMin()); - s += " " + DbU::getValueString(getVMax()) + "]"; + s += ""; return s; } -} // Anonymous namespace. +} GETSTRING_VALUE_SUPPORT(::SweepInterval); @@ -98,10 +195,14 @@ GETSTRING_VALUE_SUPPORT(::SweepInterval); namespace { - class SweepLine { +// ------------------------------------------------------------------- +// Class : "VSweepLine". + + + class VSweepLine { public: - SweepLine ( const Rectilinear*, vector& ); - ~SweepLine (); + VSweepLine ( const Rectilinear*, vector& ); + ~VSweepLine (); void addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x ); void loadVEdges (); void process ( Interval ); @@ -118,7 +219,7 @@ namespace { }; - SweepLine::SweepLine ( const Rectilinear* r, vector& boxes ) + VSweepLine::VSweepLine ( const Rectilinear* r, vector& boxes ) : _rectilinear(r) , _boxes (boxes) , _vedges () @@ -126,21 +227,21 @@ namespace { , _prevX (0) , _currX (0) { - cdebug_log(17,1) << "SweepLine::SweepLine()" << endl; + cdebug_log(17,1) << "VSweepLine::VSweepLine()" << endl; } - SweepLine::~SweepLine () + VSweepLine::~VSweepLine () { cdebug_tabw(17,-1); } - void SweepLine::addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x ) + void VSweepLine::addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x ) { if (ymin > ymax) std::swap( ymin, ymax ); - cdebug_log(17,1) << "SweepLine::addVEdge() @"<< DbU::getValueString(x) + cdebug_log(17,1) << "VSweepLine::addVEdge() @"<< DbU::getValueString(x) << " [" << DbU::getValueString(ymin) << " " << DbU::getValueString(ymax) << "]" << endl; @@ -179,7 +280,7 @@ namespace { } - void SweepLine::loadVEdges () + void VSweepLine::loadVEdges () { const vector& points = _rectilinear->getPoints(); for ( size_t i=0 ; i >& intervals ) + void VSweepLine::process ( const pair< DbU::Unit, list >& intervals ) { - cdebug_log(17,1) << "SweepLine::process() @"<< DbU::getValueString(intervals.first) + cdebug_log(17,1) << "VSweepLine::process() @"<< DbU::getValueString(intervals.first) << " size=" << intervals.second.size() << endl; _currX = intervals.first; for ( const Interval& v : intervals.second ) process( v ); @@ -303,13 +404,566 @@ namespace { } - void SweepLine::asRectangles () + void VSweepLine::asRectangles () { loadVEdges(); for ( auto intervals : _vedges ) { process( intervals ); } - cdebug_log(17,0) << "SweepLine::asRectangles() size=" << _boxes.size() << endl; + cdebug_log(17,0) << "VSweepLine::asRectangles() size=" << _boxes.size() << endl; + for ( const Box& b : _boxes ) + cdebug_log(17,0) << "| " << b << endl; + } + + +// ------------------------------------------------------------------- +// Class : "HSweepLine". + + + class HSweepLine { + public: + HSweepLine ( const Rectilinear*, vector& ); + ~HSweepLine (); + void addHEdge ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit y ); + void loadHEdges (); + void process ( Interval ); + void process ( const pair< DbU::Unit, list >& ); + void toBox ( SweepInterval& ); + void asRectangles (); + private: + const Rectilinear* _rectilinear; + vector& _boxes; + list< pair< DbU::Unit, list > > _vedges; + list< SweepInterval > _sweepLine; + DbU::Unit _prevY; + DbU::Unit _currY; + }; + + + HSweepLine::HSweepLine ( const Rectilinear* r, vector& boxes ) + : _rectilinear(r) + , _boxes (boxes) + , _vedges () + , _sweepLine () + , _prevY (0) + , _currY (0) + { + cdebug_log(17,1) << "HSweepLine::HSweepLine()" << endl; + } + + + HSweepLine::~HSweepLine () + { + cdebug_tabw(17,-1); + } + + + void HSweepLine::addHEdge ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit y ) + { + if (xmin > xmax) std::swap( xmin, xmax ); + + cdebug_log(17,1) << "HSweepLine::addHEdge() @"<< DbU::getValueString(y) + << " [" << DbU::getValueString(xmin) + << " " << DbU::getValueString(xmax) << "]" << endl; + + bool inserted = false; + for ( auto iy = _vedges.begin() ; iy != _vedges.end() ; ++iy ) { + cdebug_log(17,0) << "| Looking @" << DbU::getValueString(iy->first) + << " size=" << iy->second.size() << endl; + + if (iy->first > y) { + _vedges.insert( iy, make_pair( y, list() )); + cdebug_log(17,0) << "+ add new @" << DbU::getValueString(y) << endl; + --iy; + } + if (iy->first == y) { + for ( auto iintv = iy->second.begin() ; iintv != iy->second.end() ; ++iintv ) { + if (iintv->getVMin() >= xmax) { + iy->second.insert( iintv, Interval(xmin,xmax) ); + inserted = true; + break; + } + } + if (not inserted) { + iy->second.push_back( Interval(xmin,xmax) ); + inserted = true; + } + break; + } + } + if (not inserted) { + cdebug_log(17,0) << "+ add new (back) @" << DbU::getValueString(y) << endl; + _vedges.push_back( make_pair( y, list() )); + _vedges.back().second.push_back( Interval(xmin,xmax) ); + } + + cdebug_tabw(17,-1); + } + + + void HSweepLine::loadHEdges () + { + const vector& points = _rectilinear->getPoints(); + for ( size_t i=0 ; igetVMin()) { + _sweepLine.insert( iintv, SweepInterval(v,_currY) ); + done = true; + break; + } + // Extractor p. 9 (f). + if ( (v.getVMin() == iintv->getVMin()) + and (v.getVMax() == iintv->getVMax()) ) { + toBox( *iintv ); + _sweepLine.erase( iintv ); + done = true; + break; + } + // Extractor p. 9 (b). + if (v.getVMax() == iintv->getVMin()) { + toBox( *iintv ); + iintv->merge( v.getVMin() ); + done = true; + break; + } + // Extractor p. 9 (g). + if (v.getVMax() == iintv->getVMax()) { + toBox( *iintv ); + cdebug_log(17,0) << "case (g): carve" << endl; + iintv->inflate( 0, v.getVMin() - iintv->getVMax() ); + cdebug_log(17,0) << "| " << (*iintv) << endl; + done = true; + break; + } + // Extractor p. 9 (h). + if (v.getVMin() == iintv->getVMin()) { + toBox( *iintv ); + iintv->inflate(iintv->getVMin() - v.getVMax(), 0 ); + done = true; + break; + } + // Extractor p. 9 (c). + if ( (v.getVMin() > iintv->getVMin()) + and (v.getVMax() < iintv->getVMax()) ) { + toBox( *iintv ); + cdebug_log(17,0) << "case (c): carve" << endl; + DbU::Unit wholeVMin = iintv->getVMin(); + iintv->inflate( iintv->getVMin() - v.getVMax(), 0 ); + cdebug_log(17,0) << "| " << (*iintv) << endl; + _sweepLine.insert( iintv, SweepInterval( wholeVMin, v.getVMin(), _currY ) ); + cdebug_log(17,0) << "| " << (*(--iintv)) << endl; + done = true; + break; + } + // Extractor p. 9 (d,e). + if (v.getVMin() == iintv->getVMax()) { + auto iintvNext = iintv; + ++iintvNext; + // Extractor p. 9 (d). + if (iintvNext == _sweepLine.end()) { + toBox( *iintv ); + iintv->merge( v.getVMax() ); + } else { + // Extractor p. 9 (d). + if (v.getVMax() < iintvNext->getVMin()) { + toBox( *iintv ); + iintv->merge( v.getVMax() ); + } else { + // Extractor p. 9 (e). + toBox( *iintv ); + toBox( *iintvNext ); + iintv->merge( iintvNext->getVMax() ); + _sweepLine.erase( iintvNext ); + } + } + done = true; + break; + } + } + if (not done) { + _sweepLine.push_back( SweepInterval(v,_currY) ); + } + + cdebug_tabw(17,-1); + } + + + void HSweepLine::process ( const pair< DbU::Unit, list >& intervals ) + { + cdebug_log(17,1) << "HSweepLine::process() @"<< DbU::getValueString(intervals.first) + << " size=" << intervals.second.size() << endl; + _currY = intervals.first; + for ( const Interval& v : intervals.second ) process( v ); + cdebug_tabw(17,-1); + } + + + void HSweepLine::asRectangles () + { + loadHEdges(); + for ( auto intervals : _vedges ) { + process( intervals ); + } + cdebug_log(17,0) << "HSweepLine::asRectangles() size=" << _boxes.size() << endl; + for ( const Box& b : _boxes ) + cdebug_log(17,0) << "| " << b << endl; + } + + +// ------------------------------------------------------------------- +// Class : "SweepLineBig". + + + class SweepLineBig { + public: + SweepLineBig ( const Rectilinear* + , vector& + , DbU::Unit xThreshold + , DbU::Unit yThreshold ); + ~SweepLineBig (); + void addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x ); + void loadVEdges (); + void updateLeftSide (); + void process ( Interval ); + void process ( const pair< DbU::Unit, list >& ); + void flushBoxes ( const Interval& ); + void toBox ( SweepInterval& ); + void asRectangles (); + private: + const Rectilinear* _rectilinear; + vector& _boxes; + list< pair< DbU::Unit, list > > _vedges; + list< SweepInterval > _sweepLine; + list< SweepInterval > _leftSides; + DbU::Unit _currX; + DbU::Unit _xThreshold; + DbU::Unit _yThreshold; + }; + + + SweepLineBig::SweepLineBig ( const Rectilinear* r + , vector& boxes + , DbU::Unit xThreshold + , DbU::Unit yThreshold ) + : _rectilinear(r) + , _boxes (boxes) + , _vedges () + , _sweepLine () + , _leftSides () + , _currX (0) + , _xThreshold (xThreshold) + , _yThreshold (yThreshold) + { + cdebug_log(17,1) << "SweepLineBig::SweepLineBig()" << endl; + cdebug_log(17,0) << "_xThreshold=" << DbU::getValueString(_xThreshold) << endl; + cdebug_log(17,0) << "_yThreshold=" << DbU::getValueString(_yThreshold) << endl; + } + + + SweepLineBig::~SweepLineBig () + { + cdebug_tabw(17,-1); + } + + + void SweepLineBig::addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x ) + { + if (ymin > ymax) std::swap( ymin, ymax ); + + cdebug_log(17,1) << "SweepLineBig::addVEdge() @"<< DbU::getValueString(x) + << " [" << DbU::getValueString(ymin) + << " " << DbU::getValueString(ymax) << "]" << endl; + + bool inserted = false; + for ( auto ix = _vedges.begin() ; ix != _vedges.end() ; ++ix ) { + cdebug_log(17,0) << "| Looking @" << DbU::getValueString(ix->first) + << " size=" << ix->second.size() << endl; + + if (ix->first > x) { + _vedges.insert( ix, make_pair( x, list() )); + cdebug_log(17,0) << "+ add new @" << DbU::getValueString(x) << endl; + --ix; + } + if (ix->first == x) { + for ( auto iintv = ix->second.begin() ; iintv != ix->second.end() ; ++iintv ) { + if (iintv->getVMin() >= ymax) { + ix->second.insert( iintv, Interval(ymin,ymax) ); + inserted = true; + break; + } + } + if (not inserted) { + ix->second.push_back( Interval(ymin,ymax) ); + inserted = true; + } + break; + } + } + if (not inserted) { + cdebug_log(17,0) << "+ add new (back) @" << DbU::getValueString(x) << endl; + _vedges.push_back( make_pair( x, list() )); + _vedges.back().second.push_back( Interval(ymin,ymax) ); + } + + cdebug_tabw(17,-1); + } + + + void SweepLineBig::loadVEdges () + { + const vector& points = _rectilinear->getPoints(); + for ( size_t i=0 ; i 0) and (_currX - intv.getXMin() < _xThreshold)) return; + if ((_yThreshold > 0) and (intv.getSize() < _yThreshold)) return; + + _boxes.push_back( Box( intv.getXMin(), intv.getVMin() + , _currX , intv.getVMax() )); + cdebug_log(17,0) << " toBox() " << _boxes.back() << endl; + } + + + void SweepLineBig::updateLeftSide () + { + cdebug_log(17,1) << "SweepLineBig::updateLeftSide() @" << DbU::getValueString(_currX) << endl; + for ( auto isweep = _sweepLine.begin() ; isweep != _sweepLine.end() ; ++isweep ) { + cdebug_log(17,1) << "Sweep " << *isweep << endl; + DbU::Unit leftX = _currX; + for ( auto ileft = _leftSides.begin() ; (ileft != _leftSides.end()) ; ++ileft ) { + cdebug_log(17,0) << "| Left side " << *ileft << endl; + if (ileft->isNewLeft()) { + ileft->unsetNewLeft(); + continue; + } + if (isweep->getSpan() == ileft->getSpan()) { + cdebug_log(17,0) << "> Exact match" << endl; + isweep->setExactMatch(); + ileft ->setKeep(); + continue; + } + if (isweep->getSpan().contains( ileft->getSpan() )) { + cdebug_log(17,0) << "> Contained" << endl; + ileft->setKeep(); + continue; + } + if (ileft->getSpan().contains( isweep->getSpan() )) { + cdebug_log(17,0) << "> Full shrink" << endl; + if (not ileft->isSplinter()) toBox( *ileft ); + ileft->setKeep(); + _leftSides.push_back( SweepInterval( isweep->getVMax(), ileft->getVMax(), ileft->getXMin() ) ); + _leftSides.back().setSplinter(); + cdebug_log(17,0) << "+ Add remainder " << _leftSides.back() << endl; + ileft->updateSpan( isweep->getSpan() ); + ileft->unsetSplinter(); + isweep->setExactMatch(); + continue; + } + if (isweep->getSpan().intersect( ileft->getSpan() )) { + cdebug_log(17,0) << "> Intersect" << endl; + toBox( *ileft ); + ileft->updateSpan( isweep->getSpan() ); + ileft->unsetSplinter(); + if (not ileft->isPonctual()) ileft->setKeep(); + cdebug_log(17,0) << "> Shrinked span " << *ileft << endl; + continue; + } + } + + if (not isweep->isExactMatch()) { + _leftSides.push_back( SweepInterval( *isweep )); + _leftSides.back().setXMin( leftX ); + _leftSides.back().setKeep(); + cdebug_log(17,0) << "+ Added span " << _leftSides.back() << endl; + } + cdebug_tabw(17,-1); + } + + cdebug_log(17,0) << "Clean sweepline flags" << endl; + for ( auto isweep = _sweepLine.begin() ; isweep != _sweepLine.end() ; ++isweep ) { + isweep->clearUpdateFlags(); + } + _leftSides.sort(); + cdebug_log(17,0) << "Delete closed left sides & clean flags" << endl; + for ( auto ileft = _leftSides.begin() ; ileft != _leftSides.end() ; ) { + cdebug_log(17,0) << "| " << *ileft << endl; + auto ileftNext = ileft; + ileftNext++; + if (ileftNext != _leftSides.end()) { + if ( (ileft->getSpan().getVMin() == ileftNext->getSpan().getVMin()) + and (ileft->getSpan().getVMax() == ileftNext->getSpan().getVMax())) { + cdebug_log(17,0) << "> Remove duplicate " << *ileftNext << endl; + _leftSides.erase( ileftNext ); + continue; + } + } + if (not ileft->isKeep()) { + cdebug_log(17,0) << "> Remove/close " << *ileft << endl; + auto ileftNext = ileft; + ++ileftNext; + if (not ileft->isSplinter()) { + toBox( *ileft ); + } + _leftSides.erase( ileft ); + ileft = ileftNext; + continue; + } + ileft->clearUpdateFlags(); + ileft++; + } + cdebug_tabw(17,-1); + } + + + void SweepLineBig::process ( Interval v ) + { + cdebug_log(17,1) << "SweepLineBig::process(Interval&) " + << " [" << DbU::getValueString(v.getVMin()) + << " " << DbU::getValueString(v.getVMax()) << "]" << endl; + bool done = false; + for ( auto iintv = _sweepLine.begin() ; iintv != _sweepLine.end() ; ++iintv ) { + cdebug_log(17,0) << "> Sweepline element " << *iintv << endl; + // Extractor p. 9 (a). + if (v.getVMax() < iintv->getVMin()) { + cdebug_log(17,0) << "case (a): new left side" << endl; + _sweepLine.insert( iintv, SweepInterval(v,_currX) ); + done = true; + break; + } + // Extractor p. 9 (f). + if ( (v.getVMin() == iintv->getVMin()) + and (v.getVMax() == iintv->getVMax()) ) { + cdebug_log(17,0) << "case (f): closing right side" << endl; + _sweepLine.erase( iintv ); + done = true; + break; + } + // Extractor p. 9 (b). + if (v.getVMax() == iintv->getVMin()) { + cdebug_log(17,0) << "case (b): extend min" << endl; + iintv->merge( v.getVMin() ); + done = true; + break; + } + // Extractor p. 9 (g). + if (v.getVMax() == iintv->getVMax()) { + cdebug_log(17,0) << "case (g): carve" << endl; + iintv->inflate( 0, v.getVMin() - iintv->getVMax() ); + cdebug_log(17,0) << "| " << (*iintv) << endl; + done = true; + break; + } + // Extractor p. 9 (h). + if (v.getVMin() == iintv->getVMin()) { + cdebug_log(17,0) << "case (h): carve" << endl; + iintv->inflate(iintv->getVMin() - v.getVMax(), 0 ); + done = true; + break; + } + // Extractor p. 9 (c). + if ( (v.getVMin() > iintv->getVMin()) + and (v.getVMax() < iintv->getVMax()) ) { + cdebug_log(17,0) << "case (c): carve" << endl; + DbU::Unit wholeVMin = iintv->getVMin(); + iintv->inflate( iintv->getVMin() - v.getVMax(), 0 ); + cdebug_log(17,0) << "| " << (*iintv) << endl; + _sweepLine.insert( iintv, SweepInterval( wholeVMin, v.getVMin(), _currX ) ); + cdebug_log(17,0) << "| " << (*iintv) << endl; + done = true; + break; + } + // Extractor p. 9 (d,e). + if (v.getVMin() == iintv->getVMax()) { + cdebug_log(17,0) << "case (d,e): merge" << endl; + auto iintvNext = iintv; + ++iintvNext; + // Extractor p. 9 (d). + if (iintvNext == _sweepLine.end()) { + cdebug_log(17,0) << "case (d): end of vertical line" << endl; + iintv->merge( v.getVMax() ); + iintv->setXMin( _currX ); + } else { + // Extractor p. 9 (d). + if (v.getVMax() < iintvNext->getVMin()) { + cdebug_log(17,0) << "case (d): extend max" << endl; + iintv->merge( v.getVMax() ); + iintv->setXMin( _currX ); + } else { + // Extractor p. 9 (e). + cdebug_log(17,0) << "case (e): interval joining" << endl; + iintv->merge( iintvNext->getVMax() ); + iintv->setXMin( _currX ); + _sweepLine.erase( iintvNext ); + } + } + done = true; + break; + } + } + if (not done) { + _sweepLine.push_back( SweepInterval(v,_currX) ); + } + + cdebug_tabw(17,-1); + } + + + void SweepLineBig::process ( const pair< DbU::Unit, list >& intervals ) + { + cdebug_log(17,1) << "SweepLineBig::process() @"<< DbU::getValueString(intervals.first) + << " size=" << intervals.second.size() << endl; + _currX = intervals.first; + for ( const Interval& v : intervals.second ) process( v ); + updateLeftSide(); + cdebug_tabw(17,-1); + } + + + void SweepLineBig::asRectangles () + { + loadVEdges(); + for ( auto intervals : _vedges ) { + process( intervals ); + } + cdebug_log(17,0) << "SweepLineBig::asRectangles() size=" << _boxes.size() << endl; for ( const Box& b : _boxes ) cdebug_log(17,0) << "| " << b << endl; } @@ -470,11 +1124,28 @@ namespace Hurricane { } - bool Rectilinear::getAsRectangles ( std::vector& rectangles ) const + bool Rectilinear::getAsRectangles ( std::vector& rectangles, uint32_t flags ) const + { + rectangles.clear(); + if (not isRectilinear()) return false; + if (flags & VSliced) + VSweepLine( this, rectangles ).asRectangles(); + else + HSweepLine( this, rectangles ).asRectangles(); + return true; + } + + + bool Rectilinear::getAsBiggestRectangles ( std::vector& rectangles + , DbU::Unit xThreshold + , DbU::Unit yThreshold + ) const { + //DebugSession::open( 17, 18 ); rectangles.clear(); if (not isRectilinear()) return false; - SweepLine( this, rectangles ).asRectangles(); + SweepLineBig( this, rectangles, xThreshold, yThreshold ).asRectangles(); + //DebugSession::close(); return true; } diff --git a/hurricane/src/hurricane/RoutingPad.cpp b/hurricane/src/hurricane/RoutingPad.cpp index e2cd13e6f..6b9dc3e77 100644 --- a/hurricane/src/hurricane/RoutingPad.cpp +++ b/hurricane/src/hurricane/RoutingPad.cpp @@ -57,6 +57,7 @@ namespace Hurricane { RoutingPad::RoutingPad ( Net* net, Occurrence occurrence ) : Inherit (net) , _occurrence(occurrence) + , _flags (0) { } @@ -267,12 +268,26 @@ namespace Hurricane { jsonWrite( writer, "_occurrence", &_occurrence ); } + + std::string RoutingPad::getStringFlags () const + { + string s; + s += ((_flags & SelectedComponent) ? "S" : "-"); + s += ((_flags & HSmall ) ? "h" : "-"); + s += ((_flags & VSmall ) ? "v" : "-"); + s += ((_flags & Punctual ) ? "p" : "-"); + s += ((_flags & M1Offgrid ) ? "o" : "-"); + return s; + } + + string RoutingPad::_getString () const { string s = Inherit::_getString(); s.insert(s.length() - 1, " [" + DbU::getValueString(getX())); s.insert(s.length() - 1, " " + DbU::getValueString(getY())); s.insert(s.length() - 1, "] "); + s.insert(s.length() - 1, getStringFlags() + " "); s.insert(s.length() - 1, getString(_occurrence)); return s; } @@ -283,6 +298,7 @@ namespace Hurricane { Record* record = Inherit::_getRecord(); if ( record ) { record->add(getSlot("_occurrence",_occurrence)); + record->add(getSlot("_flags" ,_flags )); } return record; } diff --git a/hurricane/src/hurricane/hurricane/Query.h b/hurricane/src/hurricane/hurricane/Query.h index 3324cbe08..d0080af71 100644 --- a/hurricane/src/hurricane/hurricane/Query.h +++ b/hurricane/src/hurricane/hurricane/Query.h @@ -130,6 +130,7 @@ namespace Hurricane { inline void setStartLevel ( unsigned int level ); inline void setStopLevel ( unsigned int level ); inline void setStopCellFlags ( Cell::Flags ); + inline void unsetStopCellFlags ( Cell::Flags ); inline void init (); inline void updateTransformation (); inline bool levelDown (); @@ -197,6 +198,7 @@ namespace Hurricane { inline void QueryStack::setStartLevel ( unsigned int level ) { _startLevel = level; } inline void QueryStack::setStopLevel ( unsigned int level ) { _stopLevel = level; } inline void QueryStack::setStopCellFlags ( Cell::Flags flags ) { _stopCellFlags = flags; } + inline void QueryStack::unsetStopCellFlags ( Cell::Flags flags ) { _stopCellFlags.reset(flags); } inline void QueryStack::init () @@ -372,6 +374,7 @@ namespace Hurricane { inline void setStartLevel ( unsigned int level ); inline void setStopLevel ( unsigned int level ); inline void setStopCellFlags ( Cell::Flags ); + inline void unsetStopCellFlags ( Cell::Flags ); virtual void doQuery (); protected: @@ -385,15 +388,16 @@ namespace Hurricane { // Query Inline Functions. - inline void Query::setCell ( Cell* cell ) { _stack.setTopCell(cell); } - inline void Query::setArea ( const Box& area ) { _stack.setTopArea(area); } - inline void Query::setThreshold ( DbU::Unit threshold ) { _stack.setThreshold(threshold); } - inline void Query::setTransformation ( const Transformation& transformation ) { _stack.setTopTransformation(transformation); } - inline void Query::setFilter ( Mask filter ) { _filter = filter; } - inline void Query::setExtensionMask ( ExtensionSlice::Mask mask ) { _extensionMask = mask; } - inline void Query::setStartLevel ( unsigned int level ) { _stack.setStartLevel(level); } - inline void Query::setStopLevel ( unsigned int level ) { _stack.setStopLevel(level); } - inline void Query::setStopCellFlags ( Cell::Flags flags ) { _stack.setStopCellFlags(flags); } + inline void Query::setCell ( Cell* cell ) { _stack.setTopCell(cell); } + inline void Query::setArea ( const Box& area ) { _stack.setTopArea(area); } + inline void Query::setThreshold ( DbU::Unit threshold ) { _stack.setThreshold(threshold); } + inline void Query::setTransformation ( const Transformation& transformation ) { _stack.setTopTransformation(transformation); } + inline void Query::setFilter ( Mask filter ) { _filter = filter; } + inline void Query::setExtensionMask ( ExtensionSlice::Mask mask ) { _extensionMask = mask; } + inline void Query::setStartLevel ( unsigned int level ) { _stack.setStartLevel(level); } + inline void Query::setStopLevel ( unsigned int level ) { _stack.setStopLevel(level); } + inline void Query::setStopCellFlags ( Cell::Flags flags ) { _stack.setStopCellFlags(flags); } + inline void Query::unsetStopCellFlags ( Cell::Flags flags ) { _stack.unsetStopCellFlags(flags); } inline unsigned int Query::getStartLevel () const { return _stack.getStartLevel(); } inline unsigned int Query::getStopLevel () const { return _stack.getStopLevel(); } @@ -409,3 +413,6 @@ namespace Hurricane { } // Hurricane namespace. + + +INSPECTOR_PR_SUPPORT(Hurricane::Query::Mask); diff --git a/hurricane/src/hurricane/hurricane/Rectilinear.h b/hurricane/src/hurricane/hurricane/Rectilinear.h index 9a51ddb7b..63669cade 100644 --- a/hurricane/src/hurricane/hurricane/Rectilinear.h +++ b/hurricane/src/hurricane/hurricane/Rectilinear.h @@ -44,7 +44,8 @@ namespace Hurricane { public: typedef Component Super; static const uint32_t IsRectilinear = (1<<0); - + static const uint32_t VSliced = (1<<1); + static const uint32_t HSliced = (1<<2); public: static Rectilinear* create ( Net*, const Layer*, const vector& ); // Accessors. @@ -58,7 +59,11 @@ namespace Hurricane { virtual Point getPoint ( size_t i ) const; virtual const Layer* getLayer () const; inline Points getContour () const; - bool getAsRectangles ( std::vector& ) const; + bool getAsRectangles ( std::vector&, uint32_t flags=VSliced ) const; + bool getAsBiggestRectangles + ( std::vector& + , DbU::Unit xThreshold=0 + , DbU::Unit yThreshold=0 ) const; inline const vector& getPoints () const; Box getNearestHSide ( DbU::Unit y ) const; // Mutators. diff --git a/hurricane/src/hurricane/hurricane/RoutingPad.h b/hurricane/src/hurricane/hurricane/RoutingPad.h index aa81e8bde..575a4fa5d 100644 --- a/hurricane/src/hurricane/hurricane/RoutingPad.h +++ b/hurricane/src/hurricane/hurricane/RoutingPad.h @@ -53,6 +53,13 @@ namespace Hurricane { static const uint32_t IsOnSegment = (1 << 4); static const uint32_t IsOnPad = (1 << 5); static const uint32_t ComponentSelection = BiggestArea|HighestLayer|LowestLayer; + static const uint32_t HSmall = (1 << 6); + static const uint32_t VSmall = (1 << 7); + static const uint32_t Punctual = (1 << 8); + static const uint32_t M1Offgrid = (1 << 9); + static const uint32_t UserCenter = (1 << 10); + static const uint32_t SizeFlags = HSmall|VSmall|Punctual|M1Offgrid; + static const uint32_t SelectedComponent = (1 << 10); public: static RoutingPad* create ( Net*, Occurrence, uint32_t flags=0 ); static RoutingPad* create ( Pin* ); @@ -60,6 +67,14 @@ namespace Hurricane { // Accessors. bool isPlacedOccurrence ( uint32_t flags ) const; inline bool isAtTopLevel () const; + inline bool isHSmall () const; + inline bool isVSmall () const; + inline bool isPunctual () const; + inline bool isM1Offgrid () const; + inline bool hasUserCenter () const; + inline bool hasSelectedComponent () const; + inline Point getUserCenter () const; + inline uint32_t getFlags () const; inline Occurrence getOccurrence () const; Occurrence getPlugOccurrence (); virtual const Layer* getLayer () const; @@ -75,11 +90,15 @@ namespace Hurricane { DbU::Unit getSourceY () const; DbU::Unit getTargetX () const; DbU::Unit getTargetY () const; + std::string getStringFlags () const; // Mutators. virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); void setExternalComponent ( Component* ); Component* setOnBestComponent ( uint32_t flags ); + inline void setUserCenter ( const Point& ); void restorePlugOccurrence (); + inline void setFlags ( uint32_t ); + inline void unsetFlags ( uint32_t ); // Miscellaeous. template T* _getEntityAs () const; @@ -95,11 +114,24 @@ namespace Hurricane { private: // Attributes. Occurrence _occurrence; + uint32_t _flags; + Point _userCenter; }; - inline bool RoutingPad::isAtTopLevel () const { return _occurrence.getPath().isEmpty(); } - inline Occurrence RoutingPad::getOccurrence () const { return _occurrence; }; + inline bool RoutingPad::isAtTopLevel () const { return _occurrence.getPath().isEmpty(); } + inline bool RoutingPad::isHSmall () const { return (_flags & HSmall); } + inline bool RoutingPad::isVSmall () const { return (_flags & VSmall); } + inline bool RoutingPad::isPunctual () const { return (_flags & Punctual); } + inline bool RoutingPad::isM1Offgrid () const { return (_flags & M1Offgrid); } + inline bool RoutingPad::hasSelectedComponent () const { return (_flags & SelectedComponent); } + inline bool RoutingPad::hasUserCenter () const { return (_flags & UserCenter); } + inline Point RoutingPad::getUserCenter () const { return (hasUserCenter()) ? _userCenter : getCenter(); } + inline uint32_t RoutingPad::getFlags () const { return _flags; } + inline Occurrence RoutingPad::getOccurrence () const { return _occurrence; }; + inline void RoutingPad::setFlags ( uint32_t flags ) { _flags |= flags; } + inline void RoutingPad::unsetFlags ( uint32_t flags ) { _flags &= ~flags; } + inline void RoutingPad::setUserCenter ( const Point& center ) { _flags |= UserCenter; _userCenter = center; } template diff --git a/hurricane/src/isobar/PyHurricane.cpp b/hurricane/src/isobar/PyHurricane.cpp index 3abe04cee..e97aeca5a 100644 --- a/hurricane/src/isobar/PyHurricane.cpp +++ b/hurricane/src/isobar/PyHurricane.cpp @@ -901,6 +901,7 @@ extern "C" { PyBasicLayer_postModuleInit(); PyPin_postModuleInit(); PyRoutingPad_postModuleInit(); + PyRectilinear_postModuleInit(); PyNet_postModuleInit(); PyNetRoutingState_postModuleInit(); PyCell_postModuleInit(); diff --git a/hurricane/src/isobar/PyRectilinear.cpp b/hurricane/src/isobar/PyRectilinear.cpp index ca0e371b4..56f66616a 100644 --- a/hurricane/src/isobar/PyRectilinear.cpp +++ b/hurricane/src/isobar/PyRectilinear.cpp @@ -193,8 +193,9 @@ extern "C" { HTRY METHOD_HEAD( "Rectilinear.getAsRectangles()" ) - PyObject* pyList = NULL; - if (not PyArg_ParseTuple( args, "O:Rectilinear.getAsRectangles", &pyList )) { + PyObject* pyList = NULL; + unsigned int pyFlags = Rectilinear::VSliced; + if (not PyArg_ParseTuple( args, "O|I:Rectilinear.getAsRectangles", &pyList, &pyFlags )) { PyErr_SetString( ConstructorError, "Rectilinear.getAsRectangles(): Must have exactly one parameter." ); return NULL; } @@ -205,7 +206,45 @@ extern "C" { PyList_SetSlice( pyList, 0, PyList_Size(pyList), NULL ); vector boxes; - rectilinear->getAsRectangles( boxes ); + rectilinear->getAsRectangles( boxes, pyFlags ); + for ( size_t i=0 ; i_object = new Box ( boxes[i] ); + PyList_Append( pyList, (PyObject*)pyBox ); + } + HCATCH + + Py_RETURN_NONE; + } + + + static PyObject* PyRectilinear_getAsBiggestRectangles ( PyRectilinear *self, PyObject* args ) + { + cdebug_log(20,0) << "Rectilinear.getAsBiggestRectangles()" << endl; + + HTRY + METHOD_HEAD( "Rectilinear.getAsBiggestRectangles()" ) + + PyObject* pyList = NULL; + PyObject* pyHT = NULL; + PyObject* pyVT = NULL; + if (not PyArg_ParseTuple( args, "O|OO:Rectilinear.getAsBiggestRectangles", &pyList, &pyHT, &pyVT )) { + PyErr_SetString( ConstructorError, "Rectilinear.getAsBiggestRectangles(): Must have exactly one parameter." ); + return NULL; + } + if (not PyList_Check(pyList)) { + PyErr_SetString( ConstructorError, "Rectilinear.getAsBiggestRectangles(): Argument must be a list." ); + return NULL; + } + + PyList_SetSlice( pyList, 0, PyList_Size(pyList), NULL ); + vector boxes; + if (pyHT and pyVT) + rectilinear->getAsBiggestRectangles( boxes, PyAny_AsLong(pyHT), PyAny_AsLong(pyVT) ); + else + rectilinear->getAsBiggestRectangles( boxes ); for ( size_t i=0 ; i(message.c_str()) ); \ std::cerr << message << std::endl; \ } \ catch ( const Error& e ) { \ - std::string message = getString(e); \ + std::string message = "\n" + getString(e); \ if (not e.where().empty()) message += "\n" + e.where(); \ PyErr_SetString ( HurricaneError, message.c_str() ); \ std::cerr << message << std::endl; \ return NULL; \ } \ catch ( const Bug& e ) { \ - std::string message = getString(e); \ + std::string message = "\n" + getString(e); \ PyErr_SetString ( HurricaneError, message.c_str() ); \ std::cerr << message << std::endl; \ return NULL; \ @@ -1677,7 +1677,7 @@ extern "C" { return NULL; \ } \ catch ( const std::exception& e ) { \ - std::string message = std::string(e.what()); \ + std::string message = "\n" + std::string(e.what()); \ PyErr_SetString ( HurricaneError, message.c_str() ); \ std::cerr << message << std::endl; \ return NULL; \ diff --git a/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h b/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h index a3938f193..0d3e45574 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h +++ b/hurricane/src/isobar/hurricane/isobar/PyRectilinear.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef PY_RECTILINEAR_H -#define PY_RECTILINEAR_H - +#pragma once #include "hurricane/isobar/PyComponent.h" #include "hurricane/Rectilinear.h" @@ -40,8 +38,9 @@ namespace Isobar { extern PyTypeObject PyTypeRectilinear; extern PyMethodDef PyRectilinear_Methods[]; - extern PyObject* PyRectilinear_Link ( Hurricane::Rectilinear* object ); - extern void PyRectilinear_LinkPyType (); + extern PyObject* PyRectilinear_Link ( Hurricane::Rectilinear* object ); + extern void PyRectilinear_LinkPyType (); + extern void PyRectilinear_postModuleInit (); #define IsPyRectilinear(v) ( (v)->ob_type == &PyTypeRectilinear ) @@ -52,5 +51,3 @@ namespace Isobar { } // extern "C". } // Isobar namespace. - -#endif // PY_RECTILINEAR_H diff --git a/hurricane/src/viewer/BreakpointWidget.cpp b/hurricane/src/viewer/BreakpointWidget.cpp index ce5272417..38d24ea07 100644 --- a/hurricane/src/viewer/BreakpointWidget.cpp +++ b/hurricane/src/viewer/BreakpointWidget.cpp @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -29,6 +30,30 @@ namespace Hurricane { + QByteArray BreakpointWidget::_geometry; + + + void BreakpointWidget::readQtSettings () + { + QSettings settings; + QString sizeKey = QString( "BreakpointWidget/geometry" ); + if (not settings.contains(sizeKey)) return; + settings.beginGroup( QString("BreakpointWidget") ); + _geometry = settings.value( "geometry" ).toByteArray(); + settings.endGroup(); + } + + + void BreakpointWidget::saveQtSettings () + { + if (_geometry.isNull()) return; + QSettings settings; + settings.beginGroup( QString("BreakpointWidget") ); + settings.setValue( "geometry", _geometry ); + settings.endGroup(); + } + + BreakpointWidget::BreakpointWidget ( QWidget* parent ) : QDialog (parent) , _message (new QLabel()) @@ -43,14 +68,16 @@ namespace Hurricane { //_message->setTextFormat ( Qt::RichText ); _message->setText ( "No Message Yet" ); + _message->setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ); QLabel* stopLabel = new QLabel (); stopLabel->setText ( "Adjust Stop Level:" ); QPushButton* ok = new QPushButton (); - ok->setIcon ( QIcon(":/images/angry-birds-chuck.png") ); - ok->setFlat ( true ); - ok->setIconSize ( (Graphics::isHighDpi() ? QSize(200,200) : QSize(80,80)) ); + ok->setIcon ( QIcon(":/images/angry-birds-chuck.png") ); + ok->setFlat ( true ); + ok->setIconSize ( (Graphics::isHighDpi() ? QSize(200,200) : QSize(80,80)) ); + ok->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed ); QFrame* vLine = new QFrame (); vLine->setFrameShape ( QFrame::VLine ); @@ -58,7 +85,7 @@ namespace Hurricane { QGridLayout* layout = new QGridLayout (); //layout->setSizeConstraint ( QLayout::SetFixedSize ); - layout->addWidget ( _message , 0, 0 ); + layout->addWidget ( _message , 0, 0, 1, 2 ); layout->addWidget ( stopLabel , 1, 0 ); layout->addWidget ( _stopLevel, 1, 1 ); layout->addWidget ( vLine , 0, 2, 2, 1 ); @@ -83,6 +110,7 @@ namespace Hurricane { _isFinished = false; show (); + if (not _geometry.isNull()) restoreGeometry( _geometry ); // Snipet code from Qt's QDialog. _eventLoop = new QEventLoop (); @@ -90,6 +118,7 @@ namespace Hurricane { _eventLoop->exec( QEventLoop::DialogExec ); _eventLoop = NULL; + _geometry = saveGeometry(); if (guard.isNull()) return QDialog::Rejected; return result(); diff --git a/hurricane/src/viewer/CellViewer.cpp b/hurricane/src/viewer/CellViewer.cpp index a2b3f40e9..8f0cc0bc7 100644 --- a/hurricane/src/viewer/CellViewer.cpp +++ b/hurricane/src/viewer/CellViewer.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -88,7 +89,8 @@ namespace Hurricane { // ------------------------------------------------------------------- // Class : "CellViewer". - QString CellViewer::_prefixWPath ( "viewer.menuBar." ); + QString CellViewer::_prefixWPath ( "viewer.menuBar." ); + vector CellViewer::_allViewers; CellViewer::CellViewer ( QWidget* parent ) : QMainWindow (parent) @@ -115,6 +117,7 @@ namespace Hurricane { , _updateState (ExternalEmit) , _pyScriptName () { + _allViewers.push_back( this ); setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); setObjectName( "viewer" ); menuBar()->setObjectName ( _getAbsWidgetPath("") ); @@ -183,6 +186,12 @@ namespace Hurricane { _controller->deleteLater (); //_script->deleteLater (); _goto->deleteLater (); + for ( auto iviewer = _allViewers.begin() ; iviewer != _allViewers.end() ; ++iviewer ) { + if (*iviewer == this ) { + _allViewers.erase( iviewer ); + break; + } + } } @@ -490,12 +499,6 @@ namespace Hurricane { ); connect( action, SIGNAL(triggered()), this, SLOT(close()) ); - action = addToMenu( "file.close" - , tr("&Close") - , tr("Close This Coriolis CellViewer") - , QKeySequence(tr("CTRL+W")) - ); - action = addToMenu( "file.exit" , tr("&Exit") , tr("Exit All Coriolis CellViewer") @@ -711,6 +714,31 @@ namespace Hurricane { } + void CellViewer::readQtSettings () + { + size_t viewerId = getAllViewers().size() - 1; + QSettings settings; + QString sizeKey = QString( "CellViewer/%1/geometry" ).arg( viewerId ); + if (not settings.contains(sizeKey)) return; + settings.beginGroup( QString("CellViewer/%1").arg(viewerId) ); + restoreGeometry( settings.value( "geometry" ).toByteArray() ); + getControllerWidget()->readQtSettings( viewerId ); + settings.endGroup(); + } + + + void CellViewer::saveQtSettings () + { + QSettings settings; + for ( size_t i=0 ; i<_allViewers.size() ; ++i ) { + settings.beginGroup( QString("CellViewer/%1").arg(i) ); + settings.setValue( "geometry", _allViewers[i]->saveGeometry() ); + _allViewers[i]->getControllerWidget()->saveQtSettings( i ); + settings.endGroup(); + } + } + + void CellViewer::doGoto () { if ( _goto->exec() == QDialog::Accepted ) { diff --git a/hurricane/src/viewer/ControllerWidget.cpp b/hurricane/src/viewer/ControllerWidget.cpp index 4b425f108..fae111e58 100644 --- a/hurricane/src/viewer/ControllerWidget.cpp +++ b/hurricane/src/viewer/ControllerWidget.cpp @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -77,6 +78,14 @@ namespace Hurricane { { } + void ControllerTab::readQtSettings ( size_t viewerId ) + { } + + + void ControllerTab::saveQtSettings ( size_t viewerId ) const + { } + + // ------------------------------------------------------------------- // Class : "Hurricane::TabGraphics". @@ -107,6 +116,14 @@ namespace Hurricane { { _graphics->rereadGraphics(); } + void TabGraphics::readQtSettings ( size_t viewerId ) + { _graphics->readQtSettings( viewerId ); } + + + void TabGraphics::saveQtSettings ( size_t viewerId ) const + { _graphics->saveQtSettings( viewerId );} + + // ------------------------------------------------------------------- // Class : "Hurricane::TabDisplayFilter". @@ -133,6 +150,14 @@ namespace Hurricane { } + void TabDisplayFilter::readQtSettings ( size_t viewerId ) + { _displayFilter->readQtSettings( viewerId ); } + + + void TabDisplayFilter::saveQtSettings ( size_t viewerId ) const + { _displayFilter->saveQtSettings( viewerId );} + + // ------------------------------------------------------------------- // Class : "Hurricane::TabPalette". @@ -170,6 +195,14 @@ namespace Hurricane { { _palette->rereadGraphics(); } + void TabPalette::readQtSettings ( size_t viewerId ) + { _palette->readQtSettings( viewerId ); } + + + void TabPalette::saveQtSettings ( size_t viewerId ) const + { _palette->saveQtSettings( viewerId );} + + // ------------------------------------------------------------------- // Class : "Hurricane::TabNetlist". @@ -279,6 +312,14 @@ namespace Hurricane { } + + void TabNetlist::readQtSettings ( size_t viewerId ) + { _netlistBrowser->readQtSettings( viewerId ); } + + + void TabNetlist::saveQtSettings ( size_t viewerId ) const + { _netlistBrowser->saveQtSettings( viewerId );} + // ------------------------------------------------------------------- // Class : "Hurricane::TabNetlist". @@ -671,6 +712,42 @@ namespace Hurricane { } + void ControllerWidget::readQtSettings ( size_t viewerId ) + { + QSettings settings; + QString sizeKey = QString( "CellViewer/%1/controller/geometry" ).arg( viewerId ); + if (not settings.contains(sizeKey)) return; + settings.beginGroup( QString("CellViewer/%1/controller").arg(viewerId) ); + restoreGeometry( settings.value( "geometry" ).toByteArray() ); + _tabGraphics ->readQtSettings( viewerId ); + _tabPalette ->readQtSettings( viewerId ); + _tabDisplayFilter->readQtSettings( viewerId ); + _tabNetlist ->readQtSettings( viewerId ); + _tabHierarchy ->readQtSettings( viewerId ); + _tabSelection ->readQtSettings( viewerId ); + _tabInspector ->readQtSettings( viewerId ); + _tabSettings ->readQtSettings( viewerId ); + settings.endGroup(); + } + + + void ControllerWidget::saveQtSettings ( size_t viewerId ) const + { + QSettings settings; + settings.beginGroup( QString("CellViewer/%1/controller").arg(viewerId) ); + settings.setValue( "geometry", saveGeometry() ); + _tabGraphics ->saveQtSettings( viewerId ); + _tabPalette ->saveQtSettings( viewerId ); + _tabDisplayFilter->saveQtSettings( viewerId ); + _tabNetlist ->saveQtSettings( viewerId ); + _tabHierarchy ->saveQtSettings( viewerId ); + _tabSelection ->saveQtSettings( viewerId ); + _tabInspector ->saveQtSettings( viewerId ); + _tabSettings ->saveQtSettings( viewerId ); + settings.endGroup(); + } + + // ------------------------------------------------------------------- // Class : "ControllerWidget::GraphicsObserver". diff --git a/hurricane/src/viewer/DisplayFilterWidget.cpp b/hurricane/src/viewer/DisplayFilterWidget.cpp index 273d0f27c..3d4b28bdf 100644 --- a/hurricane/src/viewer/DisplayFilterWidget.cpp +++ b/hurricane/src/viewer/DisplayFilterWidget.cpp @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -437,4 +438,56 @@ namespace Hurricane { } + void DisplayFilterWidget::readQtSettings ( size_t viewerId ) + { + QSettings settings; + QString checkKey = QString( "CellViewer/%1/controller/displayFilter/hierarchyStartLevel" ).arg( viewerId ); + if (not settings.contains(checkKey)) return; + settings.beginGroup( QString("CellViewer/%1/controller/displayFilter").arg(viewerId) ); + + _cellWidget->setStartLevel( settings.value( "hierarchyStartLevel" ).toInt() ); + _cellWidget->setStopLevel ( settings.value( "hierarchyStopLevel" ).toInt() ); + + Query::Mask queryFilter = _cellWidget->getQueryFilter(); + queryFilter.unset( Query::DoMasterCells|Query::DoTerminalCells|Query::DoComponents ); + if (settings.value( "processMasterCells" ).toBool()) queryFilter.set( Query::DoMasterCells ); + if (settings.value( "processTerminalCells" ).toBool()) queryFilter.set( Query::DoTerminalCells ); + if (settings.value( "processComponents" ).toBool()) queryFilter.set( Query::DoComponents ); + _cellWidget->setQueryFilter( queryFilter ); + + switch ( settings.value( "rubbers" ).toInt() ) { + case CellWidget::Steiner: _cellWidget->setRubberShape( CellWidget::Steiner ); break; + case CellWidget::Centric: _cellWidget->setRubberShape( CellWidget::Centric ); break; + case CellWidget::Barycentric: _cellWidget->setRubberShape( CellWidget::Barycentric ); break; + } + + switch ( settings.value( "layoutMode" ).toInt() ) { + case 0: _cellWidget->changeDbuMode( DbU::Symbolic, _cellWidget->getUnitPower() ); break; + case 1: _cellWidget->changeDbuMode( DbU::Grid , _cellWidget->getUnitPower() ); break; + case 2: _cellWidget->changeDbuMode( DbU::Physical, DbU::Micro ); break; + case 3: _cellWidget->changeDbuMode( DbU::Physical, DbU::Nano ); break; + } + settings.endGroup(); + } + + + void DisplayFilterWidget::saveQtSettings ( size_t viewerId ) const + { + QSettings settings; + settings.beginGroup( QString("CellViewer/%1/controller/displayFilter").arg(viewerId) ); + settings.setValue( "hierarchyStartLevel" , _startSpinBox ->value () ); + settings.setValue( "hierarchyStopLevel" , _stopSpinBox ->value () ); + settings.setValue( "processMasterCells" , _doMasterCells ->isChecked() ); + settings.setValue( "processTerminalCells", _doTerminalCells->isChecked() ); + settings.setValue( "processComponents" , _doComponents ->isChecked() ); + settings.setValue( "rubbers" , (int)_cellWidget->getRubberShape() ); + int layoutMode = 0; + if (_cellWidget->symbolicMode()) layoutMode = 0; + if (_cellWidget->gridMode()) layoutMode = 1; + if (_cellWidget->physicalMode() and (_cellWidget->getUnitPower() == DbU::Micro)) layoutMode = 2; + if (_cellWidget->physicalMode() and (_cellWidget->getUnitPower() == DbU::Nano )) layoutMode = 3; + settings.setValue( "layoutMode", layoutMode ); + settings.endGroup(); + } + } diff --git a/hurricane/src/viewer/GraphicsWidget.cpp b/hurricane/src/viewer/GraphicsWidget.cpp index 72ba08689..53592d53d 100644 --- a/hurricane/src/viewer/GraphicsWidget.cpp +++ b/hurricane/src/viewer/GraphicsWidget.cpp @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -134,4 +135,34 @@ namespace Hurricane { } + void GraphicsWidget::readQtSettings ( size_t viewerId ) + { + const vector& styles = Graphics::getStyles (); + QSettings settings; + QString checkKey = QString( "CellViewer/%1/controller/graphics/displayStyle" ).arg( viewerId ); + if (not settings.contains(checkKey)) return; + settings.beginGroup( QString("CellViewer/%1/controller/graphics").arg(viewerId) ); + int styleId = settings.value( "displayStyle" ).toInt(); + if (styleId >= 0) { + if ((size_t)styleId < styles.size()) { + _cellWidget->setStyle( (size_t)styleId ); + _stylesGroup->button( styleId )->setChecked( true ); + } else { + cerr << Warning( "GraphicsWidget::readQtSettings(): Unable to restore style id=%d (only %d styles)." + , styleId, styles.size() + ) << endl; + } + } + settings.endGroup(); + } + + + void GraphicsWidget::saveQtSettings ( size_t viewerId ) const + { + QSettings settings; + settings.beginGroup( QString("CellViewer/%1/controller/graphics").arg(viewerId) ); + settings.setValue( "displayStyle" , _stylesGroup->checkedId() ); + settings.endGroup(); + } + } // Hurricane namespace. diff --git a/hurricane/src/viewer/HApplication.cpp b/hurricane/src/viewer/HApplication.cpp index f168b7fd5..244de8173 100644 --- a/hurricane/src/viewer/HApplication.cpp +++ b/hurricane/src/viewer/HApplication.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "hurricane/Bug.h" #include "hurricane/Error.h" #include "hurricane/viewer/Graphics.h" @@ -38,28 +39,28 @@ namespace Hurricane { HApplication::HApplication ( int& argc, char** argv ) : QApplication ( argc, argv ) - { } + { sharedCtor(); } HApplication::HApplication ( int& argc, char** argv, bool GUIenabled ) : QApplication ( argc, argv, GUIenabled ) - { } + { sharedCtor(); } // HApplication::HApplication ( int& argc, char** argv, Type type ) // : QApplication ( argc, argv, type ) -// { } +// { sharedCtor(); } #if defined(Q_WS_X11) HApplication::HApplication ( Display* display, Qt::HANDLE visual, Qt::HANDLE colormap ) : QApplication ( display, visual, colormap ) - { } + { sharedCtor(); } HApplication::HApplication ( Display* display, int& argc, char** argv, Qt::HANDLE visual, Qt::HANDLE colormap ) : QApplication ( display, argc, argv, visual, colormap ) - { } + { sharedCtor(); } #endif @@ -91,4 +92,12 @@ namespace Hurricane { } -} // End of Hurricane namespace. + void HApplication::sharedCtor () + { + QCoreApplication::setOrganizationName ( "SU-LIP6" ); + QCoreApplication::setOrganizationDomain( "lip6.fr" ); + QCoreApplication::setApplicationName ( "Coriolis" ); + } + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/NetlistWidget.cpp b/hurricane/src/viewer/NetlistWidget.cpp index 8902993a7..75aaa0382 100644 --- a/hurricane/src/viewer/NetlistWidget.cpp +++ b/hurricane/src/viewer/NetlistWidget.cpp @@ -14,6 +14,7 @@ // +-----------------------------------------------------------------+ +#include #include #include #include @@ -185,4 +186,23 @@ namespace Hurricane { } + void NetlistWidget::readQtSettings ( size_t viewerId ) + { + QSettings settings; + QString checkKey = QString( "CellViewer/%1/controller/netlist/filterPattern" ).arg( viewerId ); + if (not settings.contains(checkKey)) return; + settings.beginGroup( QString("CellViewer/%1/controller/netlist").arg(viewerId) ); + _filterPatternLineEdit->setText( settings.value( "filterPattern" ).toString() ); + settings.endGroup(); + } + + + void NetlistWidget::saveQtSettings ( size_t viewerId ) const + { + QSettings settings; + settings.beginGroup( QString("CellViewer/%1/controller/netlist").arg(viewerId) ); + settings.setValue( "filterPattern", _filterPatternLineEdit->text() ); + settings.endGroup(); + } + } // End of Hurricane namespace. diff --git a/hurricane/src/viewer/PaletteWidget.cpp b/hurricane/src/viewer/PaletteWidget.cpp index a17b7d7ff..68bc2f616 100644 --- a/hurricane/src/viewer/PaletteWidget.cpp +++ b/hurricane/src/viewer/PaletteWidget.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -535,4 +536,31 @@ namespace Hurricane { } + void PaletteWidget::readQtSettings ( size_t viewerId ) + { + QSettings settings; + QString fallbackKey = QString( "CellViewer/%1/controller/palette/fallback/visible" ).arg( viewerId ); + if (not settings.contains(fallbackKey)) return; + settings.beginGroup( QString("CellViewer/%1/controller/palette").arg(viewerId) ); + for ( auto item : _layerItems ) { + QString itemKey = QString("%1/visible").arg( getString(item.first).c_str() ); + if (not settings.contains(itemKey)) continue; + item.second->setItemVisible ( settings.value( itemKey ).toBool() ); + item.second->setItemSelectable( settings.value( itemKey.replace("visible","selectable") ).toBool() ); + } + settings.endGroup(); + } + + + void PaletteWidget::saveQtSettings ( size_t viewerId ) const + { + QSettings settings; + settings.beginGroup( QString("CellViewer/%1/controller/palette").arg(viewerId) ); + for ( auto item : _layerItems ) { + settings.setValue( QString( "%1/visible" ).arg(getString(item.first).c_str()), item.second->isItemVisible () ); + settings.setValue( QString( "%1/selectable" ).arg(getString(item.first).c_str()), item.second->isItemSelectable() ); + } + settings.endGroup(); + } + } // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/BreakpointWidget.h b/hurricane/src/viewer/hurricane/viewer/BreakpointWidget.h index 9d7561f5c..eee1525b1 100644 --- a/hurricane/src/viewer/hurricane/viewer/BreakpointWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/BreakpointWidget.h @@ -14,9 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef HURRICANE_BREAKPOINT_WIDGET_H -#define HURRICANE_BREAKPOINT_WIDGET_H - +#pragma once #include #include class QLabel; @@ -28,27 +26,27 @@ namespace Hurricane { class BreakpointWidget : public QDialog { Q_OBJECT; - public: - BreakpointWidget ( QWidget* parent=NULL); - void setMessage ( const QString& ); - int getStopLevel () const; - void setStopLevel ( int ); - int execNoModal (); + static void readQtSettings (); + static void saveQtSettings (); + public: + BreakpointWidget ( QWidget* parent=NULL); + void setMessage ( const QString& ); + int getStopLevel () const; + void setStopLevel ( int ); + int execNoModal (); public slots: - void updateStopLevel ( int ); + void updateStopLevel ( int ); protected slots: - void raiseFinished ( int ); - + void raiseFinished ( int ); private: - QLabel* _message; - QSpinBox* _stopLevel; - bool _isFinished; - QEventLoop* _eventLoop; + static QByteArray _geometry; + QLabel* _message; + QSpinBox* _stopLevel; + bool _isFinished; + QEventLoop* _eventLoop; }; } // Hurricane namespace. - -#endif // HURRICANE_BREAKPOINT_WIDGET_H diff --git a/hurricane/src/viewer/hurricane/viewer/CellViewer.h b/hurricane/src/viewer/hurricane/viewer/CellViewer.h index 55946f906..2813b9c78 100644 --- a/hurricane/src/viewer/hurricane/viewer/CellViewer.h +++ b/hurricane/src/viewer/hurricane/viewer/CellViewer.h @@ -82,11 +82,16 @@ namespace Hurricane { typedef std::map< const QString, boost::any > ActionLut; typedef bool (QWidget::* SlotMethod)(); public: + static inline const std::vector& + getAllViewers (); static void notify ( CellViewer*, unsigned int flags ); public: CellViewer ( QWidget* parent=NULL ); virtual ~CellViewer (); inline bool isToolInterrupted () const; + inline size_t getSettingsId () const; + void readQtSettings (); + void saveQtSettings (); void refreshTitle (); QMenu* createDebugMenu (); bool hasMenu ( const QString& path ) const; @@ -175,6 +180,7 @@ namespace Hurricane { void _runScript ( QString scriptPath ); protected: + static std::vector _allViewers; static QString _prefixWPath; Observer _cellObserver; QString _applicationName; @@ -205,6 +211,8 @@ namespace Hurricane { // Inline Functions. + inline const std::vector& + CellViewer::getAllViewers () { return _allViewers; } inline bool CellViewer::isToolInterrupted () const { return _toolInterrupt; } inline Observer* CellViewer::getCellObserver () { return &_cellObserver; } inline CellWidget* CellViewer::getCellWidget () { return _cellWidget; } @@ -226,6 +234,14 @@ namespace Hurricane { inline void CellViewer::setDbuMode ( int mode ) { _cellWidget->setDbuMode(mode); } + inline size_t CellViewer::getSettingsId () const + { + for ( size_t i=0; i<_allViewers.size() ; ++i ) { + if (_allViewers[i] == this) return i; + } + return 0; + } + } // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h b/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h index a74f27135..82ef6182d 100644 --- a/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/ControllerWidget.h @@ -14,10 +14,7 @@ // +-----------------------------------------------------------------+ -#ifndef HURRICANE_CONTROLLER_WIDGET_H -#define HURRICANE_CONTROLLER_WIDGET_H - - +#pragma once #include class QCheckBox; class QComboBox; @@ -57,6 +54,8 @@ namespace Hurricane { public: ControllerTab ( QWidget* parent=NULL ); inline CellWidget* getCellWidget (); + virtual void saveQtSettings ( size_t viewerId ) const; + virtual void readQtSettings ( size_t viewerId ); public slots: virtual void setCellWidget ( CellWidget* ); virtual void setCell ( Cell* ); @@ -86,6 +85,8 @@ namespace Hurricane { public slots: void setCellWidget ( CellWidget* ); virtual void graphicsUpdated (); + virtual void saveQtSettings ( size_t viewerId ) const; + virtual void readQtSettings ( size_t viewerId ); protected: GraphicsWidget* _graphics; @@ -105,6 +106,8 @@ namespace Hurricane { public: TabDisplayFilter ( QWidget* parent=NULL ); inline DisplayFilterWidget* getDisplayFilter (); + virtual void saveQtSettings ( size_t viewerId ) const; + virtual void readQtSettings ( size_t viewerId ); public slots: virtual void setCellWidget ( CellWidget* ); @@ -126,6 +129,8 @@ namespace Hurricane { public: TabPalette ( QWidget* parent=NULL ); inline PaletteWidget* getPalette (); + virtual void saveQtSettings ( size_t viewerId ) const; + virtual void readQtSettings ( size_t viewerId ); public slots: virtual void setCellWidget ( CellWidget* ); virtual void graphicsUpdated (); @@ -152,6 +157,8 @@ namespace Hurricane { inline QCheckBox* getSyncSelection (); virtual void cellPreModificate (); virtual void cellPostModificate (); + virtual void saveQtSettings ( size_t viewerId ) const; + virtual void readQtSettings ( size_t viewerId ); public slots: virtual void setCell ( Cell* ); virtual void setCellWidget ( CellWidget* ); @@ -313,6 +320,8 @@ namespace Hurricane { void setCellWidget ( CellWidget* ); //inline int addSetting ( QWidget* page, const QString& label ); void insertTabAfter ( const QString& ref, QWidget*, const QString& label ); + void saveQtSettings ( size_t viewerId ) const; + void readQtSettings ( size_t viewerId ); public slots: void graphicsUpdated (); void cellPreModificate (); @@ -347,7 +356,4 @@ namespace Hurricane { //inline int ControllerWidget::addSetting ( QWidget* page, const QString& label ) { return _tabSettings->addSetting(page,label); } -} // End of Hurricane namespace. - - -#endif // __HURRICANE_CONTROLLER_WIDGET__ +} // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/DisplayFilterWidget.h b/hurricane/src/viewer/hurricane/viewer/DisplayFilterWidget.h index b3f5ef26a..6d043aca5 100644 --- a/hurricane/src/viewer/hurricane/viewer/DisplayFilterWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/DisplayFilterWidget.h @@ -14,11 +14,8 @@ // +-----------------------------------------------------------------+ -#ifndef HURRICANE_DISPLAY_FILTER_WIDGET_H -#define HURRICANE_DISPLAY_FILTER_WIDGET_H - - -#include +#pragma once +#include class QSpinBox; class QCheckBox; @@ -36,6 +33,8 @@ namespace Hurricane { public: DisplayFilterWidget ( QWidget* parent=NULL ); void setCellWidget ( CellWidget* ); + void saveQtSettings ( size_t viewerId ) const; + void readQtSettings ( size_t viewerId ); signals: void queryFilterChanged (); void dbuModeChanged ( unsigned int mode, DbU::UnitPower ); @@ -76,5 +75,3 @@ namespace Hurricane { } // Hurricane namespace. - -#endif // HURRICANE_DISPLAY_FILTER_WIDGET_H diff --git a/hurricane/src/viewer/hurricane/viewer/GraphicsWidget.h b/hurricane/src/viewer/hurricane/viewer/GraphicsWidget.h index 76667d79f..57a316868 100644 --- a/hurricane/src/viewer/hurricane/viewer/GraphicsWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/GraphicsWidget.h @@ -14,11 +14,8 @@ // +-----------------------------------------------------------------+ -#ifndef HURRICANE_GRAPHICS_WIDGET_H -#define HURRICANE_GRAPHICS_WIDGET_H - - -#include +#pragma once +#include class QGridLayout; class QButtonGroup; @@ -37,6 +34,8 @@ namespace Hurricane { void readGraphics (); void resetGraphics (); void rereadGraphics (); + void saveQtSettings ( size_t viewerId ) const; + void readQtSettings ( size_t viewerId ); public slots: void changeStyle (); void setStyle ( int id ); @@ -50,5 +49,3 @@ namespace Hurricane { } // Hurricane namespace. - -#endif diff --git a/hurricane/src/viewer/hurricane/viewer/HApplication.h b/hurricane/src/viewer/hurricane/viewer/HApplication.h index 5df116bbf..c69061bdc 100644 --- a/hurricane/src/viewer/hurricane/viewer/HApplication.h +++ b/hurricane/src/viewer/hurricane/viewer/HApplication.h @@ -1,25 +1,21 @@ // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC 2008-2018, All Rights Reserved +// Copyright (c) Sorbonne Université 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | U n i c o r n - M a i n G U I | // | | // | Author : Jean-Paul CHAPUT | -// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./HApplication.h" | // +-----------------------------------------------------------------+ - - -#ifndef HURRICANE_HAPPLICATION_H -#define HURRICANE_HAPPLICATION_H - -#include +#pragma once +#include namespace Hurricane { @@ -27,7 +23,6 @@ namespace Hurricane { class HApplication : public QApplication { Q_OBJECT; - public: HApplication ( int& argc, char** argv ); HApplication ( int& argc, char** argv, bool GUIenabled ); @@ -37,11 +32,9 @@ namespace Hurricane { HApplication ( Display*, int& argc, char** argv, Qt::HANDLE visual=0, Qt::HANDLE colormap=0 ); #endif virtual bool notify ( QObject*, QEvent* ); + void sharedCtor (); }; } // End of Hurricane namespace. - -#endif // __HURRICANE_HAPPLICATION__ - diff --git a/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h b/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h index 68dedac9b..e1b328940 100644 --- a/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/NetlistWidget.h @@ -138,6 +138,8 @@ namespace Hurricane { void setCell ( Cell* ); void goTo ( int ); void updateSelecteds (); + void saveQtSettings ( size_t viewerId ) const; + void readQtSettings ( size_t viewerId ); signals: void netSelected ( Occurrence ); void netUnselected ( Occurrence ); diff --git a/hurricane/src/viewer/hurricane/viewer/PaletteWidget.h b/hurricane/src/viewer/hurricane/viewer/PaletteWidget.h index 624501fd6..e188400f0 100644 --- a/hurricane/src/viewer/hurricane/viewer/PaletteWidget.h +++ b/hurricane/src/viewer/hurricane/viewer/PaletteWidget.h @@ -64,6 +64,8 @@ namespace Hurricane { void readGraphics (); void resetGraphics (); void rereadGraphics (); + void saveQtSettings ( size_t viewerId ) const; + void readQtSettings ( size_t viewerId ); signals: void paletteChanged (); public slots: diff --git a/katana/src/DataNegociate.cpp b/katana/src/DataNegociate.cpp index 1121355e8..fb9d10a82 100644 --- a/katana/src/DataNegociate.cpp +++ b/katana/src/DataNegociate.cpp @@ -160,17 +160,19 @@ namespace Katana { Interval trackFree ( false ); if (source->canDrag()) { + DbU::Unit slack = (source->isMetalOnly()) ? pitch : 0; if (direction & Flags::Horizontal) - trackFree.intersection( source->getCBYMin(), source->getCBYMax() ); + trackFree.intersection( source->getCBYMin()-slack, source->getCBYMax()+slack ); else - trackFree.intersection( source->getCBXMin(), source->getCBXMax() ); + trackFree.intersection( source->getCBXMin()-slack, source->getCBXMax()+slack ); cdebug_log(159,0) << "trackFree (source drag): " << trackFree << endl; } if (target->canDrag()) { + DbU::Unit slack = (target->isMetalOnly()) ? pitch : 0; if (direction & Flags::Horizontal) - trackFree.intersection( target->getCBYMin(), target->getCBYMax() ); + trackFree.intersection( target->getCBYMin()-slack, target->getCBYMax()+slack ); else - trackFree.intersection( target->getCBXMin(), target->getCBXMax() ); + trackFree.intersection( target->getCBXMin()-slack, target->getCBXMax()+slack ); cdebug_log(159,0) << "trackFree (target drag): " << trackFree << endl; } diff --git a/katana/src/GlobalRoute.cpp b/katana/src/GlobalRoute.cpp index 262e1914b..504cf4f7e 100644 --- a/katana/src/GlobalRoute.cpp +++ b/katana/src/GlobalRoute.cpp @@ -506,8 +506,11 @@ namespace Katana { if (not isChannelStyle()) { if (!(flags & Flags::PlacementCallback)) { setupPowerRails(); - Flags protectFlags = (getConfiguration()->getNetBuilderStyle() == "VH,2RL") - ? Flags::ProtectSelf : Flags::NoFlags; + Flags protectFlags = Flags::NoFlags; + if (getConfiguration()->getNetBuilderStyle() == "VH,2RL") + protectFlags |= Flags::ProtectSelf; + if (getConfiguration()->getLayerGauge(0)->getType() == Constant::LocalOnly) + protectFlags |= Flags::ProtectSelf; protectRoutingPads( protectFlags ); } } diff --git a/katana/src/KatanaEngine.cpp b/katana/src/KatanaEngine.cpp index a4ca24431..5a43feda5 100644 --- a/katana/src/KatanaEngine.cpp +++ b/katana/src/KatanaEngine.cpp @@ -246,15 +246,6 @@ namespace Katana { setState( Anabatic::EngineDriving ); throw Error( "KatanaEngine::digitalInit(): All nets are already routed, doing nothing." ); } - - if (not isChannelStyle()) { - if (!(flags & Flags::PlacementCallback)) { - setupPowerRails(); - Flags protectFlags = (getConfiguration()->getNetBuilderStyle() == "VH,2RL") - ? Flags::ProtectSelf : Flags::NoFlags; - protectRoutingPads( protectFlags ); - } - } cdebug_tabw(155,-1); } @@ -491,16 +482,7 @@ namespace Katana { } cdebug_log(159,0) << "Capacity from: " << element << ":" << elementCapacity << endl; - Segment* segment = element->getSegment(); - Interval segmentUSpan; - - source = segment->getSourcePosition(); - target = segment->getTargetPosition(); - if (track->getDirection() == Flags::Vertical) - segmentUSpan = Interval( source.getY(), target.getY() ); - else - segmentUSpan = Interval( source.getX(), target.getX() ); - + Interval segmentUSpan = Interval( element->getSourceU(), element->getTargetU() ); if (uspan.isEmpty()) { uspan = segmentUSpan; continue; diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index 71f8366a0..daffb1e2a 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -207,7 +207,10 @@ namespace { size_t rlDepth = depth - rg->getFirstRoutingLayer(); if (rlDepth == 0) { TrackMarker::create( rp, depth+1 ); - //if (isVH) TrackMarker::create( rp, depth+2 ); + // if (rp->isM1Offgrid()) { + // TrackMarker::create( rp, depth+2 ); + // } + // if (isVH) TrackMarker::create( rp, depth+2 ); } if (rlDepth == 1) { if ((depth == 0) and (depth+1 < rg->getDepth())) @@ -621,6 +624,7 @@ namespace Katana { _eventQueue.load( _segments ); cmess2 << " " << endl; if (cdebug.enabled(9000)) _eventQueue.dump(); + _statistics.setLoadedEventsCount( _eventQueue.size() ); size_t count = 0; _katana->setStage( StageNegociate ); @@ -665,69 +669,69 @@ namespace Katana { event->process( _eventQueue, _eventHistory, _eventLoop ); count++; - // if (event->getSegment()->getNet()->getId() == 239546) { - // UpdateSession::close(); - // ostringstream message; - // message << "After processing an event from Net id:239546\n" << event; - // Breakpoint::stop( 0, message.str() ); - // UpdateSession::open(); - // } + //if (event->getSegment()->getNet()->getId() == 239546) { + // UpdateSession::close(); + // ostringstream message; + // message << "After processing an event from Net id:239546\n" << event; + // Breakpoint::stop( 0, message.str() ); + // UpdateSession::open(); + //} //if (count and not (count % 500)) { // _pack( count, false ); //} - // if (RoutingEvent::getProcesseds() == 65092) { - // UpdateSession::close(); - // Breakpoint::stop( 0, "Overlap has happened" ); - // UpdateSession::open(); - // } + //if (RoutingEvent::getProcesseds() == 65092) { + // UpdateSession::close(); + // Breakpoint::stop( 0, "Overlap has happened" ); + // UpdateSession::open(); + //} if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true ); } + _statistics.setProcessedEventsCount( RoutingEvent::getProcesseds() ); //_pack( count, true ); - _negociateRepair(); + _negociateRepair(); - if (_katana->getConfiguration()->runRealignStage()) { - cmess1 << " o Realign Stage." << endl; - - cdebug_log(159,0) << "Loadind realign queue." << endl; - _katana->setStage( StageRealign ); - for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) { - RoutingEvent* event = _eventHistory.getNth(i); - if (not event->isCloned() and event->getSegment()->canRealign()) - event->reschedule( _eventQueue, 0 ); - } - _eventQueue.commit(); - cmess2 << " " << setfill(' ') << endl; - count = 0; - while ( not _eventQueue.empty() and not isInterrupted() ) { - RoutingEvent* event = _eventQueue.pop(); - if (tty::enabled()) { - cmess2 << " " - << setfill(' ') << tty::reset << tty::cr; - cmess2.flush(); - } else { - cmess2 << " getEventLevel() << ":" << event->getPriority() << "> " - << event->getSegment() - << endl; - cmess2.flush(); - } - event->process( _eventQueue, _eventHistory, _eventLoop ); - count++; - if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true ); + if (_katana->getConfiguration()->runRealignStage()) { + cmess1 << " o Realign Stage." << endl; + + cdebug_log(159,0) << "Loadind realign queue." << endl; + _katana->setStage( StageRealign ); + for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) { + RoutingEvent* event = _eventHistory.getNth(i); + if (not event->isCloned() and event->getSegment()->canRealign()) + event->reschedule( _eventQueue, 0 ); + } + _eventQueue.commit(); + cmess2 << " " << setfill(' ') << endl; + count = 0; + while ( not _eventQueue.empty() and not isInterrupted() ) { + RoutingEvent* event = _eventQueue.pop(); + if (tty::enabled()) { + cmess2 << " " + << setfill(' ') << tty::reset << tty::cr; + cmess2.flush(); + } else { + cmess2 << " getEventLevel() << ":" << event->getPriority() << "> " + << event->getSegment() + << endl; + cmess2.flush(); } - - _negociateRepair(); + event->process( _eventQueue, _eventHistory, _eventLoop ); + count++; + if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true ); } - if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl; - //} + _negociateRepair(); + } + + if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl; size_t eventsCount = _eventHistory.size(); @@ -857,9 +861,14 @@ namespace Katana { void NegociateWindow::printStatistics () const { + float ripupRatio = 100.0 * _statistics.getRipupRatio(); + ostringstream os; + os << setprecision(2) << fixed << ripupRatio << "%"; + cmess1 << " o Computing statistics." << endl; - cmess1 << Dots::asSizet(" - Processeds Events Total",RoutingEvent::getProcesseds()) << endl; - cmess1 << Dots::asSizet(" - Unique Events Total" + cmess1 << Dots::asString( " - Event ripup ratio", os.str() ) << endl; + cmess1 << Dots::asSizet ( " - Processeds Events Total",RoutingEvent::getProcesseds()) << endl; + cmess1 << Dots::asSizet ( " - Unique Events Total" ,(RoutingEvent::getProcesseds() - RoutingEvent::getCloneds())) << endl; cmess1 << Dots::asSizet(" - # of GCells",_statistics.getGCellsCount()) << endl; _katana->printCompletion(); diff --git a/katana/src/PowerRails.cpp b/katana/src/PowerRails.cpp index 32e9bd401..a7722f831 100644 --- a/katana/src/PowerRails.cpp +++ b/katana/src/PowerRails.cpp @@ -38,6 +38,7 @@ #include "anabatic/GCell.h" #include "katana/RoutingPlane.h" #include "katana/TrackFixedSegment.h" +#include "katana/TrackFixedSpan.h" #include "katana/Track.h" #include "katana/KatanaEngine.h" @@ -510,8 +511,8 @@ namespace { << " , ww/2:" << DbU::getValueString(plane->getLayerGauge()->getHalfWireWidth()) << ")" << endl; - // if ( type == Constant::PinOnly ) { - // cdebug_log(159,0) << " Layer is PinOnly." << endl; + // if ( (type == Constant::PinOnly) or (type == Constant::LocalOnly) ) { + // cdebug_log(159,0) << " Layer is PinOnly or LocalOnly." << endl; // return; // } @@ -813,7 +814,7 @@ namespace { _planes.insert( make_pair(basicLayer,new Plane(lg->getLayer(),rp)) ); - //if (lg->getType() == Constant::PinOnly) continue; + //if (not lg->isUsable()) continue; const BasicLayer* blockageLayer = dynamic_cast( lg->getBlockageLayer() ); if (not blockageLayer) continue; @@ -982,6 +983,12 @@ namespace { if (not activePlane) return; cmess1 << " - PowerRails in " << activePlane->getLayer()->getName() << " ..." << endl; + if (static_cast(activePlane->getLayer())->getMaterial() + != BasicLayer::Material::blockage) + setStopCellFlags( Cell::Flags::AbstractedSupply ); + else + unsetStopCellFlags( Cell::Flags::AbstractedSupply ); + Query::doQuery(); } @@ -1008,8 +1015,8 @@ namespace { , const Transformation& transformation ) { - const Component* component = dynamic_cast(go); - if ( component ) { + const Component* component = dynamic_cast( go ); + if (component) { if ( _framework->isPad(getMasterCell()) and ( (_routingGauge->getLayerDepth(component->getLayer()) < 2) or (component->getLayer()->getBasicLayers().getFirst()->getMaterial() != BasicLayer::Material::blockage) ) ) @@ -1017,19 +1024,19 @@ namespace { Net* rootNet = _katana->getBlockageNet(); if (not _isBlockagePlane) { - rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath()); + rootNet = _powerRailsPlanes.getRootNet( component->getNet(), getPath() ); } #if 0 - Net* rootNet = NULL; - if ( not _isBlockagePlane ) - rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath()); + Net* rootNet = nullptr; + if (not _isBlockagePlane) + rootNet = _powerRailsPlanes.getRootNet( component->getNet(), getPath() ); else { rootNet = _katana->getBlockageNet(); } #endif - if ( rootNet == NULL ) { + if (not rootNet) { cdebug_log(159,0) << " rootNet is NULL, not taken into account." << endl; return; } @@ -1043,14 +1050,13 @@ namespace { return; } - const Segment* segment = dynamic_cast(component); - if ( segment != NULL ) { + const Segment* segment = dynamic_cast( component ); + if (segment) { _goMatchCount++; cdebug_log(159,0) << " Merging PowerRail element: " << segment << endl; - Box bb = segment->getBoundingBox ( basicLayer ); - - uint32_t depth = _routingGauge->getLayerDepth ( segment->getLayer() ); + Box bb = segment->getBoundingBox( basicLayer ); + uint32_t depth = _routingGauge->getLayerDepth( segment->getLayer() ); if ( _chipTools.isChip() and ((depth == 2) or (depth == 3)) @@ -1058,54 +1064,80 @@ namespace { and (segment->getLength() > _chipTools.getPadWidth()) and (_katana->getChipTools().getCorona().contains(bb)) ) { switch ( depth ) { - case 2: _vRingSegments.push_back ( segment ); break; // M3 V. - case 3: _hRingSegments.push_back ( segment ); break; // M4 H. + case 2: _vRingSegments.push_back( segment ); break; // M3 V. + case 3: _hRingSegments.push_back( segment ); break; // M4 H. } return; } - transformation.applyOn ( bb ); + transformation.applyOn( bb ); + _powerRailsPlanes.merge( bb, rootNet ); + return; + } - _powerRailsPlanes.merge ( bb, rootNet ); - } else { - const Contact* contact = dynamic_cast(component); - if ( contact != NULL ) { - _goMatchCount++; + const Contact* contact = dynamic_cast( component ); + if (contact) { + _goMatchCount++; - Box bb = contact->getBoundingBox ( basicLayer ); - transformation.applyOn ( bb ); + Box bb = contact->getBoundingBox ( basicLayer ); + transformation.applyOn( bb ); - cdebug_log(159,0) << " Merging PowerRail element: " << contact << " bb:" << bb - << " " << basicLayer << endl; + cdebug_log(159,0) << " Merging PowerRail element: " << contact << " bb:" << bb + << " " << basicLayer << endl; - _powerRailsPlanes.merge ( bb, rootNet ); - } else { - const Pad* pad = dynamic_cast(component); - if (pad != NULL) { - _goMatchCount++; + _powerRailsPlanes.merge( bb, rootNet ); + return; + } - Box bb = pad->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); + const Pad* pad = dynamic_cast( component ); + if (pad) { + _goMatchCount++; + + Box bb = pad->getBoundingBox( basicLayer ); + transformation.applyOn( bb ); - cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb + cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb + << " " << basicLayer << endl; + + _powerRailsPlanes.merge( bb, rootNet ); + return; + } + + const Rectilinear* rectilinear = dynamic_cast( component ); + if (rectilinear) { + if (not _powerRailsPlanes.getActivePlane()->getLayer()->isBlockage()) { + _goMatchCount++; + vector boxes; + rectilinear->getAsRectangles( boxes, Rectilinear::VSliced ); + for ( Box bb : boxes ) { + transformation.applyOn( bb ); + cdebug_log(159,0) << " Merging PowerRail element: " << rectilinear << " bb:" << bb << " " << basicLayer << endl; - _powerRailsPlanes.merge( bb, rootNet ); - } else { - const Rectilinear* rectilinear = dynamic_cast(component); - if (rectilinear and (rectilinear->getPoints().size() == 5)) { - _goMatchCount++; + } + return; + } - Box bb = rectilinear->getBoundingBox( basicLayer ); - transformation.applyOn( bb ); - - cdebug_log(159,0) << " Merging PowerRail element: " << rectilinear << " bb:" << bb - << " " << basicLayer << endl; - - _powerRailsPlanes.merge( bb, rootNet ); + _goMatchCount++; + RoutingPlane* plane = _powerRailsPlanes.getActivePlane()->getRoutingPlane(); + RoutingLayerGauge* rlg = plane->getLayerGauge(); + DbU::Unit delta = plane->getLayerGauge()->getPitch() - 1; + vector boxes; + rectilinear->getAsRectangles( boxes ); + if (rlg->isHorizontal()) { + for ( Box bb : boxes ) { + transformation.applyOn( bb ); + DbU::Unit axisMin = bb.getYMin() - delta; + DbU::Unit axisMax = bb.getYMax() + delta; + + Track* track = plane->getTrackByPosition( axisMin, Constant::Superior ); + for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { + TrackElement* element = TrackFixedSpan::create ( nullptr, bb, track ); + cdebug_log(159,0) << " Insert in " << track << "+" << element << endl; } } } + return; } } } @@ -1195,7 +1227,6 @@ namespace Katana { QueryPowerRails query ( this ); Technology* technology = DataBase::getDB()->getTechnology(); - query.setStopCellFlags( Cell::Flags::AbstractedSupply ); for ( BasicLayer* layer : technology->getBasicLayers() ) { if ( (layer->getMaterial() != BasicLayer::Material::metal) and (layer->getMaterial() != BasicLayer::Material::blockage) ) diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index fda16fef7..bd41d8d6e 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -120,6 +120,7 @@ namespace { void propagateCagedConstraints ( TrackElement* segment, set& faileds ) { + DebugSession::open( segment->getNet(), 150, 160 ); cdebug_log(159,0) << "propagateCagedConstraints(): " << segment << endl; if (not segment->isFixed()) return; @@ -136,6 +137,7 @@ namespace { if ( not track ) { cerr << Bug( "%s is not inserted in a ", getString(segment).c_str() ) << endl; + DebugSession::close(); return; } @@ -167,12 +169,15 @@ namespace { if (minConstraint > maxConstraint) { cerr << Bug( "%s have too tight caging constraints.", getString(segment).c_str() ) << endl; + cdebug_tabw(159,-1); + DebugSession::close(); return; } if ( (minConstraint <= uside.getVMin()) and (maxConstraint >= uside.getVMax()) ) { cdebug_log(159,0) << "No constraints [" << DbU::getValueString(minConstraint) << ":" << DbU::getValueString(maxConstraint) << " vs. " << uside << endl; + DebugSession::close(); return; } @@ -203,6 +208,7 @@ namespace { if (perpandiculars.size() == 0) { cdebug_log(159,0) << "No perpandiculars to " << segment << endl; cdebug_tabw(159,-1); + DebugSession::close(); return; } @@ -217,6 +223,7 @@ namespace { } cdebug_tabw(159,-1); + DebugSession::close(); } diff --git a/katana/src/ProtectRoutingPads.cpp b/katana/src/ProtectRoutingPads.cpp index af8486950..2bf508cf9 100644 --- a/katana/src/ProtectRoutingPads.cpp +++ b/katana/src/ProtectRoutingPads.cpp @@ -24,6 +24,7 @@ #include "hurricane/RegularLayer.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" +#include "hurricane/Rectilinear.h" #include "hurricane/RoutingPad.h" #include "hurricane/Occurrence.h" #include "hurricane/Cell.h" @@ -37,6 +38,7 @@ #include "katana/RoutingPlane.h" #include "katana/TrackSegment.h" #include "katana/TrackFixedSegment.h" +#include "katana/TrackFixedSpan.h" #include "katana/Track.h" #include "katana/KatanaEngine.h" @@ -57,6 +59,7 @@ namespace { using Hurricane::RegularLayer; using Hurricane::Horizontal; using Hurricane::Vertical; + using Hurricane::Rectilinear; using Hurricane::Plug; using Hurricane::Transformation; using Hurricane::RoutingPad; @@ -71,6 +74,29 @@ namespace { using namespace Katana; + class CompareIntervalByVMin { + public: + inline bool operator () ( const Interval& lhs, const Interval& rhs ) const + { + if (lhs.getVMin() < rhs.getVMin()) + return true; + else { + if ( (lhs.getVMin() == rhs.getVMin()) + and (lhs.getVMax() > rhs.getVMax()) ) + return true; + } + return false; + } + }; + + + class CompareTrackByAxis { + public: + inline bool operator () ( const Track* lhs, const Track* rhs ) const + { return lhs->getAxis() < rhs->getAxis(); } + }; + + void protectRoutingPad ( RoutingPad* rp, Flags flags ) { cdebug_log(145,1) << "::protectRoutingPad() " << rp << endl; @@ -78,19 +104,23 @@ namespace { Name padNetName = "pad"; Component* usedComponent = rp->_getEntityAs(); Path path = rp->getOccurrence().getPath(); + Net* net = rp->getNet(); Net* masterNet = usedComponent->getNet(); Transformation transformation = path.getTransformation(); + Box ab = rp->getCell()->getAbutmentBox(); if (dynamic_cast(usedComponent)) { cerr << Error( "Katana::protectRoutingPad(): A RoutingPad of \"%s\" is still on it's Plug.\n" " (%s)" - , getString(rp->getNet()->getName()).c_str() + , getString(net->getName()).c_str() , getString(usedComponent).c_str() ) << endl; cdebug_tabw(145,-1); return; } - if (Session::getRoutingGauge()->getLayerType(usedComponent->getLayer()) == Constant::PinOnly) { + RoutingLayerGauge* rlg = Session::getLayerGauge( rp->getLayer() ); + if (not ( (rlg->getType() == Constant::Default ) + or (rlg->getType() == Constant::LocalOnly))) { cdebug_tabw(145,-1); return; } @@ -99,75 +129,170 @@ namespace { cdebug_log(145,0) << "masterNet: " << masterNet << endl; if (CatalogExtension::isPad(masterNet->getCell())) { - if ( rp->getNet()->isPower() - or (rp->getNet()->getName() == padNetName) ) { + if ( net->isPower() + or (net->getName() == padNetName) ) { cdebug_tabw(145,-1); return; } } - vector segments; - - for ( Segment* segment : masterNet->getSegments() ) { - RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(segment->getLayer()); + vector< pair > bbs; + for ( Component* component : masterNet->getComponents() ) { + const Layer* layer = component->getLayer(); + RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer( layer ); if (not plane) continue; - if (usedComponent == dynamic_cast(segment) - and not (flags & Flags::ProtectSelf)) continue; - if (not NetExternalComponents::isExternal(segment)) continue; + Segment* segment = dynamic_cast( component ); + if (segment) { + Box bb = segment->getBoundingBox(); + transformation.applyOn( bb ); + bbs.push_back( make_pair( bb, layer )); + cdebug_log(145,0) << "@ " << segment << " bb:" << bb << endl; + continue; + } - segments.push_back( segment ); + Rectilinear* rectilinear = dynamic_cast( component ); + if (rectilinear) { + cdebug_log(145,0) << "@ " << rectilinear << endl; + vector rbbs; + rectilinear->getAsRectangles( rbbs, (plane->isVertical() ? Rectilinear::HSliced + : Rectilinear::VSliced )); + for ( Box& bb : rbbs ) { + transformation.applyOn( bb ); + bbs.push_back( make_pair( bb, layer )); + cdebug_log(145,0) << "| bb:" << bb << endl; + } + continue; + } } - for ( size_t i=0 ; igetRoutingPlaneByLayer(segments[i]->getLayer()); + map, CompareTrackByAxis > intervalsByTracks; + for ( auto item : bbs ) { + RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer( item.second ); Flags direction = plane->getDirection(); DbU::Unit wireWidth = plane->getLayerGauge()->getWireWidth(); DbU::Unit delta = plane->getLayerGauge()->getPitch() - wireWidth/2 - DbU::fromLambda(0.1); - DbU::Unit extension = segments[i]->getLayer()->getExtentionCap(); - Box bb ( segments[i]->getBoundingBox() ); - - transformation.applyOn ( bb ); + DbU::Unit cap = plane->getLayer()->getMinimalSpacing() / 2; + DbU::Unit extension = item.second->getExtentionCap(); + Box bb = item.first.getIntersection( ab ); - cdebug_log(145,0) << "@ " << segments[i] << " bb:" << bb << endl; + cdebug_log(145,0) << "@ bb:" << bb << endl; cdebug_log(145,0) << "delta=" << DbU::getValueString(delta) << endl; + cdebug_log(145,0) << "cap=" << DbU::getValueString(cap) << endl; + if (bb.isEmpty()) continue; - if ( direction == Flags::Horizontal ) { + if (direction == Flags::Horizontal) { DbU::Unit axisMin = bb.getYMin() - delta; DbU::Unit axisMax = bb.getYMax() + delta; - Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); + Track* track = plane->getTrackByPosition( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { - Horizontal* segment = Horizontal::create ( rp->getNet() - , segments[i]->getLayer() - , track->getAxis() - , wireWidth - , bb.getXMin()+extension - , bb.getXMax()-extension - ); - TrackFixedSegment::create ( track, segment ); - cdebug_log(145,0) << "| " << segment << endl; + cdebug_log(145,0) << "> track " << track << endl; + intervalsByTracks[ track ].push_back( Interval( bb.getXMin(), bb.getXMax() )); } } else { DbU::Unit axisMin = bb.getXMin() - delta; DbU::Unit axisMax = bb.getXMax() + delta; - Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); + Track* track = plane->getTrackByPosition( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { - Vertical* segment = Vertical::create ( rp->getNet() - , segments[i]->getLayer() - , track->getAxis() - , wireWidth - , bb.getYMin()+extension - , bb.getYMax()-extension - ); - TrackFixedSegment::create ( track, segment ); - cdebug_log(145,0) << "| " << segment << endl; + cdebug_log(145,0) << "> track " << track << endl; + intervalsByTracks[ track ].push_back( Interval( bb.getYMin(), bb.getYMax() ) ); } } } + + for ( auto item : intervalsByTracks ) { + Track*& track = const_cast( item.first ); + vector& intervals = item.second; + DbU::Unit cap = track->getLayer()->getMinimalSpacing() / 2; + DbU::Unit halfWidth = track->getLayer()->getMinimalSize () / 2; + cdebug_log(145,0) << "> track " << track << endl; + + sort( intervals.begin(), intervals.end(), CompareIntervalByVMin() ); + Interval fullSpan = intervals[0]; + cdebug_log(145,0) << "| fullSpan " << fullSpan << endl; + for ( size_t i=1 ; i < intervals.size() ; ) { + if (fullSpan.contains(intervals[i])) { + cdebug_log(145,0) << "| contained " << intervals[i] << endl; + intervals.erase( intervals.begin() + i ); + continue; + } + if (fullSpan.intersect(intervals[i])) { + cdebug_log(145,0) << "| intersect " << intervals[i] << endl; + fullSpan.merge( intervals[i].getVMax() ); + cdebug_log(145,0) << "| fullSpan " << fullSpan << endl; + if ( (intervals[i ].getSize() < 2*cap) + or (intervals[i-1].getSize() < 2*cap)) { + cdebug_log(145,0) << "| too narrow, merge " << endl; + intervals[i-1].merge( fullSpan.getVMax() ); + intervals.erase( intervals.begin() + i ); + continue; + } + cdebug_log(145,0) << "| separate" << endl; + intervals[i-1] = Interval( intervals[i-1].getVMin() , intervals[i].getVMin() - cap ); + intervals[i ] = Interval( intervals[i ].getVMin() + cap, intervals[i].getVMax() ); + ++i; + continue; + } + if (fullSpan.getVMax() > intervals[i-1].getVMax()) { + cdebug_log(145,0) << "| expand last" << endl; + intervals[i-1].merge( fullSpan.getVMax()); + } + + fullSpan = intervals[i]; + ++i; + } + + cdebug_log(145,0) << "Cleaned up on " << track << endl; + for ( size_t i=0 ; igetFreeInterval( intervals[i].getCenter(), net ); + cdebug_log(145,0) << "| termSpan " << termSpan << endl; + cdebug_log(145,0) << "| freeSpan " << freeSpan << endl; + bool overlap = false; + bool conflict = false; + if (freeSpan.isEmpty() or not freeSpan.contains(termSpan)) { + overlap = true; + size_t ovBegin = 0; + size_t ovEnd = 0; + track->getOverlapBounds( termSpan, ovBegin, ovEnd ); + if (ovBegin != Track::npos) { + for ( ; ovBegin <= ovEnd ; ++ovBegin ) { + TrackElement* overlaped = track->getSegment( ovBegin ); + TrackFixedSpan* fixedSpan = dynamic_cast( overlaped ); + if (fixedSpan) { + if (not fixedSpan->isBlockage()) + fixedSpan->setNet( nullptr ); + } else + conflict = true; + } + } + } + cdebug_log(145,0) << "| overlap =" << overlap << endl; + cdebug_log(145,0) << "| conflict=" << conflict << endl; + if (not conflict) { + Box bb; + if (track->isHorizontal()) + bb = Box( intervals[i].getVMin(), track->getAxis()-halfWidth + , intervals[i].getVMax(), track->getAxis()+halfWidth ); + else + bb = Box( track->getAxis()-halfWidth, intervals[i].getVMin() + , track->getAxis()+halfWidth, intervals[i].getVMax() ); + TrackFixedSpan* element = TrackFixedSpan::create( ((overlap) ? nullptr : net), bb, track ); + cdebug_log(145,0) << "| " << element << endl; + } + + } + } + Session::revalidate(); cdebug_tabw(145,-1); } diff --git a/katana/src/RoutingEvent.cpp b/katana/src/RoutingEvent.cpp index 41cda40e3..85e7be787 100644 --- a/katana/src/RoutingEvent.cpp +++ b/katana/src/RoutingEvent.cpp @@ -712,6 +712,10 @@ namespace Katana { _constraints.inflate( Session::getSliceHeight() ); cdebug_log(159,0) << "Expanding (after):" << _constraints << endl; } + } else { + if (_segment->isForOffgrid()) { + _constraints.inflate( _segment->getPitch() ); + } } if (_segment->isShortDogleg()) { diff --git a/katana/src/RoutingPlane.cpp b/katana/src/RoutingPlane.cpp index ee4fefaf1..aa171a489 100644 --- a/katana/src/RoutingPlane.cpp +++ b/katana/src/RoutingPlane.cpp @@ -95,9 +95,6 @@ namespace Katana { if (not plane->_layerGauge) throw Error( badLayerGauge, depth, getString(katana->getConfiguration()->getRoutingGauge()).c_str() ); - uint32_t gaugeDepth = 0; - if (Session::getLayerGauge(gaugeDepth)->getType() == Constant::PinOnly) ++gaugeDepth; - DbU::Unit extensionCap = ( std::max( Session::getWireWidth(depth), Session::getViaWidth(depth) ) + Session::getPitch(depth) ) / 2; @@ -160,10 +157,14 @@ namespace Katana { Track* RoutingPlane::getTrackByPosition ( DbU::Unit axis, uint32_t mode ) const { + if (_tracks.empty()) return nullptr; + if (axis < getAxisMin()) return _tracks.front(); + if (axis > getAxisMax()) return _tracks.back(); + size_t index = getLayerGauge()->getTrackIndex( getAxisMin(), getAxisMax(), axis, mode ); if (index == getTracksSize()) { - if (not index) return NULL; - if ((mode == Constant::Superior) or (mode == Constant::Exact)) return NULL; + if (not index) return nullptr; + if ((mode == Constant::Superior) or (mode == Constant::Exact)) return nullptr; --index; } diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index 633bb9531..679bdba13 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -558,6 +558,8 @@ namespace Katana { Track* baseTrack = plane->getTrackByPosition( segment1->base()->getSourcePosition(), Constant::Superior ); RoutingPlane* perpPlane = plane->getTop(); if (not perpPlane) perpPlane = plane->getBottom(); + cdebug_log(155,0) << "sourcePosition():" << DbU::getValueString(segment1->base()->getSourcePosition()) << endl; + cdebug_log(155,0) << " -> baseTrack:" << baseTrack << endl; for ( Track* ptrack : Tracks_Range::get(perpPlane,_constraint) ) { _costs.push_back( new TrackCost(segment1,NULL,baseTrack,NULL,ptrack->getAxis(),0) ); @@ -626,6 +628,7 @@ namespace Katana { , getString(_constraint).c_str() ) << endl; } + cdebug_log(155,0) << "-> No candidate track found." << endl; _state = EmptyTrackList; } diff --git a/katana/src/Session.cpp b/katana/src/Session.cpp index 8d7be68ff..dd7f51ee8 100644 --- a/katana/src/Session.cpp +++ b/katana/src/Session.cpp @@ -258,6 +258,7 @@ namespace Katana { _doRemovalEvents(); //if (checkTrack) checkTrack->check( overlaps, "Session::_revalidate() - check track 82 @270." ); + cdebug_log(159,1) << "Processing Track insert event" << endl; for ( const Event& event : _insertEvents ) { if (event._segment) { if (event._segment->getAxis() != event._axis) event._segment->setAxis( event._axis ); @@ -266,6 +267,7 @@ namespace Katana { if (event._marker) event._track->insert( event._marker ); } _insertEvents.clear(); + cdebug_log(159,-1) << "Insert events processeds" << endl; _doRemovalEvents( false ); //if (checkTrack) checkTrack->check( overlaps, "Session::_revalidate() - check track 82 @270." ); @@ -418,14 +420,20 @@ namespace Katana { << "\n @" << DbU::getValueString(axis) << " " << track << endl; - if ( check and (segment->getTrack() != NULL) ) { - cerr << Bug("Session::addInsertEvent(): Segment already in Track." - "\n %s." - "\n to %s." - ,getString(segment).c_str() - ,getString(track).c_str() - ) << endl; - return; + if (segment->getTrack()) { + if (segment->isForwardSetTrack()) { + segment->unsetFlags( TElemForwardSetTrack ); + } else { + if (check) { + cerr << Bug( "Session::addInsertEvent(): Segment already in Track." + "\n %s." + "\n to %s." + , getString(segment).c_str() + , getString(track).c_str() + ) << endl; + return; + } + } } _insertEvents.push_back( Event(segment,track,axis) ); diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index 07d1ebcb6..5b7cfb2c7 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -288,6 +288,8 @@ namespace Katana { , _localAssigned(false) , _segmentsValid(false) , _markersValid (false) + , _minInvalid (routingPlane->getTrackMin()) + , _maxInvalid (routingPlane->getTrackMax()) { } @@ -466,15 +468,22 @@ namespace Katana { vector::const_iterator lowerBound = lower_bound( _segments.begin(), _segments.end(), position, SourceCompare() ); begin = lowerBound - _segments.begin(); + cdebug_log(155,0) << " lower_bound begin=" << begin << endl; - // This is suspicious. - // I guess this has been written for the case of overlapping segments from the same - // net, we find the first one of the overlapped sets. But what if they are not overlapping - // but still from the same net? size_t sameNetDelta = 0; if (begin < _segments.size()) { - for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet()) - ; --begin, ++sameNetDelta ); + Interval span = _segments[begin]->getCanonicalInterval(); + size_t minBegin = begin; + for ( size_t i=begin; (i > 0) and (_segments[i-1]->getNet() == _segments[i]->getNet()) + ; --i ) { + Interval current = _segments[i-1]->getCanonicalInterval(); + if (current.intersect(span)) { + span.merge( current ); + minBegin = i - 1; + } + } + sameNetDelta = begin - minBegin; + begin = minBegin; } state = 0; @@ -719,6 +728,11 @@ namespace Katana { minFree = getOccupiedInterval(begin).getVMax(); cdebug_log(155,0) << "minFree:" << DbU::getValueString(minFree) << " begin:" << begin << endl; } + } else { + if (state & BeginIsSegmentMax) { + if (_segments[begin]->getNet() != net) + minFree = getOccupiedInterval(begin).getVMax(); + } } if (not (state & EndIsTrackMax) ) { @@ -775,6 +789,7 @@ namespace Katana { cdebug_log(159,0) << "Insert in [" << 0 << "] " << this << segment << endl; _segments.push_back( segment ); _segmentsValid = false; + updateInvalidBounds( segment ); if (segment->isWide() or segment->isNonPref()) { cdebug_log(155,0) << "Segment is wide or non-pref, trackSpan:" << segment->getTrackSpan() << endl; @@ -783,6 +798,7 @@ namespace Katana { cdebug_log(159,0) << "Insert in [" << i << "] " << wtrack << segment << endl; wtrack->_segments.push_back ( segment ); wtrack->_segmentsValid = false; + wtrack->updateInvalidBounds( segment ); wtrack = wtrack->getNextTrack(); } } @@ -811,13 +827,14 @@ namespace Katana { for ( size_t i=0 ; i<_segments.size() ; i++ ) { if (_segments[i]) { - bool inTrackRange = false; + bool inTrackRange = false; + Interval axisSpan; if (_segments[i]->isNonPref()) { - DbU::Unit min = 0; - DbU::Unit max = 0; - _segments[i]->base()->getCanonical( min, max ); - inTrackRange = Interval(min,max).contains( _axis ); + axisSpan = Interval ( _segments[i]->base()->getSourcePosition() + , _segments[i]->base()->getTargetPosition() ); + axisSpan.inflate( _segments[i]->base()->getExtensionCap( Anabatic::Flags::NoFlags )); + inTrackRange = axisSpan.contains( _axis ); } else { Interval trackRange ( _segments[i]->getAxis() - (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2 , _segments[i]->getAxis() + (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2 ); @@ -835,13 +852,16 @@ namespace Katana { cerr << "[CHECK] incoherency at " << i << " " << _segments[i] << " is detached." << endl; coherency = false; - } else { + } else { if ( (_segments[i]->getTrack() != this) and not inTrackRange ) { cerr << "[CHECK] incoherency at " << i << " " - << _segments[i] << " is in track " - << _segments[i]->getTrack() << endl; + << _segments[i] << " (span=" + << _segments[i]->getTrackSpan() << ") " << axisSpan + << "\n is in track " + << this << "\n instead of " + << _segments[i]->getTrack() + << endl; coherency = false; - cerr << _segments[i]->getTrackSpan() << endl; } } if ( (_segments[i]->getAxis() != getAxis()) and not inTrackRange ) { @@ -1024,6 +1044,28 @@ namespace Katana { std::sort( _segments.begin(), _segments.end(), SegmentCompare() ); _segmentsValid = true; } + // Net* blockageNet = Session::getBlockageNet(); + // uint32_t state = 0; + // size_t i = 0; + // getBeginIndex( _minInvalid+1, i, state ); + // for ( ; (i+1<_segments.size()) and (_segments[i+1]->getSourceU() < _maxInvalid) ; ++i ) { + // TrackFixedSpan* first = dynamic_cast( _segments[i ] ); + // TrackFixedSpan* second = dynamic_cast( _segments[i+1] ); + // if (not first or not second) continue; + // if ( (first->getTargetU() > second->getSourceU()) + // and (first->getNet() != second->getNet() )) { + // if (first->getTargetU() >= second->getTargetU()) { + // // End of second is fully enclosed in first. + // // Shrink first, set second as blockage. + // } else { + // // End of second sticks out of first. + // // Changes boudaries so they no longer overlap. + // } + // } + // } + + _minInvalid = _routingPlane->getTrackMin(); + _maxInvalid = _routingPlane->getTrackMax(); if (not _markersValid) { std::sort( _markers.begin(), _markers.end(), TrackMarker::Compare() ); @@ -1216,7 +1258,7 @@ namespace Katana { { if (not getKatanaEngine()->getTrackFill()) return; if (getIndex() % getKatanaEngine()->getTrackFill() != 0) return; - if (getLayerGauge()->getType() == Constant::PinOnly) return; + if (not getLayerGauge()->isUsable()) return; if (getLayerGauge()->getDepth() > getKatanaEngine()->getConfiguration()->getAllowedDepth()) return; Net* fillNet = getKatanaEngine()->getCell()->getNet( "dummy_filler_net" ); diff --git a/katana/src/TrackElement.cpp b/katana/src/TrackElement.cpp index 0adfa03b0..4e41e9165 100644 --- a/katana/src/TrackElement.cpp +++ b/katana/src/TrackElement.cpp @@ -143,6 +143,7 @@ namespace Katana { bool TrackElement::isStrongTerminal ( Flags ) const { return false; } bool TrackElement::isStrap () const { return false; } bool TrackElement::isUnbreakable () const { return false; } + bool TrackElement::isForOffgrid () const { return false; } bool TrackElement::isSlackened () const { return false; } bool TrackElement::isDogleg () const { return false; } bool TrackElement::isShortDogleg () const { return false; } @@ -185,7 +186,6 @@ namespace Katana { TrackElement* TrackElement::getSymmetric () { return NULL; } // Mutators. void TrackElement::addTrackCount ( int32_t ) { } - void TrackElement::setTrack ( Track* track ) { _track = track; } void TrackElement::setSymmetric ( TrackElement* ) { } void TrackElement::updateFreedomDegree () { } void TrackElement::setDoglegLevel ( uint32_t ) { } @@ -277,6 +277,14 @@ namespace Katana { } + void TrackElement::setTrack ( Track* track ) + { + cdebug_log(155,0) << "TrackElement::setTrack(): " << this << endl; + cdebug_log(155,0) << " -> " << track << endl; + _track = track; + } + + string TrackElement::_getTypeName () const { return "TrackElement"; } diff --git a/katana/src/TrackFixedSpan.cpp b/katana/src/TrackFixedSpan.cpp new file mode 100644 index 000000000..244cd81c4 --- /dev/null +++ b/katana/src/TrackFixedSpan.cpp @@ -0,0 +1,251 @@ +// -*- 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 | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackFixedSpan.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/DataBase.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "anabatic/AutoContact.h" +#include "crlcore/RoutingGauge.h" +#include "katana/DataNegociate.h" +#include "katana/TrackFixedSpan.h" +#include "katana/TrackCost.h" +#include "katana/Track.h" +#include "katana/RoutingPlane.h" +#include "katana/Session.h" +#include "katana/RoutingEvent.h" +#include "katana/NegociateWindow.h" +#include "katana/KatanaEngine.h" + + +namespace Katana { + + using namespace std; + using Hurricane::Warning; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Net; + using Hurricane::Name; + using Hurricane::RegularLayer; + using Hurricane::Technology; + using Hurricane::DataBase; + using Hurricane::Horizontal; + using Hurricane::Vertical; + using Anabatic::GCellsUnder; + + +// ------------------------------------------------------------------- +// Class : "TrackFixedSpan". + + + TrackFixedSpan::TrackFixedSpan ( Net* net, const Box& bb, Track* track ) + : TrackElement(NULL) + , _net (net) + , _boundingBox(bb) + { + uint32_t depth = track->getDepth(); + //Technology* technology = DataBase::getDB()->getTechnology(); + //const Layer* layer1 = track->getLayer()->getTerminalLayer(); + //RegularLayer* layer2 = dynamic_cast(technology->getLayer(layer1->getMask())); + //if (layer2) { + //cerr << track->getLayer() << " minSpace:" << DbU::getValueString(track->getLayer()->getMinimalSpacing()) << endl; + + Point source; + Point target; + Interval segside; + Interval uside = track->getKatanaEngine()->getUSide( track->getDirection() ); + DbU::Unit cap = track->getLayer()->getMinimalSpacing()/2 /*+ track->getLayer()->getExtentionCap()*/; + cdebug_log(159,0) << "uside:" << uside << " cap:" << DbU::getValueString(cap) << endl; + cdebug_log(159,0) << "bb:" << _boundingBox << endl; + if (track->getDirection() == Flags::Horizontal) { + segside = Interval( _boundingBox.getXMin(), _boundingBox.getXMax() ); + _sourceU = max( _boundingBox.getXMin() - cap, uside.getVMin()); + _targetU = min( _boundingBox.getXMax() + cap, uside.getVMax()); + source = Point( _boundingBox.getXMin(), track->getAxis() ); + target = Point( _boundingBox.getXMax(), track->getAxis() ); + } else { + segside = Interval( _boundingBox.getYMin(), _boundingBox.getYMax() ); + _sourceU = max( _boundingBox.getYMin() - cap, uside.getVMin()); + _targetU = min( _boundingBox.getYMax() + cap, uside.getVMax()); + source = Point( track->getAxis(), _boundingBox.getYMin() ); + target = Point( track->getAxis(), _boundingBox.getYMax() ); + } + + setFlags( TElemFixed|TElemForwardSetTrack ); + setTrack( track ); + + if (not net or (net == Session::getBlockageNet())) { + _net = Session::getBlockageNet(); + setFlags( TElemBlockage ); + if (track->getRoutingPlane()->getLayerGauge()->isUsable()) { + GCellsUnder gcells = track->getKatanaEngine()->getGCellsUnder( source, target ); + for ( size_t i=0 ; isize() ; ++i ) { + GCell* gcell = gcells->gcellAt(i); + gcell->addBlockage + ( depth, gcell->getSide( track->getDirection() ).getIntersection( segside ).getSize() ); + } + } + } + } + + + void TrackFixedSpan::_postCreate () + { TrackElement::_postCreate(); } + + + TrackFixedSpan::~TrackFixedSpan () + { } + + + void TrackFixedSpan::_preDestroy () + { + cdebug_log(155,0) << "TrackFixedSpan::_preDestroy() - " << (void*)this << endl; + TrackElement::_preDestroy(); + } + + + TrackFixedSpan* TrackFixedSpan::create ( Net* net, const Box& bb, Track* track ) + { + TrackFixedSpan* trackTerminal = nullptr; + if (not track) + throw Error( "TrackFixedSpan::create(): NULL track argument." ); + + cdebug_log(159,0) << "TrackFixedSpan::create() track:" << track << endl; + trackTerminal = new TrackFixedSpan ( net, bb, track ); + trackTerminal->_postCreate(); + cdebug_log(159,0) << trackTerminal << endl; + Session::addInsertEvent( trackTerminal, track, track->getAxis() ); + return trackTerminal; + } + + + AutoSegment* TrackFixedSpan::base () const { return nullptr; } + Segment* TrackFixedSpan::getSegment () const { return nullptr; } + DbU::Unit TrackFixedSpan::getAxis () const { return getTrack()->getAxis(); } + bool TrackFixedSpan::isHorizontal () const { return getTrack()->isHorizontal(); } + bool TrackFixedSpan::isVertical () const { return getTrack()->isVertical(); } + bool TrackFixedSpan::isFixed () const { return true; } + bool TrackFixedSpan::isPriorityLocked () const { return false; } + Net* TrackFixedSpan::getNet () const { return _net; } + Flags TrackFixedSpan::getDirection () const { return getTrack()->getDirection(); } + DbU::Unit TrackFixedSpan::getWidth () const { return _boundingBox.getWidth(); } + const Layer* TrackFixedSpan::getLayer () const { return getTrack()->getLayer(); } + unsigned int TrackFixedSpan::getDepth () const { return Session::getLayerDepth(getLayer()); } + Interval TrackFixedSpan::getFreeInterval () const { return Interval(); } + size_t TrackFixedSpan::getTrackSpan () const { return 1; } + + + DbU::Unit TrackFixedSpan::getSourceAxis () const + { return (isHorizontal()) ? _boundingBox.getXMin() : _boundingBox.getYMin(); } + + + DbU::Unit TrackFixedSpan::getTargetAxis () const + { return (isHorizontal()) ? _boundingBox.getXMax() : _boundingBox.getYMax(); } + + + unsigned long TrackFixedSpan::getId () const + { + cerr << Error("TrackFixedSpan::getId() called on %s.",_getString().c_str()) << endl; + return 0; + } + + + TrackElement* TrackFixedSpan::getNext () const + { + size_t dummy = _track->find( this ); + return _track->getNext( dummy, getNet() ); + } + + + TrackElement* TrackFixedSpan::getPrevious () const + { + size_t dummy = _track->find( this ); + return _track->getPrevious( dummy, getNet() ); + } + + + void TrackFixedSpan::addOverlapCost ( TrackCost& cost ) const + { cost.getTrack()->addOverlapCost( cost ); } + + + float TrackFixedSpan::getPriority () const + { return 0.0; } + + + void TrackFixedSpan::setPriorityLock ( bool ) + { } + + + void TrackFixedSpan::forcePriority ( float ) + { } + + + void TrackFixedSpan::computePriority () + { } + + + void TrackFixedSpan::computeAlignedPriority () + { } + + + void TrackFixedSpan::detach ( TrackSet& removeds ) + { + // cerr << Error( "TrackFixedSpan::detach(): Must never be called on %s." + // , getString(this).c_str()) << endl; + } + + + string TrackFixedSpan::_getTypeName () const + { return "TrackFixedSpan"; } + + + string TrackFixedSpan::_getString () const + { + string s1 = string("getName()) : "net") + "\" "; + if (getTrack()) { + s1 += "[" + getString(getTrack()->getIndex()) + "] " + + getString(getLayer()->getName()) + " @" + + DbU::getValueString(getTrack()->getAxis()); + } else { + s1 += "[i] layer @axis"; + } + s1 += " [" + DbU::getValueString(_sourceU) + + ":" + DbU::getValueString(_targetU) + "]" + + " " + DbU::getValueString(_targetU-_sourceU) + + " F"; + s1 += (isBlockage() ? "B" : "-"); + s1 += "N>"; + return s1; + } + + + Record* TrackFixedSpan::_getRecord () const + { + Record* record = TrackElement::_getRecord(); + record->add( getSlot( "_net", _net ) ); + record->add( getSlot( "_boundingBox", &_boundingBox ) ); + return record; + } + + +} // Katana namespace. diff --git a/katana/src/TrackSegment.cpp b/katana/src/TrackSegment.cpp index 77382dfbe..89f29d503 100644 --- a/katana/src/TrackSegment.cpp +++ b/katana/src/TrackSegment.cpp @@ -180,6 +180,7 @@ namespace Katana { bool TrackSegment::isGlobal () const { return _base->isWeakGlobal() or _base->isGlobal(); } bool TrackSegment::isWeakGlobal () const { return _base->isWeakGlobal(); } bool TrackSegment::isUnbreakable () const { return _base->isUnbreakable() and not _base->isWeakGlobal(); } + bool TrackSegment::isForOffgrid () const { return _base->isForOffgrid(); } bool TrackSegment::isBipoint () const { return _base->isBipoint(); } bool TrackSegment::isTerminal () const { return _base->isTerminal(); } bool TrackSegment::isDrag () const { return _base->isDrag(); } @@ -487,7 +488,7 @@ namespace Katana { if (isNonPref()) { Interval perpandicularSpan ( getAxis() ); - perpandicularSpan.inflate( base()->getExtensionCap( Anabatic::Flags::Source ) ); + perpandicularSpan.inflate( base()->getExtensionCap( Anabatic::Flags::Source )); _sourceU = perpandicularSpan.getVMin(); _targetU = perpandicularSpan.getVMax(); diff --git a/katana/src/TrackSegmentNonPref.cpp b/katana/src/TrackSegmentNonPref.cpp index d1f5afd18..3b9d3a157 100644 --- a/katana/src/TrackSegmentNonPref.cpp +++ b/katana/src/TrackSegmentNonPref.cpp @@ -98,8 +98,13 @@ namespace Katana { RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_base->getLayer()); Interval newAxisSpan ( _base->getSourcePosition(), _base->getTargetPosition() ); + //newAxisSpan.inflate( base()->getExtensionCap( Anabatic::Flags::NoFlags )); Track* ntrack = plane->getTrackByPosition( newAxisSpan.getVMin(), Constant::Superior ); + cdebug_log(159,0) << "getSourceU(): " << DbU::getValueString( _base->getSourceU() ) << endl; + cdebug_log(159,0) << "getTargetU(): " << DbU::getValueString( _base->getTargetU() ) << endl; + cdebug_log(159,0) << "getSourcePosition(): " << DbU::getValueString( _base->getSourcePosition() ) << endl; + cdebug_log(159,0) << "getTargetPosition(): " << DbU::getValueString( _base->getTargetPosition() ) << endl; cdebug_log(159,0) << "new Axis span: " << newAxisSpan << endl; if (ntrack) { diff --git a/katana/src/katana/NegociateWindow.h b/katana/src/katana/NegociateWindow.h index a48cc587c..243f5ba33 100644 --- a/katana/src/katana/NegociateWindow.h +++ b/katana/src/katana/NegociateWindow.h @@ -39,40 +39,53 @@ namespace Katana { class Statistics { public: - inline Statistics (); - inline size_t getGCellsCount () const; - inline size_t getSegmentsCount () const; - inline size_t getEventsCount () const; - inline void setGCellsCount ( size_t ); - inline void setSegmentsCount ( size_t ); - inline void setEventsCount ( size_t ); - inline void incGCellCount ( size_t ); - inline void incSegmentsCount ( size_t ); - inline void incEventsCount ( size_t ); - inline Statistics& operator+= ( const Statistics& ); + inline Statistics (); + inline size_t getGCellsCount () const; + inline size_t getSegmentsCount () const; + inline size_t getEventsCount () const; + inline size_t getLoadedEventsCount () const; + inline size_t getProcessedEventsCount () const; + inline float getRipupRatio () const; + inline void setGCellsCount ( size_t ); + inline void setSegmentsCount ( size_t ); + inline void setEventsCount ( size_t ); + inline void setLoadedEventsCount ( size_t ); + inline void setProcessedEventsCount ( size_t ); + inline void incGCellCount ( size_t ); + inline void incSegmentsCount ( size_t ); + inline void incEventsCount ( size_t ); + inline Statistics& operator+= ( const Statistics& ); private: size_t _gcellsCount; size_t _segmentsCount; size_t _eventsCount; - + size_t _loadedEventsCount; + size_t _processedEventsCount; }; inline Statistics::Statistics () - : _gcellsCount (0) - , _segmentsCount (0) - , _eventsCount (0) + : _gcellsCount (0) + , _segmentsCount (0) + , _eventsCount (0) + , _loadedEventsCount (0) + , _processedEventsCount(0) { } - inline size_t Statistics::getGCellsCount () const { return _gcellsCount; } - inline size_t Statistics::getSegmentsCount () const { return _segmentsCount; } - inline size_t Statistics::getEventsCount () const { return _eventsCount; } - inline void Statistics::setGCellsCount ( size_t count ) { _gcellsCount = count; } - inline void Statistics::setSegmentsCount ( size_t count ) { _segmentsCount = count; } - inline void Statistics::setEventsCount ( size_t count ) { _eventsCount = count; } - inline void Statistics::incGCellCount ( size_t count ) { _gcellsCount += count; } - inline void Statistics::incSegmentsCount ( size_t count ) { _segmentsCount += count; } - inline void Statistics::incEventsCount ( size_t count ) { _eventsCount += count; } + inline size_t Statistics::getGCellsCount () const { return _gcellsCount; } + inline size_t Statistics::getSegmentsCount () const { return _segmentsCount; } + inline size_t Statistics::getEventsCount () const { return _eventsCount; } + inline size_t Statistics::getLoadedEventsCount () const { return _loadedEventsCount; } + inline size_t Statistics::getProcessedEventsCount () const { return _processedEventsCount; } + inline float Statistics::getRipupRatio () const { return (_loadedEventsCount) ? ((float)(_processedEventsCount - _loadedEventsCount) / (float)_loadedEventsCount) : 0.0; } + inline void Statistics::setGCellsCount ( size_t count ) { _gcellsCount = count; } + inline void Statistics::setSegmentsCount ( size_t count ) { _segmentsCount = count; } + inline void Statistics::setLoadedEventsCount ( size_t count ) { _loadedEventsCount = count; } + inline void Statistics::setProcessedEventsCount ( size_t count ) { _processedEventsCount = count; } + inline void Statistics::setEventsCount ( size_t count ) { _eventsCount = count; } + inline void Statistics::incGCellCount ( size_t count ) { _gcellsCount += count; } + inline void Statistics::incSegmentsCount ( size_t count ) { _segmentsCount += count; } + inline void Statistics::incEventsCount ( size_t count ) { _eventsCount += count; } inline Statistics& Statistics::operator+= ( const Statistics& other ) { diff --git a/katana/src/katana/Track.h b/katana/src/katana/Track.h index d504d62af..f49440fac 100644 --- a/katana/src/katana/Track.h +++ b/katana/src/katana/Track.h @@ -111,6 +111,7 @@ namespace Katana { void invalidate (); void insert ( TrackElement* ); void insert ( TrackMarker* ); + inline void updateInvalidBounds ( TrackElement* ); void setSegment ( TrackElement*, size_t ); size_t doRemoval (); void doReorder (); @@ -130,6 +131,8 @@ namespace Katana { bool _localAssigned; bool _segmentsValid; bool _markersValid; + DbU::Unit _minInvalid; + DbU::Unit _maxInvalid; protected: // Constructors & Destructors. @@ -220,6 +223,13 @@ namespace Katana { } + inline void Track::updateInvalidBounds ( TrackElement* element ) + { + _minInvalid = std::min( _minInvalid, element->getSourceU() ); + _maxInvalid = std::max( _maxInvalid, element->getTargetU() ); + } + + inline bool Track::Compare::operator() ( const Track* lhs, const Track* rhs ) const { if (lhs->isHorizontal() xor rhs->isHorizontal()) return lhs->isHorizontal(); diff --git a/katana/src/katana/TrackElement.h b/katana/src/katana/TrackElement.h index 12fa0dc3a..1aabb1364 100644 --- a/katana/src/katana/TrackElement.h +++ b/katana/src/katana/TrackElement.h @@ -64,20 +64,21 @@ namespace Katana { // ------------------------------------------------------------------- // Class : "TrackElement". - const uint32_t TElemCreated = (1 << 0); - const uint32_t TElemBlockage = (1 << 2); - const uint32_t TElemFixed = (1 << 3); - const uint32_t TElemLocked = (1 << 4); - const uint32_t TElemRouted = (1 << 5); - const uint32_t TElemUseBlockageNet = (1 << 6); - const uint32_t TElemShortDogleg = (1 << 7); - const uint32_t TElemSourceDogleg = (1 << 8); - const uint32_t TElemTargetDogleg = (1 << 9); - const uint32_t TElemAlignBottom = (1 << 10); - const uint32_t TElemAlignCenter = (1 << 11); - const uint32_t TElemAlignTop = (1 << 12); - const uint32_t TElemRipple = (1 << 13); - const uint32_t TElemInvalidated = (1 << 14); + const uint32_t TElemCreated = (1 << 0); + const uint32_t TElemBlockage = (1 << 2); + const uint32_t TElemFixed = (1 << 3); + const uint32_t TElemLocked = (1 << 4); + const uint32_t TElemRouted = (1 << 5); + const uint32_t TElemUseBlockageNet = (1 << 6); + const uint32_t TElemShortDogleg = (1 << 7); + const uint32_t TElemSourceDogleg = (1 << 8); + const uint32_t TElemTargetDogleg = (1 << 9); + const uint32_t TElemAlignBottom = (1 << 10); + const uint32_t TElemAlignCenter = (1 << 11); + const uint32_t TElemAlignTop = (1 << 12); + const uint32_t TElemRipple = (1 << 13); + const uint32_t TElemInvalidated = (1 << 14); + const uint32_t TElemForwardSetTrack = (1 << 15); struct Compare { @@ -115,6 +116,7 @@ namespace Katana { virtual bool isTerminal () const; virtual bool isDrag () const; virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; + virtual bool isForOffgrid () const; virtual bool isStrap () const; virtual bool isSlackened () const; virtual bool isDogleg () const; @@ -131,6 +133,7 @@ namespace Katana { inline bool isBlockage () const; inline bool isLocked () const; inline bool isRouted () const; + inline bool isForwardSetTrack () const; virtual bool hasSymmetric () const; inline bool hasSourceDogleg () const; inline bool hasTargetDogleg () const; @@ -256,6 +259,7 @@ namespace Katana { inline bool TrackElement::isBlockage () const { return _flags & TElemBlockage; } inline bool TrackElement::isLocked () const { return _flags & TElemLocked; } inline bool TrackElement::isRouted () const { return _flags & TElemRouted; } + inline bool TrackElement::isForwardSetTrack () const { return _flags & TElemForwardSetTrack; } inline bool TrackElement::hasSourceDogleg () const { return _flags & TElemSourceDogleg; } inline bool TrackElement::hasTargetDogleg () const { return _flags & TElemTargetDogleg; } inline bool TrackElement::canRipple () const { return _flags & TElemRipple; } diff --git a/katana/src/katana/TrackFixedSpan.h b/katana/src/katana/TrackFixedSpan.h new file mode 100644 index 000000000..b36c272b7 --- /dev/null +++ b/katana/src/katana/TrackFixedSpan.h @@ -0,0 +1,101 @@ +// -*- 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 | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./katana/TrackFixedSpan.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include "katana/TrackElement.h" + + +namespace Katana { + + using std::string; + using std::map; + using Hurricane::Record; + using Hurricane::Interval; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Layer; + + class Track; + + +// ------------------------------------------------------------------- +// Class : "TrackFixedSpan". + + class TrackFixedSpan : public TrackElement { + public: + static TrackFixedSpan* create ( Net*, const Box&, Track* ); + public: + virtual AutoSegment* base () const; + virtual Segment* getSegment () const; + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual bool isFixed () const; + virtual bool isPriorityLocked () const; + virtual unsigned long getId () const; + virtual Net* getNet () const; + virtual Flags getDirection () const; + virtual DbU::Unit getWidth () const; + virtual unsigned int getDepth () const; + virtual const Layer* getLayer () const; + virtual size_t getTrackSpan () const; + 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; + virtual void setPriorityLock ( bool ); + virtual void forcePriority ( float ); + virtual void computePriority (); + virtual void computeAlignedPriority (); + inline void setNet ( Net* ); + virtual void detach ( TrackSet& ); + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + private: + Net* _net; + Box _boundingBox; + protected: + // Constructors & Destructors. + TrackFixedSpan ( Net*, const Box&, Track* ) ; + virtual ~TrackFixedSpan (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + TrackFixedSpan ( const TrackFixedSpan& ) = delete; + TrackFixedSpan& operator= ( const TrackFixedSpan& ) = delete; + }; + + + inline void TrackFixedSpan::setNet ( Net* net ) + { + if (not net or (net == Session::getBlockageNet())) { + _net = Session::getBlockageNet(); + setFlags( TElemBlockage ); + } else { + _net = net; + unsetFlags( TElemBlockage ); + } + } + + +} // Katana namespace. + + +INSPECTOR_P_SUPPORT(Katana::TrackFixedSpan); diff --git a/katana/src/katana/TrackSegment.h b/katana/src/katana/TrackSegment.h index 79f4d36af..8a3a1c847 100644 --- a/katana/src/katana/TrackSegment.h +++ b/katana/src/katana/TrackSegment.h @@ -73,6 +73,7 @@ namespace Katana { virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const; virtual bool isStrap () const; virtual bool isUnbreakable () const; + virtual bool isForOffgrid () const; virtual bool isSlackened () const; virtual bool isDogleg () const; virtual bool isShortDogleg () const; diff --git a/katana/src/meson.build b/katana/src/meson.build index 401ed6769..1dca979c0 100644 --- a/katana/src/meson.build +++ b/katana/src/meson.build @@ -29,6 +29,7 @@ katana = shared_library( 'TrackSegmentNonPref.cpp', 'TrackSegmentWide.cpp', 'TrackFixedSegment.cpp', + 'TrackFixedSpan.cpp', 'TrackMarker.cpp', 'Track.cpp', 'Tracks.cpp', diff --git a/meson.build b/meson.build index d1ca26218..342ac088b 100644 --- a/meson.build +++ b/meson.build @@ -111,9 +111,10 @@ subdir('katana') subdir('tramontana') subdir('equinox') subdir('solstice') -subdir('unicorn') subdir('oroshi') +subdir('karakaze') subdir('bora') +subdir('unicorn') subdir('cumulus') subdir('tutorial') subdir('documentation') diff --git a/oroshi/python/stack.py b/oroshi/python/stack.py index 1f83a72b6..607194c2c 100644 --- a/oroshi/python/stack.py +++ b/oroshi/python/stack.py @@ -602,7 +602,7 @@ def __init__ ( self, device, NERC, NIRC ): else: self.tImplantLayer = rules.getRealLayer( 'pImplant' ) self.bImplantLayer = rules.getRealLayer( 'nImplant' ) - self.wellLayer = rules.getRealLayer( 'pWell' ) + self.wellLayer = rules.getRealLayer( 'nWell' ) return diff --git a/unicorn/src/UnicornGui.cpp b/unicorn/src/UnicornGui.cpp index 99d6dd067..eb604d281 100644 --- a/unicorn/src/UnicornGui.cpp +++ b/unicorn/src/UnicornGui.cpp @@ -23,6 +23,7 @@ #include "hurricane/isobar/Script.h" #include "hurricane/viewer/CellViewer.h" #include "hurricane/viewer/PyCellViewer.h" +#include "hurricane/viewer/BreakpointWidget.h" #include "crlcore/Utilities.h" #include "crlcore/Catalog.h" #include "crlcore/AllianceFramework.h" @@ -54,6 +55,7 @@ namespace Unicorn { using Hurricane::jsonCellParse; using Hurricane::DataBase; using Hurricane::Library; + using Hurricane::BreakpointWidget; using CRL::System; using CRL::Catalog; using CRL::AllianceFramework; @@ -171,15 +173,24 @@ namespace Unicorn { connect ( exportAction, SIGNAL(triggered()), this, SLOT(exportCell()) ); } - QAction* action = addToMenu( "tools.libraryManager" - , tr("Library Manager") - , tr("Browse through Views, Cells & Libraries") - , QKeySequence(tr("CTRL+M")) - , QIcon() - , "tools.script" + QAction* action = addToMenu( "file.saveSettings" + , tr("Save settings") + , tr("Save windows size & positions") + , QKeySequence() ); + connect( action, SIGNAL(triggered()), this, SLOT(saveQtSettings()) ); + + action = addToMenu( "tools.libraryManager" + , tr("Library Manager") + , tr("Browse through Views, Cells & Libraries") + , QKeySequence(tr("CTRL+M")) + , QIcon() + , "tools.script" + ); connect( action, SIGNAL(triggered()), _libraryManager, SLOT(toggleShow()) ); connect( this , SIGNAL(cellLoadedFromDisk(Cell*)), _libraryManager, SLOT(updateLibrary(Cell*)) ); + + readQtSettings(); } @@ -191,6 +202,22 @@ namespace Unicorn { } + void UnicornGui::readQtSettings () + { + CellViewer::readQtSettings(); + BreakpointWidget::readQtSettings(); + _libraryManager->readQtSettings(); + } + + + void UnicornGui::saveQtSettings () + { + CellViewer::saveQtSettings(); + BreakpointWidget::saveQtSettings(); + _libraryManager->saveQtSettings(); + } + + Cell* UnicornGui::getCellFromDb ( const char* name ) { Cell* cell = DataBase::getDB()->getCell( name ); diff --git a/unicorn/src/unicorn/UnicornGui.h b/unicorn/src/unicorn/UnicornGui.h index c610f46ad..bcef8ac08 100644 --- a/unicorn/src/unicorn/UnicornGui.h +++ b/unicorn/src/unicorn/UnicornGui.h @@ -52,6 +52,7 @@ namespace Unicorn { public: static UnicornGui* create ( QWidget* parent=NULL ); void destroy (); + void readQtSettings (); static inline Banner& getBanner (); virtual Cell* getCellFromDb ( const char* name ); inline ImportCell* getImportCell (); @@ -59,6 +60,7 @@ namespace Unicorn { virtual UnicornGui* vcreate () const; virtual std::string _getString () const; public slots: + void saveQtSettings (); void openCell (); void saveCell (); void importCell (); diff --git a/unittests/python/dodo.py b/unittests/python/dodo.py new file mode 100644 index 000000000..d27a72fb9 --- /dev/null +++ b/unittests/python/dodo.py @@ -0,0 +1,34 @@ + +import socket +from pathlib import Path + +#useTechno = 'MOSIS' +#useTechno = 'AMS350' +useTechno = 'CMOS' + +checkToolkit = Path.home() / 'coriolis-2.x' / 'src' / 'alliance-check-toolkit' +if useTechno == 'AMS350': + hostname = socket.gethostname() + if hostname.startswith('lepka'): + ndaTop = Path( '/dsk/l1/jpc/crypted/soc/techno' ) + if not ndaTop.is_dir(): + print( '[ERROR] You forgot to mount the NDA encrypted directory, stupid!' ) + else: + ndaTop = '/users/soft/techno/techno' + from coriolis.designflow.technos import setupAMS350 + setupAMS350( checkToolkit=checkToolkit, ndaTop=ndaTop ) +elif useTechno == 'MOSIS': + from coriolis.designflow.technos import setupMOSIS + setupMOSIS( checkToolkit=checkToolkit ) +elif useTechno == 'CMOS': + from coriolis.designflow.technos import setupCMOS + setupCMOS( checkToolkit=checkToolkit ) + +DOIT_CONFIG = { 'verbosity' : 2 } + +from coriolis.designflow.pnr import PnR +from coriolis.designflow.clean import Clean +PnR.textMode = True + +ruleCgt = PnR .mkRule( 'cgt' ) +ruleClean = Clean.mkRule() diff --git a/unittests/python/test_rectilinear.py b/unittests/python/test_rectilinear.py index 447dce17b..184b58e05 100644 --- a/unittests/python/test_rectilinear.py +++ b/unittests/python/test_rectilinear.py @@ -17,7 +17,7 @@ def testRectilinear ( editor ): with UpdateSession(): cell = AllianceFramework.get().createCell( 'Rectilinear' ) cell.setTerminalNetlist( True ) - cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(400.0), l(200.0) ) ) + cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(704.0), l(200.0) ) ) #cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(21.0), l(35.0) ) ) if editor: editor.setCell( cell ) @@ -28,6 +28,7 @@ def testRectilinear ( editor ): metal2 = technology.getLayer( "METAL2" ) metal3 = technology.getLayer( "METAL3" ) metal4 = technology.getLayer( "METAL4" ) + metal5 = technology.getLayer( "METAL5" ) poly = technology.getLayer( "POLY" ) ptrans = technology.getLayer( "PTRANS" ) ntrans = technology.getLayer( "NTRANS" ) @@ -155,6 +156,18 @@ def testRectilinear ( editor ): for box in boxes: box.translate( l(180.0), l(0.0) ) Pad.create( net, metal3, box ) + boxes = [] + r.getAsBiggestRectangles( boxes, l(15.0), l(15.0) ) + #print( 'boxes={}'.format( boxes )) + for box in boxes: + box.translate( l(360.0), l(0.0) ) + Pad.create( net, metal4, box ) + boxes = [] + r.getAsRectangles( boxes, Rectilinear.HSliced ) + #print( 'boxes={}'.format( boxes )) + for box in boxes: + box.translate( l(540.0), l(0.0) ) + Pad.create( net, metal5, box ) Gds.save( cell )