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:
Jean-Paul Chaput 2015-02-24 13:13:17 +01:00
parent 3b343f08cf
commit 6d366a08bc
30 changed files with 481 additions and 233 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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 );
} }

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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;
} }
} }
} }

View File

@ -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();

View File

@ -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 )

View File

@ -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
// *********************************************************************************** // ***********************************************************************************
{ {

View File

@ -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
// ********************************** // **********************************
{ {

View File

@ -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

View File

@ -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) )

View File

@ -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
// ********* // *********

View File

@ -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;

View File

@ -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

View File

@ -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();
} }

View File

@ -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();

View File

@ -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)

View File

@ -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; }

View File

@ -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; }

View File

@ -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) );

View File

@ -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;

View File

@ -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();