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