From 24dedce09cf5192827cffa48723405786c097564 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 17 Sep 2019 17:05:54 +0200 Subject: [PATCH] Added core2chip support for Phenitec80. This commit degrades the run success rate of ARMv2a to 87% (40 iters). * New: In CRLcore/etc/.../kite.conf, add configuration parameters: katana.termSatReservedlocal katana.termSatthreshold for the new edge capacity computation system. * New: In CRLcore/etc/symbolic/phenitec06/, add support for N. Shimizu small I/O pads (supplied in phlib80). Tune various parameters of Anabatic/Katana to increase routing success. * Change: In CRLcore/alliance/ap/ApParser, make Pin external components, so RoutingPad will be build upon in global routing. Do not complain when a I/O pad has a physical instance that did not exists in the netlist. Just create it (appeared in phlib80). When no netlist instance exists in a pad, the pad Cell is still considered as terminal. * New: In Etesian::BloatCells, new profile named "3metals" better suited for two routing metals technologies (i.e. Phenitec). * New: In Anabatic::RawGCellsUnder, new CTOR which take only source & target points instead of a segment. Needed to manage wide segment for which the axis to consider is not that of the segment (one axis for each track it intersect). * New: In Anabatic::GCell, add a RoutingPad count attribute, for Edge reservation computation. * New: In AnabaticEngine::computeEdgeCapacities(), instead of decreasing all edges of a fixed amount (hTrackReservedLocal), guess the GCell cluttering from the number of RoutingPads that it contains. For non-saturated GCells, the four edges are decreased by the number of RoutingPads. We use the maximum from the two neigboring GCells. The hTrackReservedLocal parameter is now used only as a *maximum* that the edge reservation can reach. If a GCell is saturated (more than 8 RoutingPads, the saturation is propagated horizontally to 2 neigboring GCells). * Change: In AutoContactTerminal::getNativeConstraintBox(), use a more flexible gauge name matching for terminal vertical extensions correction. Namely, match all "msxlib*" kind of gauges. * Change: In AutoSegment::setAxis(), add the ability to force the axis position, even if it is a non-canonical segment. Maybe needed in the initialisation steo, before the first canonisation is performed. * New: In NetBuilder, added new methods _do_1G_1PinM1() and _do_2G_1PinM1(), to manage coronas for Phenitec designs. To avoid various side effects from segments being too close from the north / east side of the routing area, make those segments fixeds. * Change: In KatanaEngine::annotateGlobalGraph(), the management of wide wires was wrong. The axis to use to find the underlying GCells is the one of the track, not of the segment. This was creating bad edge capacity computation under the power ring of a block and subsequently routing failures. * New: In Kanata::Manipulator, added method reprocessParallels(), not used though, but keep it anyway, might be of use later... * New: In Kanata::Manipulator, added method avoidBlockage() for terminal METAL2 in non-preferred direction, restrict the terminal and turn constraint box at the current position of the perpandicular, so it doesn't create a deadlock in METAL2. * Change: In SegmentFsm::conflictSolveByPlaceds(), if we cannot break using the whole overlap, try the first atomic overlap. * New: In SegmentFsm::_slackenStrap(), manage conflict between a non-prefered segment and a blockage, this when to call avoidBlockage()... * New: In Katana::Configuration, management of the new edge computation parameters: katana.termSatReservedlocal katana.termSatthreshold * New: In Cumulus/plugins/Core2Chip, support for Phenitec I/O pads. --- anabatic/src/AnabaticEngine.cpp | 168 +++++++++++++---- anabatic/src/AutoContactTerminal.cpp | 2 +- anabatic/src/AutoSegment.cpp | 2 +- anabatic/src/Configuration.cpp | 4 +- anabatic/src/Constants.cpp | 1 + anabatic/src/GCell.cpp | 2 + anabatic/src/LayerAssign.cpp | 2 +- anabatic/src/NetBuilder.cpp | 18 +- anabatic/src/NetBuilderHV.cpp | 175 +++++++++++++++++- anabatic/src/anabatic/AnabaticEngine.h | 5 + anabatic/src/anabatic/Constants.h | 1 + anabatic/src/anabatic/GCell.h | 11 +- anabatic/src/anabatic/NetBuilder.h | 5 + anabatic/src/anabatic/NetBuilderHV.h | 3 + crlcore/etc/common/etesian.conf | 3 +- crlcore/etc/symbolic/cmos/kite.conf | 2 + crlcore/etc/symbolic/cmos45/kite.conf | 16 +- crlcore/etc/symbolic/phenitec06/alliance.conf | 2 +- crlcore/etc/symbolic/phenitec06/etesian.conf | 5 - crlcore/etc/symbolic/phenitec06/kite.conf | 62 ++++--- crlcore/etc/symbolic/phenitec06/plugins.conf | 2 +- crlcore/src/ccore/alliance/ap/ApParser.cpp | 73 ++++---- cumulus/src/CMakeLists.txt | 2 + cumulus/src/plugins/CoreToChip_phlib80.py | 65 +++++++ cumulus/src/plugins/chip/PadsCorona.py | 17 +- cumulus/src/plugins/core2chip/CoreToChip.py | 9 +- cumulus/src/plugins/core2chip/phlib.py | 154 +++++++++++++++ cumulus/src/plugins/core2chip/phlib80.py | 133 +++++++++++++ etesian/src/BloatCells.cpp | 33 ++++ etesian/src/etesian/BloatCells.h | 9 + katana/src/Configuration.cpp | 21 ++- katana/src/GlobalRoute.cpp | 7 + katana/src/KatanaEngine.cpp | 28 ++- katana/src/Manipulator.cpp | 109 ++++++++++- katana/src/NegociateWindow.cpp | 4 +- katana/src/PowerRails.cpp | 11 ++ katana/src/SegmentFsm.cpp | 18 +- katana/src/Track.cpp | 7 + katana/src/TrackFixedSegment.cpp | 2 +- katana/src/TrackSegment.cpp | 2 +- katana/src/katana/Configuration.h | 6 + katana/src/katana/KatanaEngine.h | 4 + katana/src/katana/Manipulator.h | 2 + 43 files changed, 1064 insertions(+), 143 deletions(-) create mode 100644 cumulus/src/plugins/CoreToChip_phlib80.py create mode 100644 cumulus/src/plugins/core2chip/phlib.py create mode 100644 cumulus/src/plugins/core2chip/phlib80.py diff --git a/anabatic/src/AnabaticEngine.cpp b/anabatic/src/AnabaticEngine.cpp index ee75f16a..475cee37 100644 --- a/anabatic/src/AnabaticEngine.cpp +++ b/anabatic/src/AnabaticEngine.cpp @@ -170,28 +170,67 @@ namespace Anabatic { RawGCellsUnder::RawGCellsUnder ( const AnabaticEngine* engine, Segment* segment ) { - cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(): " << segment << endl; + cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(Segment*): " << segment << endl; - Box gcellsArea = engine->getCell()->getAbutmentBox(); - Point sourcePosition = segment->getSourcePosition(); - Point targetPosition = segment->getTargetPosition(); + commonCtor( engine, segment->getSourcePosition(), segment->getTargetPosition() ); - if ( (sourcePosition.getX() > gcellsArea.getXMax()) - or (sourcePosition.getY() > gcellsArea.getYMax()) - or (targetPosition.getX() <= gcellsArea.getXMin()) - or (targetPosition.getY() <= gcellsArea.getYMin()) ) { - cerr << Error( "RawGCellsUnder::RawGCellsUnder(): %s is completly outside the GCells area (ignored)." - , getString(segment).c_str() + cdebug_tabw(112,-1); + } + + + RawGCellsUnder::RawGCellsUnder ( const AnabaticEngine* engine, Point source, Point target ) + { + cdebug_log(112,1) << "RawGCellsUnder::RawGCellsUnder(Point,Point): s:" + << source << " t:" << target << endl; + + commonCtor( engine, source, target ); + + cdebug_tabw(112,-1); + } + + + void RawGCellsUnder::commonCtor ( const AnabaticEngine* engine, Point source, Point target ) + { + cdebug_log(112,1) << "RawGCellsUnder::commontCtor(): s:" << source << " t:" << target << endl; + + Box gcellsArea = engine->getCell()->getAbutmentBox(); + DbU::Unit axis = 0; + Flags side = Flags::NoFlags; + + if (source.getY() == target.getY()) { + side = Flags::EastSide; + axis = source.getY(); + if (source.getX() > target.getX()) std::swap( source, target ); + } + if (source.getX() == target.getX()) { + side = Flags::NorthSide; + axis = source.getX(); + if (source.getY() > target.getY()) std::swap( source, target ); + } + + if (side == Flags::NoFlags) { + cerr << Error( "RawGCellsUnder::commonCtor(): Points are neither horizontally nor vertically aligneds (ignored)." ) << endl; cdebug_tabw(112,-1); DebugSession::close(); return; } - DbU::Unit xsource = std::max( sourcePosition.getX(), gcellsArea.getXMin() ); - DbU::Unit ysource = std::max( sourcePosition.getY(), gcellsArea.getYMin() ); - DbU::Unit xtarget = std::min( targetPosition.getX(), gcellsArea.getXMax() ); - DbU::Unit ytarget = std::min( targetPosition.getY(), gcellsArea.getYMax() ); + if ( (source.getX() > gcellsArea.getXMax()) + or (source.getY() > gcellsArea.getYMax()) + or (target.getX() <= gcellsArea.getXMin()) + or (target.getY() <= gcellsArea.getYMin()) ) { + cerr << Error( "RawGCellsUnder::commonCtor(): Area is completly outside the GCells area (ignored)." + ) << endl; + cdebug_tabw(112,-1); + DebugSession::close(); + return; + } + + DbU::Unit xsource = std::max( source.getX(), gcellsArea.getXMin() ); + DbU::Unit ysource = std::max( source.getY(), gcellsArea.getYMin() ); + DbU::Unit xtarget = std::min( target.getX(), gcellsArea.getXMax() ); + DbU::Unit ytarget = std::min( target.getY(), gcellsArea.getYMax() ); if (xtarget == gcellsArea.getXMax()) --xtarget; if (ytarget == gcellsArea.getYMax()) --ytarget; @@ -200,16 +239,14 @@ namespace Anabatic { GCell* gtarget = engine->getGCellUnder( xtarget, ytarget ); if (not gsource) { - cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): %s source not under a GCell (ignored)." - , getString(segment).c_str() + cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): Source not under a GCell (ignored)." ) << endl; cdebug_tabw(112,-1); DebugSession::close(); return; } if (not gtarget) { - cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): %s target not under a GCell (ignored)." - , getString(segment).c_str() + cerr << Bug( "RawGCellsUnder::RawGCellsUnder(): Target not under a GCell (ignored)." ) << endl; cdebug_tabw(112,-1); DebugSession::close(); @@ -223,24 +260,6 @@ namespace Anabatic { return; } - Flags side = Flags::NoFlags; - DbU::Unit axis = 0; - Horizontal* horizontal = dynamic_cast( segment ); - if (horizontal) { - side = Flags::EastSide; - axis = horizontal->getY(); - - if (horizontal->getSourceX() > horizontal->getTargetX()) - std::swap( gsource, gtarget ); - } else { - Vertical* vertical = dynamic_cast( segment ); - side = Flags::NorthSide; - axis = vertical->getX(); - - if (vertical->getSourceY() > vertical->getTargetY()) - std::swap( gsource, gtarget ); - } - cdebug_log(112,0) << "flags:" << side << " axis:" << DbU::getValueString(axis) << endl; Edge* edge = gsource->getEdgeAt( side, axis ); @@ -1406,6 +1425,83 @@ namespace Anabatic { } + void AnabaticEngine::computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat ) + { + vector rps; + vector saturateds; + const vector& netDatas = getNetOrdering(); + + for ( NetData* netData : netDatas ) { + for ( Component* component : netData->getNet()->getComponents() ) { + RoutingPad* rp = dynamic_cast( component ); + if (rp) rps.push_back( rp ); + } + } + + UpdateSession::open(); + + for ( auto rp : rps ) { + if (not getConfiguration()->selectRpComponent(rp)) + cerr << Warning( "AnabaticEngine::computeEdgeCapacities(): %s has no components on grid.", getString(rp).c_str() ) << endl; + + Point center = rp->getBoundingBox().getCenter(); + GCell* gcell = getGCellUnder( center ); + + if (not gcell) { + cerr << Error( "AnabaticEngine::computeEdgeCapacities(): %s\n" + " @%s of %s is not under any GCell.\n" + " It will be ignored so the edge capacity estimate may be wrong." + , getString(rp).c_str() + , getString(center).c_str() + , getString(rp->getNet()).c_str() + ) << endl; + continue; + } + + gcell->incRpCount( 1 ); + if (gcell->getRpCount() == termSatThreshold) saturateds.push_back( gcell ); + } + + for ( GCell* gcell : getGCells() ) { + if (not gcell->isMatrix()) continue; + + for ( Edge* edge : gcell->getEdges(Flags::EastSide|Flags::NorthSide) ) { + GCell* opposite = edge->getOpposite( gcell ); + int maxReserved = maxHCap; + int reserved = std::max( gcell->getRpCount(), opposite->getRpCount() ); + + if (edge->isVertical()) maxReserved = maxVCap; + edge->reserveCapacity( std::min( maxReserved, reserved ) ); + } + } + + for ( GCell* gcell : saturateds ) { + GCell* neighbor = gcell; + for ( size_t i=0 ; i<2; ++i ) { + Edge* edge = neighbor->getWestEdge(); + if (not edge) break; + + if (edge->getReservedCapacity() < maxTermSat) + edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() ); + neighbor = neighbor->getWest(); + } + neighbor = gcell; + for ( size_t i=0 ; i<2; ++i ) { + Edge* edge = neighbor->getEastEdge(); + if (not edge) break; + + if (edge->getReservedCapacity() < maxTermSat) + edge->reserveCapacity( maxTermSat - edge->getReservedCapacity() ); + neighbor = neighbor->getEast(); + } + } + + UpdateSession::close(); + + //Breakpoint::stop( 1, "Edge capacities computeds." ); + } + + void AnabaticEngine::_check ( Net* net ) const { cdebug_log(149,1) << "Checking " << net << endl; diff --git a/anabatic/src/AutoContactTerminal.cpp b/anabatic/src/AutoContactTerminal.cpp index e9483699..6705801d 100644 --- a/anabatic/src/AutoContactTerminal.cpp +++ b/anabatic/src/AutoContactTerminal.cpp @@ -194,7 +194,7 @@ namespace Anabatic { // SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on // their extremities. Should modificate all the standard cells layout... // HARDCODED. - if (Session::getRoutingGauge()->getName() == "msxlib") + if (getString(Session::getRoutingGauge()->getName()).substr(0,6) == "msxlib") yborder -= DbU::fromLambda( 1.0 ); else yborder -= DbU::fromLambda( 0.5 ); diff --git a/anabatic/src/AutoSegment.cpp b/anabatic/src/AutoSegment.cpp index edc9d40d..3b3b324a 100644 --- a/anabatic/src/AutoSegment.cpp +++ b/anabatic/src/AutoSegment.cpp @@ -1076,7 +1076,7 @@ namespace Anabatic { void AutoSegment::setAxis ( DbU::Unit axis, Flags flags ) { - if (not isCanonical()) return; + if (not isCanonical() and not (flags & Flags::Force)) return; if ( (axis == getAxis()) and not (flags & Flags::Realignate) ) return; diff --git a/anabatic/src/Configuration.cpp b/anabatic/src/Configuration.cpp index 7cb5b865..bdf31511 100644 --- a/anabatic/src/Configuration.cpp +++ b/anabatic/src/Configuration.cpp @@ -77,8 +77,8 @@ namespace Anabatic { , _cg (NULL) , _rg (NULL) , _extensionCaps () - , _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble()) - , _saturateRp (Cfg::getParamInt ("katabatic.saturateRp" ,8 )->asInt()) + , _saturateRatio (Cfg::getParamPercentage("anabatic.saturateRatio",80.0)->asDouble()) + , _saturateRp (Cfg::getParamInt ("anabatic.saturateRp" ,8 )->asInt()) , _globalThreshold (0) , _allowedDepth (0) , _edgeLength (DbU::fromLambda(Cfg::getParamInt("anabatic.edgeLength",24)->asInt())) diff --git a/anabatic/src/Constants.cpp b/anabatic/src/Constants.cpp index 1efa5865..3fd5f6d0 100644 --- a/anabatic/src/Constants.cpp +++ b/anabatic/src/Constants.cpp @@ -118,6 +118,7 @@ namespace Anabatic { const BaseFlags Flags::NoUpdate = (1L << 32); const BaseFlags Flags::NorthPath = (1L << 33); const BaseFlags Flags::UseNonPref = (1L << 34); + const BaseFlags Flags::Force = (1L << 35); Flags::~Flags () diff --git a/anabatic/src/GCell.cpp b/anabatic/src/GCell.cpp index 01acc0f9..3abe863f 100644 --- a/anabatic/src/GCell.cpp +++ b/anabatic/src/GCell.cpp @@ -298,6 +298,7 @@ namespace Anabatic { , _contacts () , _depth (Session::getRoutingGauge()->getDepth()) , _pinDepth (0) + , _rpCount (0) , _blockages (new DbU::Unit [_depth]) , _cDensity (0.0) , _densities (new float [_depth]) @@ -1790,6 +1791,7 @@ namespace Anabatic { string s = Super::_getString(); s.insert( s.size()-1, " "+getString(getBoundingBox()) ); s.insert( s.size()-1, " "+getString(_flags) ); + s.insert( s.size()-1, " "+getString(_rpCount) ); /* string s = "getDensity(depth) << " " << *igcell << endl; + << (*igcell)->getDensity(depth) << " " << *igcell << endl; if (not (*igcell)->isSaturated(depth)) { cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl; diff --git a/anabatic/src/NetBuilder.cpp b/anabatic/src/NetBuilder.cpp index 6707ed8f..6d288620 100644 --- a/anabatic/src/NetBuilder.cpp +++ b/anabatic/src/NetBuilder.cpp @@ -616,6 +616,8 @@ namespace Anabatic { case Conn_4G: _do_xG(); break; // End xG cascaded cases. // Optimized specific cases. + case Conn_1G_1PinM1: _do_1G_1PinM1 (); break; + case Conn_2G_1PinM1: _do_2G_1PinM1 (); break; case Conn_1G_1PinM2: _do_1G_1PinM2 (); break; case Conn_2G_1PinM2: case Conn_3G_1PinM2: _do_xG_1PinM2 (); break; @@ -628,7 +630,7 @@ namespace Anabatic { default: if (not isTwoMetals()) throw Bug( "Unmanaged Configuration [%d] = [%d+%d+%d+%d,%d+%d] %s in %s\n" - " The global routing seems to be defective." + " The global routing seems to be defective." , _connexity.connexity , _connexity.fields.globals , _connexity.fields.M1 @@ -962,6 +964,20 @@ namespace Anabatic { } + bool NetBuilder::_do_1G_1PinM1 () + { + throw Error ( "%s::_do_1G_1PinM1() method *not* reimplemented from base class.", getTypeName().c_str() ); + return false; + } + + + bool NetBuilder::_do_2G_1PinM1 () + { + throw Error ( "%s::_do_2G_1PinM1() method *not* reimplemented from base class.", getTypeName().c_str() ); + return false; + } + + bool NetBuilder::_do_xG_1PinM2 () { throw Error ( "%s::_do_xG_1PinM2() method *not* reimplemented from base class.", getTypeName().c_str() ); diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp index eec4f6d7..82a4705d 100644 --- a/anabatic/src/NetBuilderHV.cpp +++ b/anabatic/src/NetBuilderHV.cpp @@ -32,6 +32,7 @@ #include "hurricane/RoutingPad.h" #include "hurricane/RoutingPads.h" #include "hurricane/Pad.h" +#include "hurricane/Pin.h" #include "hurricane/Plug.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" @@ -54,6 +55,8 @@ namespace Anabatic { using std::swap; using Hurricane::Transformation; using Hurricane::Warning; + using Hurricane::Error; + using Hurricane::Pin; NetBuilderHV::NetBuilderHV () @@ -105,7 +108,7 @@ namespace Anabatic { } // Non-M1 terminal or punctual M1 protections. - if ((rpDepth != 0) or (sourcePosition == targetPosition)) { + if ( ((rpDepth != 0) or (sourcePosition == targetPosition)) and not (flags & NoProtect) ) { map::iterator irp = getRpLookup().find( rp ); if (irp == getRpLookup().end()) { AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell @@ -499,15 +502,185 @@ namespace Anabatic { } + bool NetBuilderHV::_do_1G_1PinM1 () + { + cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl; + + AutoContact* rpSourceContact = NULL; + AutoContact* rpContactTarget = NULL; + AutoContact* turn = NULL; + + doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoProtect ); + + Pin* pin = dynamic_cast( getRoutingPads()[0]->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + if ( (pinDir == Pin::AccessDirection::NORTH) + or (pinDir == Pin::AccessDirection::SOUTH) ) { + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) ); + AutoSegment::create( rpSourceContact, turn, Flags::Vertical|Flags::UseNonPref ); + rpSourceContact = turn; + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment* horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + + DbU::Unit axis = getGCell()->getYMax() - Session::getDHorizontalPitch(); + if (pinDir == Pin::AccessDirection::SOUTH) + axis = getGCell()->getYMin() + Session::getDHorizontalPitch(); + cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl; + + horizontal->setAxis( axis, Flags::Force ); + horizontal->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + cdebug_log(145,0) << horizontal << endl; + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) ); + AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical ); + rpSourceContact = turn; + vertical->setAxis( pin->getX(), Flags::Force ); + vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + cdebug_log(145,0) << vertical << endl; + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + horizontal->setAxis( axis, Flags::Force ); + rpSourceContact = turn; + } else { + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + } + + if (east() or west()) { + rpSourceContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment* vertical = AutoSegment::create( turn, rpSourceContact, Flags::Vertical ); + + DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch(); + if (pinDir == Pin::AccessDirection::WEST) + axis = getGCell()->getXMin() + Session::getDVerticalPitch(); + cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl; + + vertical->setAxis( axis, Flags::Force ); + vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + + turn = rpSourceContact; + } + setBothCornerContacts( turn ); + + cdebug_tabw(145,-1); + return true; + } + + + bool NetBuilderHV::_do_2G_1PinM1 () + { + cdebug_log(145,1) << getTypeName() << "::_do_2G_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl; + + AutoContact* rpSourceContact = NULL; + AutoContact* rpContactTarget = NULL; + AutoContact* tee = NULL; + AutoContact* turn = NULL; + + doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoProtect ); + + Pin* pin = dynamic_cast( getRoutingPads()[0]->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + if ( (pinDir == Pin::AccessDirection::NORTH) + or (pinDir == Pin::AccessDirection::SOUTH) ) { + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) ); + AutoSegment::create( rpSourceContact, turn, Flags::Vertical|Flags::UseNonPref ); + rpSourceContact = turn; + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment* horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + + DbU::Unit axis = getGCell()->getYMax() - Session::getDHorizontalPitch(); + if (pinDir == Pin::AccessDirection::SOUTH) + axis = getGCell()->getYMin() + Session::getDHorizontalPitch(); + horizontal->setAxis( axis, Flags::Force ); + horizontal->setFlags( AutoSegment::SegFixed ); + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getRoutingLayer(1) ); + AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical ); + rpSourceContact = turn; + vertical->setFlags( AutoSegment::SegFixed ); + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + horizontal = AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + horizontal->setAxis( axis, Flags::Force ); + rpSourceContact = turn; + turn = NULL; + } + + if (east() and west()) { + // Pin must be North or South. + tee = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpSourceContact, tee, Flags::Vertical ); + } else if (north() and south()) { + // Pin must be East or West. + tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpSourceContact, tee, Flags::Horizontal ); + } else { + if ( (pinDir == Pin::AccessDirection::EAST) + or (pinDir == Pin::AccessDirection::WEST) ) { + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + } + + tee = AutoContactVTee::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment* vertical = AutoSegment::create( rpSourceContact, tee, Flags::Vertical ); + + if ( (pinDir == Pin::AccessDirection::EAST) + or (pinDir == Pin::AccessDirection::WEST) ) { + DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch(); + if (pinDir == Pin::AccessDirection::WEST) + axis = getGCell()->getXMin() + Session::getDVerticalPitch(); + cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl; + + vertical->setAxis( axis, Flags::Force ); + vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + } + } + + setBothCornerContacts( tee ); + + cdebug_tabw(145,-1); + return true; + } + + bool NetBuilderHV::_do_xG_1PinM2 () { cdebug_log(145,1) << getTypeName() << "::_do_xG_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl; AutoContact* rpSourceContact = NULL; AutoContact* rpContactTarget = NULL; + AutoContact* turn = NULL; doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpSourceContact, rpContactTarget, NoFlags ); + Pin* pin = dynamic_cast( getRoutingPads()[0]->getOccurrence().getEntity() ); + Pin::AccessDirection pinDir = pin->getAccessDirection(); + if ( (pinDir == Pin::AccessDirection::EAST) + or (pinDir == Pin::AccessDirection::WEST) ) { + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpSourceContact, turn, Flags::Horizontal ); + rpSourceContact = turn; + + turn = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment* vertical = AutoSegment::create( rpSourceContact, turn, Flags::Vertical ); + rpSourceContact = turn; + + DbU::Unit axis = getGCell()->getXMax() - Session::getDVerticalPitch(); + if (pinDir == Pin::AccessDirection::WEST) + axis = getGCell()->getXMin() + Session::getDVerticalPitch(); + cdebug_log(145,0) << "axis:" << DbU::getValueString(axis) << endl; + + vertical->setAxis( axis, Flags::Force ); + vertical->setFlags( AutoSegment::SegFixed|AutoSegment::SegFixedAxis ); + } + if (getConnexity().fields.globals == 2) { if (west() and south()) { AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); diff --git a/anabatic/src/anabatic/AnabaticEngine.h b/anabatic/src/anabatic/AnabaticEngine.h index d09d1ba7..b7f40c23 100644 --- a/anabatic/src/anabatic/AnabaticEngine.h +++ b/anabatic/src/anabatic/AnabaticEngine.h @@ -68,6 +68,8 @@ namespace Anabatic { }; public: RawGCellsUnder ( const AnabaticEngine*, Segment* ); + RawGCellsUnder ( const AnabaticEngine*, Point source, Point target ); + void commonCtor ( const AnabaticEngine*, Point source, Point target ); inline bool empty () const; inline size_t size () const; inline GCell* gcellAt ( size_t ) const; @@ -208,6 +210,7 @@ namespace Anabatic { inline GCell* getGCellUnder ( DbU::Unit x, DbU::Unit y ) const; inline GCell* getGCellUnder ( Point ) const; inline GCellsUnder getGCellsUnder ( Segment* ) const; + inline GCellsUnder getGCellsUnder ( Point source, Point target ) const; inline Edges getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags=Flags::NorthPath ) const; Interval getUSide ( Flags direction ) const; int getCapacity ( Interval, Flags ) const; @@ -255,6 +258,7 @@ namespace Anabatic { inline void setSaturateRp ( size_t ); inline void setBlockageNet ( Net* ); void chipPrep (); + void computeEdgeCapacities ( int maxHCap, int maxVCap, int termSatThreshold, int maxTermSat ); void setupSpecialNets (); size_t setupPreRouteds (); void loadGlobalRouting ( uint32_t method ); @@ -346,6 +350,7 @@ namespace Anabatic { inline GCell* AnabaticEngine::getGCellUnder ( DbU::Unit x, DbU::Unit y ) const { return _matrix.getUnder(x,y); } inline GCell* AnabaticEngine::getGCellUnder ( Point p ) const { return _matrix.getUnder(p); } inline GCellsUnder AnabaticEngine::getGCellsUnder ( Segment* s ) const { return std::shared_ptr( new RawGCellsUnder(this,s) ); } + inline GCellsUnder AnabaticEngine::getGCellsUnder ( Point source, Point target ) const { return std::shared_ptr( new RawGCellsUnder(this,source,target) ); } inline Edges AnabaticEngine::getEdgesUnderPath ( GCell* source, GCell* target, Flags pathFlags ) const { return new Path_Edges(source,target,pathFlags); } inline uint64_t AnabaticEngine::getDensityMode () const { return _densityMode; } inline void AnabaticEngine::setDensityMode ( uint64_t mode ) { _densityMode=mode; } diff --git a/anabatic/src/anabatic/Constants.h b/anabatic/src/anabatic/Constants.h index 46a124f9..42f9b83e 100644 --- a/anabatic/src/anabatic/Constants.h +++ b/anabatic/src/anabatic/Constants.h @@ -101,6 +101,7 @@ namespace Anabatic { static const BaseFlags NoUpdate ; static const BaseFlags NorthPath ; static const BaseFlags UseNonPref ; + static const BaseFlags Force ; public: inline Flags ( uint64_t flags = NoFlags ); inline Flags ( const Hurricane::BaseFlags& ); diff --git a/anabatic/src/anabatic/GCell.h b/anabatic/src/anabatic/GCell.h index e47c994d..f9b6965f 100644 --- a/anabatic/src/anabatic/GCell.h +++ b/anabatic/src/anabatic/GCell.h @@ -217,6 +217,7 @@ namespace Anabatic { bool hasFreeTrack ( size_t depth, float reserve ) const; inline size_t getDepth () const; size_t getNetCount () const; + inline int getRpCount () const; int getHCapacity () const; int getVCapacity () const; int getCapacity ( size_t depth ) const; @@ -264,7 +265,7 @@ namespace Anabatic { bool stepNetDesaturate ( size_t depth , set& globalNets , Set& invalidateds ); - + inline void incRpCount ( int ); void forceEdgesCapacities ( unsigned int hcapacities, unsigned int vcapacities ); // Misc. functions. inline const Flags& flags () const; @@ -321,6 +322,7 @@ namespace Anabatic { vector _contacts; size_t _depth; size_t _pinDepth; + int _rpCount; DbU::Unit* _blockages; float _cDensity; float* _densities; @@ -374,7 +376,8 @@ namespace Anabatic { inline GCell* GCell::getUnder ( Point p ) const { return getUnder(p.getX(),p.getY()); } inline const vector& GCell::getGContacts () const { return _gcontacts; } - inline size_t GCell::getDepth () const { return _depth; } + inline size_t GCell::getDepth () const { return _depth; } + inline int GCell::getRpCount () const { return _rpCount; } const vector& GCell::getVSegments () const { return _vsegments; } inline const vector& GCell::getHSegments () const { return _hsegments; } inline const vector& GCell::getContacts () const { return _contacts; } @@ -418,6 +421,10 @@ namespace Anabatic { return Interval( getXMin(), getConstraintXMax(shrink) ); } + inline void GCell::incRpCount ( int delta ) + { _rpCount = (_rpCount + delta > 0) ? (_rpCount + delta) : 0; } + + inline void GCell::setObserver ( size_t slot, BaseObserver* observer ) { _observable.setObserver( slot, observer ); } diff --git a/anabatic/src/anabatic/NetBuilder.h b/anabatic/src/anabatic/NetBuilder.h index db4ed055..81df3be5 100644 --- a/anabatic/src/anabatic/NetBuilder.h +++ b/anabatic/src/anabatic/NetBuilder.h @@ -99,6 +99,7 @@ namespace Anabatic { , EastBound = (1 << 15) , Middle = (1 << 16) , UseNonPref = (1 << 17) + , NoProtect = (1 << 18) , HBothAccess = HAccess|HAccessEW , SouthWest = SouthBound|WestBound , NorthEast = NorthBound|EastBound @@ -204,6 +205,8 @@ namespace Anabatic { virtual bool _do_xG (); virtual bool _do_2G (); virtual bool _do_xG_1Pad (); + virtual bool _do_1G_1PinM1 (); + virtual bool _do_2G_1PinM1 (); virtual bool _do_1G_1PinM2 (); virtual bool _do_xG_1PinM2 (); virtual bool _do_1G_1PinM3 (); @@ -298,6 +301,8 @@ namespace Anabatic { , Conn_1G_1Pad = CONNEXITY_VALUE( 1, 0, 0, 0, 1 , 0 ) , Conn_2G_1Pad = CONNEXITY_VALUE( 2, 0, 0, 0, 1 , 0 ) , Conn_3G_1Pad = CONNEXITY_VALUE( 3, 0, 0, 0, 1 , 0 ) + , Conn_1G_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 ) + , Conn_2G_1PinM1 = CONNEXITY_VALUE( 2, 1, 0, 0, 0 , 1 ) , Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 ) , Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 ) , Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 ) diff --git a/anabatic/src/anabatic/NetBuilderHV.h b/anabatic/src/anabatic/NetBuilderHV.h index a2dcf829..59f79fda 100644 --- a/anabatic/src/anabatic/NetBuilderHV.h +++ b/anabatic/src/anabatic/NetBuilderHV.h @@ -25,6 +25,7 @@ namespace Anabatic { // ----------------------------------------------------------------- // Class : "NetBuilderHV". + class NetBuilderHV : public NetBuilder { public: NetBuilderHV (); @@ -38,6 +39,8 @@ namespace Anabatic { virtual bool _do_2G (); virtual bool _do_2G_1M1 (); virtual bool _do_xG_1Pad (); + virtual bool _do_1G_1PinM1 (); + virtual bool _do_2G_1PinM1 (); virtual bool _do_1G_1PinM2 (); virtual bool _do_xG_1PinM2 (); virtual bool _do_1G_1PinM3 (); diff --git a/crlcore/etc/common/etesian.conf b/crlcore/etc/common/etesian.conf index ca8240c4..575ba42b 100644 --- a/crlcore/etc/common/etesian.conf +++ b/crlcore/etc/common/etesian.conf @@ -8,7 +8,8 @@ parametersTable = \ , ('etesian.routingDriven' , TypeBool , False ) , ('etesian.feedNames' , TypeString , 'tie_x0,rowend_x0') , ('etesian.cell.zero' , TypeString , 'zero_x0' ) - , ('etesian.cell.one' , TypeString , 'one_x0' ) + , ('etesian.cell.one' , TypeString , 'one_x0' ) + , ('etesian.bloat' , TypeString , 'default' ) , ("etesian.effort" , TypeEnumerate , 2 , { 'values':( ("Fast" , 1) diff --git a/crlcore/etc/symbolic/cmos/kite.conf b/crlcore/etc/symbolic/cmos/kite.conf index 4251d91c..4ae6b8db 100644 --- a/crlcore/etc/symbolic/cmos/kite.conf +++ b/crlcore/etc/symbolic/cmos/kite.conf @@ -41,6 +41,8 @@ parametersTable = \ ) , ("katana.hTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':20 } ) , ("katana.vTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':20 } ) + , ("katana.termSatReservedLocal" ,TypeInt ,8 ) + , ("katana.termSatThreshold" ,TypeInt ,9 ) , ("katana.eventsLimit" ,TypeInt ,4000002 ) , ("katana.ripupCost" ,TypeInt ,3 , { 'min':0 } ) , ("katana.strapRipupLimit" ,TypeInt ,16 , { 'min':1 } ) diff --git a/crlcore/etc/symbolic/cmos45/kite.conf b/crlcore/etc/symbolic/cmos45/kite.conf index 31bff38b..e7164c71 100644 --- a/crlcore/etc/symbolic/cmos45/kite.conf +++ b/crlcore/etc/symbolic/cmos45/kite.conf @@ -31,10 +31,21 @@ parametersTable = \ , ("anabatic.edgeHInc" ,TypeDouble ,1.0 ) , ("anabatic.edgeHScaling" ,TypeDouble ,1.0 ) , ("anabatic.globalIterations" ,TypeInt ,20 , { 'min':1, 'max':100 } ) + , ("anabatic.saturateRatio" ,TypePercentage,80 ) , ("anabatic.gcell.displayMode" ,TypeEnumerate ,1 , { 'values':( ("Boundary" , 1) , ("Density" , 2) ) } ) + , ("katana.hTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':20 } ) + , ("katana.vTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':20 } ) + , ("katana.termSatReservedLocal" ,TypeInt ,8 ) + , ("katana.termSatThreshold" ,TypeInt ,9 ) + , ("katana.eventsLimit" ,TypeInt ,4000002 ) + , ("katana.ripupCost" ,TypeInt ,3 , { 'min':0 } ) + , ("katana.strapRipupLimit" ,TypeInt ,16 , { 'min':1 } ) + , ("katana.localRipupLimit" ,TypeInt ,9 , { 'min':1 } ) + , ("katana.globalRipupLimit" ,TypeInt ,5 , { 'min':1 } ) + , ("katana.longGlobalRipupLimit" ,TypeInt ,5 , { 'min':1 } ) ) @@ -71,6 +82,7 @@ routingGaugesTable['msxlib-2M'] = \ # ( METAL_PIN, xy_common_pitch, slice_height, slice_step ) cellGaugesTable = {} -cellGaugesTable['msxlib' ] = ('metal2', l(10), l(100), l(10)) -cellGaugesTable['msxlib4'] = ('metal2', l(10), l(100), l(10)) +cellGaugesTable['msxlib' ] = ('metal2', l(10), l(100), l( 10)) +cellGaugesTable['msxlib4'] = ('metal2', l(10), l(100), l( 10)) +cellGaugesTable['phlib80'] = ('metal2', l(10), l(312), l(246)) diff --git a/crlcore/etc/symbolic/phenitec06/alliance.conf b/crlcore/etc/symbolic/phenitec06/alliance.conf index b1706899..b3fabad4 100644 --- a/crlcore/etc/symbolic/phenitec06/alliance.conf +++ b/crlcore/etc/symbolic/phenitec06/alliance.conf @@ -30,7 +30,7 @@ allianceConfig = \ , ( 'GROUND' , 'vss') , ( 'CLOCK' , '^ck.*') , ( 'BLOCKAGE' , '^blockage[Nn]et*') - , ( 'PAD' , '.*_mpx$') + , ( 'PAD' , '.*_sp$') # The following are only read by the Alliance tool wrappers. , ( 'ALLIANCE_TOP' , allianceTop) , ( 'MBK_TARGET_LIB' , cellsTop+'/msxlib') diff --git a/crlcore/etc/symbolic/phenitec06/etesian.conf b/crlcore/etc/symbolic/phenitec06/etesian.conf index 629a916f..9cea23f6 100644 --- a/crlcore/etc/symbolic/phenitec06/etesian.conf +++ b/crlcore/etc/symbolic/phenitec06/etesian.conf @@ -3,8 +3,3 @@ import helpers execfile( helpers.sysConfDir+'/common/etesian.conf' ) - -parametersTable = \ - ( ('etesian.bloat' , TypeString , "nsxlib" ) - , - ) diff --git a/crlcore/etc/symbolic/phenitec06/kite.conf b/crlcore/etc/symbolic/phenitec06/kite.conf index 694aadaf..c751a66a 100644 --- a/crlcore/etc/symbolic/phenitec06/kite.conf +++ b/crlcore/etc/symbolic/phenitec06/kite.conf @@ -8,36 +8,45 @@ execfile( helpers.sysConfDir+'/common/kite.conf' ) parametersTable = \ - ( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 ) - , ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters. - , ("katabatic.saturateRatio" ,TypePercentage,80 ) - , ("katabatic.saturateRp" ,TypeInt ,8 ) - , ('katabatic.topRoutingLayer' ,TypeString , 'METAL3') - # Kite parameters. - , ("kite.hTracksReservedLocal" ,TypeInt ,4 , { 'min':0, 'max':18 } ) - , ("kite.vTracksReservedLocal" ,TypeInt ,3 , { 'min':0, 'max':18 } ) - , ("kite.eventsLimit" ,TypeInt ,4000002 ) - , ("kite.ripupCost" ,TypeInt ,3 , { 'min':0 } ) - , ("kite.strapRipupLimit" ,TypeInt ,16 , { 'min':1 } ) - , ("kite.localRipupLimit" ,TypeInt ,9 , { 'min':1 } ) - , ("kite.globalRipupLimit" ,TypeInt ,5 , { 'min':1 } ) - , ("kite.longGlobalRipupLimit" ,TypeInt ,5 , { 'min':1 } ) + ( ('lefImport.minTerminalWidth' , TypeDouble , 0.0 ) + , ("katabatic.globalLengthThreshold", TypeInt , 1450 ) # Katabatic parameters. + , ("katabatic.saturateRatio" , TypePercentage, 80 ) + , ("katabatic.saturateRp" , TypeInt , 8 ) + , ('katabatic.topRoutingLayer' , TypeString , 'METAL3' ) + # Kite parameters. + , ("kite.hTracksReservedLocal" , TypeInt , 4 , { 'min':0, 'max':18 } ) + , ("kite.vTracksReservedLocal" , TypeInt , 3 , { 'min':0, 'max':18 } ) + , ("kite.eventsLimit" , TypeInt , 4000002 ) + , ("kite.ripupCost" , TypeInt , 3 , { 'min':0 } ) + , ("kite.strapRipupLimit" , TypeInt , 16 , { 'min':1 } ) + , ("kite.localRipupLimit" , TypeInt , 9 , { 'min':1 } ) + , ("kite.globalRipupLimit" , TypeInt , 5 , { 'min':1 } ) + , ("kite.longGlobalRipupLimit" , TypeInt , 5 , { 'min':1 } ) # Anabatic parameters are temporarily hosted here. - , ('anabatic.topRoutingLayer' ,TypeString , 'METAL3') - , ("anabatic.routingGauge" ,TypeString ,'msxlib3') - , ("anabatic.edgeLength" ,TypeInt ,48 ) - , ("anabatic.edgeWidth" ,TypeInt ,8 ) - , ("anabatic.edgeCostH" ,TypeDouble ,19.0 ) - , ("anabatic.edgeCostK" ,TypeDouble ,-60.0 ) - , ("anabatic.edgeHInc" ,TypeDouble ,1.0 ) - , ("anabatic.edgeHScaling" ,TypeDouble ,1.0 ) - , ("anabatic.globalIterations" ,TypeInt ,20 , { 'min':1, 'max':100 } ) - , ("anabatic.gcell.displayMode" ,TypeEnumerate ,1 + , ('anabatic.topRoutingLayer' , TypeString , 'METAL3' ) + , ("anabatic.routingGauge" , TypeString , 'msxlib3') + , ("anabatic.edgeLength" , TypeInt , 48 ) + , ("anabatic.edgeWidth" , TypeInt , 8 ) + , ("anabatic.edgeCostH" , TypeDouble , 19.0 ) + , ("anabatic.edgeCostK" , TypeDouble , -60.0 ) + , ("anabatic.edgeHInc" , TypeDouble , 1.0 ) + , ("anabatic.edgeHScaling" , TypeDouble , 1.0 ) + , ("anabatic.globalIterations" , TypeInt , 20 , { 'min':1, 'max':100 } ) + , ("anabatic.gcell.displayMode" , TypeEnumerate , 1 , { 'values':( ("Boundary" , 1) , ("Density" , 2) ) } ) - , ("katana.hTracksReservedLocal" , TypeInt , 5 ) - , ("katana.vTracksReservedLocal" , TypeInt , 3 ) + , ("katana.hTracksReservedLocal" , TypeInt , 5 ) + , ("katana.vTracksReservedLocal" , TypeInt , 3 ) + , ("katana.termSatReservedLocal" , TypeInt , 5 ) + , ("katana.termSatThreshold" , TypeInt , 11 ) + , ("katana.eventsLimit" , TypeInt , 4000002 ) + , ("katana.ripupCost" , TypeInt , 3 , { 'min':0 } ) + , ("katana.strapRipupLimit" , TypeInt , 16 , { 'min':1 } ) + , ("katana.localRipupLimit" , TypeInt , 9 , { 'min':1 } ) + , ("katana.globalRipupLimit" , TypeInt , 5 , { 'min':1 } ) + , ("katana.longGlobalRipupLimit" , TypeInt , 5 , { 'min':1 } ) + , ('chip.padCoreSide' , TypeString , 'South' ) ) @@ -83,4 +92,5 @@ cellGaugesTable = {} cellGaugesTable['msxlib' ] = ('metal2', l(10), l(100), l(10)) cellGaugesTable['msxlib4'] = ('metal2', l(10), l(100), l(10)) cellGaugesTable['msxlib3'] = ('metal2', l(10), l(100), l(10)) +cellGaugesTable['phlib80'] = ('metal2', l( 1), l(312), l(246)) diff --git a/crlcore/etc/symbolic/phenitec06/plugins.conf b/crlcore/etc/symbolic/phenitec06/plugins.conf index 79e43d67..d89fb2a1 100644 --- a/crlcore/etc/symbolic/phenitec06/plugins.conf +++ b/crlcore/etc/symbolic/phenitec06/plugins.conf @@ -12,7 +12,7 @@ from helpers import l, u, n # # Parameters for chip plugin. parametersTable = \ - ( ("chip.block.rails.count" , TypeInt , l(5 ) ) + ( ("chip.block.rails.count" , TypeInt , 5 ) , ("chip.block.rails.hWidth" , TypeInt , l(24) ) , ("chip.block.rails.vWidth" , TypeInt , l(24) ) , ("chip.block.rails.hSpacing" , TypeInt , l(12) ) diff --git a/crlcore/src/ccore/alliance/ap/ApParser.cpp b/crlcore/src/ccore/alliance/ap/ApParser.cpp index cf238896..535f8909 100644 --- a/crlcore/src/ccore/alliance/ap/ApParser.cpp +++ b/crlcore/src/ccore/alliance/ap/ApParser.cpp @@ -522,16 +522,17 @@ namespace { if (layerInfo and net) { net->setExternal( true ); - /*pin =*/ Pin::create( net - , pinName - , accessDirection - , Pin::PlacementStatus::PLACED - , layerInfo->getLayer() - , XCON - , YCON - , WIDTH - , HEIGHT - ); + Pin* pin = Pin::create( net + , pinName + , accessDirection + , Pin::PlacementStatus::PLACED + , layerInfo->getLayer() + , XCON + , YCON + , WIDTH + , HEIGHT + ); + NetExternalComponents::setExternal( pin ); } if (not net ) _printError( false, "Unknown net name <%s>." , fields[5] ); if (not layerInfo ) _printError( false, "Unknown layer name <%s>.", fields[6] ); @@ -687,18 +688,18 @@ namespace { _printError ( false, "Unknown orientation (%s).", getString(orientName).c_str() ); Instance* instance = _cell->getInstance ( instanceName ); - if ( instance ) { + if (instance) { instance->setTransformation - ( getTransformation ( instance->getMasterCell()->getAbutmentBox() - , XINS - , YINS - , orient - ) + ( getTransformation( instance->getMasterCell()->getAbutmentBox() + , XINS + , YINS + , orient + ) ); - instance->setPlacementStatus ( Instance::PlacementStatus::FIXED ); + instance->setPlacementStatus( Instance::PlacementStatus::FIXED ); } else { - bool ignoreInstance = (getString(masterCellName).substr(0,7) == padreal); - Catalog::State* instanceState = _framework->getCatalog()->getState ( masterCellName ); + bool ignoreInstance = _framework->isPad( _cell ); + Catalog::State* instanceState = _framework->getCatalog()->getState( masterCellName ); if ( not ignoreInstance and ( not instanceState or (not instanceState->isFeed()) ) ) { _printError ( false , "No logical instance associated to physical instance %s." @@ -710,30 +711,30 @@ namespace { // Load a cell that is not in the logical view. Only feedthrough Cell // could be in that case. tab++; - Cell* masterCell = _framework->getCell ( getString(masterCellName) - , Catalog::State::Views - ); + Cell* masterCell = _framework->getCell( getString(masterCellName) + , Catalog::State::Views + ); tab--; - if ( !masterCell ) { - _printError ( "Unable to load model %s.", getString(masterCellName).c_str() ); + if (not masterCell) { + _printError( "Unable to load model %s.", getString(masterCellName).c_str() ); return; } ignoreInstance = ignoreInstance and _cell->isTerminal(); - instance = Instance::create ( _cell - , instanceName - , masterCell - , getTransformation ( masterCell->getAbutmentBox() - , XINS - , YINS - , orient - ) - , Instance::PlacementStatus::FIXED - , true // Checking of recursive calls - ); - _cell->setTerminal ( ignoreInstance ); + instance = Instance::create( _cell + , instanceName + , masterCell + , getTransformation ( masterCell->getAbutmentBox() + , XINS + , YINS + , orient + ) + , Instance::PlacementStatus::FIXED + , true // Checking of recursive calls + ); + _cell->setTerminal( ignoreInstance ); } } } diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 9c0f0d5d..0012e879 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -8,6 +8,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTreePlugin.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/CoreToChip_cmos.py #${CMAKE_CURRENT_SOURCE_DIR}/plugins/CoreToChip_c35b4.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/CoreToChip_phlib80.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipPlace.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipRoute.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePlugin.py @@ -23,6 +24,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/CoreToChip.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/cmos.py #${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/c35b4.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/phlib80.py ) set ( pyPluginChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/Configuration.py diff --git a/cumulus/src/plugins/CoreToChip_phlib80.py b/cumulus/src/plugins/CoreToChip_phlib80.py new file mode 100644 index 00000000..8f7cc23a --- /dev/null +++ b/cumulus/src/plugins/CoreToChip_phlib80.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2019-2018, All Rights Reserved +# +# +-----------------------------------------------------------------+ +# | C O R I O L I S | +# | C u m u l u s - P y t h o n T o o l s | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@lip6.fr | +# | =============================================================== | +# | Python : "./plugins/CoreToChip_phlib80.py" | +# +-----------------------------------------------------------------+ + +import sys +import helpers +from helpers.io import ErrorMessage +from helpers.io import WarningMessage +import plugins +import core2chip.phlib80 + + +# -------------------------------------------------------------------- +# Plugin hook functions, unicornHook:menus, ScritMain:call + +def unicornHook ( **kw ): + kw['beforeAction'] = 'placeAndRoute.stepByStep' + #kw['beforeAction'] = 'placeAndRoute.clockTree' + + plugins.kwAddMenu ( 'placeAndRoute' , 'P&&R', **kw ) + plugins.kwAddMenu ( 'placeAndRoute.core2chip', 'Core To Chip', **kw ) + plugins.kwUnicornHook( 'placeAndRoute.core2chip.phlib80' + , 'Phenitec08 Symbolic CMOS I/O pads' + , 'Wrap a complete chip around a Core for Phenitec generic CMOS' + , sys.modules[__name__].__file__ + , **kw + ) + return + + +def ScriptMain ( **kw ): + rvalue = True + try: + helpers.staticInitialization( quiet=True ) + #helpers.setTraceLevel( 550 ) + + cell, editor = plugins.kwParseMain( **kw ) + if not cell: + raise ErrorMessage( 1, 'CoreToChip_phlib80.ScriptMain(): No cell (core) loaded in the editor yet.' ) + + chip_phlib80 = core2chip.phlib80.phlib80( cell ) + chip_phlib80.buildChip() + + if editor: editor.setCell( chip_phlib80.chip ) + + except Exception, e: + helpers.io.catch( e ) + rvalue = False + + sys.stdout.flush() + sys.stderr.flush() + + return rvalue diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index 5d6dc064..24878d7f 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -258,9 +258,6 @@ class Side ( object ): def check ( self ): self.validated = True if self.type == chip.North: - #print DbU.getValueString(self.conf.coreSize.getWidth()) - #print DbU.getValueString(self.conf.minCorona) - #print DbU.getValueString(self.conf.getIoPadHeight()) self.validated = self._check( self.conf.coreSize.getWidth() + 2*self.conf.minCorona + 2*self.conf.getIoPadHeight() @@ -1086,8 +1083,10 @@ class Corona ( object ): rg = self.conf.gaugeConf.routingGauge hsegments = { } vsegments = { } + for component in padNet.getExternalComponents(): - if isinstance(component,Segment): + if isinstance(component,Segment) or isinstance(component,Contact): + bb = component.getBoundingBox() padInstance.getTransformation().applyOn( bb ) if bb.intersect(innerBb): @@ -1136,6 +1135,16 @@ class Corona ( object ): side.updateGap ( gapWidth ) side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) ) count += 1 + else: + if not chipIntNet.isGlobal(): + raise ErrorMessage( 1, [ 'PadsCorona._createCoreWire(): In I/O pad "%s" (%s),' + % ( padInstance.getMasterCell().getName() + , padInstance.getName() ) + , 'connector "%s" has no suitable segment for net "%s".' + % ( padNet.getName() + , chipIntNet.getName() ) + ] ) + return count diff --git a/cumulus/src/plugins/core2chip/CoreToChip.py b/cumulus/src/plugins/core2chip/CoreToChip.py index e2de5a6b..8c871468 100644 --- a/cumulus/src/plugins/core2chip/CoreToChip.py +++ b/cumulus/src/plugins/core2chip/CoreToChip.py @@ -138,7 +138,9 @@ class IoNet ( object ): # Chip "external" net, connected to the pad I/O to the outside world. if not self.chipExtNet and (context & IoNet.DoExtNet): - self.chipExtNet = Net.create( self.coreToChip.chip, self.padNetName ) + self.chipExtNet = self.coreToChip.chip.getNet( self.padNetName ) + if not self.chipExtNet: + self.chipExtNet = Net.create( self.coreToChip.chip, self.padNetName ) self.chipExtNet.setExternal ( True ) self.chipExtNet.setDirection( self.coreNet.getDirection() ) @@ -190,6 +192,7 @@ class IoPad ( object ): if len(self.nets) == 1: if self.nets[0].coreNet.getDirection() == Net.Direction.IN: self.direction = IoPad.IN elif self.nets[0].coreNet.getDirection() == Net.Direction.OUT: self.direction = IoPad.OUT + elif self.nets[0].coreNet.getName() == 'scout': self.direction = IoPad.OUT else: raise ErrorMessage( 1, 'IoPad.addNet(): Unsupported direction %d (%s) for core net "%s" in I/O pad \"%s\".' \ % ( self.nets[0].coreNet.getDirection() @@ -339,7 +342,9 @@ class CoreToChip ( object ): for ringNetSpec in self.ringNetNames: if isinstance(ringNetSpec,tuple): ringNetName = ringNetSpec[0] else: ringNetName = ringNetSpec - ringNet = Net.create( self.chip, ringNetName ) + ringNet = self.chip.getNet( ringNetName ) + if not ringNet: + ringNet = Net.create( self.chip, ringNetName ) ringNet.setType ( self.getNetType(ringNetName) ) ringNet.setGlobal( self.isGlobal (ringNetName) ) return diff --git a/cumulus/src/plugins/core2chip/phlib.py b/cumulus/src/plugins/core2chip/phlib.py new file mode 100644 index 00000000..5b03c394 --- /dev/null +++ b/cumulus/src/plugins/core2chip/phlib.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2019-2018, All Rights Reserved +# +# +-----------------------------------------------------------------+ +# | C O R I O L I S | +# | C u m u l u s - P y t h o n T o o l s | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +# | =============================================================== | +# | Python : "./plugins/core2chip/cmos.py" | +# +-----------------------------------------------------------------+ + +import re +from Hurricane import DbU +from Hurricane import DataBase +from Hurricane import UpdateSession +from Hurricane import Breakpoint +from Hurricane import Transformation +from Hurricane import Instance +from Hurricane import Net +import Viewer +from CRL import Catalog +from CRL import AllianceFramework +from helpers.io import ErrorMessage +from core2chip.CoreToChip import IoPad +from core2chip.CoreToChip import CoreToChip + + +class cmos ( CoreToChip ): + + def __init__ ( self, core ): + CoreToChip.__init__ ( self, core ) + self.ringNetNames = [ 'vsse', 'vssi', 'vdde', 'vddi', ('cki', 'ck') ] + self.ioPadInfos = { IoPad.IN : CoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] ) + , IoPad.OUT : CoreToChip.IoPadInfo( 'po_px' , 'pad', ['i',] ) + , IoPad.TRI_OUT : CoreToChip.IoPadInfo( 'pot_px' , 'pad', ['i', 'b' ] ) + , IoPad.BIDIR : CoreToChip.IoPadInfo( 'piot_px', 'pad', ['i', 't', 'b' ] ) + } + self._getPadLib() + return + + def _getPadLib ( self ): + self.padLib = AllianceFramework.get().getLibrary( "pxlib" ) + + if not self.padLib: + message = [ 'CoreToChip.cmos._getPadLib(): Unable to find Alliance "pxlib" library' ] + raise ErrorMessage( 1, message ) + + return + + def getNetType ( self, netName ): + if netName.startswith('vss'): return Net.Type.GROUND + if netName.startswith('vdd'): return Net.Type.POWER + if netName in ('cki', 'ck'): return Net.Type.CLOCK + return Net.Type.LOGICAL + + def isGlobal ( self, netName ): + if netName in self.ringNetNames: return True + return False + + def getCell ( self, masterCellName ): + #cell = self.padLib.getCell( masterCellName ) + cell = AllianceFramework.get().getCell( masterCellName, Catalog.State.Views ) + if not cell: + raise ErrorMessage( 1, 'cmos.getCell(): I/O pad library "%s" does not contain cell named "%s"' \ + % (self.padLib.getName(),masterCellName) ) + return cell + + def _buildGroundPads ( self, ioNet ): + ioNet.buildNets() + vssi = self.chip.getNet( 'vssi' ) + vssi.setExternal( True ) + vssi.setGlobal ( True ) + vssi.setType ( Net.Type.GROUND ) + vssi.merge( ioNet.chipIntNet ) + ioNet.chipIntNet = vssi + + vsse = self.chip.getNet( 'vsse' ) + vsse.setExternal( True ) + vsse.setGlobal ( True ) + vsse.setType ( Net.Type.GROUND ) + vsse.merge( ioNet.chipExtNet ) + ioNet.chipExtNet = vsse + + pads = [] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'ick_%d' % self.groundPadCount + , self.getCell('pvssick_px') ) ) + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'eck_%d' % self.groundPadCount + , self.getCell('pvsseck_px') ) ) + + CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vssi' ) + CoreToChip._connect( pads[1], ioNet.chipExtNet, 'vsse' ) + + for pad in pads: self._connectRing( pad ) + self.groundPadCount += 1 + self.chipPads += pads + return + + def _buildPowerPads ( self, ioNet ): + ioNet.buildNets() + vddi = self.chip.getNet( 'vddi' ) + vddi.setExternal( True ) + vddi.setGlobal ( True ) + vddi.setType ( Net.Type.POWER ) + vddi.merge( ioNet.chipIntNet ) + ioNet.chipIntNet = vddi + + vdde = self.chip.getNet( 'vdde' ) + vdde.setExternal( True ) + vdde.setGlobal ( True ) + vdde.setType ( Net.Type.POWER ) + vdde.merge( ioNet.chipExtNet ) + ioNet.chipExtNet = vdde + + pads = [ ] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'ick_%d' % self.powerPadCount + , self.getCell('pvddick_px') ) ) + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'eck_%d' % self.powerPadCount + , self.getCell('pvddeck_px') ) ) + + CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vddi' ) + CoreToChip._connect( pads[1], ioNet.chipExtNet, 'vdde' ) + + for pad in pads: self._connectRing( pad ) + self.powerPadCount += 1 + self.chipPads += pads + return + + def _buildClockPads ( self, ioNet ): + ioNet.buildNets() + pads = [ ] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + '_%d' % self.clockPadCount + , self.getCell('pck_px') ) ) + + CoreToChip._connect( pads[0], ioNet.chipExtNet, 'pad' ) + + for pad in pads: self._connectRing( pad ) + self.clockPadCount += 1 + self.chipPads += pads + + p = re.compile( r'pv[ds]{2}[ei]ck_px' ) + for pad in self.chipPads: + if p.match( pad.getMasterCell().getName() ): + CoreToChip._connect( pad, ioNet.chipIntNet, 'cko' ) + return diff --git a/cumulus/src/plugins/core2chip/phlib80.py b/cumulus/src/plugins/core2chip/phlib80.py new file mode 100644 index 00000000..0282afa0 --- /dev/null +++ b/cumulus/src/plugins/core2chip/phlib80.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2019-2018, All Rights Reserved +# +# +-----------------------------------------------------------------+ +# | C O R I O L I S | +# | C u m u l u s - P y t h o n T o o l s | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@lip6.fr | +# | =============================================================== | +# | Python : "./plugins/core2chip/phlib80.py" | +# +-----------------------------------------------------------------+ + + +import re +from Hurricane import DbU +from Hurricane import DataBase +from Hurricane import UpdateSession +from Hurricane import Breakpoint +from Hurricane import Transformation +from Hurricane import Instance +from Hurricane import Net +import Viewer +from CRL import Catalog +from CRL import AllianceFramework +from helpers.io import ErrorMessage +from core2chip.CoreToChip import IoPad +from core2chip.CoreToChip import CoreToChip + + +class phlib80 ( CoreToChip ): + + def __init__ ( self, core ): + CoreToChip.__init__ ( self, core ) + self.ringNetNames = [ 'vss', 'vss', ('cki', 'ck') ] + self.ioPadInfos = { IoPad.IN : CoreToChip.IoPadInfo( 'pi_sp' , 'pad', ['t',] ) + , IoPad.OUT : CoreToChip.IoPadInfo( 'po_sp' , 'pad', ['i',] ) + #, IoPad.TRI_OUT : CoreToChip.IoPadInfo( 'pot_sp' , 'pad', ['i', 'b' ] ) + #, IoPad.BIDIR : CoreToChip.IoPadInfo( 'piot_sp', 'pad', ['i', 't', 'b' ] ) + } + self._getPadLib() + return + + def _getPadLib ( self ): + self.padLib = AllianceFramework.get().getLibrary( 'phlib80' ) + + if not self.padLib: + message = [ 'CoreToChip.phlib80._getPadLib(): Unable to find Alliance "phlib80" library' ] + raise ErrorMessage( 1, message ) + + return + + def getNetType ( self, netName ): + if netName.startswith('vss'): return Net.Type.GROUND + if netName.startswith('vdd'): return Net.Type.POWER + if netName in ('cko', 'ck'): return Net.Type.CLOCK + return Net.Type.LOGICAL + + def isGlobal ( self, netName ): + if netName in self.ringNetNames: return True + return False + + def getCell ( self, masterCellName ): + #cell = self.padLib.getCell( masterCellName ) + cell = AllianceFramework.get().getCell( masterCellName, Catalog.State.Views ) + if not cell: + raise ErrorMessage( 1, 'cmos.getCell(): I/O pad library "%s" does not contain cell named "%s"' \ + % (self.padLib.getName(),masterCellName) ) + return cell + + def _buildGroundPads ( self, ioNet ): + ioNet.buildNets() + vss = self.chip.getNet( 'vss' ) + vss.setExternal( True ) + vss.setGlobal ( True ) + vss.setType ( Net.Type.GROUND ) + vss.merge( ioNet.chipIntNet ) + ioNet.chipIntNet = vss + + pads = [] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'ck_%d' % self.groundPadCount + , self.getCell('pvssck2_sp') ) ) + + CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vss' ) + + for pad in pads: self._connectRing( pad ) + self.groundPadCount += 1 + self.chipPads += pads + return + + def _buildPowerPads ( self, ioNet ): + ioNet.buildNets() + vdd = self.chip.getNet( 'vdd' ) + vdd.setExternal( True ) + vdd.setGlobal ( True ) + vdd.setType ( Net.Type.POWER ) + vdd.merge( ioNet.chipIntNet ) + ioNet.chipIntNet = vdd + + pads = [ ] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + 'ck_%d' % self.powerPadCount + , self.getCell('pvddck2_sp') ) ) + + CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vdd' ) + + for pad in pads: self._connectRing( pad ) + self.powerPadCount += 1 + self.chipPads += pads + return + + def _buildClockPads ( self, ioNet ): + ioNet.buildNets() + pads = [ ] + pads.append( Instance.create( self.chip + , 'p_' + ioNet.padInstanceName + '_%d' % self.clockPadCount + , self.getCell('pck_sp') ) ) + + CoreToChip._connect( pads[0], ioNet.chipExtNet, 'pad' ) + + for pad in pads: self._connectRing( pad ) + self.clockPadCount += 1 + self.chipPads += pads + + p = re.compile( r'pv[ds]{2}ck2_sp' ) + for pad in self.chipPads: + if p.match( pad.getMasterCell().getName() ): + CoreToChip._connect( pad, ioNet.chipIntNet, 'cko' ) + return diff --git a/etesian/src/BloatCells.cpp b/etesian/src/BloatCells.cpp index 76ee28c4..d082b68a 100644 --- a/etesian/src/BloatCells.cpp +++ b/etesian/src/BloatCells.cpp @@ -88,6 +88,39 @@ namespace Etesian { } + Bloat3Metals::Bloat3Metals () + : BloatCell("3metals") + { } + + + Bloat3Metals::~Bloat3Metals () + { } + + + DbU::Unit Bloat3Metals::getDx ( const Cell* cell, const EtesianEngine* etesian ) const + { + int terminals = 0; + for ( Net* net : cell->getNets() ) { + if (net->isExternal() and not net->isPower()) ++terminals; + } + + Box ab ( cell->getAbutmentBox() ); + DbU::Unit vpitch = etesian->getVerticalPitch();; + int xsize = (ab.getWidth() + vpitch - 1) / vpitch; + + // float termRatio = (float)terminals / (float)(ab.getWidth() / vpitch); + // if (termRatio > 0.5) { + // return vpitch*6; + // } + + if (xsize < 4) return vpitch*4; + if (xsize < 6) return vpitch*2; + if (xsize < 8) return vpitch*1; + + return 0; + } + + bool BloatCells::select ( std::string profile ) { BloatKey key ( profile ); diff --git a/etesian/src/etesian/BloatCells.h b/etesian/src/etesian/BloatCells.h index 6dbc929d..6d4b712a 100644 --- a/etesian/src/etesian/BloatCells.h +++ b/etesian/src/etesian/BloatCells.h @@ -82,6 +82,14 @@ namespace Etesian { virtual ~BloatNsxlib (); virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const; }; + + + class Bloat3Metals : public BloatCell { + public: + Bloat3Metals (); + virtual ~Bloat3Metals (); + virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const; + }; class BloatCells { @@ -108,6 +116,7 @@ namespace Etesian { { _bloatCells.insert( new BloatDisabled() ); _bloatCells.insert( new BloatNsxlib () ); + _bloatCells.insert( new Bloat3Metals () ); select( "disabled" ); } diff --git a/katana/src/Configuration.cpp b/katana/src/Configuration.cpp index 6693bcb5..be8ea48a 100644 --- a/katana/src/Configuration.cpp +++ b/katana/src/Configuration.cpp @@ -42,6 +42,8 @@ namespace Katana { , _postEventCb () , _hTracksReservedLocal(Cfg::getParamInt ("katana.hTracksReservedLocal", 3)->asInt()) , _vTracksReservedLocal(Cfg::getParamInt ("katana.vTracksReservedLocal", 3)->asInt()) + , _termSatReservedLocal(Cfg::getParamInt ("katana.termSatReservedLocal", 9)->asInt()) + , _termSatThreshold (Cfg::getParamInt ("katana.termSatThreshold" , 8)->asInt()) , _ripupLimits () , _ripupCost (Cfg::getParamInt ("katana.ripupCost" , 3)->asInt()) , _eventsLimit (Cfg::getParamInt ("katana.eventsLimit" ,4000000)->asInt()) @@ -80,6 +82,8 @@ namespace Katana { , _postEventCb (other._postEventCb) , _hTracksReservedLocal(other._hTracksReservedLocal) , _vTracksReservedLocal(other._vTracksReservedLocal) + , _termSatReservedLocal(other._termSatReservedLocal) + , _termSatThreshold (other._termSatThreshold) , _ripupLimits () , _ripupCost (other._ripupCost) , _eventsLimit (other._eventsLimit) @@ -148,13 +152,16 @@ namespace Katana { if (not cmess1.enabled()) return; cout << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; - cout << Dots::asUInt (" - Global router H reserved local" ,_hTracksReservedLocal) << endl; - cout << Dots::asUInt (" - Global router V reserved local" ,_vTracksReservedLocal) << endl; - cout << Dots::asULong(" - Events limit (iterations)" ,_eventsLimit) << endl; - cout << Dots::asUInt (" - Ripup limit, straps & unbreakables" ,_ripupLimits[StrapRipupLimit]) << endl; - cout << Dots::asUInt (" - Ripup limit, locals" ,_ripupLimits[LocalRipupLimit]) << endl; - cout << Dots::asUInt (" - Ripup limit, globals" ,_ripupLimits[GlobalRipupLimit]) << endl; - cout << Dots::asUInt (" - Ripup limit, long globals" ,_ripupLimits[LongGlobalRipupLimit]) << endl; + cout << Dots::asDouble(" - GCell saturate ratio (LA)" ,getSaturateRatio()) << endl; + cout << Dots::asUInt (" - Edge max H reserved local" ,_hTracksReservedLocal) << endl; + cout << Dots::asUInt (" - Edge max V reserved local" ,_vTracksReservedLocal) << endl; + cout << Dots::asUInt (" - Terminal saturated edge capacity" ,_termSatReservedLocal) << endl; + cout << Dots::asUInt (" - Terminal saturated GCell threshold" ,_termSatThreshold) << endl; + cout << Dots::asULong (" - Events limit (iterations)" ,_eventsLimit) << endl; + cout << Dots::asUInt (" - Ripup limit, straps & unbreakables" ,_ripupLimits[StrapRipupLimit]) << endl; + cout << Dots::asUInt (" - Ripup limit, locals" ,_ripupLimits[LocalRipupLimit]) << endl; + cout << Dots::asUInt (" - Ripup limit, globals" ,_ripupLimits[GlobalRipupLimit]) << endl; + cout << Dots::asUInt (" - Ripup limit, long globals" ,_ripupLimits[LongGlobalRipupLimit]) << endl; Super::print ( cell ); } diff --git a/katana/src/GlobalRoute.cpp b/katana/src/GlobalRoute.cpp index 6a80c101..83264bda 100644 --- a/katana/src/GlobalRoute.cpp +++ b/katana/src/GlobalRoute.cpp @@ -228,7 +228,13 @@ namespace Katana { printMeasures( "Anabatic Grid" ); setupNetDatas(); + computeEdgeCapacities( getHTracksReservedLocal() + , getVTracksReservedLocal() + , getTermSatThreshold() + , getTermSatReservedLocal() + ); +#if UNIFORM_EDGE_CAPACITY for ( GCell* gcell : getGCells() ) { if (not gcell->isMatrix()) continue; @@ -237,6 +243,7 @@ namespace Katana { else edge->reserveCapacity( getVTracksReservedLocal() ); } } +#endif } diff --git a/katana/src/KatanaEngine.cpp b/katana/src/KatanaEngine.cpp index 87393edc..fb69b1ac 100644 --- a/katana/src/KatanaEngine.cpp +++ b/katana/src/KatanaEngine.cpp @@ -480,19 +480,28 @@ namespace Katana { Segment* segment = element->getSegment(); Flags side = Flags::EastSide; - DbU::Unit axis = segment->getY(); + DbU::Unit axis = track->getAxis(); + Point source = segment->getSourcePosition(); + Point target = segment->getTargetPosition(); + if (track->getDirection() == Flags::Vertical) { side = Flags::NorthSide; - axis = segment->getX(); + source.setX( axis ); + target.setX( axis ); + } else { + source.setY( axis ); + target.setY( axis ); } int elementCapacity = 1; cdebug_log(159,0) << "Capacity from: " << element << ":" << elementCapacity << endl; - GCellsUnder gcells = getGCellsUnder( segment ); + GCellsUnder gcells = getGCellsUnder( source, target ); if (not gcells->empty()) { - for ( size_t i=0 ; isize()-1 ; ++i ) - gcells->gcellAt(i)->getEdgeAt( side, axis )->reserveCapacity( elementCapacity ); + for ( size_t i=0 ; isize()-1 ; ++i ) { + Edge* edge = gcells->gcellAt(i)->getEdgeAt( side, axis ); + edge->reserveCapacity( elementCapacity ); + } } } } @@ -522,6 +531,15 @@ namespace Katana { edge->reserveCapacity( capacity ); } } + } else { + for ( GCell* gcell : getGCells() ) { + if (not gcell->isMatrix()) continue; + + for ( Edge* edge : gcell->getEdges( Flags::EastSide|Flags::NorthSide) ) { + if (edge->getReservedCapacity() == 0) + edge->reserveCapacity( 1 ); + } + } } } diff --git a/katana/src/Manipulator.cpp b/katana/src/Manipulator.cpp index 31ab4a57..ad81b722 100644 --- a/katana/src/Manipulator.cpp +++ b/katana/src/Manipulator.cpp @@ -1152,7 +1152,9 @@ namespace Katana { float reserve = (_segment->isLocal()) ? 0.5 : 1.0; if (not _segment->canMoveUp(reserve)) return false; - return _segment->moveUp( Flags::NoFlags ); + //reprocessParallels(); + bool success = _segment->moveUp( Flags::NoFlags ); + return success; } @@ -1193,7 +1195,9 @@ namespace Katana { if (not _segment->canMoveUp(0.5,kflags)) return false; } + //reprocessParallels(); bool success = _segment->moveUp( kflags|Flags::Propagate ); + _fsm.addAction ( _segment, SegmentAction::OtherRipup ); return success; } @@ -1573,6 +1577,45 @@ namespace Katana { } + void Manipulator::reprocessParallels () + { + cdebug_log(159,0) << "Manipulator::reprocessParallels() " << _segment << endl; + + //if (_event->getPerpandiculars().size() > 2) return; + + unsigned int rpDistance = _segment->base()->getRpDistance(); + + const vector& perpandiculars = _event->getPerpandiculars(); + for ( size_t iperpand=0 ; iperpandgetDataNegociate(); + + if (perpandicular->isFixed()) continue; + if (not data) continue; + if (not perpandicular->getTrack()) continue; + if (perpandicular->base()->getRpDistance() > rpDistance) continue; + if (not Manipulator(perpandicular,_fsm).canRipup() + or (data->getState() >= DataNegociate::MaximumSlack)) continue; + + _fsm.addAction( perpandicular, SegmentAction::SelfRipupPerpand ); + + const vector& parallels = data->getRoutingEvent()->getPerpandiculars(); + for ( size_t iparallel=0 ; iparallelgetDataNegociate(); + + if (parallel->isFixed()) continue; + if (not data) continue; + if (not parallel->getTrack()) continue; + if (parallel->base()->getRpDistance() > rpDistance) continue; + if (not Manipulator(parallel,_fsm).canRipup() + or (data->getState() >= DataNegociate::MaximumSlack)) continue; + + _fsm.addAction( parallel, SegmentAction::SelfRipupPerpand ); + } + } + } + void Manipulator::reprocessPerpandiculars () { if ( _event->getAxisHistory() == _event->getAxisHint() ) return; @@ -1640,4 +1683,68 @@ namespace Katana { } + bool Manipulator::avoidBlockage () + { + cdebug_log(159,1) << "Manipulator::avoidBlockage()" << endl; + + if (not _segment->isVertical()) { + cdebug_tabw(159,-1); + return false; + } + + AutoContact* terminal = _segment->base()->getAutoSource(); + AutoContact* turn = _segment->base()->getAutoTarget(); + bool isSourceTerminal = true; + + if (not terminal->isTerminal()) { + std::swap( terminal, turn ); + isSourceTerminal = false; + } + + + TrackElement* perpandicular = _event->getPerpandiculars()[0]; + DataNegociate* data = perpandicular->getDataNegociate(); + + if (not data or (data->getState() >= DataNegociate::RepairFailed)) { + cdebug_tabw(159,-1); + return false; + } + + Box termConstraints ( terminal->getConstraintBox() ); + Box turnConstraints ( turn ->getConstraintBox() ); + + if (isSourceTerminal) { + terminal->setConstraintBox( Box( termConstraints.getXMin() + , termConstraints.getYMin() + , termConstraints.getXMax() + , perpandicular->getAxis() - perpandicular->getPitch() + ) ); + turn->setConstraintBox( Box( turnConstraints.getXMin() + , turnConstraints.getYMin() + , turnConstraints.getXMax() + , perpandicular->getAxis() - perpandicular->getPitch() + ) ); + } else { + terminal->setConstraintBox( Box( termConstraints.getXMin() + , perpandicular->getAxis() + perpandicular->getPitch() + , termConstraints.getXMax() + , termConstraints.getYMax() + ) ); + turn->setConstraintBox( Box( turnConstraints.getXMin() + , perpandicular->getAxis() + perpandicular->getPitch() + , turnConstraints.getXMax() + , turnConstraints.getYMax() + ) ); + } + + cdebug_log(159,0) << "Restrict: " << terminal << " to " << terminal->getConstraintBox() << endl; + cdebug_log(159,0) << "Restrict: " << turn << " to " << turn ->getConstraintBox() << endl; + + _fsm.addAction ( perpandicular, SegmentAction::SelfRipupPerpand|SegmentAction::EventLevel4 ); + + cdebug_tabw(159,-1); + return true; + } + + } // Katana namespace. diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index e2b89c3f..50f77a6d 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -377,14 +377,14 @@ namespace Katana { cdebug_log(159,0) << "* Nearest " << track << endl; if (not track) - throw Error( "NegociateWindow::createTracksegment(): No track near axis of %s." + throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s." , getString(autoSegment).c_str() ); if (track->getAxis() > uside.getVMax()) track = track->getPreviousTrack(); if (track->getAxis() < uside.getVMin()) track = track->getNextTrack(); if (not track) - throw Error( "NegociateWindow::createTracksegment(): No track near axis of %s (after adjust)." + throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s (after adjust)." , getString(autoSegment).c_str() ); cdebug_log(159,0) << "* GCell U-side " << uside << endl; diff --git a/katana/src/PowerRails.cpp b/katana/src/PowerRails.cpp index a1e7b348..a7c42502 100644 --- a/katana/src/PowerRails.cpp +++ b/katana/src/PowerRails.cpp @@ -562,11 +562,22 @@ namespace { axisMax += delta; } + // if (segment->getId() == 51904) { + // DebugSession::open( 0, 1000 ); + // } Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) { TrackElement* element = TrackFixedSegment::create ( track, segment ); cdebug_log(159,0) << " Insert in " << track << "+" << element << endl; + + if (segment->getId() == 51904) { + cerr << " Insert in " << track << endl; + cerr << " +" << element << endl; + } } + // if (segment->getId() == 51904) { + // DebugSession::close(); + // } } } else { list::iterator ichunk = _chunks.begin(); diff --git a/katana/src/SegmentFsm.cpp b/katana/src/SegmentFsm.cpp index de1c6687..71e5e85b 100644 --- a/katana/src/SegmentFsm.cpp +++ b/katana/src/SegmentFsm.cpp @@ -999,7 +999,7 @@ namespace Katana { << " " << candidates[icandidate].getTrack() << endl; Interval overlap0 = candidates[icandidate].getLongestConflict(); - cdebug_log(159,0) << "overlap0: " << overlap0 << endl; + cdebug_log(159,0) << "| overlap0: " << overlap0 << endl; if (overlap0.isEmpty()) { cdebug_log(159,0) << "overlap0 is empty, no conflict, ignoring Track candidate." << endl; @@ -1009,9 +1009,15 @@ namespace Katana { Track* track = candidates[icandidate].getTrack(); TrackElement* other = track->getSegment( overlap.getCenter() ); if (not other) { - cbug << Error("conflictSolveByPlaceds(): No segment under overlap center.") << endl; - continue; + cdebug_log(159,0) << "conflictSolveByPlaceds(): No segment under overlap center." << endl; + other = track->getSegment( overlap0.getCenter() ); + + if (not other) { + cdebug_log(159,0) << "conflictSolveByPlaceds(): No segment under overlap0 center." << endl; + continue; + } } + cdebug_log(159,0) << "| other: " << other << endl; if (Session::getConfiguration()->isVH() and (segment->getDepth() == 1)) { if (Manipulator(segment,*this).makeDogleg(overlap0,Flags::ShortDogleg)) { @@ -1020,6 +1026,7 @@ namespace Katana { break; } } else { + cdebug_log(159,0) << "conflictSolveByPlaceds() other->isGlobal():" << other->isGlobal() << endl; if (other->isGlobal()) { cdebug_log(159,0) << "conflictSolveByPlaceds() - Conflict with global, other move up" << endl; if ((success = Manipulator(other,*this).moveUp(Manipulator::IgnoreContacts))) break; @@ -1204,6 +1211,11 @@ namespace Katana { switch ( data->getState() ) { case DataNegociate::RipupPerpandiculars: nextState = DataNegociate::Minimize; + if (segment->isNonPref() and getCost(0)->isBlockage()) { + cdebug_log(159,0) << "Non-preferred conflicts with a blockage." << endl; + success = manipulator.avoidBlockage(); + if (success) break; + } success = manipulator.ripupPerpandiculars(); if (success) break; case DataNegociate::Minimize: diff --git a/katana/src/Track.cpp b/katana/src/Track.cpp index f25bf3bf..b7bc78fd 100644 --- a/katana/src/Track.cpp +++ b/katana/src/Track.cpp @@ -161,6 +161,8 @@ namespace Katana { size_t begin; getBeginIndex( position, begin, state ); + cdebug_log(159,0) << " getSegment(position): begin:" << begin << endl; + if (state & (BeginIsTrackMin|EndIsTrackMax)) return NULL; return getSegment(begin); } @@ -237,21 +239,26 @@ namespace Katana { // 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? + cdebug_log(159,0) << " begin:" << begin << endl; size_t sameNetDelta = 0; if (begin < _segments.size()) { for ( ; (begin > 0) and (_segments[begin-1]->getNet() == _segments[begin]->getNet()) ; --begin, ++sameNetDelta ); } + cdebug_log(159,0) << " begin:" << begin << endl; state = 0; if ( (begin == 0) and (position < _segments[0]->getSourceU()) ) { state = BeforeFirstElement; } else { if (begin and not sameNetDelta) begin -= 1; + cdebug_log(159,0) << " begin:" << begin << endl; size_t usedBegin = begin; Interval usedInterval = getOccupiedInterval( usedBegin ); + cdebug_log(159,0) << " position:" << DbU::getValueString(position) + << " " << usedInterval << endl; if (position < usedInterval.getVMax()) state = InsideElement; else diff --git a/katana/src/TrackFixedSegment.cpp b/katana/src/TrackFixedSegment.cpp index 80bd6b7b..d9942b74 100644 --- a/katana/src/TrackFixedSegment.cpp +++ b/katana/src/TrackFixedSegment.cpp @@ -253,7 +253,7 @@ namespace Katana { string s2 = " [" + DbU::getValueString(_sourceU) + ":" + DbU::getValueString(_targetU) + "]" + " " + DbU::getValueString(_targetU-_sourceU) - + "F" + + " F" + ((isBlockage()) ? "B" : "-"); s1.insert ( s1.size()-1, s2 ); diff --git a/katana/src/TrackSegment.cpp b/katana/src/TrackSegment.cpp index d7662016..52a6ba12 100644 --- a/katana/src/TrackSegment.cpp +++ b/katana/src/TrackSegment.cpp @@ -156,7 +156,7 @@ namespace Katana { trackElement->_postCreate(); trackElement->invalidate(); created = true; - cdebug_log(159,0) << "TrackSegment::create(): " << "nonPref:" <getRipupCost(); } inline uint32_t KatanaEngine::getHTracksReservedLocal () const { return _configuration->getHTracksReservedLocal(); } inline uint32_t KatanaEngine::getVTracksReservedLocal () const { return _configuration->getVTracksReservedLocal(); } + inline uint32_t KatanaEngine::getTermSatReservedLocal () const { return _configuration->getTermSatReservedLocal(); } + inline uint32_t KatanaEngine::getTermSatThreshold () const { return _configuration->getTermSatThreshold(); } inline uint32_t KatanaEngine::getRipupLimit ( uint32_t type ) const { return _configuration->getRipupLimit(type); } inline bool KatanaEngine::profileEventCosts () const { return _configuration->profileEventCosts(); } inline const DataSymmetricMap& KatanaEngine::getSymmetrics () const { return _symmetrics; } diff --git a/katana/src/katana/Manipulator.h b/katana/src/katana/Manipulator.h index a532e5c1..57026168 100644 --- a/katana/src/katana/Manipulator.h +++ b/katana/src/katana/Manipulator.h @@ -65,6 +65,8 @@ namespace Katana { bool ripupPerpandiculars ( uint32_t flags=0 ); void repackPerpandiculars ( uint32_t flags ); void reprocessPerpandiculars (); + void reprocessParallels (); + bool avoidBlockage (); bool ripple (); bool minimize (); bool dragMinimize ();