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 )
|
static PyObject* PyRoutingGauge_getRoutingLayer ( PyRoutingGauge* self, PyObject* args )
|
||||||
{
|
{
|
||||||
trace << "PyRoutingGauge_getRoutingLayer()" << endl;
|
trace << "PyRoutingGauge_getRoutingLayer()" << endl;
|
||||||
|
@ -318,6 +349,8 @@ extern "C" {
|
||||||
, "Return the RoutingLayerGauge of the given layer/depth." }
|
, "Return the RoutingLayerGauge of the given layer/depth." }
|
||||||
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection, METH_VARARGS
|
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection, METH_VARARGS
|
||||||
, "Return the direction of the given layer/depth." }
|
, "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
|
, { "getRoutingLayer" , (PyCFunction)PyRoutingGauge_getRoutingLayer , METH_VARARGS
|
||||||
, "Return the routing layer used for the requested depth." }
|
, "Return the routing layer used for the requested depth." }
|
||||||
, { "getContactLayer" , (PyCFunction)PyRoutingGauge_getContactLayer , METH_VARARGS
|
, { "getContactLayer" , (PyCFunction)PyRoutingGauge_getContactLayer , METH_VARARGS
|
||||||
|
|
|
@ -48,6 +48,7 @@ try:
|
||||||
import Nimbus
|
import Nimbus
|
||||||
import Metis
|
import Metis
|
||||||
import Mauka
|
import Mauka
|
||||||
|
import Etesian
|
||||||
import Katabatic
|
import Katabatic
|
||||||
import Kite
|
import Kite
|
||||||
import Unicorn
|
import Unicorn
|
||||||
|
@ -140,17 +141,28 @@ class PlaceCore ( chip.Configuration.ChipConfWrapper ):
|
||||||
if self.useClockTree and ckCore:
|
if self.useClockTree and ckCore:
|
||||||
ht = clocktree.ClockTree.HTree.create( self, coreCell, ckCore, coreCell.getAbutmentBox() )
|
ht = clocktree.ClockTree.HTree.create( self, coreCell, ckCore, coreCell.getAbutmentBox() )
|
||||||
ht.addCloned( self.cell )
|
ht.addCloned( self.cell )
|
||||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
|
||||||
mauka.run()
|
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||||
mauka.destroy()
|
mauka.run()
|
||||||
|
mauka.destroy()
|
||||||
|
else:
|
||||||
|
etesian = Etesian.EtesianEngine.create( coreCell )
|
||||||
|
etesian.place( Etesian.EtesianEngine.SlowMotion )
|
||||||
|
etesian.destroy()
|
||||||
|
|
||||||
ht.connectLeaf()
|
ht.connectLeaf()
|
||||||
ht.prune()
|
#ht.prune()
|
||||||
ht.route()
|
ht.route()
|
||||||
ht.save( self.cell )
|
ht.save( self.cell )
|
||||||
else:
|
else:
|
||||||
mauka = Mauka.MaukaEngine.create( coreCell )
|
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
|
||||||
mauka.run()
|
mauka = Mauka.MaukaEngine.create( coreCell )
|
||||||
mauka.destroy()
|
mauka.run()
|
||||||
|
mauka.destroy()
|
||||||
|
else:
|
||||||
|
etesian = Etesian.EtesianEngine.create( coreCell )
|
||||||
|
etesian.place( Etesian.EtesianEngine.SlowMotion )
|
||||||
|
etesian.destroy()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,18 @@ class StackedVia ( object ):
|
||||||
if depth > self._topDepth: self._topDepth = depth
|
if depth > self._topDepth: self._topDepth = depth
|
||||||
return
|
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 ):
|
def getVia ( self, metal ):
|
||||||
if not self._hasLayout: return None
|
if not self._hasLayout: return None
|
||||||
for via in self._vias:
|
for via in self._vias:
|
||||||
|
|
|
@ -150,7 +150,7 @@ class VerticalRail ( Rail ):
|
||||||
, via[2].getY()
|
, via[2].getY()
|
||||||
, via[2].getHeight()
|
, via[2].getHeight()
|
||||||
)
|
)
|
||||||
railVias.append( via[1].getVia( self.side.getVLayer()) )
|
railVias.append( via[1].getVia(self.side.getVLayer()) )
|
||||||
|
|
||||||
railVias.sort( key=methodcaller('getY') )
|
railVias.sort( key=methodcaller('getY') )
|
||||||
|
|
||||||
|
@ -161,6 +161,21 @@ class VerticalRail ( Rail ):
|
||||||
, self.axis
|
, self.axis
|
||||||
, self.side.vRailWidth
|
, 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
|
return
|
||||||
|
|
||||||
def connect ( self, contact ):
|
def connect ( self, contact ):
|
||||||
|
@ -224,25 +239,31 @@ class Side ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def railsNb ( self ): return self._corona._railsNb
|
def railsNb ( self ): return self._corona._railsNb
|
||||||
@property
|
@property
|
||||||
def innerBb ( self ): return self._corona._innerBb
|
def innerBb ( self ): return self._corona._innerBb
|
||||||
@property
|
@property
|
||||||
def hRailWidth ( self ): return self._corona._hRailWidth
|
def hRailWidth ( self ): return self._corona._hRailWidth
|
||||||
@property
|
@property
|
||||||
def hRailSpace ( self ): return self._corona._hRailSpace
|
def hRailSpace ( self ): return self._corona._hRailSpace
|
||||||
@property
|
@property
|
||||||
def vRailWidth ( self ): return self._corona._vRailWidth
|
def vRailWidth ( self ): return self._corona._vRailWidth
|
||||||
@property
|
@property
|
||||||
def vRailSpace ( self ): return self._corona._vRailSpace
|
def vRailSpace ( self ): return self._corona._vRailSpace
|
||||||
@property
|
@property
|
||||||
def corners ( self ): return self._corona._corners
|
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 getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal)
|
||||||
def getRail ( self, i ): return self._rails[i]
|
def getRail ( self, i ): return self._rails[i]
|
||||||
def getRailNet ( self, i ): return self._corona.getRailNet(i)
|
def getRailNet ( self, i ): return self._corona.getRailNet(i)
|
||||||
def getHLayer ( self ): return self._corona.getHLayer()
|
def getHLayer ( self ): return self._corona.getHLayer()
|
||||||
def getVLayer ( self ): return self._corona.getVLayer()
|
def getVLayer ( self ): return self._corona.getVLayer()
|
||||||
|
|
||||||
def getRailAxis ( self, i ):
|
def getRailAxis ( self, i ):
|
||||||
raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' )
|
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 \
|
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
|
||||||
- i*(self.hRailWidth + 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]
|
def corner1 ( self, i ): return self.corners[chip.SouthEast][i]
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,6 +400,8 @@ class Corona ( object ):
|
||||||
self._innerBb = self._block.bb
|
self._innerBb = self._block.bb
|
||||||
self._block.path.getTransformation().applyOn( self._innerBb )
|
self._block.path.getTransformation().applyOn( self._innerBb )
|
||||||
self._innerBb.inflate( self._hRailSpace/2, self._vRailSpace/2 )
|
self._innerBb.inflate( self._hRailSpace/2, self._vRailSpace/2 )
|
||||||
|
|
||||||
|
if not self.useClockTree: self._railsNb -= 1
|
||||||
|
|
||||||
self._southSide = SouthSide( self )
|
self._southSide = SouthSide( self )
|
||||||
self._northSide = NorthSide( self )
|
self._northSide = NorthSide( self )
|
||||||
|
@ -387,6 +410,8 @@ class Corona ( object ):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def useClockTree ( self ): return self._block.useClockTree
|
||||||
@property
|
@property
|
||||||
def routingGauge ( self ): return self._block.routingGauge
|
def routingGauge ( self ): return self._block.routingGauge
|
||||||
@property
|
@property
|
||||||
|
@ -395,12 +420,14 @@ class Corona ( object ):
|
||||||
def horizontalDepth ( self ): return self._block.horizontalDepth
|
def horizontalDepth ( self ): return self._block.horizontalDepth
|
||||||
@property
|
@property
|
||||||
def verticalDepth ( self ): return self._block.verticalDepth
|
def verticalDepth ( self ): return self._block.verticalDepth
|
||||||
|
@property
|
||||||
|
def blockageNet ( self ): return self._block.blockageNet
|
||||||
|
|
||||||
def getLayerDepth ( self, metal ):
|
def getLayerDepth ( self, metal ):
|
||||||
return self.routingGauge.getLayerDepth( metal )
|
return self.routingGauge.getLayerDepth( metal )
|
||||||
|
|
||||||
def getRailNet ( self, i ):
|
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
|
if i % 2: return self._block.vssi
|
||||||
return self._block.vddi
|
return self._block.vddi
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ class Block ( chip.Configuration.ChipConfWrapper ):
|
||||||
|
|
||||||
def connectClock ( self ):
|
def connectClock ( self ):
|
||||||
if not self.useClockTree:
|
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
|
return
|
||||||
|
|
||||||
if not self.cko:
|
if not self.cko:
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import Cfg
|
import Cfg
|
||||||
|
from Hurricane import Breakpoint
|
||||||
from Hurricane import DbU
|
from Hurricane import DbU
|
||||||
from Hurricane import Box
|
from Hurricane import Box
|
||||||
from Hurricane import Transformation
|
from Hurricane import Transformation
|
||||||
|
@ -433,13 +434,14 @@ class ChipConf ( object ):
|
||||||
|
|
||||||
|
|
||||||
def _guessGlobalNet ( self, name, net ):
|
def _guessGlobalNet ( self, name, net ):
|
||||||
if name == self._vddeName: self._vdde = net
|
if name == self._vddeName: self._vdde = net
|
||||||
if name == self._vddiName: self._vddi = net
|
if name == self._vddiName: self._vddi = net
|
||||||
if name == self._vsseName: self._vsse = net
|
if name == self._vsseName: self._vsse = net
|
||||||
if name == self._vssiName: self._vssi = net
|
if name == self._vssiName: self._vssi = net
|
||||||
if name == self._ckiName: self._cki = net
|
if name == self._ckiName: self._cki = net
|
||||||
if name == self._ckoName: self._cko = net
|
if name == self._ckoName: self._cko = net
|
||||||
if name == self._ckName: self._ck = net
|
if name == self._ckName: self._ck = net
|
||||||
|
if name == self._blockageName: self._blockageNet = net
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -469,6 +471,7 @@ class ChipConf ( object ):
|
||||||
self._ckiName = "ck"
|
self._ckiName = "ck"
|
||||||
self._ckoName = "cko"
|
self._ckoName = "cko"
|
||||||
self._ckName = "pad"
|
self._ckName = "pad"
|
||||||
|
self._blockageName = "blockagenet"
|
||||||
# Global Nets.
|
# Global Nets.
|
||||||
self._vdde = None
|
self._vdde = None
|
||||||
self._vddi = None
|
self._vddi = None
|
||||||
|
@ -477,6 +480,7 @@ class ChipConf ( object ):
|
||||||
self._cki = None
|
self._cki = None
|
||||||
self._cko = None
|
self._cko = None
|
||||||
self._ck = None
|
self._ck = None
|
||||||
|
self._blockageNet = None
|
||||||
|
|
||||||
self._clockPad = None
|
self._clockPad = None
|
||||||
self._powerPad = None
|
self._powerPad = None
|
||||||
|
@ -553,10 +557,10 @@ class ChipConf ( object ):
|
||||||
self._guessGlobalNet( masterNet.getName(), net )
|
self._guessGlobalNet( masterNet.getName(), net )
|
||||||
|
|
||||||
if self._clockPad:
|
if self._clockPad:
|
||||||
for plug in self._powerPad.getPlugs():
|
for plug in self._clockPad.getPlugs():
|
||||||
masterNet = plug.getMasterNet()
|
masterNet = plug.getMasterNet()
|
||||||
netType = masterNet.getType()
|
netType = masterNet.getType()
|
||||||
net = plug.getNet()
|
net = plug.getNet()
|
||||||
|
|
||||||
if not net:
|
if not net:
|
||||||
net = self._cell.getNet( masterNet.getName() )
|
net = self._cell.getNet( masterNet.getName() )
|
||||||
|
@ -567,6 +571,22 @@ class ChipConf ( object ):
|
||||||
|
|
||||||
if masterNet.getName() == self._ckName:
|
if masterNet.getName() == self._ckName:
|
||||||
self._guessGlobalNet( masterNet.getName(), net )
|
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
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -653,19 +673,21 @@ class ChipConfWrapper ( GaugeConfWrapper ):
|
||||||
|
|
||||||
# Global Nets.
|
# Global Nets.
|
||||||
@property
|
@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
|
@property
|
||||||
def vsse ( self ): return self._chipConf._vsse
|
def blockageNet ( self ): return self._chipConf._blockageNet
|
||||||
@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
|
|
||||||
|
|
||||||
# Various.
|
# Various.
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -181,7 +181,8 @@ class Side ( object ):
|
||||||
#print 'Power pad:', pad
|
#print 'Power pad:', pad
|
||||||
self._createPowerContacts( pad, self._corona.vddi )
|
self._createPowerContacts( pad, self._corona.vddi )
|
||||||
self._createPowerContacts( pad, self._corona.vssi )
|
self._createPowerContacts( pad, self._corona.vssi )
|
||||||
self._createPowerContacts( pad, self._corona.cko )
|
if self._corona.useClockTree:
|
||||||
|
self._createPowerContacts( pad, self._corona.cko )
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ class HTree ( GaugeConfWrapper ):
|
||||||
yslice = self.toYCellGrid(y)
|
yslice = self.toYCellGrid(y)
|
||||||
|
|
||||||
transformation = Transformation.Orientation.ID
|
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
|
transformation = Transformation.Orientation.MY
|
||||||
yslice += self.cellGauge.getSliceHeight()
|
yslice += self.cellGauge.getSliceHeight()
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ class HTreeNode ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
def route ( self ):
|
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 )
|
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 )
|
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 ):
|
def connectLeafs ( self ):
|
||||||
if not self.hasLeafs():
|
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:
|
if self.childs:
|
||||||
self.childs[0].connectLeafs()
|
self.childs[0].connectLeafs()
|
||||||
|
|
|
@ -304,14 +304,67 @@ namespace Etesian {
|
||||||
using Hurricane::Occurrence;
|
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 ()
|
void EtesianEngine::addFeeds ()
|
||||||
{
|
{
|
||||||
UpdateSession::open();
|
UpdateSession::open();
|
||||||
|
|
||||||
bool yspinSet = false;
|
SliceHoles sliceHoles ( this );
|
||||||
size_t yspinSlice0 = 0;
|
Box topCellAb = getCell()->getAbutmentBox();
|
||||||
SliceHoles sliceHoles ( this );
|
|
||||||
Box toCellAb = getCell()->getAbutmentBox();
|
sliceHoles.setSpinSlice0( _yspinSlice0 );
|
||||||
|
|
||||||
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
|
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
|
||||||
{
|
{
|
||||||
|
@ -329,41 +382,12 @@ namespace Etesian {
|
||||||
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
|
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
|
||||||
instanceTransf.applyOn( instanceAb );
|
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."
|
cerr << Warning( "Instance %s is not fully enclosed in the top cell."
|
||||||
, getString(instance->getName()).c_str() ) << endl;
|
, getString(instance->getName()).c_str() ) << endl;
|
||||||
continue;
|
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 );
|
sliceHoles.merge( instanceAb );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -284,10 +284,16 @@ namespace Etesian {
|
||||||
|
|
||||||
void EtesianEngine::_postCreate ()
|
void EtesianEngine::_postCreate ()
|
||||||
{
|
{
|
||||||
// Ugly. Direct uses of Alliance Framework.
|
// Ugly: Name based detection of ISPD benchmarks.
|
||||||
// Must change toward something in the settings.
|
if (getString(getCell()->getName()).substr(0,7) == "bigblue") {
|
||||||
_feedCells.useFeed( AllianceFramework::get()->getCell("tie_x0" ,Catalog::State::Views) );
|
cmess1 << " o ISPD benchmark <" << getCell()->getName()
|
||||||
_feedCells.useFeed( AllianceFramework::get()->getCell("rowend_x0",Catalog::State::Views) );
|
<< ">, 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();
|
DbU::Unit pitch = getPitch();
|
||||||
|
|
||||||
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
|
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
|
||||||
getCell()->flattenNets( Cell::BuildRings );
|
getCell()->flattenNets( Cell::BuildRings|Cell::NoClockFlatten );
|
||||||
|
|
||||||
// Coloquinte circuit description data-structures.
|
// Coloquinte circuit description data-structures.
|
||||||
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
|
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
|
||||||
vector<Transformation> idsToTransf ( instancesNb );
|
vector<Transformation> idsToTransf ( instancesNb );
|
||||||
vector<temporary_cell> instances ( instancesNb );
|
vector<temporary_cell> instances ( instancesNb );
|
||||||
vector< point<int_t> > positions ( 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;
|
cmess1 << " - Converting " << instancesNb << " instances" << endl;
|
||||||
cout.flush();
|
cout.flush();
|
||||||
|
@ -614,6 +620,7 @@ namespace Etesian {
|
||||||
|
|
||||||
if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb();
|
if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb();
|
||||||
|
|
||||||
|
findYSpin();
|
||||||
toColoquinte();
|
toColoquinte();
|
||||||
|
|
||||||
cmess1 << " o Running Coloquinte." << endl;
|
cmess1 << " o Running Coloquinte." << endl;
|
||||||
|
@ -740,7 +747,7 @@ namespace Etesian {
|
||||||
_progressReport1( startTime, " Local Swaps ...." );
|
_progressReport1( startTime, " Local Swaps ...." );
|
||||||
|
|
||||||
if (i == legalizeIterations-1) {
|
if (i == legalizeIterations-1) {
|
||||||
row_compatible_orientation( _circuit, legalizer, true );
|
row_compatible_orientation( _circuit, legalizer, (_yspinSlice0 == 0) );
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
_progressReport1( startTime, " Final Legalize ." );
|
_progressReport1( startTime, " Final Legalize ." );
|
||||||
}
|
}
|
||||||
|
@ -822,7 +829,6 @@ namespace Etesian {
|
||||||
{
|
{
|
||||||
Point instancePosition;
|
Point instancePosition;
|
||||||
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
|
||||||
//Cell* masterCell = instance->getMasterCell();
|
|
||||||
string instanceName = (*ioccurrence).getCompactString();
|
string instanceName = (*ioccurrence).getCompactString();
|
||||||
// Remove the enclosing brackets...
|
// Remove the enclosing brackets...
|
||||||
instanceName.erase( 0, 1 );
|
instanceName.erase( 0, 1 );
|
||||||
|
@ -832,23 +838,15 @@ namespace Etesian {
|
||||||
if (iid == _cellsToIds.end() ) {
|
if (iid == _cellsToIds.end() ) {
|
||||||
cerr << Error( "Unable to lookup instance <%s>.", instanceName.c_str() ) << endl;
|
cerr << Error( "Unable to lookup instance <%s>.", instanceName.c_str() ) << endl;
|
||||||
} else {
|
} else {
|
||||||
point<int_t> position = placement.positions_[(*iid).second];
|
if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED)
|
||||||
|
|
||||||
/*
|
|
||||||
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 );
|
|
||||||
continue;
|
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;
|
//cerr << "Setting <" << instanceName << " @" << instancePosition << endl;
|
||||||
|
|
||||||
// This is temporary as it's not trans-hierarchic: we ignore the posutions
|
// This is temporary as it's not trans-hierarchic: we ignore the posutions
|
||||||
|
|
|
@ -55,7 +55,8 @@ namespace Etesian {
|
||||||
enum Flag { NoPlacement=0x0001
|
enum Flag { NoPlacement=0x0001
|
||||||
, FlatDesign =0x0002
|
, FlatDesign =0x0002
|
||||||
, ForceUpdate=0x0004
|
, ForceUpdate=0x0004
|
||||||
, SlowMotion =0x0008
|
, YSpinSet =0x0008
|
||||||
|
, SlowMotion =0x0010
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
static const Name& staticGetName ();
|
static const Name& staticGetName ();
|
||||||
|
@ -79,6 +80,7 @@ namespace Etesian {
|
||||||
void toColoquinte ();
|
void toColoquinte ();
|
||||||
void place ( unsigned int flags=SlowMotion );
|
void place ( unsigned int flags=SlowMotion );
|
||||||
inline void useFeed ( Cell* );
|
inline void useFeed ( Cell* );
|
||||||
|
size_t findYSpin ();
|
||||||
void addFeeds ();
|
void addFeeds ();
|
||||||
virtual Record* _getRecord () const;
|
virtual Record* _getRecord () const;
|
||||||
virtual std::string _getString () const;
|
virtual std::string _getString () const;
|
||||||
|
@ -99,6 +101,7 @@ namespace Etesian {
|
||||||
std::vector<Instance*> _idsToInsts;
|
std::vector<Instance*> _idsToInsts;
|
||||||
Hurricane::CellWidget* _cellWidget;
|
Hurricane::CellWidget* _cellWidget;
|
||||||
FeedCells _feedCells;
|
FeedCells _feedCells;
|
||||||
|
size_t _yspinSlice0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Constructors & Destructors.
|
// Constructors & Destructors.
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace Etesian {
|
||||||
class FeedCells {
|
class FeedCells {
|
||||||
public:
|
public:
|
||||||
inline FeedCells ( EtesianEngine* );
|
inline FeedCells ( EtesianEngine* );
|
||||||
|
inline size_t feedNumbers () const;
|
||||||
void useFeed ( Cell* );
|
void useFeed ( Cell* );
|
||||||
Cell* getBiggestFeed () const;
|
Cell* getBiggestFeed () const;
|
||||||
Cell* getSmallestFeed () const;
|
Cell* getSmallestFeed () const;
|
||||||
|
@ -50,6 +51,9 @@ namespace Etesian {
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
inline size_t FeedCells::feedNumbers () const { return _feedCells.size(); }
|
||||||
|
|
||||||
|
|
||||||
} // Etesian namespace.
|
} // Etesian namespace.
|
||||||
|
|
||||||
#endif // ETESIAN_FEEDCELLS_H
|
#endif // ETESIAN_FEEDCELLS_H
|
||||||
|
|
|
@ -192,29 +192,29 @@ void Cell::setAbutmentBox(const Box& abutmentBox)
|
||||||
void Cell::flattenNets(unsigned int flags)
|
void Cell::flattenNets(unsigned int flags)
|
||||||
// ***************************************
|
// ***************************************
|
||||||
{
|
{
|
||||||
|
trace << "Cell::flattenNets() flags:0x" << hex << flags << endl;
|
||||||
|
|
||||||
UpdateSession::open();
|
UpdateSession::open();
|
||||||
|
|
||||||
_flags |= FlattenedNets;
|
_flags |= FlattenedNets;
|
||||||
|
|
||||||
|
vector<HyperNet> hyperNets;
|
||||||
|
vector<HyperNet> topHyperNets;
|
||||||
|
|
||||||
forEach ( Occurrence, ioccurrence, getHyperNetRootNetOccurrences() ) {
|
forEach ( Occurrence, ioccurrence, getHyperNetRootNetOccurrences() ) {
|
||||||
Net* net = static_cast<Net*>((*ioccurrence).getEntity());
|
Net* net = static_cast<Net*>((*ioccurrence).getEntity());
|
||||||
|
|
||||||
|
if (net->isClock() and (flags & NoClockFlatten)) continue;
|
||||||
|
|
||||||
HyperNet hyperNet ( *ioccurrence );
|
HyperNet hyperNet ( *ioccurrence );
|
||||||
if ( not (*ioccurrence).getPath().isEmpty() ) {
|
if ( not (*ioccurrence).getPath().isEmpty() ) {
|
||||||
DeepNet* deepNet = DeepNet::create( hyperNet );
|
Net* duplicate = getNet( (*ioccurrence).getName() );
|
||||||
if (deepNet) deepNet->_createRoutingPads( flags );
|
if (not duplicate) {
|
||||||
} else {
|
hyperNets.push_back( HyperNet(*ioccurrence) );
|
||||||
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 {
|
} else {
|
||||||
buildRing = flags & Cell::BuildRings;
|
cerr << "Found " << duplicate << " in " << duplicate->getCell() << endl;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
bool hasRoutingPads = false;
|
bool hasRoutingPads = false;
|
||||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( *icomponent );
|
RoutingPad* rp = dynamic_cast<RoutingPad*>( *icomponent );
|
||||||
|
@ -228,51 +228,72 @@ void Cell::flattenNets(unsigned int flags)
|
||||||
}
|
}
|
||||||
if (hasRoutingPads) continue;
|
if (hasRoutingPads) continue;
|
||||||
|
|
||||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
topHyperNets.push_back( HyperNet(*ioccurrence) );
|
||||||
Plug* primaryPlug = dynamic_cast<Plug*>( *icomponent );
|
}
|
||||||
if (primaryPlug) {
|
}
|
||||||
if ( !primaryPlug->getBodyHook()->getSlaveHooks().isEmpty() ) {
|
|
||||||
cerr << "[ERROR] " << primaryPlug << "\n"
|
for ( size_t i=0 ; i<hyperNets.size() ; ++i ) {
|
||||||
<< " has attached components, not managed yet." << endl;
|
DeepNet* deepNet = DeepNet::create( hyperNets[i] );
|
||||||
} else {
|
if (deepNet) deepNet->_createRoutingPads( flags );
|
||||||
primaryPlug->getBodyHook()->detach();
|
}
|
||||||
}
|
|
||||||
|
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() ) {
|
forEach ( Occurrence, iplugOccurrence, topHyperNets[i].getLeafPlugOccurrences() ) {
|
||||||
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
|
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
|
||||||
currentRp->materialize();
|
currentRp->materialize();
|
||||||
|
|
||||||
if (flags & WarnOnUnplacedInstances)
|
if (flags & WarnOnUnplacedInstances)
|
||||||
currentRp->isPlacedOccurrence( RoutingPad::ShowWarning );
|
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 (buildRing) {
|
||||||
if (previousRp) {
|
if (previousRp) {
|
||||||
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
|
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
|
||||||
}
|
}
|
||||||
Plug* plug = static_cast<Plug*>( (*iplugOccurrence).getEntity() );
|
pin->getBodyHook()->attach( currentRp->getBodyHook() );
|
||||||
if ( (*iplugOccurrence).getPath().isEmpty() ) {
|
pin->getBodyHook()->detach();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
previousRp = currentRp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4780,10 +4780,13 @@ void Cell_HyperNetRootNetOccurrences::Locator::progress()
|
||||||
{
|
{
|
||||||
if (_netLocator.isValid())
|
if (_netLocator.isValid())
|
||||||
{
|
{
|
||||||
do {
|
_netLocator.progress();
|
||||||
_netLocator.progress();
|
while ( _netLocator.isValid() ) {
|
||||||
}
|
if ( not dynamic_cast<DeepNet*>(_netLocator.getElement())
|
||||||
while (_netLocator.isValid() && !isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path)));
|
and isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path))) break;
|
||||||
|
|
||||||
|
_netLocator.progress();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_hyperNetRootNetOccurrenceLocator.isValid())
|
else if (_hyperNetRootNetOccurrenceLocator.isValid())
|
||||||
_hyperNetRootNetOccurrenceLocator.progress();
|
_hyperNetRootNetOccurrenceLocator.progress();
|
||||||
|
|
|
@ -55,7 +55,9 @@ namespace Hurricane {
|
||||||
,netOccurrence.getName()
|
,netOccurrence.getName()
|
||||||
)
|
)
|
||||||
, _netOccurrence(netOccurrence)
|
, _netOccurrence(netOccurrence)
|
||||||
{ }
|
{
|
||||||
|
//trace << "DeepNet::DeepNet() " << getCell() << " " << this << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DeepNet* DeepNet::create ( HyperNet& hyperNet )
|
DeepNet* DeepNet::create ( HyperNet& hyperNet )
|
||||||
|
|
|
@ -259,30 +259,21 @@ class HyperNet_LeafPlugOccurrences : public Collection<Occurrence> {
|
||||||
// ****************************************************************************************************
|
// ****************************************************************************************************
|
||||||
|
|
||||||
HyperNet::HyperNet(const Occurrence& occurrence)
|
HyperNet::HyperNet(const Occurrence& occurrence)
|
||||||
// *******************************************
|
// *********************************************
|
||||||
: _netOccurrence()
|
: _netOccurrence(occurrence.getNetOccurrence())
|
||||||
{
|
{
|
||||||
if (occurrence.isValid()) {
|
if (not occurrence.isValid())
|
||||||
Entity* entity = occurrence.getEntity();
|
throw Error("Can't create " + _TName("HyperNet") + " : bad occurrence entity type");
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HyperNet::HyperNet(const HyperNet& other)
|
||||||
|
// *********************************************
|
||||||
|
: _netOccurrence(other._netOccurrence)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Occurrences HyperNet::getNetOccurrences(bool doExtraction, bool allowInterruption) const
|
Occurrences HyperNet::getNetOccurrences(bool doExtraction, bool allowInterruption) const
|
||||||
// ***********************************************************************************
|
// ***********************************************************************************
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,6 +126,27 @@ Properties Occurrence::getProperties() const
|
||||||
return Properties();
|
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
|
Box Occurrence::getBoundingBox() const
|
||||||
// **********************************
|
// **********************************
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,7 +68,8 @@ class Cell : public Entity {
|
||||||
public: enum Flag { BuildRings = 0x0001
|
public: enum Flag { BuildRings = 0x0001
|
||||||
, BuildClockRings = 0x0002
|
, BuildClockRings = 0x0002
|
||||||
, BuildSupplyRings = 0x0004
|
, BuildSupplyRings = 0x0004
|
||||||
, WarnOnUnplacedInstances = 0x0008
|
, NoClockFlatten = 0x0008
|
||||||
|
, WarnOnUnplacedInstances = 0x0010
|
||||||
// Flags set for Observers.
|
// Flags set for Observers.
|
||||||
, CellAboutToChange = 0x0001
|
, CellAboutToChange = 0x0001
|
||||||
, CellChanged = 0x0002
|
, CellChanged = 0x0002
|
||||||
|
|
|
@ -61,6 +61,7 @@ namespace Hurricane {
|
||||||
static inline void addToTrace ( const void* symbol );
|
static inline void addToTrace ( const void* symbol );
|
||||||
static inline void addToTrace ( const Cell*, const Name& );
|
static inline void addToTrace ( const Cell*, const Name& );
|
||||||
static inline void addToTrace ( const Net* );
|
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 open ( const void* symbol, unsigned int traceLevel=80 );
|
||||||
static inline void close ();
|
static inline void close ();
|
||||||
// Singleton Access.
|
// Singleton Access.
|
||||||
|
@ -91,6 +92,12 @@ namespace Hurricane {
|
||||||
|
|
||||||
// Inline Functions.
|
// Inline Functions.
|
||||||
|
|
||||||
|
void DebugSession::open ( unsigned int traceLevel )
|
||||||
|
{
|
||||||
|
_singleton->_levels.push ( ltracelevel(traceLevel) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DebugSession::open ( const void* symbol, unsigned int traceLevel )
|
void DebugSession::open ( const void* symbol, unsigned int traceLevel )
|
||||||
{
|
{
|
||||||
if ( _singleton->_isTraced(symbol) )
|
if ( _singleton->_isTraced(symbol) )
|
||||||
|
|
|
@ -42,8 +42,7 @@ class HyperNet {
|
||||||
// ************
|
// ************
|
||||||
|
|
||||||
public: HyperNet(const Occurrence& occurrence);
|
public: HyperNet(const Occurrence& occurrence);
|
||||||
|
public: HyperNet(const HyperNet& hyperNet);
|
||||||
private: HyperNet(const HyperNet& hyperNet); // not implemented to forbid copy construction
|
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
// *********
|
// *********
|
||||||
|
|
|
@ -72,6 +72,7 @@ class Occurrence {
|
||||||
public: Cell* getMasterCell() const;
|
public: Cell* getMasterCell() const;
|
||||||
public: Property* getProperty(const Name& name) const;
|
public: Property* getProperty(const Name& name) const;
|
||||||
public: Properties getProperties() const;
|
public: Properties getProperties() const;
|
||||||
|
public: Occurrence getNetOccurrence() const;
|
||||||
public: Box getBoundingBox() const;
|
public: Box getBoundingBox() const;
|
||||||
public: Box getBoundingBox(const BasicLayer*) 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)
|
DirectSetLongAttribute (PyBasicLayer_setExtractNumber,setExtractNumber,"BasicLayer.setExtractNumber",PyBasicLayer,BasicLayer)
|
||||||
DirectSetCStringAttribute(PyBasicLayer_setRealName ,setRealName ,"BasicLayer.setRealName" ,PyBasicLayer,BasicLayer)
|
DirectSetCStringAttribute(PyBasicLayer_setRealName ,setRealName ,"BasicLayer.setRealName" ,PyBasicLayer,BasicLayer)
|
||||||
|
|
||||||
|
@ -125,6 +126,8 @@ extern "C" {
|
||||||
, "Create a new BasicLayer." }
|
, "Create a new BasicLayer." }
|
||||||
, { "getMaterial" , (PyCFunction)PyBasicLayer_getMaterial , METH_NOARGS
|
, { "getMaterial" , (PyCFunction)PyBasicLayer_getMaterial , METH_NOARGS
|
||||||
, "Returns the type of Material." }
|
, "Returns the type of Material." }
|
||||||
|
, { "getBlockageLayer" , (PyCFunction)PyBasicLayer_getBlockageLayer , METH_NOARGS
|
||||||
|
, "Returns the associated blockage layer, if any." }
|
||||||
, { "setBlockageLayer" , (PyCFunction)PyBasicLayer_setBlockageLayer , METH_VARARGS
|
, { "setBlockageLayer" , (PyCFunction)PyBasicLayer_setBlockageLayer , METH_VARARGS
|
||||||
, "Sets the blockage layer associated to this one." }
|
, "Sets the blockage layer associated to this one." }
|
||||||
, { "setExtractNumber" , (PyCFunction)PyBasicLayer_setExtractNumber , METH_VARARGS
|
, { "setExtractNumber" , (PyCFunction)PyBasicLayer_setExtractNumber , METH_VARARGS
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include "hurricane/DebugSession.h"
|
||||||
#include "hurricane/Error.h"
|
#include "hurricane/Error.h"
|
||||||
#include "hurricane/Warning.h"
|
#include "hurricane/Warning.h"
|
||||||
#include "hurricane/DataBase.h"
|
#include "hurricane/DataBase.h"
|
||||||
|
@ -45,6 +46,7 @@ namespace {
|
||||||
using Hurricane::inltrace;
|
using Hurricane::inltrace;
|
||||||
using Hurricane::ltracein;
|
using Hurricane::ltracein;
|
||||||
using Hurricane::ltraceout;
|
using Hurricane::ltraceout;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
using Hurricane::ForEachIterator;
|
using Hurricane::ForEachIterator;
|
||||||
using Hurricane::Warning;
|
using Hurricane::Warning;
|
||||||
using Hurricane::Error;
|
using Hurricane::Error;
|
||||||
|
@ -101,35 +103,39 @@ namespace {
|
||||||
|
|
||||||
class GlobalNetTable {
|
class GlobalNetTable {
|
||||||
public:
|
public:
|
||||||
GlobalNetTable ( KiteEngine* );
|
enum Flag { ClockIsRouted=0x0001 };
|
||||||
Net* getRootNet ( const Net*, Path ) const;
|
public:
|
||||||
inline Net* getVdde () const;
|
GlobalNetTable ( KiteEngine* );
|
||||||
inline Net* getVddi () const;
|
bool isCoreClockNetRouted ( const Net* ) const;
|
||||||
inline Net* getVsse () const;
|
Net* getRootNet ( const Net*, Path ) const;
|
||||||
inline Net* getVssi () const;
|
inline Net* getVdde () const;
|
||||||
inline Net* getCk () const;
|
inline Net* getVddi () const;
|
||||||
inline Net* getCki () const;
|
inline Net* getVsse () const;
|
||||||
inline Net* getCko () const;
|
inline Net* getVssi () const;
|
||||||
inline Net* getBlockage () const;
|
inline Net* getCk () const;
|
||||||
inline void setBlockage ( Net* );
|
inline Net* getCki () const;
|
||||||
|
inline Net* getCko () const;
|
||||||
|
inline Net* getBlockage () const;
|
||||||
|
inline void setBlockage ( Net* );
|
||||||
|
private:
|
||||||
|
bool guessGlobalNet ( const Name&, Net* );
|
||||||
private:
|
private:
|
||||||
bool guessGlobalNet ( const Name&, Net* );
|
unsigned int _flags;
|
||||||
private:
|
Name _vddePadNetName;
|
||||||
Name _vddePadNetName;
|
Name _vddiPadNetName;
|
||||||
Name _vddiPadNetName;
|
Name _vssePadNetName;
|
||||||
Name _vssePadNetName;
|
Name _vssiPadNetName;
|
||||||
Name _vssiPadNetName;
|
Name _ckPadNetName;
|
||||||
Name _ckPadNetName;
|
Name _ckiPadNetName;
|
||||||
Name _ckiPadNetName;
|
Name _ckoPadNetName;
|
||||||
Name _ckoPadNetName;
|
Net* _vdde;
|
||||||
Net* _vdde;
|
Net* _vddi;
|
||||||
Net* _vddi;
|
Net* _vsse;
|
||||||
Net* _vsse;
|
Net* _vssi;
|
||||||
Net* _vssi;
|
Net* _ck; // Clock net on the (external) pad.
|
||||||
Net* _ck; // Clock net on the (external) pad.
|
Net* _cki; // Clock net in the pad ring.
|
||||||
Net* _cki; // Clock net in the pad ring.
|
Net* _cko; // Clock net of the core (design).
|
||||||
Net* _cko; // Clock net of the core (design).
|
Net* _blockage;
|
||||||
Net* _blockage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,7 +150,8 @@ namespace {
|
||||||
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
|
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
|
||||||
|
|
||||||
GlobalNetTable::GlobalNetTable ( KiteEngine* kite )
|
GlobalNetTable::GlobalNetTable ( KiteEngine* kite )
|
||||||
: _vddePadNetName("vdde")
|
: _flags (0)
|
||||||
|
, _vddePadNetName("vdde")
|
||||||
, _vddiPadNetName("vddi")
|
, _vddiPadNetName("vddi")
|
||||||
, _vssePadNetName("vsse")
|
, _vssePadNetName("vsse")
|
||||||
, _vssiPadNetName("vssi")
|
, _vssiPadNetName("vssi")
|
||||||
|
@ -249,7 +256,7 @@ namespace {
|
||||||
if (netType == Net::Type::POWER) {
|
if (netType == Net::Type::POWER) {
|
||||||
if (_vddiPadNetName.isEmpty()) {
|
if (_vddiPadNetName.isEmpty()) {
|
||||||
_vddiPadNetName = inet->getName();
|
_vddiPadNetName = inet->getName();
|
||||||
_vddi = *inet;
|
_vddi = *inet;
|
||||||
} else {
|
} else {
|
||||||
cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n"
|
cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n"
|
||||||
" (will consider only <%s>)"
|
" (will consider only <%s>)"
|
||||||
|
@ -276,7 +283,13 @@ namespace {
|
||||||
if (_ckoPadNetName.isEmpty()) {
|
if (_ckoPadNetName.isEmpty()) {
|
||||||
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
|
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
|
||||||
_ckoPadNetName = inet->getName();
|
_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 {
|
} else {
|
||||||
cerr << Error("Second clock net <%s> net at top block level will be ignored.\n"
|
cerr << Error("Second clock net <%s> net at top block level will be ignored.\n"
|
||||||
" (will consider only <%s>)"
|
" (will consider only <%s>)"
|
||||||
|
@ -332,6 +345,13 @@ namespace {
|
||||||
if (name == _ckoPadNetName) {
|
if (name == _ckoPadNetName) {
|
||||||
cmess1 << " - Using <" << net->getName() << "> as core (internal:cko) clock net." << endl;
|
cmess1 << " - Using <" << net->getName() << "> as core (internal:cko) clock net." << endl;
|
||||||
_cko = net;
|
_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,6 +379,7 @@ namespace {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track up, *only* for clocks.
|
||||||
const Net* upNet = net;
|
const Net* upNet = net;
|
||||||
|
|
||||||
if (not path.isEmpty()) {
|
if (not path.isEmpty()) {
|
||||||
|
@ -367,10 +388,10 @@ namespace {
|
||||||
Plug* plug = NULL;
|
Plug* plug = NULL;
|
||||||
|
|
||||||
while ( true ) {
|
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 (path.isEmpty()) break;
|
||||||
|
if ((upNet == NULL) or not upNet->isExternal()) return _blockage;
|
||||||
|
|
||||||
instance = path.getTailInstance();
|
instance = path.getTailInstance();
|
||||||
plug = instance->getPlug(upNet);
|
plug = instance->getPlug(upNet);
|
||||||
|
@ -386,14 +407,23 @@ namespace {
|
||||||
<< " cko:" << ((_cko) ? _cko->getName() : "NULL")
|
<< " cko:" << ((_cko) ? _cko->getName() : "NULL")
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
if ( _ck and (upNet->getName() == _ck->getName() ) ) return _ck;
|
if (_ck and (upNet->getName() == _ck->getName() )) return _ck;
|
||||||
if ( _cki and (upNet->getName() == _cki->getName()) ) return _cki;
|
if (_cki and (upNet->getName() == _cki->getName())) return _cki;
|
||||||
if ( _cko and (upNet->getName() == _cko->getName()) ) return _cko;
|
|
||||||
|
if (_cko) {
|
||||||
|
if (upNet->getName() == _cko->getName()) {
|
||||||
|
if (isCoreClockNetRouted(upNet)) return _cko;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const
|
||||||
|
{ return (net == _cko) and (_flags & ClockIsRouted); }
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Class : "::PowerRailsPlanes".
|
// Class : "::PowerRailsPlanes".
|
||||||
|
|
||||||
|
@ -481,6 +511,7 @@ namespace {
|
||||||
PowerRailsPlanes ( KiteEngine* );
|
PowerRailsPlanes ( KiteEngine* );
|
||||||
~PowerRailsPlanes ();
|
~PowerRailsPlanes ();
|
||||||
inline Net* getRootNet ( Net*, Path );
|
inline Net* getRootNet ( Net*, Path );
|
||||||
|
inline bool isCoreClockNetRouted ( const Net* ) const;
|
||||||
bool hasPlane ( const BasicLayer* );
|
bool hasPlane ( const BasicLayer* );
|
||||||
bool setActivePlane ( const BasicLayer* );
|
bool setActivePlane ( const BasicLayer* );
|
||||||
inline Plane* getActivePlane () const;
|
inline Plane* getActivePlane () const;
|
||||||
|
@ -661,7 +692,10 @@ namespace {
|
||||||
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
||||||
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) {
|
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) {
|
||||||
TrackElement* element = TrackFixedSegment::create ( track, segment );
|
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 )
|
inline Net* PowerRailsPlanes::getRootNet ( Net* net, Path path )
|
||||||
{ return _globalNets.getRootNet(net,path); }
|
{ return _globalNets.getRootNet(net,path); }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool PowerRailsPlanes::isCoreClockNetRouted ( const Net* net ) const
|
||||||
|
{ return _globalNets.isCoreClockNetRouted(net); }
|
||||||
|
|
||||||
|
|
||||||
bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer )
|
bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer )
|
||||||
{ return (_planes.find(layer) != _planes.end()); }
|
{ return (_planes.find(layer) != _planes.end()); }
|
||||||
|
@ -1076,11 +1114,20 @@ namespace {
|
||||||
and (_routingGauge->getLayerDepth(component->getLayer()) < 2) )
|
and (_routingGauge->getLayerDepth(component->getLayer()) < 2) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Net* rootNet = _kite->getBlockageNet();
|
||||||
|
if (not _isBlockagePlane) {
|
||||||
|
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
Net* rootNet = NULL;
|
Net* rootNet = NULL;
|
||||||
if ( not _isBlockagePlane )
|
if ( not _isBlockagePlane )
|
||||||
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
|
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
|
||||||
else
|
else {
|
||||||
rootNet = _kite->getBlockageNet();
|
rootNet = _kite->getBlockageNet();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( rootNet == NULL ) {
|
if ( rootNet == NULL ) {
|
||||||
ltrace(300) << " rootNet is NULL, not taken into account." << endl;
|
ltrace(300) << " rootNet is NULL, not taken into account." << endl;
|
||||||
return;
|
return;
|
||||||
|
@ -1199,6 +1246,8 @@ namespace Kite {
|
||||||
|
|
||||||
void KiteEngine::buildPowerRails ()
|
void KiteEngine::buildPowerRails ()
|
||||||
{
|
{
|
||||||
|
//DebugSession::open( 300 );
|
||||||
|
|
||||||
if (not _blockageNet) {
|
if (not _blockageNet) {
|
||||||
_blockageNet = getCell()->getNet("blockagenet");
|
_blockageNet = getCell()->getNet("blockagenet");
|
||||||
if (not _blockageNet)
|
if (not _blockageNet)
|
||||||
|
@ -1226,6 +1275,8 @@ namespace Kite {
|
||||||
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
|
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
|
||||||
|
|
||||||
Session::revalidate ();
|
Session::revalidate ();
|
||||||
|
|
||||||
|
//DebugSession::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace Kite {
|
||||||
, _ripupLimits ()
|
, _ripupLimits ()
|
||||||
, _ripupCost (Cfg::getParamInt("kite.ripupCost" , 3)->asInt())
|
, _ripupCost (Cfg::getParamInt("kite.ripupCost" , 3)->asInt())
|
||||||
, _eventsLimit (Cfg::getParamInt("kite.eventsLimit" ,4000000)->asInt())
|
, _eventsLimit (Cfg::getParamInt("kite.eventsLimit" ,4000000)->asInt())
|
||||||
|
, _flags (0)
|
||||||
{
|
{
|
||||||
_ripupLimits[StrapRipupLimit] = Cfg::getParamInt("kite.strapRipupLimit" ,16)->asInt();
|
_ripupLimits[StrapRipupLimit] = Cfg::getParamInt("kite.strapRipupLimit" ,16)->asInt();
|
||||||
_ripupLimits[LocalRipupLimit] = Cfg::getParamInt("kite.localRipupLimit" , 7)->asInt();
|
_ripupLimits[LocalRipupLimit] = Cfg::getParamInt("kite.localRipupLimit" , 7)->asInt();
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace Kite {
|
||||||
: KatabaticEngine (cell)
|
: KatabaticEngine (cell)
|
||||||
, _viewer (NULL)
|
, _viewer (NULL)
|
||||||
, _knik (NULL)
|
, _knik (NULL)
|
||||||
, _blockageNet (NULL)
|
, _blockageNet (cell->getNet("blockagenet"))
|
||||||
, _configuration (new Configuration(getKatabaticConfiguration()))
|
, _configuration (new Configuration(getKatabaticConfiguration()))
|
||||||
, _routingPlanes ()
|
, _routingPlanes ()
|
||||||
, _negociateWindow (NULL)
|
, _negociateWindow (NULL)
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace Kite {
|
||||||
, RipupLimitsTableSize=4
|
, RipupLimitsTableSize=4
|
||||||
};
|
};
|
||||||
enum Constants { MaxMetalDepth=20 };
|
enum Constants { MaxMetalDepth=20 };
|
||||||
|
enum Flag { UseClockTree=0x0001 };
|
||||||
public:
|
public:
|
||||||
// Constructor & Destructor.
|
// Constructor & Destructor.
|
||||||
virtual Configuration* clone () const;
|
virtual Configuration* clone () const;
|
||||||
|
@ -58,6 +59,7 @@ namespace Kite {
|
||||||
// Decorateds.
|
// Decorateds.
|
||||||
virtual bool isGMetal ( const Layer* ) const;
|
virtual bool isGMetal ( const Layer* ) const;
|
||||||
virtual bool isGContact ( const Layer* ) const;
|
virtual bool isGContact ( const Layer* ) const;
|
||||||
|
inline bool useClockTree () const;
|
||||||
virtual size_t getDepth () const;
|
virtual size_t getDepth () const;
|
||||||
virtual size_t getAllowedDepth () const;
|
virtual size_t getAllowedDepth () const;
|
||||||
virtual DbU::Unit getSliceHeight () const;
|
virtual DbU::Unit getSliceHeight () const;
|
||||||
|
@ -102,6 +104,8 @@ namespace Kite {
|
||||||
inline void setPostEventCb ( PostEventCb_t );
|
inline void setPostEventCb ( PostEventCb_t );
|
||||||
void setHTracksReservedLocal ( size_t );
|
void setHTracksReservedLocal ( size_t );
|
||||||
void setVTracksReservedLocal ( size_t );
|
void setVTracksReservedLocal ( size_t );
|
||||||
|
inline void setFlags ( unsigned int );
|
||||||
|
inline void unsetFlags ( unsigned int );
|
||||||
virtual Record* _getRecord () const;
|
virtual Record* _getRecord () const;
|
||||||
virtual string _getString () const;
|
virtual string _getString () const;
|
||||||
virtual string _getTypeName () const;
|
virtual string _getTypeName () const;
|
||||||
|
@ -114,6 +118,7 @@ namespace Kite {
|
||||||
unsigned int _ripupLimits [RipupLimitsTableSize];
|
unsigned int _ripupLimits [RipupLimitsTableSize];
|
||||||
unsigned int _ripupCost;
|
unsigned int _ripupCost;
|
||||||
unsigned long _eventsLimit;
|
unsigned long _eventsLimit;
|
||||||
|
unsigned int _flags;
|
||||||
private:
|
private:
|
||||||
Configuration ( const Configuration& other, Katabatic::Configuration* base=NULL );
|
Configuration ( const Configuration& other, Katabatic::Configuration* base=NULL );
|
||||||
Configuration& operator= ( const Configuration& );
|
Configuration& operator= ( const Configuration& );
|
||||||
|
@ -130,6 +135,9 @@ namespace Kite {
|
||||||
inline void Configuration::setRipupCost ( unsigned int cost ) { _ripupCost = cost; }
|
inline void Configuration::setRipupCost ( unsigned int cost ) { _ripupCost = cost; }
|
||||||
inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; }
|
inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; }
|
||||||
inline void Configuration::setEventsLimit ( unsigned long limit ) { _eventsLimit = limit; }
|
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* create ( Cell* );
|
||||||
static KiteEngine* get ( const Cell* );
|
static KiteEngine* get ( const Cell* );
|
||||||
public:
|
public:
|
||||||
|
inline bool useClockTree () const;
|
||||||
inline CellViewer* getViewer () const;
|
inline CellViewer* getViewer () const;
|
||||||
inline KatabaticEngine* base ();
|
inline KatabaticEngine* base ();
|
||||||
inline Configuration* getKiteConfiguration ();
|
inline Configuration* getKiteConfiguration ();
|
||||||
|
@ -148,6 +149,7 @@ namespace Kite {
|
||||||
|
|
||||||
|
|
||||||
// Inline Functions.
|
// Inline Functions.
|
||||||
|
inline bool KiteEngine::useClockTree () const { return _configuration->useClockTree(); }
|
||||||
inline CellViewer* KiteEngine::getViewer () const { return _viewer; }
|
inline CellViewer* KiteEngine::getViewer () const { return _viewer; }
|
||||||
inline KatabaticEngine* KiteEngine::base () { return static_cast<KatabaticEngine*>(this); }
|
inline KatabaticEngine* KiteEngine::base () { return static_cast<KatabaticEngine*>(this); }
|
||||||
inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; }
|
inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; }
|
||||||
|
|
|
@ -1274,6 +1274,7 @@ void Graph::Dijkstra()
|
||||||
ostringstream message;
|
ostringstream message;
|
||||||
message << "In Graph::Dijkstra():\n";
|
message << "In Graph::Dijkstra():\n";
|
||||||
message << " Unable to reach target on net " << _working_net->getName() << ".";
|
message << " Unable to reach target on net " << _working_net->getName() << ".";
|
||||||
|
for ( auto iv : _vertexes_to_route ) message << "\n | " << iv;
|
||||||
throw Error( message.str() );
|
throw Error( message.str() );
|
||||||
}
|
}
|
||||||
assert( reachedDistance < (float)(HUGE_VAL) );
|
assert( reachedDistance < (float)(HUGE_VAL) );
|
||||||
|
|
|
@ -237,7 +237,6 @@ void KnikEngine::initGlobalRouting( const map<Name,Net*>& excludedNets )
|
||||||
|
|
||||||
if ( inet->isGlobal()
|
if ( inet->isGlobal()
|
||||||
or inet->isSupply()
|
or inet->isSupply()
|
||||||
or inet->isClock()
|
|
||||||
or (inet->getName() == obstacleNetName) ) {
|
or (inet->getName() == obstacleNetName) ) {
|
||||||
cmess2 << " - <" << inet->getName() << "> not routed (global, supply, clock or obstacle)." << endl;
|
cmess2 << " - <" << inet->getName() << "> not routed (global, supply, clock or obstacle)." << endl;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace Mauka {
|
||||||
|
|
||||||
void FeedCells::addFeed ( Cell* cell )
|
void FeedCells::addFeed ( Cell* cell )
|
||||||
{
|
{
|
||||||
if ( cell == NULL ) return;
|
if (cell == NULL) return;
|
||||||
|
if (not _feedCells.size()) return;
|
||||||
|
|
||||||
DbU::Unit pitch = _mauka->getPitch();
|
DbU::Unit pitch = _mauka->getPitch();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue