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 )
{
trace << "PyRoutingGauge_getRoutingLayer()" << endl;
@ -318,6 +349,8 @@ extern "C" {
, "Return the RoutingLayerGauge of the given layer/depth." }
, { "getLayerDirection" , (PyCFunction)PyRoutingGauge_getLayerDirection, METH_VARARGS
, "Return the direction of the given layer/depth." }
, { "getLayerPitch" , (PyCFunction)PyRoutingGauge_getLayerPitch , METH_VARARGS
, "Return the pitch of the given layer/depth." }
, { "getRoutingLayer" , (PyCFunction)PyRoutingGauge_getRoutingLayer , METH_VARARGS
, "Return the routing layer used for the requested depth." }
, { "getContactLayer" , (PyCFunction)PyRoutingGauge_getContactLayer , METH_VARARGS

View File

@ -48,6 +48,7 @@ try:
import Nimbus
import Metis
import Mauka
import Etesian
import Katabatic
import Kite
import Unicorn
@ -140,17 +141,28 @@ class PlaceCore ( chip.Configuration.ChipConfWrapper ):
if self.useClockTree and ckCore:
ht = clocktree.ClockTree.HTree.create( self, coreCell, ckCore, coreCell.getAbutmentBox() )
ht.addCloned( self.cell )
mauka = Mauka.MaukaEngine.create( coreCell )
mauka.run()
mauka.destroy()
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
mauka = Mauka.MaukaEngine.create( coreCell )
mauka.run()
mauka.destroy()
else:
etesian = Etesian.EtesianEngine.create( coreCell )
etesian.place( Etesian.EtesianEngine.SlowMotion )
etesian.destroy()
ht.connectLeaf()
ht.prune()
#ht.prune()
ht.route()
ht.save( self.cell )
else:
mauka = Mauka.MaukaEngine.create( coreCell )
mauka.run()
mauka.destroy()
if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian':
mauka = Mauka.MaukaEngine.create( coreCell )
mauka.run()
mauka.destroy()
else:
etesian = Etesian.EtesianEngine.create( coreCell )
etesian.place( Etesian.EtesianEngine.SlowMotion )
etesian.destroy()
return

View File

@ -121,6 +121,18 @@ class StackedVia ( object ):
if depth > self._topDepth: self._topDepth = depth
return
def getLayer ( self, fromTop ):
if self._topDepth-fromTop >= self._bottomDepth:
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
return routingGauge.getRoutingLayer(self._topDepth-fromTop)
return None
def getBlockageLayer ( self, fromTop ):
if self._topDepth-fromTop >= self._bottomDepth:
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
return routingGauge.getRoutingLayer(self._topDepth-fromTop).getBlockageLayer()
return None
def getVia ( self, metal ):
if not self._hasLayout: return None
for via in self._vias:

View File

@ -150,7 +150,7 @@ class VerticalRail ( Rail ):
, via[2].getY()
, via[2].getHeight()
)
railVias.append( via[1].getVia( self.side.getVLayer()) )
railVias.append( via[1].getVia(self.side.getVLayer()) )
railVias.sort( key=methodcaller('getY') )
@ -161,6 +161,21 @@ class VerticalRail ( Rail ):
, self.axis
, self.side.vRailWidth
)
routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
for depth in range(self.side.verticalDepth-2,self.vias.values()[0][1]._bottomDepth,-2):
blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer()
pitch = routingGauge.getLayerPitch(depth)
for i in range(1,len(railVias)):
Vertical.create( self.side.blockageNet
, blockageLayer
, self.axis
, self.side.vRailWidth
, railVias[i-1].getBoundingBox().getYMax() + pitch
, railVias[i ].getBoundingBox().getYMin() - pitch
)
return
def connect ( self, contact ):
@ -224,25 +239,31 @@ class Side ( object ):
return
@property
def railsNb ( self ): return self._corona._railsNb
@property
def innerBb ( self ): return self._corona._innerBb
@property
def hRailWidth ( self ): return self._corona._hRailWidth
@property
def hRailSpace ( self ): return self._corona._hRailSpace
@property
def vRailWidth ( self ): return self._corona._vRailWidth
@property
def vRailSpace ( self ): return self._corona._vRailSpace
@property
def corners ( self ): return self._corona._corners
def railsNb ( self ): return self._corona._railsNb
@property
def innerBb ( self ): return self._corona._innerBb
@property
def hRailWidth ( self ): return self._corona._hRailWidth
@property
def hRailSpace ( self ): return self._corona._hRailSpace
@property
def vRailWidth ( self ): return self._corona._vRailWidth
@property
def vRailSpace ( self ): return self._corona._vRailSpace
@property
def corners ( self ): return self._corona._corners
@property
def horizontalDepth ( self ): return self._corona.horizontalDepth
@property
def verticalDepth ( self ): return self._corona.verticalDepth
@property
def blockageNet ( self ): return self._corona.blockageNet
def getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal)
def getRail ( self, i ): return self._rails[i]
def getRailNet ( self, i ): return self._corona.getRailNet(i)
def getHLayer ( self ): return self._corona.getHLayer()
def getVLayer ( self ): return self._corona.getVLayer()
def getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal)
def getRail ( self, i ): return self._rails[i]
def getRailNet ( self, i ): return self._corona.getRailNet(i)
def getHLayer ( self ): return self._corona.getHLayer()
def getVLayer ( self ): return self._corona.getVLayer()
def getRailAxis ( self, i ):
raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' )
@ -306,7 +327,7 @@ class SouthSide ( HorizontalSide ):
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
- i*(self.hRailWidth + self.hRailSpace)
def corner0 ( self, i ): return self.corners[chip.SouthWest ][i]
def corner0 ( self, i ): return self.corners[chip.SouthWest][i]
def corner1 ( self, i ): return self.corners[chip.SouthEast][i]
@ -379,6 +400,8 @@ class Corona ( object ):
self._innerBb = self._block.bb
self._block.path.getTransformation().applyOn( self._innerBb )
self._innerBb.inflate( self._hRailSpace/2, self._vRailSpace/2 )
if not self.useClockTree: self._railsNb -= 1
self._southSide = SouthSide( self )
self._northSide = NorthSide( self )
@ -387,6 +410,8 @@ class Corona ( object ):
return
@property
def useClockTree ( self ): return self._block.useClockTree
@property
def routingGauge ( self ): return self._block.routingGauge
@property
@ -395,12 +420,14 @@ class Corona ( object ):
def horizontalDepth ( self ): return self._block.horizontalDepth
@property
def verticalDepth ( self ): return self._block.verticalDepth
@property
def blockageNet ( self ): return self._block.blockageNet
def getLayerDepth ( self, metal ):
return self.routingGauge.getLayerDepth( metal )
def getRailNet ( self, i ):
if i == self._railsNb-1: return self._block.cko
if self.useClockTree and i == self._railsNb-1: return self._block.cko
if i % 2: return self._block.vssi
return self._block.vddi

View File

@ -219,7 +219,7 @@ class Block ( chip.Configuration.ChipConfWrapper ):
def connectClock ( self ):
if not self.useClockTree:
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False) ignored." )
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
return
if not self.cko:

View File

@ -17,6 +17,7 @@
import sys
import os.path
import Cfg
from Hurricane import Breakpoint
from Hurricane import DbU
from Hurricane import Box
from Hurricane import Transformation
@ -433,13 +434,14 @@ class ChipConf ( object ):
def _guessGlobalNet ( self, name, net ):
if name == self._vddeName: self._vdde = net
if name == self._vddiName: self._vddi = net
if name == self._vsseName: self._vsse = net
if name == self._vssiName: self._vssi = net
if name == self._ckiName: self._cki = net
if name == self._ckoName: self._cko = net
if name == self._ckName: self._ck = net
if name == self._vddeName: self._vdde = net
if name == self._vddiName: self._vddi = net
if name == self._vsseName: self._vsse = net
if name == self._vssiName: self._vssi = net
if name == self._ckiName: self._cki = net
if name == self._ckoName: self._cko = net
if name == self._ckName: self._ck = net
if name == self._blockageName: self._blockageNet = net
return
@ -469,6 +471,7 @@ class ChipConf ( object ):
self._ckiName = "ck"
self._ckoName = "cko"
self._ckName = "pad"
self._blockageName = "blockagenet"
# Global Nets.
self._vdde = None
self._vddi = None
@ -477,6 +480,7 @@ class ChipConf ( object ):
self._cki = None
self._cko = None
self._ck = None
self._blockageNet = None
self._clockPad = None
self._powerPad = None
@ -553,10 +557,10 @@ class ChipConf ( object ):
self._guessGlobalNet( masterNet.getName(), net )
if self._clockPad:
for plug in self._powerPad.getPlugs():
for plug in self._clockPad.getPlugs():
masterNet = plug.getMasterNet()
netType = masterNet.getType()
net = plug.getNet()
net = plug.getNet()
if not net:
net = self._cell.getNet( masterNet.getName() )
@ -567,6 +571,22 @@ class ChipConf ( object ):
if masterNet.getName() == self._ckName:
self._guessGlobalNet( masterNet.getName(), net )
for netData in ( (self._vddeName,self._vdde,'pad ring external power')
, (self._vddiName,self._vddi,'pad ring internal power')
, (self._vsseName,self._vsse,'pad ring external ground')
, (self._vssiName,self._vssi,'pad ring external ground')
, (self._ckiName ,self._cki ,'pad ring inner clock')
, (self._ckoName ,self._cko ,'core clock')
, (self._ckName ,self._ck ,'external chip clock')
):
if not netData[1]:
print ErrorMessage( 1, 'Missing global net <%s> (%s) at chip level.' % (netData[0],netData[2]) )
self._validated = False
self._blockageNet = self._cell.getNet(self._blockageName)
if not self._blockageNet:
self._blockageNet = Net.create( self._cell, self._blockageName )
return
@ -653,19 +673,21 @@ class ChipConfWrapper ( GaugeConfWrapper ):
# Global Nets.
@property
def vdde ( self ): return self._chipConf._vdde
def vdde ( self ): return self._chipConf._vdde
@property
def vsse ( self ): return self._chipConf._vsse
@property
def vddi ( self ): return self._chipConf._vddi
@property
def vssi ( self ): return self._chipConf._vssi
@property
def cki ( self ): return self._chipConf._cki
@property
def cko ( self ): return self._chipConf._cko
@property
def ck ( self ): return self._chipConf._ck
@property
def vsse ( self ): return self._chipConf._vsse
@property
def vddi ( self ): return self._chipConf._vddi
@property
def vssi ( self ): return self._chipConf._vssi
@property
def cki ( self ): return self._chipConf._cki
@property
def cko ( self ): return self._chipConf._cko
@property
def ck ( self ): return self._chipConf._ck
def blockageNet ( self ): return self._chipConf._blockageNet
# Various.
@property

View File

@ -181,7 +181,8 @@ class Side ( object ):
#print 'Power pad:', pad
self._createPowerContacts( pad, self._corona.vddi )
self._createPowerContacts( pad, self._corona.vssi )
self._createPowerContacts( pad, self._corona.cko )
if self._corona.useClockTree:
self._createPowerContacts( pad, self._corona.cko )
return

View File

@ -165,7 +165,7 @@ class HTree ( GaugeConfWrapper ):
yslice = self.toYCellGrid(y)
transformation = Transformation.Orientation.ID
if (yslice / self.cellGauge.getSliceHeight()) % 2 != 0:
if ((yslice-self.area.getYMin()) / self.cellGauge.getSliceHeight()) % 2 != 0:
transformation = Transformation.Orientation.MY
yslice += self.cellGauge.getSliceHeight()
@ -505,7 +505,7 @@ class HTreeNode ( object ):
return
def route ( self ):
if not self.hasLeafs(): return
trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() )
leftSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
rightSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
@ -527,7 +527,7 @@ class HTreeNode ( object ):
def connectLeafs ( self ):
if not self.hasLeafs():
trace( 550, '\tHTree %s has no leafs\n' % self.sourceBuffer.getName() )
trace( 550, '\tHTreeNode.connectLeafs() %s has no leafs\n' % self.sourceBuffer.getName() )
if self.childs:
self.childs[0].connectLeafs()

View File

@ -304,14 +304,67 @@ namespace Etesian {
using Hurricane::Occurrence;
size_t EtesianEngine::findYSpin ()
{
_flags &= ~YSpinSet;
_yspinSlice0 = 0;
Box topCellAb = getCell()->getAbutmentBox();
if (not topCellAb.isEmpty()) {
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
{
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
Cell* masterCell = instance->getMasterCell();
Box instanceAb = masterCell->getAbutmentBox();
Transformation instanceTransf = instance->getTransformation();
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
instanceTransf.applyOn( instanceAb );
if (not topCellAb.contains(instanceAb)) continue;
_flags |= YSpinSet;
int islice = (instanceAb.getYMin() - getCell()->getAbutmentBox().getYMin()) / getSliceHeight();
switch ( instanceTransf.getOrientation() ) {
case Transformation::Orientation::ID:
case Transformation::Orientation::MX:
_yspinSlice0 = (islice % 2);
break;
case Transformation::Orientation::R2:
case Transformation::Orientation::MY:
_yspinSlice0 = ((islice+1) % 2);
break;
case Transformation::Orientation::R1:
case Transformation::Orientation::R3:
case Transformation::Orientation::XR:
case Transformation::Orientation::YR:
cerr << Warning( "Instance %s has invalid transformation %s."
, getString(instance->getName()).c_str()
, getString(instanceTransf.getOrientation()).c_str()
) << endl;
_flags &= ~YSpinSet;
break;
}
if (_flags & YSpinSet) break;
}
}
return _yspinSlice0;
}
void EtesianEngine::addFeeds ()
{
UpdateSession::open();
bool yspinSet = false;
size_t yspinSlice0 = 0;
SliceHoles sliceHoles ( this );
Box toCellAb = getCell()->getAbutmentBox();
SliceHoles sliceHoles ( this );
Box topCellAb = getCell()->getAbutmentBox();
sliceHoles.setSpinSlice0( _yspinSlice0 );
forEach ( Occurrence, ioccurrence, getCell()->getLeafInstanceOccurrences() )
{
@ -329,41 +382,12 @@ namespace Etesian {
(*ioccurrence).getPath().getTransformation().applyOn( instanceTransf );
instanceTransf.applyOn( instanceAb );
if (not toCellAb.contains(instanceAb)) {
if (not topCellAb.contains(instanceAb)) {
cerr << Warning( "Instance %s is not fully enclosed in the top cell."
, getString(instance->getName()).c_str() ) << endl;
continue;
}
if (not yspinSet) {
yspinSet = true;
int islice = (instanceAb.getYMin() - getCell()->getAbutmentBox().getYMin()) / getSliceHeight();
switch ( instanceTransf.getOrientation() ) {
case Transformation::Orientation::ID:
case Transformation::Orientation::MX:
yspinSlice0 = (islice % 2);
break;
case Transformation::Orientation::R2:
case Transformation::Orientation::MY:
yspinSlice0 = ((islice+1) % 2);
break;
case Transformation::Orientation::R1:
case Transformation::Orientation::R3:
case Transformation::Orientation::XR:
case Transformation::Orientation::YR:
cerr << Warning( "Instance %s has invalid transformation %s."
, getString(instance->getName()).c_str()
, getString(instanceTransf.getOrientation()).c_str()
) << endl;
yspinSet = false;
break;
}
sliceHoles.setSpinSlice0( yspinSlice0 );
}
sliceHoles.merge( instanceAb );
}

View File

@ -284,10 +284,16 @@ namespace Etesian {
void EtesianEngine::_postCreate ()
{
// Ugly. Direct uses of Alliance Framework.
// Must change toward something in the settings.
_feedCells.useFeed( AllianceFramework::get()->getCell("tie_x0" ,Catalog::State::Views) );
_feedCells.useFeed( AllianceFramework::get()->getCell("rowend_x0",Catalog::State::Views) );
// Ugly: Name based detection of ISPD benchmarks.
if (getString(getCell()->getName()).substr(0,7) == "bigblue") {
cmess1 << " o ISPD benchmark <" << getCell()->getName()
<< ">, no feed cells will be added." << endl;
} else {
// Ugly: Direct uses of Alliance Framework.
// Must change toward something in the settings.
_feedCells.useFeed( AllianceFramework::get()->getCell("tie_x0" ,Catalog::State::Views) );
_feedCells.useFeed( AllianceFramework::get()->getCell("rowend_x0",Catalog::State::Views) );
}
}
@ -469,14 +475,14 @@ namespace Etesian {
DbU::Unit pitch = getPitch();
cmess1 << " - Building RoutingPads (transhierarchical) ..." << endl;
getCell()->flattenNets( Cell::BuildRings );
getCell()->flattenNets( Cell::BuildRings|Cell::NoClockFlatten );
// Coloquinte circuit description data-structures.
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
vector<Transformation> idsToTransf ( instancesNb );
vector<temporary_cell> instances ( instancesNb );
size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize();
vector<Transformation> idsToTransf ( instancesNb );
vector<temporary_cell> instances ( instancesNb );
vector< point<int_t> > positions ( instancesNb );
vector< point<bool> > orientations( instancesNb, point<bool>(true, true) );
vector< point<bool> > orientations( instancesNb, point<bool>(true, true) );
cmess1 << " - Converting " << instancesNb << " instances" << endl;
cout.flush();
@ -614,6 +620,7 @@ namespace Etesian {
if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb();
findYSpin();
toColoquinte();
cmess1 << " o Running Coloquinte." << endl;
@ -740,7 +747,7 @@ namespace Etesian {
_progressReport1( startTime, " Local Swaps ...." );
if (i == legalizeIterations-1) {
row_compatible_orientation( _circuit, legalizer, true );
row_compatible_orientation( _circuit, legalizer, (_yspinSlice0 == 0) );
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
_progressReport1( startTime, " Final Legalize ." );
}
@ -822,7 +829,6 @@ namespace Etesian {
{
Point instancePosition;
Instance* instance = static_cast<Instance*>((*ioccurrence).getEntity());
//Cell* masterCell = instance->getMasterCell();
string instanceName = (*ioccurrence).getCompactString();
// Remove the enclosing brackets...
instanceName.erase( 0, 1 );
@ -832,23 +838,15 @@ namespace Etesian {
if (iid == _cellsToIds.end() ) {
cerr << Error( "Unable to lookup instance <%s>.", instanceName.c_str() ) << endl;
} else {
point<int_t> position = placement.positions_[(*iid).second];
/*
if ( isNan(position.x_) or isNan(position.y_) ) {
cerr << Error( "Instance <%s> is not placed yet (position == NaN)."
, instanceName.c_str() ) << endl;
instance->setPlacementStatus( Instance::PlacementStatus::UNPLACED );
if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED)
continue;
}
*/
Transformation trans = toTransformation( position
, placement.orientations_[(*iid).second]
, instance->getMasterCell()
, getPitch()
);
point<int_t> position = placement.positions_[(*iid).second];
Transformation trans = toTransformation( position
, placement.orientations_[(*iid).second]
, instance->getMasterCell()
, getPitch()
);
//cerr << "Setting <" << instanceName << " @" << instancePosition << endl;
// This is temporary as it's not trans-hierarchic: we ignore the posutions

View File

@ -55,7 +55,8 @@ namespace Etesian {
enum Flag { NoPlacement=0x0001
, FlatDesign =0x0002
, ForceUpdate=0x0004
, SlowMotion =0x0008
, YSpinSet =0x0008
, SlowMotion =0x0010
};
public:
static const Name& staticGetName ();
@ -79,6 +80,7 @@ namespace Etesian {
void toColoquinte ();
void place ( unsigned int flags=SlowMotion );
inline void useFeed ( Cell* );
size_t findYSpin ();
void addFeeds ();
virtual Record* _getRecord () const;
virtual std::string _getString () const;
@ -99,6 +101,7 @@ namespace Etesian {
std::vector<Instance*> _idsToInsts;
Hurricane::CellWidget* _cellWidget;
FeedCells _feedCells;
size_t _yspinSlice0;
protected:
// Constructors & Destructors.

View File

@ -30,6 +30,7 @@ namespace Etesian {
class FeedCells {
public:
inline FeedCells ( EtesianEngine* );
inline size_t feedNumbers () const;
void useFeed ( Cell* );
Cell* getBiggestFeed () const;
Cell* getSmallestFeed () const;
@ -50,6 +51,9 @@ namespace Etesian {
{ }
inline size_t FeedCells::feedNumbers () const { return _feedCells.size(); }
} // Etesian namespace.
#endif // ETESIAN_FEEDCELLS_H

View File

@ -192,29 +192,29 @@ void Cell::setAbutmentBox(const Box& abutmentBox)
void Cell::flattenNets(unsigned int flags)
// ***************************************
{
trace << "Cell::flattenNets() flags:0x" << hex << flags << endl;
UpdateSession::open();
_flags |= FlattenedNets;
vector<HyperNet> hyperNets;
vector<HyperNet> topHyperNets;
forEach ( Occurrence, ioccurrence, getHyperNetRootNetOccurrences() ) {
Net* net = static_cast<Net*>((*ioccurrence).getEntity());
if (net->isClock() and (flags & NoClockFlatten)) continue;
HyperNet hyperNet ( *ioccurrence );
if ( not (*ioccurrence).getPath().isEmpty() ) {
DeepNet* deepNet = DeepNet::create( hyperNet );
if (deepNet) deepNet->_createRoutingPads( flags );
} else {
RoutingPad* previousRp = NULL;
RoutingPad* currentRp = NULL;
bool buildRing = false;
if (net->isGlobal()) {
if ( (flags & Cell::BuildClockRings ) and net->isClock () ) buildRing = true;
else if ( (flags & Cell::BuildSupplyRings) and net->isSupply() ) buildRing = true;
Net* duplicate = getNet( (*ioccurrence).getName() );
if (not duplicate) {
hyperNets.push_back( HyperNet(*ioccurrence) );
} else {
buildRing = flags & Cell::BuildRings;
cerr << "Found " << duplicate << " in " << duplicate->getCell() << endl;
}
} else {
bool hasRoutingPads = false;
forEach ( Component*, icomponent, net->getComponents() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( *icomponent );
@ -228,51 +228,72 @@ void Cell::flattenNets(unsigned int flags)
}
if (hasRoutingPads) continue;
forEach ( Component*, icomponent, net->getComponents() ) {
Plug* primaryPlug = dynamic_cast<Plug*>( *icomponent );
if (primaryPlug) {
if ( !primaryPlug->getBodyHook()->getSlaveHooks().isEmpty() ) {
cerr << "[ERROR] " << primaryPlug << "\n"
<< " has attached components, not managed yet." << endl;
} else {
primaryPlug->getBodyHook()->detach();
}
topHyperNets.push_back( HyperNet(*ioccurrence) );
}
}
for ( size_t i=0 ; i<hyperNets.size() ; ++i ) {
DeepNet* deepNet = DeepNet::create( hyperNets[i] );
if (deepNet) deepNet->_createRoutingPads( flags );
}
for ( size_t i=0 ; i<topHyperNets.size() ; ++i ) {
Net* net = static_cast<Net*>(topHyperNets[i].getNetOccurrence().getEntity());
RoutingPad* previousRp = NULL;
RoutingPad* currentRp = NULL;
bool buildRing = false;
if (net->isGlobal()) {
if ( (flags & Cell::BuildClockRings ) and net->isClock () ) buildRing = true;
else if ( (flags & Cell::BuildSupplyRings) and net->isSupply() ) buildRing = true;
} else {
buildRing = flags & Cell::BuildRings;
}
forEach ( Component*, icomponent, net->getComponents() ) {
Plug* primaryPlug = dynamic_cast<Plug*>( *icomponent );
if (primaryPlug) {
if (not primaryPlug->getBodyHook()->getSlaveHooks().isEmpty()) {
cerr << "[ERROR] " << primaryPlug << "\n"
<< " has attached components, not managed yet." << endl;
} else {
primaryPlug->getBodyHook()->detach();
}
}
}
forEach ( Occurrence, iplugOccurrence, hyperNet.getLeafPlugOccurrences() ) {
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
currentRp->materialize();
forEach ( Occurrence, iplugOccurrence, topHyperNets[i].getLeafPlugOccurrences() ) {
currentRp = RoutingPad::create( net, *iplugOccurrence, RoutingPad::BiggestArea );
currentRp->materialize();
if (flags & WarnOnUnplacedInstances)
currentRp->isPlacedOccurrence( RoutingPad::ShowWarning );
if (flags & WarnOnUnplacedInstances)
currentRp->isPlacedOccurrence( RoutingPad::ShowWarning );
if (buildRing) {
if (previousRp) {
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
}
Plug* plug = static_cast<Plug*>( (*iplugOccurrence).getEntity() );
if ( (*iplugOccurrence).getPath().isEmpty() ) {
plug->getBodyHook()->attach( currentRp->getBodyHook() );
plug->getBodyHook()->detach();
}
previousRp = currentRp;
}
}
forEach ( Component*, icomponent, net->getComponents() ) {
Pin* pin = dynamic_cast<Pin*>( *icomponent );
if (pin) {
currentRp = RoutingPad::create( pin );
if (buildRing) {
if (previousRp) {
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
}
Plug* plug = static_cast<Plug*>( (*iplugOccurrence).getEntity() );
if ( (*iplugOccurrence).getPath().isEmpty() ) {
plug->getBodyHook()->attach( currentRp->getBodyHook() );
plug->getBodyHook()->detach();
}
previousRp = currentRp;
}
}
forEach ( Component*, icomponent, net->getComponents() ) {
Pin* pin = dynamic_cast<Pin*>( *icomponent );
if (pin) {
currentRp = RoutingPad::create( pin );
if (buildRing) {
if (previousRp) {
currentRp->getBodyHook()->attach( previousRp->getBodyHook() );
}
pin->getBodyHook()->attach( currentRp->getBodyHook() );
pin->getBodyHook()->detach();
}
previousRp = currentRp;
pin->getBodyHook()->attach( currentRp->getBodyHook() );
pin->getBodyHook()->detach();
}
previousRp = currentRp;
}
}
}

View File

@ -4780,10 +4780,13 @@ void Cell_HyperNetRootNetOccurrences::Locator::progress()
{
if (_netLocator.isValid())
{
do {
_netLocator.progress();
}
while (_netLocator.isValid() && !isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path)));
_netLocator.progress();
while ( _netLocator.isValid() ) {
if ( not dynamic_cast<DeepNet*>(_netLocator.getElement())
and isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path))) break;
_netLocator.progress();
}
}
else if (_hyperNetRootNetOccurrenceLocator.isValid())
_hyperNetRootNetOccurrenceLocator.progress();

View File

@ -55,7 +55,9 @@ namespace Hurricane {
,netOccurrence.getName()
)
, _netOccurrence(netOccurrence)
{ }
{
//trace << "DeepNet::DeepNet() " << getCell() << " " << this << endl;
}
DeepNet* DeepNet::create ( HyperNet& hyperNet )

View File

@ -259,30 +259,21 @@ class HyperNet_LeafPlugOccurrences : public Collection<Occurrence> {
// ****************************************************************************************************
HyperNet::HyperNet(const Occurrence& occurrence)
// *******************************************
: _netOccurrence()
// *********************************************
: _netOccurrence(occurrence.getNetOccurrence())
{
if (occurrence.isValid()) {
Entity* entity = occurrence.getEntity();
if (dynamic_cast<Net*>(entity))
_netOccurrence = occurrence;
else {
if (dynamic_cast<Rubber*>(entity)) {
Rubber* rubber = (Rubber*)entity;
_netOccurrence = Occurrence(rubber->getNet(), occurrence.getPath());
}
else {
if (dynamic_cast<Component*>(entity)) {
Component* component = (Component*)entity;
_netOccurrence = Occurrence(component->getNet(), occurrence.getPath());
}
else
throw Error("Can't create " + _TName("HyperNet") + " : bad occurrence entity type");
}
}
}
if (not occurrence.isValid())
throw Error("Can't create " + _TName("HyperNet") + " : bad occurrence entity type");
}
HyperNet::HyperNet(const HyperNet& other)
// *********************************************
: _netOccurrence(other._netOccurrence)
{
}
Occurrences HyperNet::getNetOccurrences(bool doExtraction, bool allowInterruption) const
// ***********************************************************************************
{

View File

@ -126,6 +126,27 @@ Properties Occurrence::getProperties() const
return Properties();
}
Occurrence Occurrence::getNetOccurrence() const
// ********************************************
{
if (isValid()) {
Entity* entity = getEntity();
if (dynamic_cast<Net*>(entity)) return *this;
else {
Rubber* rubber = dynamic_cast<Rubber*>(entity);
if (rubber) return Occurrence(rubber->getNet(), getPath());
else {
Component* component = dynamic_cast<Component*>(entity);
if (component) return Occurrence(component->getNet(), getPath());
}
}
}
return Occurrence();
}
Box Occurrence::getBoundingBox() const
// **********************************
{

View File

@ -68,7 +68,8 @@ class Cell : public Entity {
public: enum Flag { BuildRings = 0x0001
, BuildClockRings = 0x0002
, BuildSupplyRings = 0x0004
, WarnOnUnplacedInstances = 0x0008
, NoClockFlatten = 0x0008
, WarnOnUnplacedInstances = 0x0010
// Flags set for Observers.
, CellAboutToChange = 0x0001
, CellChanged = 0x0002

View File

@ -61,6 +61,7 @@ namespace Hurricane {
static inline void addToTrace ( const void* symbol );
static inline void addToTrace ( const Cell*, const Name& );
static inline void addToTrace ( const Net* );
static inline void open ( unsigned int traceLevel );
static inline void open ( const void* symbol, unsigned int traceLevel=80 );
static inline void close ();
// Singleton Access.
@ -91,6 +92,12 @@ namespace Hurricane {
// Inline Functions.
void DebugSession::open ( unsigned int traceLevel )
{
_singleton->_levels.push ( ltracelevel(traceLevel) );
}
void DebugSession::open ( const void* symbol, unsigned int traceLevel )
{
if ( _singleton->_isTraced(symbol) )

View File

@ -42,8 +42,7 @@ class HyperNet {
// ************
public: HyperNet(const Occurrence& occurrence);
private: HyperNet(const HyperNet& hyperNet); // not implemented to forbid copy construction
public: HyperNet(const HyperNet& hyperNet);
// Operators
// *********

View File

@ -72,6 +72,7 @@ class Occurrence {
public: Cell* getMasterCell() const;
public: Property* getProperty(const Name& name) const;
public: Properties getProperties() const;
public: Occurrence getNetOccurrence() const;
public: Box getBoundingBox() const;
public: Box getBoundingBox(const BasicLayer*) const;

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)
DirectSetCStringAttribute(PyBasicLayer_setRealName ,setRealName ,"BasicLayer.setRealName" ,PyBasicLayer,BasicLayer)
@ -125,6 +126,8 @@ extern "C" {
, "Create a new BasicLayer." }
, { "getMaterial" , (PyCFunction)PyBasicLayer_getMaterial , METH_NOARGS
, "Returns the type of Material." }
, { "getBlockageLayer" , (PyCFunction)PyBasicLayer_getBlockageLayer , METH_NOARGS
, "Returns the associated blockage layer, if any." }
, { "setBlockageLayer" , (PyCFunction)PyBasicLayer_setBlockageLayer , METH_VARARGS
, "Sets the blockage layer associated to this one." }
, { "setExtractNumber" , (PyCFunction)PyBasicLayer_setExtractNumber , METH_VARARGS

View File

@ -16,6 +16,7 @@
#include <map>
#include <list>
#include "hurricane/DebugSession.h"
#include "hurricane/Error.h"
#include "hurricane/Warning.h"
#include "hurricane/DataBase.h"
@ -45,6 +46,7 @@ namespace {
using Hurricane::inltrace;
using Hurricane::ltracein;
using Hurricane::ltraceout;
using Hurricane::DebugSession;
using Hurricane::ForEachIterator;
using Hurricane::Warning;
using Hurricane::Error;
@ -101,35 +103,39 @@ namespace {
class GlobalNetTable {
public:
GlobalNetTable ( KiteEngine* );
Net* getRootNet ( const Net*, Path ) const;
inline Net* getVdde () const;
inline Net* getVddi () const;
inline Net* getVsse () const;
inline Net* getVssi () const;
inline Net* getCk () const;
inline Net* getCki () const;
inline Net* getCko () const;
inline Net* getBlockage () const;
inline void setBlockage ( Net* );
enum Flag { ClockIsRouted=0x0001 };
public:
GlobalNetTable ( KiteEngine* );
bool isCoreClockNetRouted ( const Net* ) const;
Net* getRootNet ( const Net*, Path ) const;
inline Net* getVdde () const;
inline Net* getVddi () const;
inline Net* getVsse () const;
inline Net* getVssi () const;
inline Net* getCk () const;
inline Net* getCki () const;
inline Net* getCko () const;
inline Net* getBlockage () const;
inline void setBlockage ( Net* );
private:
bool guessGlobalNet ( const Name&, Net* );
private:
bool guessGlobalNet ( const Name&, Net* );
private:
Name _vddePadNetName;
Name _vddiPadNetName;
Name _vssePadNetName;
Name _vssiPadNetName;
Name _ckPadNetName;
Name _ckiPadNetName;
Name _ckoPadNetName;
Net* _vdde;
Net* _vddi;
Net* _vsse;
Net* _vssi;
Net* _ck; // Clock net on the (external) pad.
Net* _cki; // Clock net in the pad ring.
Net* _cko; // Clock net of the core (design).
Net* _blockage;
unsigned int _flags;
Name _vddePadNetName;
Name _vddiPadNetName;
Name _vssePadNetName;
Name _vssiPadNetName;
Name _ckPadNetName;
Name _ckiPadNetName;
Name _ckoPadNetName;
Net* _vdde;
Net* _vddi;
Net* _vsse;
Net* _vssi;
Net* _ck; // Clock net on the (external) pad.
Net* _cki; // Clock net in the pad ring.
Net* _cko; // Clock net of the core (design).
Net* _blockage;
};
@ -144,7 +150,8 @@ namespace {
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
GlobalNetTable::GlobalNetTable ( KiteEngine* kite )
: _vddePadNetName("vdde")
: _flags (0)
, _vddePadNetName("vdde")
, _vddiPadNetName("vddi")
, _vssePadNetName("vsse")
, _vssiPadNetName("vssi")
@ -249,7 +256,7 @@ namespace {
if (netType == Net::Type::POWER) {
if (_vddiPadNetName.isEmpty()) {
_vddiPadNetName = inet->getName();
_vddi = *inet;
_vddi = *inet;
} else {
cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n"
" (will consider only <%s>)"
@ -276,7 +283,13 @@ namespace {
if (_ckoPadNetName.isEmpty()) {
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
_ckoPadNetName = inet->getName();
_cko = *inet;
_cko = *inet;
if (NetRoutingExtension::isMixedPreRoute(*inet)) {
cmess1 << " (core clock net is already routed)" << endl;
_flags |= ClockIsRouted;
} else {
cmess1 << " (core clock net will be routed as an ordinary signal)" << endl;
}
} else {
cerr << Error("Second clock net <%s> net at top block level will be ignored.\n"
" (will consider only <%s>)"
@ -332,6 +345,13 @@ namespace {
if (name == _ckoPadNetName) {
cmess1 << " - Using <" << net->getName() << "> as core (internal:cko) clock net." << endl;
_cko = net;
if (NetRoutingExtension::isMixedPreRoute(_cko)) {
cmess1 << " (core clock net is already routed)" << endl;
_flags |= ClockIsRouted;
} else {
cmess1 << " (core clock net will be routed as an ordinary signal)" << endl;
}
return true;
}
@ -359,6 +379,7 @@ namespace {
return NULL;
}
// Track up, *only* for clocks.
const Net* upNet = net;
if (not path.isEmpty()) {
@ -367,10 +388,10 @@ namespace {
Plug* plug = NULL;
while ( true ) {
ltrace(300) << path << "+" << upNet << endl;
ltrace(300) << " " << path << "+" << upNet << endl;
if ((upNet == NULL) or not upNet->isExternal()) return _blockage;
if (path.isEmpty()) break;
if ((upNet == NULL) or not upNet->isExternal()) return _blockage;
instance = path.getTailInstance();
plug = instance->getPlug(upNet);
@ -386,14 +407,23 @@ namespace {
<< " cko:" << ((_cko) ? _cko->getName() : "NULL")
<< endl;
if ( _ck and (upNet->getName() == _ck->getName() ) ) return _ck;
if ( _cki and (upNet->getName() == _cki->getName()) ) return _cki;
if ( _cko and (upNet->getName() == _cko->getName()) ) return _cko;
if (_ck and (upNet->getName() == _ck->getName() )) return _ck;
if (_cki and (upNet->getName() == _cki->getName())) return _cki;
if (_cko) {
if (upNet->getName() == _cko->getName()) {
if (isCoreClockNetRouted(upNet)) return _cko;
}
}
return NULL;
}
bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const
{ return (net == _cko) and (_flags & ClockIsRouted); }
// -------------------------------------------------------------------
// Class : "::PowerRailsPlanes".
@ -481,6 +511,7 @@ namespace {
PowerRailsPlanes ( KiteEngine* );
~PowerRailsPlanes ();
inline Net* getRootNet ( Net*, Path );
inline bool isCoreClockNetRouted ( const Net* ) const;
bool hasPlane ( const BasicLayer* );
bool setActivePlane ( const BasicLayer* );
inline Plane* getActivePlane () const;
@ -661,7 +692,10 @@ namespace {
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNextTrack() ) {
TrackElement* element = TrackFixedSegment::create ( track, segment );
ltrace(300) << " Insert in " << track << "+" << element << endl;
ltrace(300) << " Insert in " << track
<< "+" << element
<< " " << (net->isExternal() ? "external" : "internal")
<< endl;
}
}
}
@ -905,6 +939,10 @@ namespace {
inline Net* PowerRailsPlanes::getRootNet ( Net* net, Path path )
{ return _globalNets.getRootNet(net,path); }
inline bool PowerRailsPlanes::isCoreClockNetRouted ( const Net* net ) const
{ return _globalNets.isCoreClockNetRouted(net); }
bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer )
{ return (_planes.find(layer) != _planes.end()); }
@ -1076,11 +1114,20 @@ namespace {
and (_routingGauge->getLayerDepth(component->getLayer()) < 2) )
return;
Net* rootNet = _kite->getBlockageNet();
if (not _isBlockagePlane) {
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
}
#if 0
Net* rootNet = NULL;
if ( not _isBlockagePlane )
rootNet = _powerRailsPlanes.getRootNet(component->getNet(),getPath());
else
else {
rootNet = _kite->getBlockageNet();
}
#endif
if ( rootNet == NULL ) {
ltrace(300) << " rootNet is NULL, not taken into account." << endl;
return;
@ -1199,6 +1246,8 @@ namespace Kite {
void KiteEngine::buildPowerRails ()
{
//DebugSession::open( 300 );
if (not _blockageNet) {
_blockageNet = getCell()->getNet("blockagenet");
if (not _blockageNet)
@ -1226,6 +1275,8 @@ namespace Kite {
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
Session::revalidate ();
//DebugSession::close();
}

View File

@ -47,6 +47,7 @@ namespace Kite {
, _ripupLimits ()
, _ripupCost (Cfg::getParamInt("kite.ripupCost" , 3)->asInt())
, _eventsLimit (Cfg::getParamInt("kite.eventsLimit" ,4000000)->asInt())
, _flags (0)
{
_ripupLimits[StrapRipupLimit] = Cfg::getParamInt("kite.strapRipupLimit" ,16)->asInt();
_ripupLimits[LocalRipupLimit] = Cfg::getParamInt("kite.localRipupLimit" , 7)->asInt();

View File

@ -110,7 +110,7 @@ namespace Kite {
: KatabaticEngine (cell)
, _viewer (NULL)
, _knik (NULL)
, _blockageNet (NULL)
, _blockageNet (cell->getNet("blockagenet"))
, _configuration (new Configuration(getKatabaticConfiguration()))
, _routingPlanes ()
, _negociateWindow (NULL)

View File

@ -49,6 +49,7 @@ namespace Kite {
, RipupLimitsTableSize=4
};
enum Constants { MaxMetalDepth=20 };
enum Flag { UseClockTree=0x0001 };
public:
// Constructor & Destructor.
virtual Configuration* clone () const;
@ -58,6 +59,7 @@ namespace Kite {
// Decorateds.
virtual bool isGMetal ( const Layer* ) const;
virtual bool isGContact ( const Layer* ) const;
inline bool useClockTree () const;
virtual size_t getDepth () const;
virtual size_t getAllowedDepth () const;
virtual DbU::Unit getSliceHeight () const;
@ -102,6 +104,8 @@ namespace Kite {
inline void setPostEventCb ( PostEventCb_t );
void setHTracksReservedLocal ( size_t );
void setVTracksReservedLocal ( size_t );
inline void setFlags ( unsigned int );
inline void unsetFlags ( unsigned int );
virtual Record* _getRecord () const;
virtual string _getString () const;
virtual string _getTypeName () const;
@ -114,6 +118,7 @@ namespace Kite {
unsigned int _ripupLimits [RipupLimitsTableSize];
unsigned int _ripupCost;
unsigned long _eventsLimit;
unsigned int _flags;
private:
Configuration ( const Configuration& other, Katabatic::Configuration* base=NULL );
Configuration& operator= ( const Configuration& );
@ -130,6 +135,9 @@ namespace Kite {
inline void Configuration::setRipupCost ( unsigned int cost ) { _ripupCost = cost; }
inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; }
inline void Configuration::setEventsLimit ( unsigned long limit ) { _eventsLimit = limit; }
inline bool Configuration::useClockTree () const { return _flags & UseClockTree; }
inline void Configuration::setFlags ( unsigned int flags ) { _flags |= flags; }
inline void Configuration::unsetFlags ( unsigned int flags ) { _flags &= ~flags; }

View File

@ -64,6 +64,7 @@ namespace Kite {
static KiteEngine* create ( Cell* );
static KiteEngine* get ( const Cell* );
public:
inline bool useClockTree () const;
inline CellViewer* getViewer () const;
inline KatabaticEngine* base ();
inline Configuration* getKiteConfiguration ();
@ -148,6 +149,7 @@ namespace Kite {
// Inline Functions.
inline bool KiteEngine::useClockTree () const { return _configuration->useClockTree(); }
inline CellViewer* KiteEngine::getViewer () const { return _viewer; }
inline KatabaticEngine* KiteEngine::base () { return static_cast<KatabaticEngine*>(this); }
inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; }

View File

@ -1274,6 +1274,7 @@ void Graph::Dijkstra()
ostringstream message;
message << "In Graph::Dijkstra():\n";
message << " Unable to reach target on net " << _working_net->getName() << ".";
for ( auto iv : _vertexes_to_route ) message << "\n | " << iv;
throw Error( message.str() );
}
assert( reachedDistance < (float)(HUGE_VAL) );

View File

@ -237,7 +237,6 @@ void KnikEngine::initGlobalRouting( const map<Name,Net*>& excludedNets )
if ( inet->isGlobal()
or inet->isSupply()
or inet->isClock()
or (inet->getName() == obstacleNetName) ) {
cmess2 << " - <" << inet->getName() << "> not routed (global, supply, clock or obstacle)." << endl;
continue;

View File

@ -43,7 +43,8 @@ namespace Mauka {
void FeedCells::addFeed ( Cell* cell )
{
if ( cell == NULL ) return;
if (cell == NULL) return;
if (not _feedCells.size()) return;
DbU::Unit pitch = _mauka->getPitch();