From 7e7e7170bac60027016f7d60da43863322722a64 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 10 Apr 2020 12:15:23 +0200 Subject: [PATCH] Improve symmetry management for analog designs. * Bug: In Hurricane::NetRoutingState::getSymValue(), outrageously bad computation of the symmetric coordinate when the value was superior to the axis... (shame on me). * Change: In Anabatic::Disjkstra::load(), for symmetrically paired nets, check that the axis of symmetry is *outside* the searchArea. Otherwise, the two mirrored areas overlaps and the two nets will unescapably be on top of each other. Issue a warning but still continue. * Change: In Anabatic::Vertex::isRestricted(), allow perpandicular wire to go through struts or thin (less than one routing pitch) node. May have to recheck in the future and restrict to struts only. * Bug: In Bora::HVSlicingNode::updateSymNetAxis(), rescursive call in child node was not systematically done (bad curly brace position). Also checks that symmetries are not empty before accessing the front element (one less core dump). --- anabatic/src/Dijkstra.cpp | 204 ++++++++++++------ bora/src/BoraEngine.cpp | 2 +- bora/src/HVSlicingNode.cpp | 28 ++- bora/src/bora/AnalogDistance.h | 1 + .../src/hurricane/NetRoutingProperty.cpp | 5 +- karakaze/python/analogdesign.py | 2 +- oroshi/python/resistor.py | 2 +- oroshi/python/wip_csp.py | 3 +- oroshi/python/wip_dp.py | 3 +- oroshi/python/wip_transistor.py | 3 +- unicorn/src/cgt.py | 7 +- 11 files changed, 169 insertions(+), 91 deletions(-) diff --git a/anabatic/src/Dijkstra.cpp b/anabatic/src/Dijkstra.cpp index 51635ccd..b21933e6 100644 --- a/anabatic/src/Dijkstra.cpp +++ b/anabatic/src/Dijkstra.cpp @@ -298,52 +298,68 @@ namespace Anabatic { GCell* c2 = v2->getGCell(); // Check from GCell 1 - if ( c1->isNorth(c2) ) { - if ( !v1->isNRestricted() ) restricted = false; - } else if ( c1->isSouth(c2) ) { - if ( !v1->isSRestricted() ) restricted = false; - } else if ( c1->isEast (c2) ) { - if ( !v1->isERestricted() ) restricted = false; - } else if ( c1->isWest (c2) ) { - if ( !v1->isWRestricted() ) restricted = false; - } else { - cerr << Error( "GCells are not side by side." ) << endl; + if ( c1->isNorth(c2) and not v1->isNRestricted() ) restricted = false; + else if ( c1->isSouth(c2) and not v1->isSRestricted() ) restricted = false; + else if ( c1->isEast (c2) and not v1->isERestricted() ) restricted = false; + else if ( c1->isWest (c2) and not v1->isWRestricted() ) restricted = false; + // else { + // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n" + // " v1:%s\n" + // " v2:%s" + // , getString(v1).c_str() + // , getString(v2).c_str() + // ) << endl; + // return true; + // } + + if (restricted) { + cdebug_log(112,0) << "v1 -> v2 edge is restricted." << endl; + return true; + } + if ( e->isVertical() and (c1->getWidth() < hpitch) ) { + cdebug_log(112,0) << "GCell 1 is too narrow for V edges." << endl; + return true; + } + if ( e->isHorizontal() and (c1->getHeight() < vpitch) ) { + cdebug_log(112,0) << "GCell 1 is too narrow for H edges." << endl; return true; } - if ( (c1->getWidth() < hpitch) - ||(c1->getHeight() < vpitch) - ||(restricted) - ) return true; - else { - restricted = true; - // Check from GCell 2 - if ( c2->isNorth(c1) ) { - if ( !v2->isNRestricted() ) restricted = false; - } else if ( c2->isSouth(c1) ) { - if ( !v2->isSRestricted() ) restricted = false; - } else if ( c2->isEast (c1) ) { - if ( !v2->isERestricted() ) restricted = false; - } else if ( c2->isWest (c1) ) { - if ( !v2->isWRestricted() ) restricted = false; - } else { - cerr << Error( "GCells are not side by side." ) << endl; - return true; - } - if ( (c2->getWidth() < hpitch) - ||(c2->getHeight() < vpitch) - ||(restricted) - ) return true; - else { - if ((v2->getGCell()->isStrut())){ - if (e->isMaxCapacity(net)) { - cdebug_log(112,0) << "Overcapacity:" << e << endl; - return true; - } - else return false; - } else return false; - } + restricted = true; + // Check from GCell 2 + if ( c2->isNorth(c1) and not v2->isNRestricted() ) restricted = false; + else if ( c2->isSouth(c1) and not v2->isSRestricted() ) restricted = false; + else if ( c2->isEast (c1) and not v2->isERestricted() ) restricted = false; + else if ( c2->isWest (c1) and not v2->isWRestricted() ) restricted = false; + // else { + // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n" + // " v1:%s\n" + // " v2:%s" + // , getString(v1).c_str() + // , getString(v2).c_str() + // ) << endl; + // return true; + // } + + if (restricted) { + cdebug_log(112,0) << "v2 -> v1 edge is restricted." << endl; + return true; } + if ( e->isVertical() and (c2->getWidth() < hpitch) ) { + cdebug_log(112,0) << "GCell 2 is too narrow for V edges." << endl; + return true; + } + if ( e->isHorizontal() and (c2->getHeight() < vpitch) ) { + cdebug_log(112,0) << "GCell 2 is too narrow for H edges." << endl; + return true; + } + + if ( v2->getGCell()->isStrut() and e->isMaxCapacity(net) ) { + cdebug_log(112,0) << "Overcapacity:" << e << endl; + return true; + } + + return false; } @@ -1568,6 +1584,34 @@ namespace Anabatic { rp->getBodyHook()->attach( vcontact->getBodyHook() ); } + if (state and state->isSymmetric() and not state->isSelfSym() and state->isSymMaster()) { + if (state->isSymVertical()) { + if ( (_searchArea.getXMin() < state->getSymAxis()) + and (_searchArea.getXMax() > state->getSymAxis()) ) { + cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n" + " Vertical symmetry axis @%s is inside the net area %s." + , getString(_net->getName()).c_str() + , getString(state->getSymNet()->getName()).c_str() + , DbU::getValueString(state->getSymAxis()).c_str() + , getString(_searchArea).c_str() + ) << endl; + } + } + + if (state->isSymHorizontal()) { + if ( (_searchArea.getYMin() < state->getSymAxis()) + and (_searchArea.getYMax() > state->getSymAxis()) ) { + cerr << Error( "Diskstra::load(): For net \"%s\" (paired with \"%s\"),\n" + " Horizontal symmetry axis @%s is inside the net area %s." + , getString(_net->getName()).c_str() + , getString(state->getSymNet()->getName()).c_str() + , DbU::getValueString(state->getSymAxis()).c_str() + , getString(_searchArea).c_str() + ) << endl; + } + } + } + _searchArea.inflate( _searchAreaHalo ); cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl; cdebug_log(112,0) << "Search area: " << _searchArea << endl; @@ -2150,6 +2194,7 @@ namespace Anabatic { , constraint.getCenter() , width ); + cdebug_log(112,0) << "| ref: " << segment << endl; for ( Edge* through : aligneds ) through->add( segment ); if (state) { @@ -2168,6 +2213,7 @@ namespace Anabatic { , constraint.getCenter() , width ); + cdebug_log(112,0) << "| ref: " << segment << endl; for ( Edge* through : aligneds ) through->add( segment ); if (state) { @@ -2330,51 +2376,66 @@ namespace Anabatic { void Dijkstra::_createSelfSymSeg ( Segment* segment ) { - cdebug_log(112,0) << "void Dijkstra::_createSelfSymSeg ( Segment* segment ): " << _net << ", seg: " << segment << endl; + cdebug_log(112,1) << "Dijkstra::_createSelfSymSeg(): " << segment << endl; + NetRoutingState* state = NetRoutingExtension::get( _net ); - //cdebug_log(112,0) << "state: " << state << endl; - if ((state != NULL)&&(segment!=NULL)){ + if (state and segment) { Horizontal* h = dynamic_cast(segment); - Vertical* v = dynamic_cast(segment); - Point sp, tp; - DbU::Unit axis; - Component* sourceContact = segment->getSource(); - Component* targetContact = segment->getTarget(); - if (h){ - if (state->isSymHorizontal()){ - cdebug_log(112,0) << "H case Horizontal" << endl; - sp = Point(sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); - tp = Point(targetContact->getX(), state->getSymValue(targetContact->getY()) ); - axis = state->getSymValue(segment->getY()); - } else if (state->isSymVertical()){ - cdebug_log(112,0) << "H case Vertical" << endl; - sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() ); - tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() ); + Vertical* v = dynamic_cast(segment); + Point sp; + Point tp; + DbU::Unit axis; + Component* sourceContact = segment->getSource(); + Component* targetContact = segment->getTarget(); + + cdebug_log(112,0) << "source: " << sourceContact << endl; + cdebug_log(112,0) << "target: " << targetContact << endl; + cdebug_log(112,0) << "sym axis: " << DbU::getValueString(state->getSymAxis()) << endl; + + if (h) { + if (state->isSymHorizontal()) { + cdebug_log(112,0) << "Horizontal + Horizontal symmetry." << endl; + + sp = Point( sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); + tp = Point( targetContact->getX(), state->getSymValue(targetContact->getY()) ); + axis = state->getSymValue( segment->getY() ); + } else if (state->isSymVertical()) { + cdebug_log(112,0) << "Horizontal + Vertical symmetry." << endl; + + sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() ); + tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() ); axis = segment->getY(); } else { - cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; + cdebug_log(112,0) << "Dijkstra::_materialize(): Horizontal + Unknown symmetry. " << endl; + cdebug_tabw(112,-1); return; } - //cerr << "sp: " << sp << endl; - //cerr << "tp: " << tp << endl; + + cdebug_log(112,0) << "sp: " << sp << endl; + cdebug_log(112,0) << "tp: " << tp << endl; + GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* tgcell = _anabatic->getGCellUnder( tp ); - //cerr << "Gcell: " << sgcell << endl; - //cerr << "Gcell: " << tgcell << endl; + + cdebug_log(112,0) << "GCell: " << sgcell << endl; + cdebug_log(112,0) << "GCell: " << tgcell << endl; + Vertex* svertex = sgcell->getObserver(GCell::Observable::Vertex); Vertex* tvertex = tgcell->getObserver(GCell::Observable::Vertex); + Contact* sourceSym = NULL; Contact* targetSym = NULL; - if (state->isSelfSym()){ - cdebug_log(112,0) << "isSelfSym" << endl; + if (state->isSelfSym()) { + cdebug_log(112,0) << "Symmetrical to myself (isSelfSym)." << endl; sourceSym = svertex->getGContact( _net ); targetSym = tvertex->getGContact( _net ); } else if (state->isSymMaster()){ - cdebug_log(112,0) << "isSymPair: " << state->getSymNet() << endl; + cdebug_log(112,0) << "Symmetrical to (isSymPair): " << state->getSymNet() << endl; sourceSym = svertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() ); } else { - cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; + cdebug_log(112,0) << "Dijkstra::_materialize(): Unknown Net pairing symmetry. " << endl; + cdebug_tabw(112,-1); return; } @@ -2386,7 +2447,7 @@ namespace Anabatic { , axis , state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")) ); - cdebug_log(112,0) << "|| " << segment2 << endl; + cdebug_log(112,0) << "| dup:" << segment2 << endl; } else if (v) { if (state->isSymVertical()){ //cerr << "V case Vertical" << endl; @@ -2400,6 +2461,7 @@ namespace Anabatic { axis = segment->getX(); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; + cdebug_tabw(112,-1); return; } GCell* sgcell = _anabatic->getGCellUnder( sp ); @@ -2416,6 +2478,7 @@ namespace Anabatic { targetSym = tvertex->getGContact( state->getSymNet() ); } else { cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; + cdebug_tabw(112,-1); return; } @@ -2430,6 +2493,7 @@ namespace Anabatic { cdebug_log(112,0) << "|| " << segment2 << endl; } } + cdebug_tabw(112,-1); } diff --git a/bora/src/BoraEngine.cpp b/bora/src/BoraEngine.cpp index 5dcba10a..d6225872 100644 --- a/bora/src/BoraEngine.cpp +++ b/bora/src/BoraEngine.cpp @@ -267,7 +267,7 @@ namespace Bora { slicingtree->expandRoutingChannel(); slicingtree->replace(); slicingtree->updateSymNetAxis(); - + katana->updateMatrix(); katana->analogInit(); Katana::Session::close(); diff --git a/bora/src/HVSlicingNode.cpp b/bora/src/HVSlicingNode.cpp index 62bc495e..b9f04653 100644 --- a/bora/src/HVSlicingNode.cpp +++ b/bora/src/HVSlicingNode.cpp @@ -377,10 +377,14 @@ namespace Bora { if (getType() == HorizontalSNode) symmetryType = HSymmetry; if (getType() == VerticalSNode ) symmetryType = VSymmetry; - if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) { - cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored." - , childIndex, copyIndex ) << endl; + cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored.\n" + " child %d: %s\n" + " child %d: %s" + , childIndex, copyIndex + , childIndex, getString(getChild(childIndex)).c_str() + , copyIndex , getString(getChild( copyIndex)).c_str() + ) << endl; return; } @@ -1128,6 +1132,9 @@ namespace Bora { void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) { + cerr << "HVSlicingNode::addSymmetryNet(): " << this << endl; + cerr << "* " << net1 << endl; + if (checkSymmetryNet(type,net1,net2)) { cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl; return; @@ -1201,6 +1208,13 @@ namespace Bora { } for ( const NetSymmetry& symNet : _netSymmetries ) { + if (_symmetries.empty()) + throw Error( "HVSlicingNode::updateSymNetAxis(): \n" + " Symmetry request for \"%s\" in non-symmetrical node \"%s\"." + , getString(get<1>(symNet)->getName()).c_str() + , getString(this).c_str() + ); + SlicingNode* n1 = getChild( _symmetries.front().first ); SlicingNode* n2 = getChild( _symmetries.front().second ); DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2; @@ -1248,11 +1262,11 @@ namespace Bora { } } } + } - for ( SlicingNode* child : _children ) { - if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) - child->updateSymNetAxis(); - } + for ( SlicingNode* child : _children ) { + if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) + child->updateSymNetAxis(); } } diff --git a/bora/src/bora/AnalogDistance.h b/bora/src/bora/AnalogDistance.h index e29196f6..bf2601d2 100644 --- a/bora/src/bora/AnalogDistance.h +++ b/bora/src/bora/AnalogDistance.h @@ -86,6 +86,7 @@ namespace Bora { DbU::Unit addedDistance = 0; if (Vertex::isRestricted(vcurr, vnext, e, _hpitch, _vpitch, _net)) { + cdebug_log(112,1) << "Unreachable, restricted "<< e << std::endl; distance = Vertex::unreachable; } else { if ( (vcurr->getGCell()->isMatrix()) and (vnext->getGCell()->isMatrix()) ) { diff --git a/hurricane/src/hurricane/NetRoutingProperty.cpp b/hurricane/src/hurricane/NetRoutingProperty.cpp index 6e464384..8d87a7d0 100644 --- a/hurricane/src/hurricane/NetRoutingProperty.cpp +++ b/hurricane/src/hurricane/NetRoutingProperty.cpp @@ -30,9 +30,8 @@ namespace Hurricane { DbU::Unit NetRoutingState::getSymValue( DbU::Unit v ) const { - if (v < _axis) { - return _axis + (_axis-v); - } else return _axis; + if (v < _axis) return _axis + (_axis-v); + return 2*_axis - v ; } diff --git a/karakaze/python/analogdesign.py b/karakaze/python/analogdesign.py index 7b2aaf3e..6d990a24 100644 --- a/karakaze/python/analogdesign.py +++ b/karakaze/python/analogdesign.py @@ -54,7 +54,7 @@ import Katana import Bora -helpers.setTraceLevel( 100 ) +#helpers.setTraceLevel( 100 ) NMOS = Transistor.NMOS diff --git a/oroshi/python/resistor.py b/oroshi/python/resistor.py index 200b18c4..ae4e28df 100644 --- a/oroshi/python/resistor.py +++ b/oroshi/python/resistor.py @@ -9,7 +9,7 @@ import helpers import helpers.io from helpers import trace -helpers.setTraceLevel( 100 ) +#helpers.setTraceLevel( 100 ) import Analog from Analog import Device diff --git a/oroshi/python/wip_csp.py b/oroshi/python/wip_csp.py index d3c651b2..39305982 100644 --- a/oroshi/python/wip_csp.py +++ b/oroshi/python/wip_csp.py @@ -7,8 +7,7 @@ from Hurricane import Box import helpers from helpers import trace -helpers.staticInitialization( quiet=True ) -helpers.setTraceLevel( 1000 ) +#helpers.setTraceLevel( 1000 ) try: import Analog diff --git a/oroshi/python/wip_dp.py b/oroshi/python/wip_dp.py index 1debae4f..f915e816 100644 --- a/oroshi/python/wip_dp.py +++ b/oroshi/python/wip_dp.py @@ -7,8 +7,7 @@ from Hurricane import Box import helpers from helpers import trace -helpers.staticInitialization( quiet=True ) -helpers.setTraceLevel( 1000 ) +#helpers.setTraceLevel( 1000 ) try: import Analog diff --git a/oroshi/python/wip_transistor.py b/oroshi/python/wip_transistor.py index 8dee2a2d..47fcb355 100644 --- a/oroshi/python/wip_transistor.py +++ b/oroshi/python/wip_transistor.py @@ -8,8 +8,7 @@ import helpers import helpers.io from helpers import trace -helpers.staticInitialization( quiet=True ) -helpers.setTraceLevel( 1000 ) +#helpers.setTraceLevel( 1000 ) try: import Analog diff --git a/unicorn/src/cgt.py b/unicorn/src/cgt.py index 46712ac1..0c30921d 100755 --- a/unicorn/src/cgt.py +++ b/unicorn/src/cgt.py @@ -53,6 +53,9 @@ def credits (): def runScript ( scriptPath, editor ): try: + sys.stdout.flush() + sys.stderr.flush() + kw = { } if editor: kw[ 'editor' ] = editor sys.path.insert( 0, os.path.dirname(scriptPath) ) @@ -75,9 +78,9 @@ def runScript ( scriptPath, editor ): #print ' Please check your design hierarchy or the Python syntax.' #print ' Error was:' #print ' %s\n' % e - helpers.showPythonTrace( scriptPath, e ) + helpers.io.catch( e ) except Exception, e: - helpers.showPythonTrace( scriptPath, e ) + helpers.io.catch( e ) return