Adjustements for analog routing.

* Change: In Anabatic::GCell::doGrid(), remove the "3 slice height"
    limit (for small digital analog blocs).
* Bug: In Anabatic::NetBuilder::setStartHook(), perform a check for
    a RoutingPad still on a Plug. Diplay an error instead of crashing.
* Bug: In CRL::RoutingLayerGauge::getTrackIndex(), the upper bound
    of the track interval must be included instead of excluded.
* New: In Hurricane::Cell, add a StayOnPlugs flags for flattenNets().
    To keep the RoutingPad occurrences on Plug instead of selecting
    physical components.
* New: In Isobar::PyNet, add setAutomatic() and isAutomatic() to the
    interface.
* Bug: In Katana::protectRoutingPads(), do not create protections on
    PinOnly layers (mostly metal1).
This commit is contained in:
Jean-Paul Chaput 2018-01-10 12:45:00 +01:00
parent 95aba574a5
commit ba3ddafdf5
13 changed files with 149 additions and 98 deletions

View File

@ -397,7 +397,7 @@ namespace Anabatic {
bool Configuration::selectRpComponent ( RoutingPad* rp ) const
{
cdebug_log(145,1) << "selectRpComponent(): " << rp << endl;
cdebug_log(112,1) << "selectRpComponent(): " << rp << endl;
Box ab = rp->getCell()->getBoundingBox();
const Layer* metal1 = getLayerGauge( 0 )->getLayer();
@ -410,16 +410,17 @@ namespace Anabatic {
Segment* current = dynamic_cast<Segment*>( rp->getOccurrence().getEntity() );
if (current and (current->getLayer()->getMask() != metal1->getMask())) {
cdebug_log(145,0) << "> using default non-metal1 segment." << endl;
cdebug_tabw(145,-1);
cdebug_log(112,0) << "> using default non-metal1 segment." << endl;
cdebug_tabw(112,-1);
return true;
}
DbU::Unit bestSpan = 0;
Component* bestComponent = NULL;
cdebug_log(112,0) << "Looking into: " << masterNet->getCell() << endl;
for ( Component* component : masterNet->getComponents() ) {
cdebug_log(145,0) << "@ " << component << endl;
cdebug_log(112,0) << "@ " << component << endl;
if (not NetExternalComponents::isExternal(component)) continue;
Segment* segment = dynamic_cast<Segment*>(component);
@ -447,30 +448,27 @@ namespace Anabatic {
maxPos = bb.getYMax();
}
cdebug_log(145,0) << "| " << occurrence.getPath() << endl;
cdebug_log(145,0) << "| " << transformation << endl;
cdebug_log(145,0) << "| " << bb << " of:" << segment << endl;
cdebug_log(145,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
cdebug_log(112,0) << "| " << transformation << endl;
cdebug_log(112,0) << "| " << bb << " of:" << segment << endl;
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
if (not bestComponent) bestComponent = component;
else {
if (bestSpan < maxPos-minPos) {
bestComponent = component;
bestSpan = maxPos - minPos;
}
if (not bestComponent or (bestSpan > maxPos-minPos)) {
bestComponent = component;
bestSpan = maxPos - minPos;
}
}
}
if (bestComponent) {
rp->setExternalComponent( bestComponent );
cdebug_log(145,0) << "Using best candidate:" << bestComponent << endl;
cdebug_tabw(145,-1);
cdebug_log(112,0) << "Using best candidate:" << bestComponent << endl;
cdebug_tabw(112,-1);
return true;
}
cdebug_tabw(145,-1);
cdebug_tabw(112,-1);
return false;
}

View File

@ -1450,7 +1450,6 @@ namespace Anabatic {
vector<RoutingPad*> rps;
NetRoutingState* state = NetRoutingExtension::get( _net );
if (state){
if (state->isSelfSym()){

View File

@ -751,24 +751,24 @@ namespace Anabatic {
Interval hspan = getSide( Flags::Horizontal );
Interval vspan = getSide( Flags::Vertical );
if (hspan.getSize() < 3*side) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
" (%s)"
, DbU::getValueString(hspan.getSize()).c_str()
, getString(this).c_str()
) << endl;
Session::close();
return false;
}
// if (hspan.getSize() < 2*side) {
// cerr << Error( "GCell::doGrid(): GCell is too narrow (dx:%s) to build a grid.\n"
// " (%s)"
// , DbU::getValueString(hspan.getSize()).c_str()
// , getString(this).c_str()
// ) << endl;
// Session::close();
// return false;
// }
if (vspan.getSize() < 3*side) {
cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
" (%s)"
, DbU::getValueString(vspan.getSize()).c_str()
, getString(this).c_str()
) << endl;
return false;
}
// if (vspan.getSize() < 2*side) {
// cerr << Error( "GCell::doGrid(): GCell is too narrow (dy:%s) to build a grid.\n"
// " (%s)"
// , DbU::getValueString(vspan.getSize()).c_str()
// , getString(this).c_str()
// ) << endl;
// return false;
// }
GCell* row = this;
GCell* column = NULL;

View File

@ -451,6 +451,14 @@ namespace Anabatic {
const Layer* layer = anchor->getLayer();
cdebug_log(145,0) << "rp: " << rp << endl;
if (not layer) {
cerr << Error( "RoutingPad is still on it's Plug, routing will be incomplete.\n"
" %s"
, getString(anchor).c_str() )
<< endl;
continue;
}
if (layer->getMask() == Session::getRoutingLayer(0)->getMask()) _connexity.fields.M1++; // M1 V
else if (layer->getMask() == Session::getRoutingLayer(1)->getMask()) _connexity.fields.M2++; // M2 H
else if (layer->getMask() == Session::getRoutingLayer(2)->getMask()) _connexity.fields.M3++; // M3 V

View File

@ -238,7 +238,7 @@ namespace CRL {
}
unsigned int tracksNumber = getTrackNumber(start,stop);
if ( (unsigned)index >= tracksNumber ) {
if ( (unsigned)index > tracksNumber ) {
cdebug_tabw(100,-1);
return (tracksNumber > 0) ? tracksNumber-1 : 0;
// throw Error ( overflowIndex

View File

@ -1,7 +1,7 @@
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2017-2018, All Rights Reserved
// Copyright (c) UPMC 2017-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
@ -381,6 +381,8 @@ namespace {
blockageNet = Net::create( cell, "blockage" );
blockageNet->setType( Net::Type::BLOCKAGE );
}
//cerr << " @ _obstructionCbk: " << blockageNet->getName() << endl;
lefiGeometries* geoms = obstruction->geometries();
for ( int igeom=0 ; igeom < geoms->numItems() ; ++ igeom ) {
@ -393,21 +395,23 @@ namespace {
lefiGeomRect* r = geoms->getRect(igeom);
double w = r->xh - r->xl;
double h = r->yh - r->yl;
Segment* segment = NULL;
if (w >= h) {
Horizontal::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, parser->fromUnitsMicrons( h )
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
segment = Horizontal::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->yl + r->yh)/2 )
, parser->fromUnitsMicrons( h )
, parser->fromUnitsMicrons( r->xl )
, parser->fromUnitsMicrons( r->xh )
);
} else {
Vertical::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, parser->fromUnitsMicrons( w )
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
);
segment = Vertical::create( blockageNet, layer
, parser->fromUnitsMicrons( (r->xl + r->xh)/2 )
, parser->fromUnitsMicrons( w )
, parser->fromUnitsMicrons( r->yl )
, parser->fromUnitsMicrons( r->yh )
);
}
//cerr << " | " << segment << endl;
}
}
@ -440,7 +444,8 @@ namespace {
parser->_pinPostProcess();
parser->clearPinSegments();
cerr << " - " << cellName << " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << endl;
cerr << " - " << cellName
<< " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << "\n" << endl;
parser->setCell( NULL );
return 0;
@ -451,7 +456,7 @@ namespace {
{
LefParser* parser = (LefParser*)ud;
//cerr << " + _pinCbk: " << pin->name() << endl;
//cerr << " @ _pinCbk: " << pin->name() << endl;
if (not parser->getCell()) parser->setCell( Cell::create( parser->getLibrary(true), "LefImportTmpCell" ) );
@ -511,6 +516,7 @@ namespace {
);
}
if (segment) parser->addPinSegment( pin->name(), segment );
//cerr << " | " << segment << endl;
continue;
}
@ -550,6 +556,8 @@ namespace {
const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 );
Box ab = _cell->getAbutmentBox();
//cerr << " @ _pinPostProcess" << endl;
for ( auto element : _pinSegments ) {
string pinName = element.first;
vector<Segment*>& segments = element.second;
@ -558,6 +566,8 @@ namespace {
for ( Segment* segment : segments ) {
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
//cerr << " > " << segment << endl;
if (not segment->getNet()->isSupply()) {
if (isVH() and (segment->getLayer()->getMask() == metal1->getMask())) {
Vertical* v = dynamic_cast<Vertical*>( segment );
@ -571,6 +581,12 @@ namespace {
} else {
DbU::Unit neighbor = nearestX
+ ((nearestX > v->getX()) ? 1 : -1) * gaugeMetal2->getPitch();
//cerr << " | X:" << DbU::getValueString(v->getX())
// << " nearestX:" << DbU::getValueString(nearestX)
// << " neighbor:" << DbU::getValueString(neighbor)
// << endl;
if ( (v->getX() - v->getHalfWidth() > neighbor)
or (v->getX() + v->getHalfWidth() < neighbor) ) {
ongrids.push_back( Vertical::create( v->getNet()
@ -581,7 +597,7 @@ namespace {
, v->getDyTarget()
)
);
//cerr << " | " << ongrids[ongrids.size()-1] << endl;
} else {
// Unpitched and not wide enough to be under a metal2 track, ignore.
}

View File

@ -875,11 +875,13 @@ void Cell::flattenNets ( const Instance* instance, uint64_t flags )
if (deepNet) deepNet->_createRoutingPads( flags );
}
unsigned int rpFlags = (flags & Flags::StayOnPlugs) ? 0 : RoutingPad::BiggestArea;
for ( size_t i=0 ; i<topHyperNets.size() ; ++i ) {
Net* net = static_cast<Net*>(topHyperNets[i].getNetOccurrence().getEntity());
for ( Occurrence plugOccurrence : topHyperNets[i].getLeafPlugOccurrences() ) {
RoutingPad* rp = RoutingPad::create( net, plugOccurrence, RoutingPad::BiggestArea );
RoutingPad* rp = RoutingPad::create( net, plugOccurrence, rpFlags );
rp->materialize();
if (flags & Flags::WarnOnUnplacedInstances)

View File

@ -85,15 +85,16 @@ namespace Hurricane {
size_t DeepNet::_createRoutingPads ( unsigned int flags )
{
size_t nbRoutingPads = 0;
HyperNet hyperNet ( _netOccurrence );
RoutingPad* currentRp = NULL;
bool createRp = true;
size_t nbRoutingPads = 0;
HyperNet hyperNet ( _netOccurrence );
RoutingPad* currentRp = NULL;
bool createRp = true;
unsigned int rpFlags = (flags & Cell::Flags::StayOnPlugs) ? 0 : RoutingPad::BiggestArea;
for ( Occurrence occurrence : hyperNet.getComponentOccurrences() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>(occurrence.getEntity());
if ( rp and (rp->getCell() == getCell()) ) { createRp = false; break; }
if ( dynamic_cast<Segment* >(occurrence.getEntity()) ) { createRp = false; break; }
if ( dynamic_cast<Segment*>(occurrence.getEntity()) ) { createRp = false; break; }
}
if (not createRp) return 0;

View File

@ -100,6 +100,9 @@ namespace Hurricane {
throw Error( "Entity::Entity(): Identifier counter has reached it's limit (%d bits)."
, std::numeric_limits<unsigned int>::digits );
}
// if (_id == 75060)
// cerr << "Entity::Entity() " << this << endl;
}

View File

@ -74,28 +74,29 @@ class Cell : public Entity {
public: class Flags : public BaseFlags {
public:
enum Flag { NoFlags = 0x00000000
, BuildRings = 0x00000001
, BuildClockRings = 0x00000002
, BuildSupplyRings = 0x00000004
, NoClockFlatten = 0x00000008
, WarnOnUnplacedInstances = 0x00000010
enum Flag { NoFlags = (1 << 0)
, BuildRings = (1 << 1)
, BuildClockRings = (1 << 2)
, BuildSupplyRings = (1 << 3)
, NoClockFlatten = (1 << 4)
, WarnOnUnplacedInstances = (1 << 5)
, StayOnPlugs = (1 << 6)
, MaskRings = BuildRings|BuildClockRings|BuildSupplyRings
// Flags set for Observers.
, CellAboutToChange = 0x00000100
, CellChanged = 0x00000200
, CellDestroyed = 0x00000400
, CellAboutToChange = (1 << 10)
, CellChanged = (1 << 11)
, CellDestroyed = (1 << 12)
// Cell states
, Terminal = 0x00001000
, FlattenLeaf = 0x00002000
, Pad = 0x00004000
, Feed = 0x00008000
, FlattenedNets = 0x00010000
, Placed = 0x00020000
, Routed = 0x00040000
, MergedQuadTree = 0x00080000
, SlavedAb = 0x00100000
, Materialized = 0x00200000
, Terminal = (1 << 20)
, FlattenLeaf = (1 << 21)
, Pad = (1 << 22)
, Feed = (1 << 23)
, FlattenedNets = (1 << 24)
, Placed = (1 << 25)
, Routed = (1 << 26)
, MergedQuadTree = (1 << 27)
, SlavedAb = (1 << 28)
, Materialized = (1 << 29)
};
public:

View File

@ -48,11 +48,11 @@ namespace Hurricane {
class RoutingPad : public Component {
public:
typedef Component Inherit;
enum Flags { BiggestArea = 0x0001
, HighestLayer = 0x0002
, LowestLayer = 0x0004
enum Flags { BiggestArea = (1 << 0)
, HighestLayer = (1 << 1)
, LowestLayer = (1 << 2)
, ComponentSelection= BiggestArea|HighestLayer|LowestLayer
, ShowWarning = 0x0008
, ShowWarning = (1 << 4)
};
public:
static RoutingPad* create ( Net*, Occurrence, unsigned int flags=0 );

View File

@ -91,15 +91,17 @@ extern "C" {
DirectGetLongAttribute(PyNet_getY,getY,PyNet,Net)
// Standart Predicates (Attributes).
DirectGetBoolAttribute(PyNet_isGlobal ,isGlobal ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isExternal,isExternal,PyNet,Net)
DirectGetBoolAttribute(PyNet_isLogical ,isLogical ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isClock ,isClock ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isGround ,isGround ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isPower ,isPower ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isSupply ,isSupply ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isGlobal ,isGlobal ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isExternal ,isExternal ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isLogical ,isLogical ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isClock ,isClock ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isGround ,isGround ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isPower ,isPower ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isSupply ,isSupply ,PyNet,Net)
DirectGetBoolAttribute(PyNet_isAutomatic ,isAutomatic ,PyNet,Net)
DirectSetBoolAttribute(PyNet_setAutomatic,setAutomatic,PyNet,Net)
GetBoundStateAttribute(PyNet_IsPyBound ,PyNet,Net)
GetBoundStateAttribute(PyNet_IsPyBound,PyNet,Net)
GetNameMethod(Net, net)
// Standart modificators.
@ -456,9 +458,11 @@ extern "C" {
, { "isGround" , (PyCFunction)PyNet_isGround , METH_NOARGS , "return true if the net is a ground" }
, { "isSupply" , (PyCFunction)PyNet_isSupply , METH_NOARGS , "return true if the net is a supply" }
, { "isBound" , (PyCFunction)PyNet_IsPyBound , METH_NOARGS , "return true if the net is bounded to the hurricane net" }
, { "isAutomatic" , (PyCFunction)PyNet_isAutomatic , METH_NOARGS , "return true if the net is automatic (auto-generated)" }
, { "setName" , (PyCFunction)PyNet_setName , METH_VARARGS, "Allows to change net name." }
, { "setGlobal" , (PyCFunction)PyNet_setGlobal , METH_VARARGS, "set the net global." }
, { "setExternal" , (PyCFunction)PyNet_setExternal , METH_VARARGS, "set the net external." }
, { "setAutomatic" , (PyCFunction)PyNet_setAutomatic , METH_VARARGS, "declare the net as automatic (auto-generated)." }
, { "setType" , (PyCFunction)PyNet_setType , METH_VARARGS, "set the type of the net." }
, { "setDirection" , (PyCFunction)PyNet_setDirection , METH_VARARGS, "set the direction of the net." }
, { "setPosition" , (PyCFunction)PyNet_setPosition , METH_VARARGS, "set the X,Y location of the net." }

View File

@ -16,6 +16,7 @@
#include <map>
#include <list>
#include "hurricane/DebugSession.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/BasicLayer.h"
@ -42,6 +43,7 @@
namespace {
using namespace std;
using Hurricane::DebugSession;
using Hurricane::tab;
using Hurricane::ForEachIterator;
using Hurricane::DbU;
@ -68,30 +70,39 @@ namespace {
void protectRoutingPad ( RoutingPad* rp )
{
cdebug_log(145,1) << "::protectRoutingPad() " << rp << endl;
Name padNetName = "pad";
Component* usedComponent = rp->_getEntityAsComponent();
Path path = rp->getOccurrence().getPath();
Net* masterNet = usedComponent->getNet();
Transformation transformation = path.getTransformation();
if ( CatalogExtension::isPad(masterNet->getCell()) ) {
if (Session::getRoutingGauge()->getLayerType(usedComponent->getLayer()) == Constant::PinOnly) {
cdebug_tabw(145,-1);
return;
}
cdebug_log(145,0) << "masterCell: " << masterNet->getCell() << endl;
cdebug_log(145,0) << "masterNet: " << masterNet << endl;
if (CatalogExtension::isPad(masterNet->getCell())) {
if ( rp->getNet()->isPower()
or (rp->getNet()->getName() == padNetName) )
cdebug_tabw(145,-1);
return;
}
vector<Segment*> segments;
for( Segment* segment : masterNet->getSegments() ) {
for ( Segment* segment : masterNet->getSegments() ) {
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(segment->getLayer());
if ( plane == NULL ) continue;
if (not plane) continue;
if ( usedComponent == dynamic_cast<Component*>(segment) ) continue;
if ( not NetExternalComponents::isExternal(segment) ) continue;
if (usedComponent == dynamic_cast<Component*>(segment)) continue;
if (not NetExternalComponents::isExternal(segment)) continue;
//cerr << "Looking " << (void*)*isegment << ":" << *isegment << endl;
segments.push_back ( segment );
segments.push_back( segment );
}
for ( size_t i=0 ; i<segments.size() ; ++i ) {
@ -105,7 +116,8 @@ namespace {
Box bb ( segments[i]->getBoundingBox() );
transformation.applyOn ( bb );
//cinfo << "bb: " << bb << endl;
cdebug_log(145,0) << "@ " << segments[i] << " bb:" << bb << endl;
if ( direction == Flags::Horizontal ) {
DbU::Unit axisMin = bb.getYMin() - delta;
@ -121,6 +133,7 @@ namespace {
, bb.getXMax()-extension
);
TrackFixedSegment::create ( track, segment );
cdebug_log(145,0) << "| " << segment << endl;
}
} else {
DbU::Unit axisMin = bb.getXMin() - delta;
@ -136,9 +149,11 @@ namespace {
, bb.getYMax()-extension
);
TrackFixedSegment::create ( track, segment );
cdebug_log(145,0) << "| " << segment << endl;
}
}
}
cdebug_tabw(145,-1);
}
@ -163,6 +178,8 @@ namespace Katana {
for ( Net* net : getCell()->getNets() ) {
if (net->isSupply()) continue;
DebugSession::open( net, 140, 150 );
NetData* data = getNetData( net );
if (data and data->isFixed()) continue;
@ -173,6 +190,8 @@ namespace Katana {
for ( size_t i=0 ; i<rps.size() ; ++i )
protectRoutingPad( rps[i] );
DebugSession::close();
}
Session::close();