Etesian integration with Chip & ClockTree plugins.
* New: In Hurricane, in DebugSession, add a new method to activate the trace inconditionally with a certain level. * New: In Hurricane, in HyperNet, allow copy construction as there is no reason to disallow it and we need it now. * New: In Hurricane, in Cell::flattenNets(), add a new option to prevent the flattening of the clock net(s). For more safety perform the DeepNet creation *outside* the Collection loop. * Bug: In Hurricane, in Cell_HyperNetRootNetOccurrences, skip the DeepNets because they are the result of another flattening operation. * New: In Isobar, in PyBasicLayer, export C++ method getBlockageLayer(). * New: In Isobar, in PyRoutingGauge, export C++ method getLayerPitch(), needed by Cumulus plugins. * New: In Etesian, EtesianEngine::findYSpin() to look for the Y orientation if some cells are already placed. Typically the buffers of a clock tree. Pass the correct orienation to row_compatible_orientation(). Do not try to add feeds in the ISPD05 benchmarks. For now the benchmarks are detected through their names (unreliable). * Change: In Knik, in KnikEngine::initGlobalRouting(), allow the clock to be routed as an ordinary signal when the clock tree is not used. * New: In Kite, in BuildPowerRails, management & detection for the pre-routed clock. In KiteEngine constructor, early initialization of the blockage net to avoid later troubles in BuildPowerRails. * New: In Cumulus, in ChipPlugin, add support for Etesian plus new configuration parameter 'clockTree.placerEngine' to select between Mauka and Etesian. * New: In Cumulus, in BlockCorona, add blockages in the vertical sides in the vertical layer to prevent the router to use the vertical tracks in under the prower lines (for example, blockage in M3 with power line M5). In Cumulus, in ChipConf add attribute to access the blockage net. * New: In Cumulus, when the clock tree is disabled, do not generate the last rail around the block (the clock rail). * Bug: In Cumulus, in ChipConf use the clock pad to guess the clock signals and *not* the power pad. Add more meaningful error messages if a pad global signal is not found (implicit connexion by name). * Bug: In Cumulus, in ClockTree, compute correctly the cells Y spin, that is *from the bottom of the cell AB* (not from 'zero').
This commit is contained in:
parent
3b343f08cf
commit
6d366a08bc
|
@ -216,6 +216,37 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getLayerPitch ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
trace << "PyRoutingGauge_getLayerPitch()" << endl;
|
||||
|
||||
DbU::Unit pitch = 0;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD("RoutingGauge.getLayerPitch()")
|
||||
|
||||
PyObject* arg0 = NULL;
|
||||
|
||||
__cs.init ("RoutingGauge.getLayerPitch");
|
||||
if (PyArg_ParseTuple( args, "O&:RoutingGauge.getLayerPitch", Converter, &arg0)) {
|
||||
if ( __cs.getObjectIds() == ":layer" ) {
|
||||
//pitch = rg->getLayerPitch( PYLAYER_O(arg0) );
|
||||
} else if ( __cs.getObjectIds() == ":int" )
|
||||
pitch = rg->getLayerPitch( (size_t)PyAny_AsLong(arg0) );
|
||||
else {
|
||||
PyErr_SetString ( ConstructorError, "invalid parameter type for RoutingGauge.getLayerPitch()." );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError, "Invalid number of parameters passed to RoutingGauge.getLayerPitch()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
return Py_BuildValue("I",pitch);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyRoutingGauge_getRoutingLayer ( PyRoutingGauge* self, PyObject* args )
|
||||
{
|
||||
trace << "PyRoutingGauge_getRoutingLayer()" << endl;
|
||||
|
@ -318,6 +349,8 @@ extern "C" {
|
|||
, "Return the RoutingLayerGauge of the given layer/depth." }
|
||||
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection, METH_VARARGS
|
||||
, "Return the direction of the given layer/depth." }
|
||||
, { "getLayerPitch" , (PyCFunction)PyRoutingGauge_getLayerPitch , METH_VARARGS
|
||||
, "Return the pitch of the given layer/depth." }
|
||||
, { "getRoutingLayer" , (PyCFunction)PyRoutingGauge_getRoutingLayer , METH_VARARGS
|
||||
, "Return the routing layer used for the requested depth." }
|
||||
, { "getContactLayer" , (PyCFunction)PyRoutingGauge_getContactLayer , METH_VARARGS
|
||||
|
|
|
@ -48,6 +48,7 @@ try:
|
|||
import Nimbus
|
||||
import Metis
|
||||
import Mauka
|
||||
import Etesian
|
||||
import Katabatic
|
||||
import Kite
|
||||
import Unicorn
|
||||
|
@ -140,17 +141,28 @@ class PlaceCore ( chip.Configuration.ChipConfWrapper ):
|
|||
if self.useClockTree and ckCore:
|
||||
ht = clocktree.ClockTree.HTree.create( self, coreCell, ckCore, coreCell.getAbutmentBox() )
|
||||
ht.addCloned( self.cell )
|
||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||
mauka.run()
|
||||
mauka.destroy()
|
||||
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
|
||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||
mauka.run()
|
||||
mauka.destroy()
|
||||
else:
|
||||
etesian = Etesian.EtesianEngine.create( coreCell )
|
||||
etesian.place( Etesian.EtesianEngine.SlowMotion )
|
||||
etesian.destroy()
|
||||
|
||||
ht.connectLeaf()
|
||||
ht.prune()
|
||||
#ht.prune()
|
||||
ht.route()
|
||||
ht.save( self.cell )
|
||||
else:
|
||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||
mauka.run()
|
||||
mauka.destroy()
|
||||
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
|
||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||
mauka.run()
|
||||
mauka.destroy()
|
||||
else:
|
||||
etesian = Etesian.EtesianEngine.create( coreCell )
|
||||
etesian.place( Etesian.EtesianEngine.SlowMotion )
|
||||
etesian.destroy()
|
||||
return
|
||||
|
||||
|
||||
|
|
|
@ -121,6 +121,18 @@ class StackedVia ( object ):
|
|||
if depth > self._topDepth: self._topDepth = depth
|
||||
return
|
||||
|
||||
def getLayer ( self, fromTop ):
|
||||
if self._topDepth-fromTop >= self._bottomDepth:
|
||||
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
|
||||
return routingGauge.getRoutingLayer(self._topDepth-fromTop)
|
||||
return None
|
||||
|
||||
def getBlockageLayer ( self, fromTop ):
|
||||
if self._topDepth-fromTop >= self._bottomDepth:
|
||||
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
|
||||
return routingGauge.getRoutingLayer(self._topDepth-fromTop).getBlockageLayer()
|
||||
return None
|
||||
|
||||
def getVia ( self, metal ):
|
||||
if not self._hasLayout: return None
|
||||
for via in self._vias:
|
||||
|
|
|
@ -150,7 +150,7 @@ class VerticalRail ( Rail ):
|
|||
, via[2].getY()
|
||||
, via[2].getHeight()
|
||||
)
|
||||
railVias.append( via[1].getVia( self.side.getVLayer()) )
|
||||
railVias.append( via[1].getVia(self.side.getVLayer()) )
|
||||
|
||||
railVias.sort( key=methodcaller('getY') )
|
||||
|
||||
|
@ -161,6 +161,21 @@ class VerticalRail ( Rail ):
|
|||
, self.axis
|
||||
, self.side.vRailWidth
|
||||
)
|
||||
|
||||
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
|
||||
for depth in range(self.side.verticalDepth-2,self.vias.values()[0][1]._bottomDepth,-2):
|
||||
blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer()
|
||||
pitch = routingGauge.getLayerPitch(depth)
|
||||
|
||||
for i in range(1,len(railVias)):
|
||||
Vertical.create( self.side.blockageNet
|
||||
, blockageLayer
|
||||
, self.axis
|
||||
, self.side.vRailWidth
|
||||
, railVias[i-1].getBoundingBox().getYMax() + pitch
|
||||
, railVias[i ].getBoundingBox().getYMin() - pitch
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
def connect ( self, contact ):
|
||||
|
@ -224,25 +239,31 @@ class Side ( object ):
|
|||
return
|
||||
|
||||
@property
|
||||
def railsNb ( self ): return self._corona._railsNb
|
||||
@property
|
||||
def innerBb ( self ): return self._corona._innerBb
|
||||
@property
|
||||
def hRailWidth ( self ): return self._corona._hRailWidth
|
||||
@property
|
||||
def hRailSpace ( self ): return self._corona._hRailSpace
|
||||
@property
|
||||
def vRailWidth ( self ): return self._corona._vRailWidth
|
||||
@property
|
||||
def vRailSpace ( self ): return self._corona._vRailSpace
|
||||
@property
|
||||
def corners ( self ): return self._corona._corners
|
||||
def railsNb ( self ): return self._corona._railsNb
|
||||
@property
|
||||
def innerBb ( self ): return self._corona._innerBb
|
||||
@property
|
||||
def hRailWidth ( self ): return self._corona._hRailWidth
|
||||
@property
|
||||
def hRailSpace ( self ): return self._corona._hRailSpace
|
||||
@property
|
||||
def vRailWidth ( self ): return self._corona._vRailWidth
|
||||
@property
|
||||
def vRailSpace ( self ): return self._corona._vRailSpace
|
||||
@property
|
||||
def corners ( self ): return self._corona._corners
|
||||
@property
|
||||
def horizontalDepth ( self ): return self._corona.horizontalDepth
|
||||
@property
|
||||
def verticalDepth ( self ): return self._corona.verticalDepth
|
||||
@property
|
||||
def blockageNet ( self ): return self._corona.blockageNet
|
||||
|
||||
def getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal)
|
||||
def getRail ( self, i ): return self._rails[i]
|
||||
def getRailNet ( self, i ): return self._corona.getRailNet(i)
|
||||
def getHLayer ( self ): return self._corona.getHLayer()
|
||||
def getVLayer ( self ): return self._corona.getVLayer()
|
||||
def getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal)
|
||||
def getRail ( self, i ): return self._rails[i]
|
||||
def getRailNet ( self, i ): return self._corona.getRailNet(i)
|
||||
def getHLayer ( self ): return self._corona.getHLayer()
|
||||
def getVLayer ( self ): return self._corona.getVLayer()
|
||||
|
||||
def getRailAxis ( self, i ):
|
||||
raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' )
|
||||
|
@ -306,7 +327,7 @@ class SouthSide ( HorizontalSide ):
|
|||
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
|
||||
- i*(self.hRailWidth + self.hRailSpace)
|
||||
|
||||
def corner0 ( self, i ): return self.corners[chip.SouthWest ][i]
|
||||
def corner0 ( self, i ): return self.corners[chip.SouthWest][i]
|
||||
def corner1 ( self, i ): return self.corners[chip.SouthEast][i]
|
||||
|
||||
|
||||
|
@ -379,6 +400,8 @@ class Corona ( object ):
|
|||
self._innerBb = self._block.bb
|
||||
self._block.path.getTransformation().applyOn( self._innerBb )
|
||||
self._innerBb.inflate( self._hRailSpace/2, self._vRailSpace/2 )
|
||||
|
||||
if not self.useClockTree: self._railsNb -= 1
|
||||
|
||||
self._southSide = SouthSide( self )
|
||||
self._northSide = NorthSide( self )
|
||||
|
@ -387,6 +410,8 @@ class Corona ( object ):
|
|||
|
||||
return
|
||||
|
||||
@property
|
||||
def useClockTree ( self ): return self._block.useClockTree
|
||||
@property
|
||||
def routingGauge ( self ): return self._block.routingGauge
|
||||
@property
|
||||
|
@ -395,12 +420,14 @@ class Corona ( object ):
|
|||
def horizontalDepth ( self ): return self._block.horizontalDepth
|
||||
@property
|
||||
def verticalDepth ( self ): return self._block.verticalDepth
|
||||
@property
|
||||
def blockageNet ( self ): return self._block.blockageNet
|
||||
|
||||
def getLayerDepth ( self, metal ):
|
||||
return self.routingGauge.getLayerDepth( metal )
|
||||
|
||||
def getRailNet ( self, i ):
|
||||
if i == self._railsNb-1: return self._block.cko
|
||||
if self.useClockTree and i == self._railsNb-1: return self._block.cko
|
||||
if i % 2: return self._block.vssi
|
||||
return self._block.vddi
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ class Block ( chip.Configuration.ChipConfWrapper ):
|
|||
|
||||
def connectClock ( self ):
|
||||
if not self.useClockTree:
|
||||
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False) ignored." )
|
||||
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
|
||||
return
|
||||
|
||||
if not self.cko:
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import sys
|
||||
import os.path
|
||||
import Cfg
|
||||
from Hurricane import Breakpoint
|
||||
from Hurricane import DbU
|
||||
from Hurricane import Box
|
||||
from Hurricane import Transformation
|
||||
|
@ -433,13 +434,14 @@ class ChipConf ( object ):
|
|||
|
||||
|
||||
def _guessGlobalNet ( self, name, net ):
|
||||
if name == self._vddeName: self._vdde = net
|
||||
if name == self._vddiName: self._vddi = net
|
||||
if name == self._vsseName: self._vsse = net
|
||||
if name == self._vssiName: self._vssi = net
|
||||
if name == self._ckiName: self._cki = net
|
||||
if name == self._ckoName: self._cko = net
|
||||
if name == self._ckName: self._ck = net
|
||||
if name == self._vddeName: self._vdde = net
|
||||
if name == self._vddiName: self._vddi = net
|
||||
if name == self._vsseName: self._vsse = net
|
||||
if name == self._vssiName: self._vssi = net
|
||||
if name == self._ckiName: self._cki = net
|
||||
if name == self._ckoName: self._cko = net
|
||||
if name == self._ckName: self._ck = net
|
||||
if name == self._blockageName: self._blockageNet = net
|
||||
return
|
||||
|
||||
|
||||
|
@ -469,6 +471,7 @@ class ChipConf ( object ):
|
|||
self._ckiName = "ck"
|
||||
self._ckoName = "cko"
|
||||
self._ckName = "pad"
|
||||
self._blockageName = "blockagenet"
|
||||
# Global Nets.
|
||||
self._vdde = None
|
||||
self._vddi = None
|
||||
|
@ -477,6 +480,7 @@ class ChipConf ( object ):
|
|||
self._cki = None
|
||||
self._cko = None
|
||||
self._ck = None
|
||||
self._blockageNet = None
|
||||
|
||||
self._clockPad = None
|
||||
self._powerPad = None
|
||||
|
@ -553,10 +557,10 @@ class ChipConf ( object ):
|
|||
self._guessGlobalNet( masterNet.getName(), net )
|
||||
|
||||
if self._clockPad:
|
||||
for plug in self._powerPad.getPlugs():
|
||||
for plug in self._clockPad.getPlugs():
|
||||
masterNet = plug.getMasterNet()
|
||||
netType = masterNet.getType()
|
||||
net = plug.getNet()
|
||||
net = plug.getNet()
|
||||
|
||||
if not net:
|
||||
net = self._cell.getNet( masterNet.getName() )
|
||||
|
@ -567,6 +571,22 @@ class ChipConf ( object ):
|
|||
|
||||
if masterNet.getName() == self._ckName:
|
||||
self._guessGlobalNet( masterNet.getName(), net )
|
||||
|
||||
for netData in ( (self._vddeName,self._vdde,'pad ring external power')
|
||||
, (self._vddiName,self._vddi,'pad ring internal power')
|
||||
, (self._vsseName,self._vsse,'pad ring external ground')
|
||||
, (self._vssiName,self._vssi,'pad ring external ground')
|
||||
, (self._ckiName ,self._cki ,'pad ring inner clock')
|
||||
, (self._ckoName ,self._cko ,'core clock')
|
||||
, (self._ckName ,self._ck ,'external chip clock')
|
||||
):
|
||||
if not netData[1]:
|
||||
print ErrorMessage( 1, 'Missing global net <%s> (%s) at chip level.' % (netData[0],netData[2]) )
|
||||
self._validated = False
|
||||
|
||||
self._blockageNet = self._cell.getNet(self._blockageName)
|
||||
if not self._blockageNet:
|
||||
self._blockageNet = Net.create( self._cell, self._blockageName )
|
||||
return
|
||||
|
||||
|
||||
|
@ -653,19 +673,21 @@ class ChipConfWrapper ( GaugeConfWrapper ):
|
|||
|
||||
# Global Nets.
|
||||
@property
|
||||
def vdde ( self ): return self._chipConf._vdde
|
||||
def vdde ( self ): return self._chipConf._vdde
|
||||
@property
|
||||
def vsse ( self ): return self._chipConf._vsse
|
||||
@property
|
||||
def vddi ( self ): return self._chipConf._vddi
|
||||
@property
|
||||
def vssi ( self ): return self._chipConf._vssi
|
||||
@property
|
||||
def cki ( self ): return self._chipConf._cki
|
||||
@property
|
||||
def cko ( self ): return self._chipConf._cko
|
||||
@property
|
||||
def ck ( self ): return self._chipConf._ck
|
||||
@property
|
||||
def vsse ( self ): return self._chipConf._vsse
|
||||
@property
|
||||
def vddi ( self ): return self._chipConf._vddi
|
||||
@property
|
||||
def vssi ( self ): return self._chipConf._vssi
|
||||
@property
|
||||
def cki ( self ): return self._chipConf._cki
|
||||
@property
|
||||
def cko ( self ): return self._chipConf._cko
|
||||
@property
|
||||
def ck ( self ): return self._chipConf._ck
|
||||
def blockageNet ( self ): return self._chipConf._blockageNet
|
||||
|
||||
# Various.
|
||||
@property
|
||||
|
|
|
@ -181,7 +181,8 @@ class Side ( object ):
|
|||
#print 'Power pad:', pad
|
||||
self._createPowerContacts( pad, self._corona.vddi )
|
||||
self._createPowerContacts( pad, self._corona.vssi )
|
||||
self._createPowerContacts( pad, self._corona.cko )
|
||||
if self._corona.useClockTree:
|
||||
self._createPowerContacts( pad, self._corona.cko )
|
||||
return
|
||||
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ class HTree ( GaugeConfWrapper ):
|
|||
yslice = self.toYCellGrid(y)
|
||||
|
||||
transformation = Transformation.Orientation.ID
|
||||
if (yslice / self.cellGauge.getSliceHeight()) % 2 != 0:
|
||||
if ((yslice-self.area.getYMin()) / self.cellGauge.getSliceHeight()) % 2 != 0:
|
||||
transformation = Transformation.Orientation.MY
|
||||
yslice += self.cellGauge.getSliceHeight()
|
||||
|
||||
|
@ -505,7 +505,7 @@ class HTreeNode ( object ):
|
|||
return
|
||||
|
||||
def route ( self ):
|
||||
if not self.hasLeafs(): return
|
||||
trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() )
|
||||
|
||||
leftSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
rightSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
|
@ -527,7 +527,7 @@ class HTreeNode ( object ):
|
|||
|
||||
def connectLeafs ( self ):
|
||||
if not self.hasLeafs():
|
||||
trace( 550, '\tHTree %s has no leafs\n' % self.sourceBuffer.getName() )
|
||||
trace( 550, '\tHTreeNode.connectLeafs() %s has no leafs\n' % self.sourceBuffer.getName() )
|
||||
|
||||
if self.childs:
|
||||
self.childs[0].connectLeafs()
|
||||
|
|
|
@ -304,14 +304,67 @@ namespace Etesian {
|
|||
using Hurricane::Occurrence;
|
||||
|
||||
|
||||
size_t EtesianEngine::findYSpin ()
|
||||
{
|
||||
_flags &= ~YSpinSet;
|
||||
_yspinSlice0 = 0;
|
||||
|
||||
Box topCellAb = getCell()->getAbutmentBox();
|
||||
|
||||
if (not topCellAb.isEmpty()) {
|
||||
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
|
||||
{
|
||||
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
||||
Cell* masterCell = instance->getMasterCell();
|
||||
Box instanceAb = masterCell->getAbutmentBox();
|
||||
Transformation instanceTransf = instance->getTransformation();
|
||||
|
||||
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
|
||||
instanceTransf.applyOn( instanceAb );
|
||||
|
||||
if (not topCellAb.contains(instanceAb)) continue;
|
||||
|
||||
_flags |= YSpinSet;
|
||||
|
||||
int islice = (instanceAb.getYMin() - getCell()->getAbutmentBox().getYMin()) / getSliceHeight();
|
||||
|
||||
switch ( instanceTransf.getOrientation() ) {
|
||||
case Transformation::Orientation::ID:
|
||||
case Transformation::Orientation::MX:
|
||||
_yspinSlice0 = (islice % 2);
|
||||
break;
|
||||
case Transformation::Orientation::R2:
|
||||
case Transformation::Orientation::MY:
|
||||
_yspinSlice0 = ((islice+1) % 2);
|
||||
break;
|
||||
case Transformation::Orientation::R1:
|
||||
case Transformation::Orientation::R3:
|
||||
case Transformation::Orientation::XR:
|
||||
case Transformation::Orientation::YR:
|
||||
cerr << Warning( "Instance %s has invalid transformation %s."
|
||||
, getString(instance->getName()).c_str()
|
||||
, getString(instanceTransf.getOrientation()).c_str()
|
||||
) << endl;
|
||||
_flags &= ~YSpinSet;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_flags & YSpinSet) break;
|
||||
}
|
||||
}
|
||||
|
||||
return _yspinSlice0;
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::addFeeds ()
|
||||
{
|
||||
UpdateSession::open();
|
||||
|
||||
bool yspinSet = false;
|
||||
size_t yspinSlice0 = 0;
|
||||
SliceHoles sliceHoles ( this );
|
||||
Box toCellAb = getCell()->getAbutmentBox();
|
||||
SliceHoles sliceHoles ( this );
|
||||
Box topCellAb = getCell()->getAbutmentBox();
|
||||
|
||||
sliceHoles.setSpinSlice0( _yspinSlice0 );
|
||||
|
||||
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
|
||||
{
|
||||
|
@ -329,41 +382,12 @@ namespace Etesian {
|
|||
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
|
||||
instanceTransf.applyOn( instanceAb );
|
||||
|
||||
if (not toCellAb.contains(instanceAb)) {
|
||||
if (not topCellAb.contains(instanceAb)) {
|
||||
cerr << Warning( "Instance %s is not fully enclosed in the top cell."
|
||||
, getString(instance->getName()).c_str() ) << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (not yspinSet) {
|
||||
yspinSet = true;
|
||||
|
||||
int islice = (instanceAb.getYMin() - getCell()->getAbutmentBox().getYMin()) / getSliceHeight();
|
||||
|
||||
switch ( instanceTransf.getOrientation() ) {
|
||||
case Transformation::Orientation::ID:
|
||||
case Transformation::Orientation::MX:
|
||||
yspinSlice0 = (islice % 2);
|
||||
break;
|
||||
case Transformation::Orientation::R2:
|
||||
case Transformation::Orientation::MY:
|
||||
yspinSlice0 = ((islice+1) % 2);
|
||||
break;
|
||||
case Transformation::Orientation::R1:
|
||||
case Transformation::Orientation::R3:
|
||||
case Transformation::Orientation::XR:
|
||||
case Transformation::Orientation::YR:
|
||||
cerr << Warning( "Instance %s has invalid transformation %s."
|
||||
, getString(instance->getName()).c_str()
|
||||
, getString(instanceTransf.getOrientation()).c_str()
|
||||
) << endl;
|
||||
yspinSet = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sliceHoles.setSpinSlice0( yspinSlice0 );
|
||||
}
|
||||
|
||||
sliceHoles.merge( instanceAb );
|
||||
}
|
||||
|
||||
|
|
|
@ -284,10 +284,16 @@ namespace Etesian {
|
|||
|
||||
void EtesianEngine::_postCreate ()
|
||||
{
|
||||
// Ugly. Direct uses of Alliance Framework.
|
||||
// Must change toward something in the settings.
|
||||
_feedCells.useFeed( AllianceFramework::get()->getCell("tie_x0" ,Catalog::State::Views) );
|
||||
_feedCells.useFeed( AllianceFramework::get()->getCell("rowend_x0",Catalog::State::Views) );
|
||||
// Ugly: Name based detection of ISPD benchmarks.
|
||||
if (getString(getCell()->getName()).substr(0,7) == "bigblue") {
|
||||
cmess1 << " o ISPD benchmark <" << getCell()->getName()
|
||||
<< ">, no feed cells will be added." << endl;
|
||||
} else {
|
||||
// Ugly: Direct uses of Alliance Framework.
|
||||
// Must change toward something in the settings.
|
||||
_feedCells.useFeed( AllianceFramework::get()->getCell("tie_x0" ,Catalog::State::Views) );
|
||||
_feedCells.useFeed( AllianceFramework::get()->getCell("rowend_x0",Catalog::State::Views) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -469,14 +475,14 @@ namespace Etesian {
|
|||
DbU::Unit pitch = getPitch();
|
||||
|
||||
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
|
||||
getCell()->flattenNets( Cell::BuildRings );
|
||||
getCell()->flattenNets( Cell::BuildRings|Cell::NoClockFlatten );
|
||||
|
||||
// Coloquinte circuit description data-structures.
|
||||
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
|
||||
vector<Transformation> idsToTransf ( instancesNb );
|
||||
vector<temporary_cell> instances ( instancesNb );
|
||||
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
|
||||
vector<Transformation> idsToTransf ( instancesNb );
|
||||
vector<temporary_cell> instances ( instancesNb );
|
||||
vector< point<int_t> > positions ( instancesNb );
|
||||
vector< point<bool> > orientations( instancesNb, point<bool>(true, true) );
|
||||
vector< point<bool> > orientations( instancesNb, point<bool>(true, true) );
|
||||
|
||||
cmess1 << " - Converting " << instancesNb << " instances" << endl;
|
||||
cout.flush();
|
||||
|
@ -614,6 +620,7 @@ namespace Etesian {
|
|||
|
||||
if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb();
|
||||
|
||||
findYSpin();
|
||||
toColoquinte();
|
||||
|
||||
cmess1 << " o Running Coloquinte." << endl;
|
||||
|
@ -740,7 +747,7 @@ namespace Etesian {
|
|||
_progressReport1( startTime, " Local Swaps ...." );
|
||||
|
||||
if (i == legalizeIterations-1) {
|
||||
row_compatible_orientation( _circuit, legalizer, true );
|
||||
row_compatible_orientation( _circuit, legalizer, (_yspinSlice0 == 0) );
|
||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||
_progressReport1( startTime, " Final Legalize ." );
|
||||
}
|
||||
|
@ -822,7 +829,6 @@ namespace Etesian {
|
|||
{
|
||||
Point instancePosition;
|
||||
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
||||
//Cell* masterCell = instance->getMasterCell();
|
||||
string instanceName = (*ioccurrence).getCompactString();
|
||||
// Remove the enclosing brackets...
|
||||
instanceName.erase( 0, 1 );
|
||||
|
@ -832,23 +838,15 @@ namespace Etesian {
|
|||
if (iid == _cellsToIds.end() ) {
|
||||
cerr << Error( "Unable to lookup instance <%s>.", instanceName.c_str() ) << endl;
|
||||
} else {
|
||||
point<int_t> position = placement.positions_[(*iid).second];
|
||||
|
||||
/*
|
||||
if ( isNan(position.x_) or isNan(position.y_) ) {
|
||||
cerr << Error( "Instance <%s> is not placed yet (position == NaN)."
|
||||
, instanceName.c_str() ) << endl;
|
||||
instance->setPlacementStatus( Instance::PlacementStatus::UNPLACED );
|
||||
if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED)
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
Transformation trans = toTransformation( position
|
||||
, placement.orientations_[(*iid).second]
|
||||
, instance->getMasterCell()
|
||||
, getPitch()
|
||||
);
|
||||
|
||||
point<int_t> position = placement.positions_[(*iid).second];
|
||||
Transformation trans = toTransformation( position
|
||||
, placement.orientations_[(*iid).second]
|
||||
, instance->getMasterCell()
|
||||
, getPitch()
|
||||
);
|
||||
//cerr << "Setting <" << instanceName << " @" << instancePosition << endl;
|
||||
|
||||
// This is temporary as it's not trans-hierarchic: we ignore the posutions
|
||||
|
|
|
@ -55,7 +55,8 @@ namespace Etesian {
|
|||
enum Flag { NoPlacement=0x0001
|
||||
, FlatDesign =0x0002
|
||||
, ForceUpdate=0x0004
|
||||
, SlowMotion =0x0008
|
||||
, YSpinSet =0x0008
|
||||
, SlowMotion =0x0010
|
||||
};
|
||||
public:
|
||||
static const Name& staticGetName ();
|
||||
|
@ -79,6 +80,7 @@ namespace Etesian {
|
|||
void toColoquinte ();
|
||||
void place ( unsigned int flags=SlowMotion );
|
||||
inline void useFeed ( Cell* );
|
||||
size_t findYSpin ();
|
||||
void addFeeds ();
|
||||
virtual Record* _getRecord () const;
|
||||
virtual std::string _getString () const;
|
||||
|
@ -99,6 +101,7 @@ namespace Etesian {
|
|||
std::vector<Instance*> _idsToInsts;
|
||||
Hurricane::CellWidget* _cellWidget;
|
||||
FeedCells _feedCells;
|
||||
size_t _yspinSlice0;
|
||||
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace Etesian {
|
|||
class FeedCells {
|
||||
public:
|
||||
inline FeedCells ( EtesianEngine* );
|
||||
inline size_t feedNumbers () const;
|
||||
void useFeed ( Cell* );
|
||||
Cell* getBiggestFeed () const;
|
||||
Cell* getSmallestFeed () const;
|
||||
|
@ -50,6 +51,9 @@ namespace Etesian {
|
|||
{ }
|
||||
|
||||
|
||||
inline size_t FeedCells::feedNumbers () const { return _feedCells.size(); }
|
||||
|
||||
|
||||
} // Etesian namespace.
|
||||
|
||||
#endif // ETESIAN_FEEDCELLS_H
|
||||
|
|
|
@ -192,29 +192,29 @@ void Cell::setAbutmentBox(const Box& abutmentBox)
|
|||
void Cell::flattenNets(unsigned int flags)
|
||||
// ***************************************
|
||||
{
|
||||
trace << "Cell::flattenNets() flags:0x" << hex << flags << endl;
|
||||
|
||||
UpdateSession::open();
|
||||
|
||||
_flags |= FlattenedNets;
|
||||
|
||||
vector<HyperNet> hyperNets;
|
||||
vector<HyperNet> topHyperNets;
|
||||
|
||||
forEach ( Occurrence, ioccurrence, getHyperNetRootNetOccurrences() ) {
|
||||
Net* net = static_cast<Net*>((*ioccurrence).getEntity());
|
||||
|
||||
if (net->isClock() and (flags & NoClockFlatten)) continue;
|
||||
|
||||
HyperNet hyperNet ( *ioccurrence );
|
||||
if ( not (*ioccurrence).getPath().isEmpty() ) {
|
||||
DeepNet* deepNet = DeepNet::create( hyperNet );
|
||||
if (deepNet) deepNet->_createRoutingPads( flags );
|
||||
} else {
|
||||
RoutingPad* previousRp = NULL;
|
||||
RoutingPad* currentRp = NULL;
|
||||
bool buildRing = false;
|
||||
|
||||
if (net->isGlobal()) {
|
||||
if ( (flags & Cell::BuildClockRings ) and net->isClock () ) buildRing = true;
|
||||
else if ( (flags & Cell::BuildSupplyRings) and net->isSupply() ) buildRing = true;
|
||||
Net* duplicate = getNet( (*ioccurrence).getName() );
|
||||
if (not duplicate) {
|
||||
hyperNets.push_back( HyperNet(*ioccurrence) );
|
||||
} else {
|
||||
buildRing = flags & Cell::BuildRings;
|
||||
cerr << "Found " << duplicate << " in " << duplicate->getCell() << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
bool hasRoutingPads = false;
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( *icomponent );
|
||||
|
@ -228,51 +228,72 @@ void Cell::flattenNets(unsigned int flags)
|
|||
}
|
||||
if (hasRoutingPads) continue;
|
||||
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
Plug* primaryPlug = dynamic_cast<Plug*>( *icomponent );
|
||||
if (primaryPlug) {
|
||||
if ( !primaryPlug->getBodyHook()->getSlaveHooks().isEmpty() ) {
|
||||
cerr << "[ERROR] " << primaryPlug << "\n"
|
||||
<< " has attached components, not managed yet." << endl;
|
||||
} else {
|
||||
primaryPlug->getBodyHook()->detach();
|
||||
}
|
||||
topHyperNets.push_back( HyperNet(*ioccurrence) );
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i=0 ; i<hyperNets.size() ; ++i ) {
|
||||
DeepNet* deepNet = DeepNet::create( hyperNets[i] );
|
||||
if (deepNet) deepNet->_createRoutingPads( flags );
|
||||
}
|
||||
|
||||
for ( size_t i=0 ; i<topHyperNets.size() ; ++i ) {
|
||||
Net* net = static_cast<Net*>(topHyperNets[i].getNetOccurrence().getEntity());
|
||||
RoutingPad* previousRp = NULL;
|
||||
RoutingPad* currentRp = NULL;
|
||||
bool buildRing = false;
|
||||
|
||||
if (net->isGlobal()) {
|
||||
if ( (flags & Cell::BuildClockRings ) and net->isClock () ) buildRing = true;
|
||||
else if ( (flags & Cell::BuildSupplyRings) and net->isSupply() ) buildRing = true;
|
||||
} else {
|
||||
buildRing = flags & Cell::BuildRings;
|
||||
}
|
||||
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
Plug* primaryPlug = dynamic_cast<Plug*>( *icomponent );
|
||||
if (primaryPlug) {
|
||||
if (not primaryPlug->getBodyHook()->getSlaveHooks().isEmpty()) {
|
||||
cerr << "[ERROR] " << primaryPlug << "\n"
|
||||
<< " has attached components, not managed yet." << endl;
|
||||
} else {
|
||||
primaryPlug->getBodyHook()->detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forEach ( Occurrence, iplugOccurrence, hyperNet.getLeafPlugOccurrences() ) {
|
||||
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
|
||||
currentRp->materialize();
|
||||
forEach ( Occurrence, iplugOccurrence, topHyperNets[i].getLeafPlugOccurrences() ) {
|
||||
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
|
||||
currentRp->materialize();
|
||||
|
||||
if (flags & WarnOnUnplacedInstances)
|
||||
currentRp->isPlacedOccurrence( RoutingPad::ShowWarning );
|
||||
if (flags & WarnOnUnplacedInstances)
|
||||
currentRp->isPlacedOccurrence( RoutingPad::ShowWarning );
|
||||
|
||||
if (buildRing) {
|
||||
if (previousRp) {
|
||||
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
|
||||
}
|
||||
Plug* plug = static_cast<Plug*>( (*iplugOccurrence).getEntity() );
|
||||
if ( (*iplugOccurrence).getPath().isEmpty() ) {
|
||||
plug->getBodyHook()->attach( currentRp->getBodyHook() );
|
||||
plug->getBodyHook()->detach();
|
||||
}
|
||||
previousRp = currentRp;
|
||||
}
|
||||
}
|
||||
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
Pin* pin = dynamic_cast<Pin*>( *icomponent );
|
||||
if (pin) {
|
||||
currentRp = RoutingPad::create( pin );
|
||||
if (buildRing) {
|
||||
if (previousRp) {
|
||||
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
|
||||
}
|
||||
Plug* plug = static_cast<Plug*>( (*iplugOccurrence).getEntity() );
|
||||
if ( (*iplugOccurrence).getPath().isEmpty() ) {
|
||||
plug->getBodyHook()->attach( currentRp->getBodyHook() );
|
||||
plug->getBodyHook()->detach();
|
||||
}
|
||||
previousRp = currentRp;
|
||||
}
|
||||
}
|
||||
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
Pin* pin = dynamic_cast<Pin*>( *icomponent );
|
||||
if (pin) {
|
||||
currentRp = RoutingPad::create( pin );
|
||||
if (buildRing) {
|
||||
if (previousRp) {
|
||||
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
|
||||
}
|
||||
pin->getBodyHook()->attach( currentRp->getBodyHook() );
|
||||
pin->getBodyHook()->detach();
|
||||
}
|
||||
previousRp = currentRp;
|
||||
pin->getBodyHook()->attach( currentRp->getBodyHook() );
|
||||
pin->getBodyHook()->detach();
|
||||
}
|
||||
previousRp = currentRp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4780,10 +4780,13 @@ void Cell_HyperNetRootNetOccurrences::Locator::progress()
|
|||
{
|
||||
if (_netLocator.isValid())
|
||||
{
|
||||
do {
|
||||
_netLocator.progress();
|
||||
}
|
||||
while (_netLocator.isValid() && !isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path)));
|
||||
_netLocator.progress();
|
||||
while ( _netLocator.isValid() ) {
|
||||
if ( not dynamic_cast<DeepNet*>(_netLocator.getElement())
|
||||
and isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path))) break;
|
||||
|
||||
_netLocator.progress();
|
||||
}
|
||||
}
|
||||
else if (_hyperNetRootNetOccurrenceLocator.isValid())
|
||||
_hyperNetRootNetOccurrenceLocator.progress();
|
||||
|
|
|
@ -55,7 +55,9 @@ namespace Hurricane {
|
|||
,netOccurrence.getName()
|
||||
)
|
||||
, _netOccurrence(netOccurrence)
|
||||
{ }
|
||||
{
|
||||
//trace << "DeepNet::DeepNet() " << getCell() << " " << this << endl;
|
||||
}
|
||||
|
||||
|
||||
DeepNet* DeepNet::create ( HyperNet& hyperNet )
|
||||
|
|
|
@ -259,30 +259,21 @@ class HyperNet_LeafPlugOccurrences : public Collection<Occurrence> {
|
|||
// ****************************************************************************************************
|
||||
|
||||
HyperNet::HyperNet(const Occurrence& occurrence)
|
||||
// *******************************************
|
||||
: _netOccurrence()
|
||||
// *********************************************
|
||||
: _netOccurrence(occurrence.getNetOccurrence())
|
||||
{
|
||||
if (occurrence.isValid()) {
|
||||
Entity* entity = occurrence.getEntity();
|
||||
if (dynamic_cast<Net*>(entity))
|
||||
_netOccurrence = occurrence;
|
||||
else {
|
||||
if (dynamic_cast<Rubber*>(entity)) {
|
||||
Rubber* rubber = (Rubber*)entity;
|
||||
_netOccurrence = Occurrence(rubber->getNet(), occurrence.getPath());
|
||||
}
|
||||
else {
|
||||
if (dynamic_cast<Component*>(entity)) {
|
||||
Component* component = (Component*)entity;
|
||||
_netOccurrence = Occurrence(component->getNet(), occurrence.getPath());
|
||||
}
|
||||
else
|
||||
throw Error("Can't create " + _TName("HyperNet") + " : bad occurrence entity type");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (not occurrence.isValid())
|
||||
throw Error("Can't create " + _TName("HyperNet") + " : bad occurrence entity type");
|
||||
}
|
||||
|
||||
|
||||
HyperNet::HyperNet(const HyperNet& other)
|
||||
// *********************************************
|
||||
: _netOccurrence(other._netOccurrence)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Occurrences HyperNet::getNetOccurrences(bool doExtraction, bool allowInterruption) const
|
||||
// ***********************************************************************************
|
||||
{
|
||||
|
|
|
@ -126,6 +126,27 @@ Properties Occurrence::getProperties() const
|
|||
return Properties();
|
||||
}
|
||||
|
||||
Occurrence Occurrence::getNetOccurrence() const
|
||||
// ********************************************
|
||||
{
|
||||
if (isValid()) {
|
||||
Entity* entity = getEntity();
|
||||
if (dynamic_cast<Net*>(entity)) return *this;
|
||||
else {
|
||||
Rubber* rubber = dynamic_cast<Rubber*>(entity);
|
||||
if (rubber) return Occurrence(rubber->getNet(), getPath());
|
||||
else {
|
||||
Component* component = dynamic_cast<Component*>(entity);
|
||||
if (component) return Occurrence(component->getNet(), getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Occurrence();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Box Occurrence::getBoundingBox() const
|
||||
// **********************************
|
||||
{
|
||||
|
|
|
@ -68,7 +68,8 @@ class Cell : public Entity {
|
|||
public: enum Flag { BuildRings = 0x0001
|
||||
, BuildClockRings = 0x0002
|
||||
, BuildSupplyRings = 0x0004
|
||||
, WarnOnUnplacedInstances = 0x0008
|
||||
, NoClockFlatten = 0x0008
|
||||
, WarnOnUnplacedInstances = 0x0010
|
||||
// Flags set for Observers.
|
||||
, CellAboutToChange = 0x0001
|
||||
, CellChanged = 0x0002
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace Hurricane {
|
|||
static inline void addToTrace ( const void* symbol );
|
||||
static inline void addToTrace ( const Cell*, const Name& );
|
||||
static inline void addToTrace ( const Net* );
|
||||
static inline void open ( unsigned int traceLevel );
|
||||
static inline void open ( const void* symbol, unsigned int traceLevel=80 );
|
||||
static inline void close ();
|
||||
// Singleton Access.
|
||||
|
@ -91,6 +92,12 @@ namespace Hurricane {
|
|||
|
||||
// Inline Functions.
|
||||
|
||||
void DebugSession::open ( unsigned int traceLevel )
|
||||
{
|
||||
_singleton->_levels.push ( ltracelevel(traceLevel) );
|
||||
}
|
||||
|
||||
|
||||
void DebugSession::open ( const void* symbol, unsigned int traceLevel )
|
||||
{
|
||||
if ( _singleton->_isTraced(symbol) )
|
||||
|
|
|
@ -42,8 +42,7 @@ class HyperNet {
|
|||
// ************
|
||||
|
||||
public: HyperNet(const Occurrence& occurrence);
|
||||
|
||||
private: HyperNet(const HyperNet& hyperNet); // not implemented to forbid copy construction
|
||||
public: HyperNet(const HyperNet& hyperNet);
|
||||
|
||||
// Operators
|
||||
// *********
|
||||
|
|
|
@ -72,6 +72,7 @@ class Occurrence {
|
|||
public: Cell* getMasterCell() const;
|
||||
public: Property* getProperty(const Name& name) const;
|
||||
public: Properties getProperties() const;
|
||||
public: Occurrence getNetOccurrence() const;
|
||||
public: Box getBoundingBox() const;
|
||||
public: Box getBoundingBox(const BasicLayer*) const;
|
||||
|
||||
|
|
|
@ -108,7 +108,8 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
updatorFromBasicLayer (setBlockageLayer ,PyBasicLayer,BasicLayer)
|
||||
updatorFromBasicLayer (setBlockageLayer,PyBasicLayer,BasicLayer)
|
||||
accessorLayerFromVoid (getBlockageLayer,PyBasicLayer,BasicLayer)
|
||||
DirectSetLongAttribute (PyBasicLayer_setExtractNumber,setExtractNumber,"BasicLayer.setExtractNumber",PyBasicLayer,BasicLayer)
|
||||
DirectSetCStringAttribute(PyBasicLayer_setRealName ,setRealName ,"BasicLayer.setRealName" ,PyBasicLayer,BasicLayer)
|
||||
|
||||
|
@ -125,6 +126,8 @@ extern "C" {
|
|||
, "Create a new BasicLayer." }
|
||||
, { "getMaterial" , (PyCFunction)PyBasicLayer_getMaterial , METH_NOARGS
|
||||
, "Returns the type of Material." }
|
||||
, { "getBlockageLayer" , (PyCFunction)PyBasicLayer_getBlockageLayer , METH_NOARGS
|
||||
, "Returns the associated blockage layer, if any." }
|
||||
, { "setBlockageLayer" , (PyCFunction)PyBasicLayer_setBlockageLayer , METH_VARARGS
|
||||
, "Sets the blockage layer associated to this one." }
|
||||
, { "setExtractNumber" , (PyCFunction)PyBasicLayer_setExtractNumber , METH_VARARGS
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/DataBase.h"
|
||||
|
@ -45,6 +46,7 @@ namespace {
|
|||
using Hurricane::inltrace;
|
||||
using Hurricane::ltracein;
|
||||
using Hurricane::ltraceout;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::ForEachIterator;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Error;
|
||||
|
@ -101,35 +103,39 @@ namespace {
|
|||
|
||||
class GlobalNetTable {
|
||||
public:
|
||||
GlobalNetTable ( KiteEngine* );
|
||||
Net* getRootNet ( const Net*, Path ) const;
|
||||
inline Net* getVdde () const;
|
||||
inline Net* getVddi () const;
|
||||
inline Net* getVsse () const;
|
||||
inline Net* getVssi () const;
|
||||
inline Net* getCk () const;
|
||||
inline Net* getCki () const;
|
||||
inline Net* getCko () const;
|
||||
inline Net* getBlockage () const;
|
||||
inline void setBlockage ( Net* );
|
||||
enum Flag { ClockIsRouted=0x0001 };
|
||||
public:
|
||||
GlobalNetTable ( KiteEngine* );
|
||||
bool isCoreClockNetRouted ( const Net* ) const;
|
||||
Net* getRootNet ( const Net*, Path ) const;
|
||||
inline Net* getVdde () const;
|
||||
inline Net* getVddi () const;
|
||||
inline Net* getVsse () const;
|
||||
inline Net* getVssi () const;
|
||||
inline Net* getCk () const;
|
||||
inline Net* getCki () const;
|
||||
inline Net* getCko () const;
|
||||
inline Net* getBlockage () const;
|
||||
inline void setBlockage ( Net* );
|
||||
private:
|
||||
bool guessGlobalNet ( const Name&, Net* );
|
||||
private:
|
||||
bool guessGlobalNet ( const Name&, Net* );
|
||||
private:
|
||||
Name _vddePadNetName;
|
||||
Name _vddiPadNetName;
|
||||
Name _vssePadNetName;
|
||||
Name _vssiPadNetName;
|
||||
Name _ckPadNetName;
|
||||
Name _ckiPadNetName;
|
||||
Name _ckoPadNetName;
|
||||
Net* _vdde;
|
||||
Net* _vddi;
|
||||
Net* _vsse;
|
||||
Net* _vssi;
|
||||
Net* _ck; // Clock net on the (external) pad.
|
||||
Net* _cki; // Clock net in the pad ring.
|
||||
Net* _cko; // Clock net of the core (design).
|
||||
Net* _blockage;
|
||||
unsigned int _flags;
|
||||
Name _vddePadNetName;
|
||||
Name _vddiPadNetName;
|
||||
Name _vssePadNetName;
|
||||
Name _vssiPadNetName;
|
||||
Name _ckPadNetName;
|
||||
Name _ckiPadNetName;
|
||||
Name _ckoPadNetName;
|
||||
Net* _vdde;
|
||||
Net* _vddi;
|
||||
Net* _vsse;
|
||||
Net* _vssi;
|
||||
Net* _ck; // Clock net on the (external) pad.
|
||||
Net* _cki; // Clock net in the pad ring.
|
||||
Net* _cko; // Clock net of the core (design).
|
||||
Net* _blockage;
|
||||
};
|
||||
|
||||
|
||||
|
@ -144,7 +150,8 @@ namespace {
|
|||
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
|
||||
|
||||
GlobalNetTable::GlobalNetTable ( KiteEngine* kite )
|
||||
: _vddePadNetName("vdde")
|
||||
: _flags (0)
|
||||
, _vddePadNetName("vdde")
|
||||
, _vddiPadNetName("vddi")
|
||||
, _vssePadNetName("vsse")
|
||||
, _vssiPadNetName("vssi")
|
||||
|
@ -249,7 +256,7 @@ namespace {
|
|||
if (netType == Net::Type::POWER) {
|
||||
if (_vddiPadNetName.isEmpty()) {
|
||||
_vddiPadNetName = inet->getName();
|
||||
_vddi = *inet;
|
||||
_vddi = *inet;
|
||||
} else {
|
||||
cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n"
|
||||
" (will consider only <%s>)"
|
||||
|
@ -276,7 +283,13 @@ namespace {
|
|||
if (_ckoPadNetName.isEmpty()) {
|
||||
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
|
||||
_ckoPadNetName = inet->getName();
|
||||
_cko = *inet;
|
||||
_cko = *inet;
|
||||
if (NetRoutingExtension::isMixedPreRoute(*inet)) {
|
||||
cmess1 << " (core clock net is already routed)" << endl;
|
||||
_flags |= ClockIsRouted;
|
||||
} else {
|
||||
cmess1 << " (core clock net will be routed as an ordinary signal)" << endl;
|
||||
}
|
||||
} else {
|
||||
cerr << Error("Second clock net <%s> net at top block level will be ignored.\n"
|
||||
" (will consider only <%s>)"
|
||||
|
@ -332,6 +345,13 @@ namespace {
|
|||
if (name == _ckoPadNetName) {
|
||||
cmess1 << " - Using <" << net->getName() << "> as core (internal:cko) clock net." << endl;
|
||||
_cko = net;
|
||||
|
||||
if (NetRoutingExtension::isMixedPreRoute(_cko)) {
|
||||
cmess1 << " (core clock net is already routed)" << endl;
|
||||
_flags |= ClockIsRouted;
|
||||
} else {
|
||||
cmess1 << " (core clock net will be routed as an ordinary signal)" << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -359,6 +379,7 @@ namespace {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Track up, *only* for clocks.
|
||||
const Net* upNet = net;
|
||||
|
||||
if (not path.isEmpty()) {
|
||||
|
@ -367,10 +388,10 @@ namespace {
|
|||
Plug* plug = NULL;
|
||||
|
||||
while ( true ) {
|
||||
ltrace(300) << path << "+" << upNet << endl;
|
||||
ltrace(300) << " " << path << "+" << upNet << endl;
|
||||
|
||||
if ((upNet == NULL) or not upNet->isExternal()) return _blockage;
|
||||
if (path.isEmpty()) break;
|
||||
if ((upNet == NULL) or not upNet->isExternal()) return _blockage;
|
||||
|
||||
instance = path.getTailInstance();
|
||||
plug = instance->getPlug(upNet);
|
||||
|
@ -386,14 +407,23 @@ namespace {
|
|||
<< " cko:" << ((_cko) ? _cko->getName() : "NULL")
|
||||
<< endl;
|
||||
|
||||
if ( _ck and (upNet->getName() == _ck->getName() ) ) return _ck;
|
||||
if ( _cki and (upNet->getName() == _cki->getName()) ) return _cki;
|
||||
if ( _cko and (upNet->getName() == _cko->getName()) ) return _cko;
|
||||
if (_ck and (upNet->getName() == _ck->getName() )) return _ck;
|
||||
if (_cki and (upNet->getName() == _cki->getName())) return _cki;
|
||||
|
||||
if (_cko) {
|
||||
if (upNet->getName() == _cko->getName()) {
|
||||
if (isCoreClockNetRouted(upNet)) return _cko;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const
|
||||
{ return (net == _cko) and (_flags & ClockIsRouted); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "::PowerRailsPlanes".
|
||||
|
||||
|
@ -481,6 +511,7 @@ namespace {
|
|||
PowerRailsPlanes ( KiteEngine* );
|
||||
~PowerRailsPlanes ();
|
||||
inline Net* getRootNet ( Net*, Path );
|
||||
inline bool isCoreClockNetRouted ( const Net* ) const;
|
||||
bool hasPlane ( const BasicLayer* );
|
||||
bool setActivePlane ( const BasicLayer* );
|
||||
inline Plane* getActivePlane () const;
|
||||
|
@ -661,7 +692,10 @@ namespace {
|
|||
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
||||
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) {
|
||||
TrackElement* element = TrackFixedSegment::create ( track, segment );
|
||||
ltrace(300) << " Insert in " << track << "+" << element << endl;
|
||||
ltrace(300) << " Insert in " << track
|
||||
<< "+" << element
|
||||
<< " " << (net->isExternal() ? "external" : "internal")
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -905,6 +939,10 @@ namespace {
|
|||
inline Net* PowerRailsPlanes::getRootNet ( Net* net, Path path )
|
||||
{ return _globalNets.getRootNet(net,path); }
|
||||
|
||||
|
||||
inline bool PowerRailsPlanes::isCoreClockNetRouted ( const Net* net ) const
|
||||
{ return _globalNets.isCoreClockNetRouted(net); }
|
||||
|
||||
|
||||
bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer )
|
||||
{ return (_planes.find(layer) != _planes.end()); }
|
||||
|
@ -1076,11 +1114,20 @@ namespace {
|
|||
and (_routingGauge->getLayerDepth(component->getLayer()) < 2) )
|
||||
return;
|
||||
|
||||
Net* rootNet = _kite->getBlockageNet();
|
||||
if (not _isBlockagePlane) {
|
||||
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
|
||||
}
|
||||
|
||||
#if 0
|
||||
Net* rootNet = NULL;
|
||||
if ( not _isBlockagePlane )
|
||||
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
|
||||
else
|
||||
else {
|
||||
rootNet = _kite->getBlockageNet();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( rootNet == NULL ) {
|
||||
ltrace(300) << " rootNet is NULL, not taken into account." << endl;
|
||||
return;
|
||||
|
@ -1199,6 +1246,8 @@ namespace Kite {
|
|||
|
||||
void KiteEngine::buildPowerRails ()
|
||||
{
|
||||
//DebugSession::open( 300 );
|
||||
|
||||
if (not _blockageNet) {
|
||||
_blockageNet = getCell()->getNet("blockagenet");
|
||||
if (not _blockageNet)
|
||||
|
@ -1226,6 +1275,8 @@ namespace Kite {
|
|||
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
|
||||
|
||||
Session::revalidate ();
|
||||
|
||||
//DebugSession::close();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace Kite {
|
|||
, _ripupLimits ()
|
||||
, _ripupCost (Cfg::getParamInt("kite.ripupCost" , 3)->asInt())
|
||||
, _eventsLimit (Cfg::getParamInt("kite.eventsLimit" ,4000000)->asInt())
|
||||
, _flags (0)
|
||||
{
|
||||
_ripupLimits[StrapRipupLimit] = Cfg::getParamInt("kite.strapRipupLimit" ,16)->asInt();
|
||||
_ripupLimits[LocalRipupLimit] = Cfg::getParamInt("kite.localRipupLimit" , 7)->asInt();
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace Kite {
|
|||
: KatabaticEngine (cell)
|
||||
, _viewer (NULL)
|
||||
, _knik (NULL)
|
||||
, _blockageNet (NULL)
|
||||
, _blockageNet (cell->getNet("blockagenet"))
|
||||
, _configuration (new Configuration(getKatabaticConfiguration()))
|
||||
, _routingPlanes ()
|
||||
, _negociateWindow (NULL)
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace Kite {
|
|||
, RipupLimitsTableSize=4
|
||||
};
|
||||
enum Constants { MaxMetalDepth=20 };
|
||||
enum Flag { UseClockTree=0x0001 };
|
||||
public:
|
||||
// Constructor & Destructor.
|
||||
virtual Configuration* clone () const;
|
||||
|
@ -58,6 +59,7 @@ namespace Kite {
|
|||
// Decorateds.
|
||||
virtual bool isGMetal ( const Layer* ) const;
|
||||
virtual bool isGContact ( const Layer* ) const;
|
||||
inline bool useClockTree () const;
|
||||
virtual size_t getDepth () const;
|
||||
virtual size_t getAllowedDepth () const;
|
||||
virtual DbU::Unit getSliceHeight () const;
|
||||
|
@ -102,6 +104,8 @@ namespace Kite {
|
|||
inline void setPostEventCb ( PostEventCb_t );
|
||||
void setHTracksReservedLocal ( size_t );
|
||||
void setVTracksReservedLocal ( size_t );
|
||||
inline void setFlags ( unsigned int );
|
||||
inline void unsetFlags ( unsigned int );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual string _getString () const;
|
||||
virtual string _getTypeName () const;
|
||||
|
@ -114,6 +118,7 @@ namespace Kite {
|
|||
unsigned int _ripupLimits [RipupLimitsTableSize];
|
||||
unsigned int _ripupCost;
|
||||
unsigned long _eventsLimit;
|
||||
unsigned int _flags;
|
||||
private:
|
||||
Configuration ( const Configuration& other, Katabatic::Configuration* base=NULL );
|
||||
Configuration& operator= ( const Configuration& );
|
||||
|
@ -130,6 +135,9 @@ namespace Kite {
|
|||
inline void Configuration::setRipupCost ( unsigned int cost ) { _ripupCost = cost; }
|
||||
inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; }
|
||||
inline void Configuration::setEventsLimit ( unsigned long limit ) { _eventsLimit = limit; }
|
||||
inline bool Configuration::useClockTree () const { return _flags & UseClockTree; }
|
||||
inline void Configuration::setFlags ( unsigned int flags ) { _flags |= flags; }
|
||||
inline void Configuration::unsetFlags ( unsigned int flags ) { _flags &= ~flags; }
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace Kite {
|
|||
static KiteEngine* create ( Cell* );
|
||||
static KiteEngine* get ( const Cell* );
|
||||
public:
|
||||
inline bool useClockTree () const;
|
||||
inline CellViewer* getViewer () const;
|
||||
inline KatabaticEngine* base ();
|
||||
inline Configuration* getKiteConfiguration ();
|
||||
|
@ -148,6 +149,7 @@ namespace Kite {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline bool KiteEngine::useClockTree () const { return _configuration->useClockTree(); }
|
||||
inline CellViewer* KiteEngine::getViewer () const { return _viewer; }
|
||||
inline KatabaticEngine* KiteEngine::base () { return static_cast<KatabaticEngine*>(this); }
|
||||
inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; }
|
||||
|
|
|
@ -1274,6 +1274,7 @@ void Graph::Dijkstra()
|
|||
ostringstream message;
|
||||
message << "In Graph::Dijkstra():\n";
|
||||
message << " Unable to reach target on net " << _working_net->getName() << ".";
|
||||
for ( auto iv : _vertexes_to_route ) message << "\n | " << iv;
|
||||
throw Error( message.str() );
|
||||
}
|
||||
assert( reachedDistance < (float)(HUGE_VAL) );
|
||||
|
|
|
@ -237,7 +237,6 @@ void KnikEngine::initGlobalRouting( const map<Name,Net*>& excludedNets )
|
|||
|
||||
if ( inet->isGlobal()
|
||||
or inet->isSupply()
|
||||
or inet->isClock()
|
||||
or (inet->getName() == obstacleNetName) ) {
|
||||
cmess2 << " - <" << inet->getName() << "> not routed (global, supply, clock or obstacle)." << endl;
|
||||
continue;
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace Mauka {
|
|||
|
||||
void FeedCells::addFeed ( Cell* cell )
|
||||
{
|
||||
if ( cell == NULL ) return;
|
||||
if (cell == NULL) return;
|
||||
if (not _feedCells.size()) return;
|
||||
|
||||
DbU::Unit pitch = _mauka->getPitch();
|
||||
|
||||
|
|
Loading…
Reference in New Issue