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.
This commit is contained in:
parent
c6ea1bccdd
commit
24dedce09c
|
@ -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<Horizontal*>( segment );
|
||||
if (horizontal) {
|
||||
side = Flags::EastSide;
|
||||
axis = horizontal->getY();
|
||||
|
||||
if (horizontal->getSourceX() > horizontal->getTargetX())
|
||||
std::swap( gsource, gtarget );
|
||||
} else {
|
||||
Vertical* vertical = dynamic_cast<Vertical*>( 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<RoutingPad*> rps;
|
||||
vector<GCell*> saturateds;
|
||||
const vector<NetData*>& netDatas = getNetOrdering();
|
||||
|
||||
for ( NetData* netData : netDatas ) {
|
||||
for ( Component* component : netData->getNet()->getComponents() ) {
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( 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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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 = "<GCell at(" + DbU::getValueString(getXMin())
|
||||
+ "-" + DbU::getValueString(getYMin())
|
||||
+ "-" + DbU::getValueString(getXMax())
|
||||
|
|
|
@ -349,7 +349,7 @@ namespace Anabatic {
|
|||
size_t i = 0;
|
||||
for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) {
|
||||
cdebug_log(149,0) << "_desaturate: [" << depth << "]:"
|
||||
<< (*igcell)->getDensity(depth) << " " << *igcell << endl;
|
||||
<< (*igcell)->getDensity(depth) << " " << *igcell << endl;
|
||||
|
||||
if (not (*igcell)->isSaturated(depth)) {
|
||||
cdebug_log(149,0) << "STOP desaturated: @" << i << " " << *igcell << endl;
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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<Component*,AutoSegment*>::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<Pin*>( 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<Pin*>( 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<Pin*>( 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) );
|
||||
|
|
|
@ -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<RawGCellsUnder>( new RawGCellsUnder(this,s) ); }
|
||||
inline GCellsUnder AnabaticEngine::getGCellsUnder ( Point source, Point target ) const { return std::shared_ptr<RawGCellsUnder>( 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; }
|
||||
|
|
|
@ -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& );
|
||||
|
|
|
@ -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<Net*>& 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<AutoContact*> _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<Contact*>& 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<AutoSegment*>& GCell::getVSegments () const { return _vsegments; }
|
||||
inline const vector<AutoSegment*>& GCell::getHSegments () const { return _hsegments; }
|
||||
inline const vector<AutoContact*>& 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 ); }
|
||||
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 } )
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -3,8 +3,3 @@
|
|||
import helpers
|
||||
|
||||
execfile( helpers.sysConfDir+'/common/etesian.conf' )
|
||||
|
||||
parametersTable = \
|
||||
( ('etesian.bloat' , TypeString , "nsxlib" )
|
||||
,
|
||||
)
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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 );
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Katana> 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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 ; i<gcells->size()-1 ; ++i )
|
||||
gcells->gcellAt(i)->getEdgeAt( side, axis )->reserveCapacity( elementCapacity );
|
||||
for ( size_t i=0 ; i<gcells->size()-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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<TrackElement*>& perpandiculars = _event->getPerpandiculars();
|
||||
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
|
||||
TrackElement* perpandicular = perpandiculars[iperpand];
|
||||
DataNegociate* data = perpandicular->getDataNegociate();
|
||||
|
||||
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<TrackElement*>& parallels = data->getRoutingEvent()->getPerpandiculars();
|
||||
for ( size_t iparallel=0 ; iparallel<parallels.size() ; iparallel++ ) {
|
||||
TrackElement* parallel = parallels[iparallel];
|
||||
DataNegociate* data = parallel->getDataNegociate();
|
||||
|
||||
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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Interval>::iterator ichunk = _chunks.begin();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ namespace Katana {
|
|||
trackElement->_postCreate();
|
||||
trackElement->invalidate();
|
||||
created = true;
|
||||
cdebug_log(159,0) << "TrackSegment::create(): " << "nonPref:" <<useNonPref
|
||||
cdebug_log(159,0) << "TrackSegment::create(): " << "nonPref:" << useNonPref
|
||||
<< " " << trackElement << endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace Katana {
|
|||
uint32_t getRipupLimit ( uint32_t type ) const;
|
||||
inline uint32_t getHTracksReservedLocal () const;
|
||||
inline uint32_t getVTracksReservedLocal () const;
|
||||
inline uint32_t getTermSatReservedLocal () const;
|
||||
inline uint32_t getTermSatThreshold () const;
|
||||
inline void setEventsLimit ( uint64_t );
|
||||
inline void setRipupCost ( uint32_t );
|
||||
void setRipupLimit ( uint32_t limit, uint32_t type );
|
||||
|
@ -89,6 +91,8 @@ namespace Katana {
|
|||
PostEventCb_t _postEventCb;
|
||||
uint32_t _hTracksReservedLocal;
|
||||
uint32_t _vTracksReservedLocal;
|
||||
uint32_t _termSatReservedLocal;
|
||||
uint32_t _termSatThreshold;
|
||||
uint32_t _ripupLimits [RipupLimitsTableSize];
|
||||
uint32_t _ripupCost;
|
||||
uint64_t _eventsLimit;
|
||||
|
@ -108,6 +112,8 @@ namespace Katana {
|
|||
inline uint32_t Configuration::getRipupCost () const { return _ripupCost; }
|
||||
inline uint32_t Configuration::getHTracksReservedLocal () const { return _hTracksReservedLocal; }
|
||||
inline uint32_t Configuration::getVTracksReservedLocal () const { return _vTracksReservedLocal; }
|
||||
inline uint32_t Configuration::getTermSatReservedLocal () const { return _termSatReservedLocal; }
|
||||
inline uint32_t Configuration::getTermSatThreshold () const { return _termSatThreshold; }
|
||||
inline void Configuration::setRipupCost ( uint32_t cost ) { _ripupCost = cost; }
|
||||
inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; }
|
||||
inline void Configuration::setEventsLimit ( uint64_t limit ) { _eventsLimit = limit; }
|
||||
|
|
|
@ -84,6 +84,8 @@ namespace Katana {
|
|||
inline uint32_t getRipupCost () const;
|
||||
inline uint32_t getHTracksReservedLocal () const;
|
||||
inline uint32_t getVTracksReservedLocal () const;
|
||||
inline uint32_t getTermSatReservedLocal () const;
|
||||
inline uint32_t getTermSatThreshold () const;
|
||||
inline bool profileEventCosts () const;
|
||||
virtual const Name& getName () const;
|
||||
inline Configuration::PostEventCb_t&
|
||||
|
@ -183,6 +185,8 @@ namespace Katana {
|
|||
inline uint32_t KatanaEngine::getRipupCost () const { return _configuration->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; }
|
||||
|
|
|
@ -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 ();
|
||||
|
|
Loading…
Reference in New Issue