From 6d366a08bcc3daf541855f0ae2d69d3ac5c44065 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 24 Feb 2015 13:13:17 +0100 Subject: [PATCH] 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'). --- crlcore/src/pyCRL/PyRoutingGauge.cpp | 33 +++++ cumulus/src/plugins/ChipPlugin.py | 26 +++- cumulus/src/plugins/__init__.py | 12 ++ cumulus/src/plugins/chip/BlockCorona.py | 69 +++++++--- cumulus/src/plugins/chip/BlockPower.py | 2 +- cumulus/src/plugins/chip/Configuration.py | 64 ++++++--- cumulus/src/plugins/chip/PadsCorona.py | 3 +- cumulus/src/plugins/clocktree/ClockTree.py | 6 +- etesian/src/AddFeeds.cpp | 92 ++++++++----- etesian/src/EtesianEngine.cpp | 50 ++++--- etesian/src/etesian/EtesianEngine.h | 5 +- etesian/src/etesian/FeedCells.h | 4 + hurricane/src/hurricane/Cell.cpp | 115 +++++++++------- hurricane/src/hurricane/CellCollections.cpp | 11 +- hurricane/src/hurricane/DeepNet.cpp | 4 +- hurricane/src/hurricane/HyperNet.cpp | 33 ++--- hurricane/src/hurricane/Occurrence.cpp | 21 +++ hurricane/src/hurricane/hurricane/Cell.h | 3 +- .../src/hurricane/hurricane/DebugSession.h | 7 + hurricane/src/hurricane/hurricane/HyperNet.h | 3 +- .../src/hurricane/hurricane/Occurrence.h | 1 + hurricane/src/isobar/PyBasicLayer.cpp | 5 +- kite/src/BuildPowerRails.cpp | 127 ++++++++++++------ kite/src/Configuration.cpp | 1 + kite/src/KiteEngine.cpp | 2 +- kite/src/kite/Configuration.h | 8 ++ kite/src/kite/KiteEngine.h | 2 + knik/src/Graph.cpp | 1 + knik/src/KnikEngine.cpp | 1 - mauka/src/FeedCells.cpp | 3 +- 30 files changed, 481 insertions(+), 233 deletions(-) diff --git a/crlcore/src/pyCRL/PyRoutingGauge.cpp b/crlcore/src/pyCRL/PyRoutingGauge.cpp index cac5843a..6a8b4926 100644 --- a/crlcore/src/pyCRL/PyRoutingGauge.cpp +++ b/crlcore/src/pyCRL/PyRoutingGauge.cpp @@ -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 diff --git a/cumulus/src/plugins/ChipPlugin.py b/cumulus/src/plugins/ChipPlugin.py index 814916dd..f7aba5b1 100644 --- a/cumulus/src/plugins/ChipPlugin.py +++ b/cumulus/src/plugins/ChipPlugin.py @@ -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 diff --git a/cumulus/src/plugins/__init__.py b/cumulus/src/plugins/__init__.py index 07d8e63f..f1b963d7 100644 --- a/cumulus/src/plugins/__init__.py +++ b/cumulus/src/plugins/__init__.py @@ -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: diff --git a/cumulus/src/plugins/chip/BlockCorona.py b/cumulus/src/plugins/chip/BlockCorona.py index d506dcfa..b18ac443 100644 --- a/cumulus/src/plugins/chip/BlockCorona.py +++ b/cumulus/src/plugins/chip/BlockCorona.py @@ -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 diff --git a/cumulus/src/plugins/chip/BlockPower.py b/cumulus/src/plugins/chip/BlockPower.py index a572ec94..2eb91007 100644 --- a/cumulus/src/plugins/chip/BlockPower.py +++ b/cumulus/src/plugins/chip/BlockPower.py @@ -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: diff --git a/cumulus/src/plugins/chip/Configuration.py b/cumulus/src/plugins/chip/Configuration.py index 77a7c56a..a64d6e4d 100644 --- a/cumulus/src/plugins/chip/Configuration.py +++ b/cumulus/src/plugins/chip/Configuration.py @@ -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 diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index ba71a646..e36c316f 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -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 diff --git a/cumulus/src/plugins/clocktree/ClockTree.py b/cumulus/src/plugins/clocktree/ClockTree.py index a5b9a854..e4f20206 100755 --- a/cumulus/src/plugins/clocktree/ClockTree.py +++ b/cumulus/src/plugins/clocktree/ClockTree.py @@ -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() diff --git a/etesian/src/AddFeeds.cpp b/etesian/src/AddFeeds.cpp index 37ee0374..09382e3f 100644 --- a/etesian/src/AddFeeds.cpp +++ b/etesian/src/AddFeeds.cpp @@ -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((*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 ); } diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index eb91264a..c6ecc420 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -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 idsToTransf ( instancesNb ); - vector instances ( instancesNb ); + size_t instancesNb = getCell()->getLeafInstanceOccurrences().getSize(); + vector idsToTransf ( instancesNb ); + vector instances ( instancesNb ); vector< point > positions ( instancesNb ); - vector< point > orientations( instancesNb, point(true, true) ); + vector< point > orientations( instancesNb, point(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((*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 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 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 diff --git a/etesian/src/etesian/EtesianEngine.h b/etesian/src/etesian/EtesianEngine.h index 2cb44114..5e064555 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -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 _idsToInsts; Hurricane::CellWidget* _cellWidget; FeedCells _feedCells; + size_t _yspinSlice0; protected: // Constructors & Destructors. diff --git a/etesian/src/etesian/FeedCells.h b/etesian/src/etesian/FeedCells.h index d99b3a4a..c8b9e448 100644 --- a/etesian/src/etesian/FeedCells.h +++ b/etesian/src/etesian/FeedCells.h @@ -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 diff --git a/hurricane/src/hurricane/Cell.cpp b/hurricane/src/hurricane/Cell.cpp index c305fad9..7067631e 100644 --- a/hurricane/src/hurricane/Cell.cpp +++ b/hurricane/src/hurricane/Cell.cpp @@ -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 hyperNets; + vector topHyperNets; + forEach ( Occurrence, ioccurrence, getHyperNetRootNetOccurrences() ) { Net* net = static_cast((*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( *icomponent ); @@ -228,51 +228,72 @@ void Cell::flattenNets(unsigned int flags) } if (hasRoutingPads) continue; - forEach ( Component*, icomponent, net->getComponents() ) { - Plug* primaryPlug = dynamic_cast( *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_createRoutingPads( flags ); + } + + for ( size_t i=0 ; i(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( *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( (*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( *icomponent ); + if (pin) { + currentRp = RoutingPad::create( pin ); if (buildRing) { if (previousRp) { currentRp->getBodyHook()->attach( previousRp->getBodyHook() ); } - Plug* plug = static_cast( (*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( *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; } } } diff --git a/hurricane/src/hurricane/CellCollections.cpp b/hurricane/src/hurricane/CellCollections.cpp index 38ff0e5b..e3e5e1d2 100644 --- a/hurricane/src/hurricane/CellCollections.cpp +++ b/hurricane/src/hurricane/CellCollections.cpp @@ -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(_netLocator.getElement()) + and isHyperNetRootNetOccurrence(Occurrence(_netLocator.getElement(),_path))) break; + + _netLocator.progress(); + } } else if (_hyperNetRootNetOccurrenceLocator.isValid()) _hyperNetRootNetOccurrenceLocator.progress(); diff --git a/hurricane/src/hurricane/DeepNet.cpp b/hurricane/src/hurricane/DeepNet.cpp index 376173be..a9f20b5f 100644 --- a/hurricane/src/hurricane/DeepNet.cpp +++ b/hurricane/src/hurricane/DeepNet.cpp @@ -55,7 +55,9 @@ namespace Hurricane { ,netOccurrence.getName() ) , _netOccurrence(netOccurrence) - { } + { + //trace << "DeepNet::DeepNet() " << getCell() << " " << this << endl; + } DeepNet* DeepNet::create ( HyperNet& hyperNet ) diff --git a/hurricane/src/hurricane/HyperNet.cpp b/hurricane/src/hurricane/HyperNet.cpp index b32c918b..cb942cbc 100644 --- a/hurricane/src/hurricane/HyperNet.cpp +++ b/hurricane/src/hurricane/HyperNet.cpp @@ -259,30 +259,21 @@ class HyperNet_LeafPlugOccurrences : public Collection { // **************************************************************************************************** HyperNet::HyperNet(const Occurrence& occurrence) -// ******************************************* -: _netOccurrence() +// ********************************************* + : _netOccurrence(occurrence.getNetOccurrence()) { - if (occurrence.isValid()) { - Entity* entity = occurrence.getEntity(); - if (dynamic_cast(entity)) - _netOccurrence = occurrence; - else { - if (dynamic_cast(entity)) { - Rubber* rubber = (Rubber*)entity; - _netOccurrence = Occurrence(rubber->getNet(), occurrence.getPath()); - } - else { - if (dynamic_cast(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 // *********************************************************************************** { diff --git a/hurricane/src/hurricane/Occurrence.cpp b/hurricane/src/hurricane/Occurrence.cpp index 8a0e67d6..b9b9d3e9 100644 --- a/hurricane/src/hurricane/Occurrence.cpp +++ b/hurricane/src/hurricane/Occurrence.cpp @@ -126,6 +126,27 @@ Properties Occurrence::getProperties() const return Properties(); } +Occurrence Occurrence::getNetOccurrence() const +// ******************************************** +{ + if (isValid()) { + Entity* entity = getEntity(); + if (dynamic_cast(entity)) return *this; + else { + Rubber* rubber = dynamic_cast(entity); + if (rubber) return Occurrence(rubber->getNet(), getPath()); + else { + Component* component = dynamic_cast(entity); + if (component) return Occurrence(component->getNet(), getPath()); + } + } + } + + return Occurrence(); +} + + + Box Occurrence::getBoundingBox() const // ********************************** { diff --git a/hurricane/src/hurricane/hurricane/Cell.h b/hurricane/src/hurricane/hurricane/Cell.h index b2d51eed..7d67c2a1 100644 --- a/hurricane/src/hurricane/hurricane/Cell.h +++ b/hurricane/src/hurricane/hurricane/Cell.h @@ -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 diff --git a/hurricane/src/hurricane/hurricane/DebugSession.h b/hurricane/src/hurricane/hurricane/DebugSession.h index 7eb61a86..ccd7992c 100644 --- a/hurricane/src/hurricane/hurricane/DebugSession.h +++ b/hurricane/src/hurricane/hurricane/DebugSession.h @@ -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) ) diff --git a/hurricane/src/hurricane/hurricane/HyperNet.h b/hurricane/src/hurricane/hurricane/HyperNet.h index 4203b26a..cd3a8e47 100644 --- a/hurricane/src/hurricane/hurricane/HyperNet.h +++ b/hurricane/src/hurricane/hurricane/HyperNet.h @@ -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 // ********* diff --git a/hurricane/src/hurricane/hurricane/Occurrence.h b/hurricane/src/hurricane/hurricane/Occurrence.h index 912200b1..6732c6aa 100644 --- a/hurricane/src/hurricane/hurricane/Occurrence.h +++ b/hurricane/src/hurricane/hurricane/Occurrence.h @@ -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; diff --git a/hurricane/src/isobar/PyBasicLayer.cpp b/hurricane/src/isobar/PyBasicLayer.cpp index b3937b20..6a6ef27e 100644 --- a/hurricane/src/isobar/PyBasicLayer.cpp +++ b/hurricane/src/isobar/PyBasicLayer.cpp @@ -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 diff --git a/kite/src/BuildPowerRails.cpp b/kite/src/BuildPowerRails.cpp index ae608040..02236945 100644 --- a/kite/src/BuildPowerRails.cpp +++ b/kite/src/BuildPowerRails.cpp @@ -16,6 +16,7 @@ #include #include +#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(); } diff --git a/kite/src/Configuration.cpp b/kite/src/Configuration.cpp index 168038b0..11bc7d93 100644 --- a/kite/src/Configuration.cpp +++ b/kite/src/Configuration.cpp @@ -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(); diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index 7bc873a8..8d258752 100644 --- a/kite/src/KiteEngine.cpp +++ b/kite/src/KiteEngine.cpp @@ -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) diff --git a/kite/src/kite/Configuration.h b/kite/src/kite/Configuration.h index 0be4b5ff..b0fa7efa 100644 --- a/kite/src/kite/Configuration.h +++ b/kite/src/kite/Configuration.h @@ -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; } diff --git a/kite/src/kite/KiteEngine.h b/kite/src/kite/KiteEngine.h index 2b30afe0..b73ccecf 100644 --- a/kite/src/kite/KiteEngine.h +++ b/kite/src/kite/KiteEngine.h @@ -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(this); } inline Configuration* KiteEngine::getKiteConfiguration () { return _configuration; } diff --git a/knik/src/Graph.cpp b/knik/src/Graph.cpp index 6c5ae593..ac0b65ff 100644 --- a/knik/src/Graph.cpp +++ b/knik/src/Graph.cpp @@ -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) ); diff --git a/knik/src/KnikEngine.cpp b/knik/src/KnikEngine.cpp index 21baee21..2f6ae25d 100644 --- a/knik/src/KnikEngine.cpp +++ b/knik/src/KnikEngine.cpp @@ -237,7 +237,6 @@ void KnikEngine::initGlobalRouting( const map& 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; diff --git a/mauka/src/FeedCells.cpp b/mauka/src/FeedCells.cpp index 2b3530f6..329ee196 100644 --- a/mauka/src/FeedCells.cpp +++ b/mauka/src/FeedCells.cpp @@ -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();