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).
This commit is contained in:
Jean-Paul Chaput 2020-04-10 12:15:23 +02:00
parent 74e4544a55
commit 7e7e7170ba
11 changed files with 169 additions and 91 deletions

View File

@ -298,52 +298,68 @@ namespace Anabatic {
GCell* c2 = v2->getGCell(); GCell* c2 = v2->getGCell();
// Check from GCell 1 // Check from GCell 1
if ( c1->isNorth(c2) ) { if ( c1->isNorth(c2) and not v1->isNRestricted() ) restricted = false;
if ( !v1->isNRestricted() ) restricted = false; else if ( c1->isSouth(c2) and not v1->isSRestricted() ) restricted = false;
} else if ( c1->isSouth(c2) ) { else if ( c1->isEast (c2) and not v1->isERestricted() ) restricted = false;
if ( !v1->isSRestricted() ) restricted = false; else if ( c1->isWest (c2) and not v1->isWRestricted() ) restricted = false;
} else if ( c1->isEast (c2) ) { // else {
if ( !v1->isERestricted() ) restricted = false; // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
} else if ( c1->isWest (c2) ) { // " v1:%s\n"
if ( !v1->isWRestricted() ) restricted = false; // " v2:%s"
} else { // , getString(v1).c_str()
cerr << Error( "GCells are not side by side." ) << endl; // , 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; return true;
} }
if ( (c1->getWidth() < hpitch) restricted = true;
||(c1->getHeight() < vpitch) // Check from GCell 2
||(restricted) if ( c2->isNorth(c1) and not v2->isNRestricted() ) restricted = false;
) return true; else if ( c2->isSouth(c1) and not v2->isSRestricted() ) restricted = false;
else { else if ( c2->isEast (c1) and not v2->isERestricted() ) restricted = false;
restricted = true; else if ( c2->isWest (c1) and not v2->isWRestricted() ) restricted = false;
// Check from GCell 2 // else {
if ( c2->isNorth(c1) ) { // cerr << Error( "Vertex::isRestricted(): Vertexes/GCells v1 & v2 do not share a side.\n"
if ( !v2->isNRestricted() ) restricted = false; // " v1:%s\n"
} else if ( c2->isSouth(c1) ) { // " v2:%s"
if ( !v2->isSRestricted() ) restricted = false; // , getString(v1).c_str()
} else if ( c2->isEast (c1) ) { // , getString(v2).c_str()
if ( !v2->isERestricted() ) restricted = false; // ) << endl;
} else if ( c2->isWest (c1) ) { // return true;
if ( !v2->isWRestricted() ) restricted = false; // }
} else {
cerr << Error( "GCells are not side by side." ) << endl; if (restricted) {
return true; cdebug_log(112,0) << "v2 -> v1 edge is restricted." << 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;
}
} }
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() ); 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 ); _searchArea.inflate( _searchAreaHalo );
cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl; cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl;
cdebug_log(112,0) << "Search area: " << _searchArea << endl; cdebug_log(112,0) << "Search area: " << _searchArea << endl;
@ -2150,6 +2194,7 @@ namespace Anabatic {
, constraint.getCenter() , constraint.getCenter()
, width , width
); );
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment ); for ( Edge* through : aligneds ) through->add( segment );
if (state) { if (state) {
@ -2168,6 +2213,7 @@ namespace Anabatic {
, constraint.getCenter() , constraint.getCenter()
, width , width
); );
cdebug_log(112,0) << "| ref: " << segment << endl;
for ( Edge* through : aligneds ) through->add( segment ); for ( Edge* through : aligneds ) through->add( segment );
if (state) { if (state) {
@ -2330,51 +2376,66 @@ namespace Anabatic {
void Dijkstra::_createSelfSymSeg ( Segment* segment ) 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 ); NetRoutingState* state = NetRoutingExtension::get( _net );
//cdebug_log(112,0) << "state: " << state << endl; if (state and segment) {
if ((state != NULL)&&(segment!=NULL)){
Horizontal* h = dynamic_cast<Horizontal*>(segment); Horizontal* h = dynamic_cast<Horizontal*>(segment);
Vertical* v = dynamic_cast<Vertical*>(segment); Vertical* v = dynamic_cast<Vertical *>(segment);
Point sp, tp; Point sp;
DbU::Unit axis; Point tp;
Component* sourceContact = segment->getSource(); DbU::Unit axis;
Component* targetContact = segment->getTarget(); Component* sourceContact = segment->getSource();
if (h){ Component* targetContact = segment->getTarget();
if (state->isSymHorizontal()){
cdebug_log(112,0) << "H case Horizontal" << endl; cdebug_log(112,0) << "source: " << sourceContact << endl;
sp = Point(sourceContact->getX(), state->getSymValue(sourceContact->getY()) ); cdebug_log(112,0) << "target: " << targetContact << endl;
tp = Point(targetContact->getX(), state->getSymValue(targetContact->getY()) ); cdebug_log(112,0) << "sym axis: " << DbU::getValueString(state->getSymAxis()) << endl;
axis = state->getSymValue(segment->getY());
} else if (state->isSymVertical()){ if (h) {
cdebug_log(112,0) << "H case Vertical" << endl; if (state->isSymHorizontal()) {
sp = Point( state->getSymValue(targetContact->getX()), targetContact->getY() ); cdebug_log(112,0) << "Horizontal + Horizontal symmetry." << endl;
tp = Point( state->getSymValue(sourceContact->getX()), sourceContact->getY() );
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(); axis = segment->getY();
} else { } 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; 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* sgcell = _anabatic->getGCellUnder( sp );
GCell* tgcell = _anabatic->getGCellUnder( tp ); 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<Vertex>(GCell::Observable::Vertex); Vertex* svertex = sgcell->getObserver<Vertex>(GCell::Observable::Vertex);
Vertex* tvertex = tgcell->getObserver<Vertex>(GCell::Observable::Vertex); Vertex* tvertex = tgcell->getObserver<Vertex>(GCell::Observable::Vertex);
Contact* sourceSym = NULL; Contact* sourceSym = NULL;
Contact* targetSym = NULL; Contact* targetSym = NULL;
if (state->isSelfSym()){ if (state->isSelfSym()) {
cdebug_log(112,0) << "isSelfSym" << endl; cdebug_log(112,0) << "Symmetrical to myself (isSelfSym)." << endl;
sourceSym = svertex->getGContact( _net ); sourceSym = svertex->getGContact( _net );
targetSym = tvertex->getGContact( _net ); targetSym = tvertex->getGContact( _net );
} else if (state->isSymMaster()){ } 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() ); sourceSym = svertex->getGContact( state->getSymNet() );
targetSym = tvertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() );
} else { } 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; return;
} }
@ -2386,7 +2447,7 @@ namespace Anabatic {
, axis , axis
, state->getWPitch()*Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")) , 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) { } else if (v) {
if (state->isSymVertical()){ if (state->isSymVertical()){
//cerr << "V case Vertical" << endl; //cerr << "V case Vertical" << endl;
@ -2400,6 +2461,7 @@ namespace Anabatic {
axis = segment->getX(); axis = segment->getX();
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong here. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
GCell* sgcell = _anabatic->getGCellUnder( sp ); GCell* sgcell = _anabatic->getGCellUnder( sp );
@ -2416,6 +2478,7 @@ namespace Anabatic {
targetSym = tvertex->getGContact( state->getSymNet() ); targetSym = tvertex->getGContact( state->getSymNet() );
} else { } else {
cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl; cdebug_log(112,0) << "Dijkstra::_materialize(): Something is wrong with the symmetry. " << endl;
cdebug_tabw(112,-1);
return; return;
} }
@ -2430,6 +2493,7 @@ namespace Anabatic {
cdebug_log(112,0) << "|| " << segment2 << endl; cdebug_log(112,0) << "|| " << segment2 << endl;
} }
} }
cdebug_tabw(112,-1);
} }

View File

@ -267,7 +267,7 @@ namespace Bora {
slicingtree->expandRoutingChannel(); slicingtree->expandRoutingChannel();
slicingtree->replace(); slicingtree->replace();
slicingtree->updateSymNetAxis(); slicingtree->updateSymNetAxis();
katana->updateMatrix(); katana->updateMatrix();
katana->analogInit(); katana->analogInit();
Katana::Session::close(); Katana::Session::close();

View File

@ -377,10 +377,14 @@ namespace Bora {
if (getType() == HorizontalSNode) symmetryType = HSymmetry; if (getType() == HorizontalSNode) symmetryType = HSymmetry;
if (getType() == VerticalSNode ) symmetryType = VSymmetry; if (getType() == VerticalSNode ) symmetryType = VSymmetry;
if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) { 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." cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored.\n"
, childIndex, copyIndex ) << endl; " child %d: %s\n"
" child %d: %s"
, childIndex, copyIndex
, childIndex, getString(getChild(childIndex)).c_str()
, copyIndex , getString(getChild( copyIndex)).c_str()
) << endl;
return; return;
} }
@ -1128,6 +1132,9 @@ namespace Bora {
void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )
{ {
cerr << "HVSlicingNode::addSymmetryNet(): " << this << endl;
cerr << "* " << net1 << endl;
if (checkSymmetryNet(type,net1,net2)) { if (checkSymmetryNet(type,net1,net2)) {
cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl; cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl;
return; return;
@ -1201,6 +1208,13 @@ namespace Bora {
} }
for ( const NetSymmetry& symNet : _netSymmetries ) { 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* n1 = getChild( _symmetries.front().first );
SlicingNode* n2 = getChild( _symmetries.front().second ); SlicingNode* n2 = getChild( _symmetries.front().second );
DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2; DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2;
@ -1248,11 +1262,11 @@ namespace Bora {
} }
} }
} }
}
for ( SlicingNode* child : _children ) { for ( SlicingNode* child : _children ) {
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
child->updateSymNetAxis(); child->updateSymNetAxis();
}
} }
} }

View File

@ -86,6 +86,7 @@ namespace Bora {
DbU::Unit addedDistance = 0; DbU::Unit addedDistance = 0;
if (Vertex::isRestricted(vcurr, vnext, e, _hpitch, _vpitch, _net)) { if (Vertex::isRestricted(vcurr, vnext, e, _hpitch, _vpitch, _net)) {
cdebug_log(112,1) << "Unreachable, restricted "<< e << std::endl;
distance = Vertex::unreachable; distance = Vertex::unreachable;
} else { } else {
if ( (vcurr->getGCell()->isMatrix()) and (vnext->getGCell()->isMatrix()) ) { if ( (vcurr->getGCell()->isMatrix()) and (vnext->getGCell()->isMatrix()) ) {

View File

@ -30,9 +30,8 @@ namespace Hurricane {
DbU::Unit NetRoutingState::getSymValue( DbU::Unit v ) const DbU::Unit NetRoutingState::getSymValue( DbU::Unit v ) const
{ {
if (v < _axis) { if (v < _axis) return _axis + (_axis-v);
return _axis + (_axis-v); return 2*_axis - v ;
} else return _axis;
} }

View File

@ -54,7 +54,7 @@ import Katana
import Bora import Bora
helpers.setTraceLevel( 100 ) #helpers.setTraceLevel( 100 )
NMOS = Transistor.NMOS NMOS = Transistor.NMOS

View File

@ -9,7 +9,7 @@ import helpers
import helpers.io import helpers.io
from helpers import trace from helpers import trace
helpers.setTraceLevel( 100 ) #helpers.setTraceLevel( 100 )
import Analog import Analog
from Analog import Device from Analog import Device

View File

@ -7,8 +7,7 @@ from Hurricane import Box
import helpers import helpers
from helpers import trace from helpers import trace
helpers.staticInitialization( quiet=True ) #helpers.setTraceLevel( 1000 )
helpers.setTraceLevel( 1000 )
try: try:
import Analog import Analog

View File

@ -7,8 +7,7 @@ from Hurricane import Box
import helpers import helpers
from helpers import trace from helpers import trace
helpers.staticInitialization( quiet=True ) #helpers.setTraceLevel( 1000 )
helpers.setTraceLevel( 1000 )
try: try:
import Analog import Analog

View File

@ -8,8 +8,7 @@ import helpers
import helpers.io import helpers.io
from helpers import trace from helpers import trace
helpers.staticInitialization( quiet=True ) #helpers.setTraceLevel( 1000 )
helpers.setTraceLevel( 1000 )
try: try:
import Analog import Analog

View File

@ -53,6 +53,9 @@ def credits ():
def runScript ( scriptPath, editor ): def runScript ( scriptPath, editor ):
try: try:
sys.stdout.flush()
sys.stderr.flush()
kw = { } kw = { }
if editor: kw[ 'editor' ] = editor if editor: kw[ 'editor' ] = editor
sys.path.insert( 0, os.path.dirname(scriptPath) ) 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 ' Please check your design hierarchy or the Python syntax.'
#print ' Error was:' #print ' Error was:'
#print ' %s\n' % e #print ' %s\n' % e
helpers.showPythonTrace( scriptPath, e ) helpers.io.catch( e )
except Exception, e: except Exception, e:
helpers.showPythonTrace( scriptPath, e ) helpers.io.catch( e )
return return