diff --git a/cumulus/src/plugins/alpha/block/block.py b/cumulus/src/plugins/alpha/block/block.py index 2a485290..cfedd2cf 100644 --- a/cumulus/src/plugins/alpha/block/block.py +++ b/cumulus/src/plugins/alpha/block/block.py @@ -527,32 +527,37 @@ class Block ( object ): def place ( self ): editor = self.conf.editor if self.conf.isCoreBlock: - etesian = Etesian.EtesianEngine.create( self.conf.corona ) - etesian.setBlock( self.conf.icore ) + self.etesian = Etesian.EtesianEngine.create( self.conf.corona ) + self.etesian.setBlock( self.conf.icore ) if editor: editor.setCell( self.conf.cell ) Breakpoint.stop( 100, 'Block.place(), corona loaded.') else: - etesian = Etesian.EtesianEngine.create( self.conf.cell ) - etesian.place() - etesian.destroy() + self.etesian = Etesian.EtesianEngine.create( self.conf.cell ) + self.etesian.place() + Breakpoint.stop( 100, 'Placement done.' ) + self.etesian.clearColoquinte() def route ( self ): routedCell = self.conf.corona if self.conf.isCoreBlock else self.conf.cell - katana = Katana.KatanaEngine.create( routedCell ) - #katana.printConfiguration () - katana.digitalInit () + self.katana = Katana.KatanaEngine.create( routedCell ) + #self.katana.printConfiguration() + self.katana.digitalInit () #katana.runNegociatePreRouted() Breakpoint.stop( 100, 'Block.route() Before global routing.' ) - katana.runGlobalRouter ( Katana.Flags.NoFlags ) - katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet ) + self.katana.runGlobalRouter ( Katana.Flags.NoFlags ) + self.katana.loadGlobalRouting( Anabatic.EngineLoadGrByNet ) Breakpoint.stop( 100, 'Block.route() After global routing.' ) - katana.layerAssign ( Anabatic.EngineNoNetLayerAssign ) - katana.runNegociate ( Katana.Flags.NoFlags ) - success = katana.isDetailedRoutingSuccess() + self.katana.layerAssign ( Anabatic.EngineNoNetLayerAssign ) + self.katana.runNegociate ( Katana.Flags.NoFlags ) + success = self.katana.isDetailedRoutingSuccess() Breakpoint.stop( 100, 'Block.route() done, success:{}.'.format(success) ) - katana.finalizeLayout() - katana.destroy() + self.katana.finalizeLayout() + self.katana.destroy() + self.katana = None + if self.etesian: + self.etesian.destroy() + self.etesian = None return success def addBlockages ( self ): diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index 60970d2a..79ef198e 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -133,6 +133,8 @@ class GaugeConf ( object ): @property def routingBb ( self ): return self._routingBb + def getLayerDepth ( self, layer ): return self._routingGauge.getLayerDepth( layer ) + def getPitch ( self, layer ): return self._routingGauge.getPitch( layer ) def setRoutingBb ( self, bb ): @@ -1100,6 +1102,8 @@ class BlockConf ( GaugeConf ): self.cfg.etesian.spaceMargin = None self.cfg.etesian.latchUpDistance = None self.cfg.block.spareSide = None + self.etesian = None + self.katana = None @property def isCoreBlock ( self ): return self.chip is not None diff --git a/cumulus/src/plugins/alpha/chip/corona.py b/cumulus/src/plugins/alpha/chip/corona.py index 4d7e33bb..0c4d4f07 100644 --- a/cumulus/src/plugins/alpha/chip/corona.py +++ b/cumulus/src/plugins/alpha/chip/corona.py @@ -536,7 +536,7 @@ class Builder ( object ): def __init__ ( self, block ): self.block = block - self.innerBb = self.block.bb + self.innerBb = self.block.icoreAb self.block.path.getTransformation().applyOn( self.innerBb ) self.innerBb.inflate( self.hRailSpace/2, self.vRailSpace/2 ) self.southSide = SouthSide( self ) diff --git a/cumulus/src/plugins/alpha/chip/power.py b/cumulus/src/plugins/alpha/chip/power.py index 3132a6b4..e67f623f 100644 --- a/cumulus/src/plugins/alpha/chip/power.py +++ b/cumulus/src/plugins/alpha/chip/power.py @@ -36,8 +36,8 @@ plugins.chip.importConstants( globals() ) class Side ( object ): - def __init__ ( self, block, side, net, metal ): - self.block = block + def __init__ ( self, builder, side, net, metal ): + self.builder = builder self.side = side self.net = net self.metal = metal @@ -74,16 +74,16 @@ class Side ( object ): def doLayout ( self ): if self.side == West: width = 0 - x = self.block.bb.getXMin() + x = self.builder.icoreAb.getXMin() elif self.side == East: width = 0 - x = self.block.bb.getXMax() + x = self.builder.icoreAb.getXMax() elif self.side == South: height = 0 - y = self.block.bb.getYMin() + y = self.builder.icoreAb.getYMin() elif self.side == North: height = 0 - y = self.block.bb.getYMax() + y = self.builder.icoreAb.getYMax() minWidth = DbU.fromLambda( 6.0 ) for terminal in self.terminals: if self.side == West or self.side == East: @@ -94,7 +94,7 @@ class Side ( object ): center = Point( terminal[0].getCenter(), y ) width = terminal[0].getSize() - self.deltaWidth if width < minWidth: width = minWidth - self.block.path.getTransformation().applyOn( center ) + self.builder.path.getTransformation().applyOn( center ) contact = Contact.create( self.net, self.metal, center.getX(), center.getY(), width, height ) terminal[ 1 ] = contact @@ -107,28 +107,33 @@ class Plane ( object ): Horizontal = 0001 Vertical = 0002 - def __init__ ( self, block, metal ): - self.block = block - self.metal = metal - self.sides = {} + def __init__ ( self, builder, metal ): + self.builder = builder + self.metal = metal + self.sides = {} def addTerminal ( self, net, direction, bb ): if not self.sides.has_key(net): - self.sides[ net ] = { North : Side(self.block,North,net,self.metal) - , South : Side(self.block,South,net,self.metal) - , East : Side(self.block,East ,net,self.metal) - , West : Side(self.block,West ,net,self.metal) + self.sides[ net ] = { North : Side(self.builder,North,net,self.metal) + , South : Side(self.builder,South,net,self.metal) + , East : Side(self.builder,East ,net,self.metal) + , West : Side(self.builder,West ,net,self.metal) } sides = self.sides[ net ] + trace( 550, '\tPlane.addTerminal() net={} bb={} direction={}\n' \ + .format( net.getName(), bb, direction )) + trace( 550, '\tbuilder.icoreAb={}\n'.format( self.builder.icoreAb )) if direction == Plane.Horizontal: - if bb.getXMin() <= self.block.bb.getXMin(): + trace( 550, '\t| Horizontal\n' ) + if bb.getXMin() <= self.builder.icoreAb.getXMin(): sides[West].addTerminal( bb.getCenter().getY(), bb.getHeight() ) - if bb.getXMax() >= self.block.bb.getXMax(): + if bb.getXMax() >= self.builder.icoreAb.getXMax(): sides[East].addTerminal( bb.getCenter().getY(), bb.getHeight() ) if direction == Plane.Vertical: - if bb.getYMin() <= self.block.bb.getYMin(): + trace( 550, '\t| Vertical\n' ) + if bb.getYMin() <= self.builder.icoreAb.getYMin(): sides[South].addTerminal( bb.getCenter().getX(), bb.getWidth() ) - if bb.getYMax() >= self.block.bb.getYMax(): + if bb.getYMax() >= self.builder.icoreAb.getYMax(): sides[North].addTerminal( bb.getCenter().getX(), bb.getWidth() ) def doLayout ( self ): @@ -142,25 +147,28 @@ class Plane ( object ): class GoCb ( object ): - def __init__ ( self, block ): - self.block = block + def __init__ ( self, builder ): + self.builder = builder def __call__ ( self, query, go ): direction = None if isinstance(go,Horizontal): direction = Plane.Horizontal if isinstance(go,Vertical): direction = Plane.Vertical if not direction: return + trace( 550, '\t| go={}\n'.format( go )) rootNet = None - if go.getNet().getType() == long(Net.Type.POWER): rootNet = self.block.conf.coronaVdd - if go.getNet().getType() == long(Net.Type.GROUND): rootNet = self.block.conf.coronaVss + if go.getNet().getType() == long(Net.Type.POWER): rootNet = self.builder.conf.coronaVdd + if go.getNet().getType() == long(Net.Type.GROUND): rootNet = self.builder.conf.coronaVss if not rootNet: return - if self.block.activePlane: - layer = self.block.activePlane.metal + if self.builder.activePlane: + layer = self.builder.activePlane.metal if layer.isSymbolic(): layer = layer.getBasicLayer() + if self.builder.conf.getLayerDepth(layer) == 0: + direction = Plane.Horizontal bb = go.getBoundingBox( layer ) query.getPath().getTransformation().applyOn( bb ) - self.block.activePlane.addTerminal( rootNet, direction, bb ) + self.builder.activePlane.addTerminal( rootNet, direction, bb ) else: print WarningMessage( 'BlockPower.GoCb() callback called without an active plane.' ) return @@ -173,9 +181,9 @@ class Builder ( object ): def __init__ ( self, conf ): self.conf = conf - self.path = Path( self.conf.icore ) - self.block = self.conf.icore.getMasterCell() - self.bb = self.block.getAbutmentBox() + self.path = Path() + self.corona = self.conf.icorona.getMasterCell() + self.icoreAb = self.conf.icore.getAbutmentBox() self.planes = {} self.activePlane = None for layerGauge in self.conf.routingGauge.getLayerGauges(): @@ -188,8 +196,8 @@ class Builder ( object ): goCb = GoCb( self ) query = Query() query.setGoCallback( goCb ) - query.setCell( self.block ) - query.setArea( self.block.getAbutmentBox() ) + query.setCell( self.corona ) + query.setArea( self.icoreAb ) query.setFilter( Query.DoComponents|Query.DoTerminalCells ) for layerGauge in self.conf.routingGauge.getLayerGauges(): self.activePlane = self.planes[ layerGauge.getLayer().getName() ] @@ -226,13 +234,11 @@ class Builder ( object ): with UpdateSession(): bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), ck, 0 ) self.conf.expandMinArea( bufferRp ) - blockAb = self.block.getAbutmentBox() - self.path.getTransformation().applyOn( blockAb ) layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth) contact = Contact.create( ck , self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth) , bufferRp.getX() - , blockAb.getYMax() + , self.icoreAb.getYMax() , layerGauge.getViaWidth() , layerGauge.getViaWidth() ) @@ -242,7 +248,6 @@ class Builder ( object ): if layer.isSymbolic(): layer = layer.getBasicLayer() bb = segment.getBoundingBox( layer ) - self.path.getTransformation().getInvert().applyOn( bb ) self.activePlane.addTerminal( ck, Plane.Vertical, bb ) trace( 550, '\tAdded terminal of {} to vertical plane @{}\n'.format(ck,bb) ) diff --git a/cumulus/src/plugins/chip/blockpower.py b/cumulus/src/plugins/chip/blockpower.py index 0037847a..76135ebe 100644 --- a/cumulus/src/plugins/chip/blockpower.py +++ b/cumulus/src/plugins/chip/blockpower.py @@ -15,24 +15,13 @@ import sys -from Hurricane import DbU -from Hurricane import Point -from Hurricane import Transformation -from Hurricane import Box -from Hurricane import Interval -from Hurricane import Path -from Hurricane import Occurrence -from Hurricane import UpdateSession -from Hurricane import Net -from Hurricane import Contact -from Hurricane import Horizontal -from Hurricane import Vertical -from Hurricane import Query +from Hurricane import DbU, Point, Transformation, Box, Interval, \ + Path, Occurrence, UpdateSession, Net, \ + Contact, Horizontal, Vertical, Query import CRL import helpers from helpers import trace -from helpers.io import ErrorMessage -from helpers.io import WarningMessage +from helpers.io import ErrorMessage, WarningMessage import plugins import plugins.chip @@ -134,6 +123,8 @@ class Plane ( object ): , West : Side(self.block,West ,net,self.metal) } sides = self.sides[ net ] + trace( 550, '\tPlane.addTerminal() net={} bb={} direction={}\n' \ + .format( net.getName(), bb, direction )) if direction == Plane.Horizontal: if bb.getXMin() <= self.block.bb.getXMin(): diff --git a/etesian/src/CMakeLists.txt b/etesian/src/CMakeLists.txt index b8572efa..2a15c050 100644 --- a/etesian/src/CMakeLists.txt +++ b/etesian/src/CMakeLists.txt @@ -11,6 +11,7 @@ ${PYTHON_INCLUDE_PATH} ) set( includes etesian/Configuration.h + etesian/Placement.h etesian/FeedCells.h etesian/BloatCells.h etesian/BloatProperty.h diff --git a/etesian/src/Configuration.cpp b/etesian/src/Configuration.cpp index 9eb97443..199cd6df 100644 --- a/etesian/src/Configuration.cpp +++ b/etesian/src/Configuration.cpp @@ -61,9 +61,13 @@ namespace Etesian { , _routingDriven ( Cfg::getParamBool ("etesian.routingDriven" , false )->asBool()) , _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() ) , _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.0)->asDouble() ) + , _antennaInsertThreshold + ( Cfg::getParamDouble ("etesian.antennaInsertThreshold", 50.0)->asDouble() ) , _feedNames ( Cfg::getParamString ("etesian.feedNames" ,"tie_x0,rowend_x0")->asString() ) + , _diodeName ( Cfg::getParamString ("etesian.diodeName" ,"dio_x0" )->asString() ) , _bloat ( Cfg::getParamString ("etesian.bloat" ,"disabled" )->asString() ) , _latchUpDistance( Cfg::getParamInt ("etesian.latchUpDistance",0 )->asInt() ) + , _antennaMaxWL ( Cfg::getParamInt ("etesian.antennaMaxWL" ,0 )->asInt() ) { string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString(); if (cg == NULL) { @@ -85,15 +89,19 @@ namespace Etesian { Configuration::Configuration ( const Configuration& other ) - : _rg (NULL) - , _cg (NULL) - , _placeEffort ( other._placeEffort ) - , _updateConf ( other._updateConf ) - , _spreadingConf( other._spreadingConf ) - , _spaceMargin ( other._spaceMargin ) - , _aspectRatio ( other._aspectRatio ) - , _feedNames ( other._feedNames ) - , _bloat ( other._bloat ) + : _rg (NULL) + , _cg (NULL) + , _placeEffort ( other._placeEffort ) + , _updateConf ( other._updateConf ) + , _spreadingConf ( other._spreadingConf ) + , _spaceMargin ( other._spaceMargin ) + , _aspectRatio ( other._aspectRatio ) + , _antennaInsertThreshold( other._antennaInsertThreshold ) + , _feedNames ( other._feedNames ) + , _diodeName ( other._diodeName ) + , _bloat ( other._bloat ) + , _latchUpDistance( other._latchUpDistance ) + , _antennaMaxWL ( other._antennaMaxWL ) { if (other._rg) _rg = other._rg->getClone(); if (other._cg) _cg = other._cg->getClone(); @@ -113,14 +121,17 @@ namespace Etesian { void Configuration::print ( Cell* cell ) const { cmess1 << " o Configuration of ToolEngine for Cell <" << cell->getName() << ">" << endl; - cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl; - cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; - cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; - cmess1 << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl; - cmess1 << Dots::asBool (" - Routing driven",_routingDriven) << endl; - cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; - cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; - cmess1 << Dots::asString (" - Bloat model" ,_bloat ) << endl; + cmess1 << Dots::asIdentifier(" - Cell Gauge" ,getString(_cg->getName())) << endl; + cmess1 << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; + cmess1 << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; + cmess1 << Dots::asInt (" - Spreading Conf" ,_spreadingConf ) << endl; + cmess1 << Dots::asBool (" - Routing driven" ,_routingDriven ) << endl; + cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; + cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; + cmess1 << Dots::asString (" - Bloat model" ,_bloat ) << endl; + cmess1 << Dots::asPercentage(" - Antenna Insert" ,_antennaInsertThreshold ) << endl; + cmess1 << Dots::asString (" - Antenna Max. WL" ,DbU::getValueString(_antennaMaxWL )) << endl; + cmess1 << Dots::asString (" - Latch up Distance",DbU::getValueString(_latchUpDistance)) << endl; } @@ -141,15 +152,19 @@ namespace Etesian { Record* Configuration::_getRecord () const { Record* record = new Record ( _getString() ); - record->add ( getSlot( "_rg" , _rg ) ); - record->add ( getSlot( "_cg" , _cg ) ); - record->add ( getSlot( "_placeEffort" , (int)_placeEffort ) ); - record->add ( getSlot( "_updateConf" , (int)_updateConf ) ); - record->add ( getSlot( "_spreadingConf" , (int)_spreadingConf ) ); - record->add ( getSlot( "_spaceMargin" , _spaceMargin ) ); - record->add ( getSlot( "_aspectRatio" , _aspectRatio ) ); - record->add ( getSlot( "_feedNames" , _feedNames ) ); - record->add ( getSlot( "_bloat" , _bloat ) ); + record->add ( getSlot( "_rg" , _rg ) ); + record->add ( getSlot( "_cg" , _cg ) ); + record->add ( getSlot( "_placeEffort" , (int)_placeEffort ) ); + record->add ( getSlot( "_updateConf" , (int)_updateConf ) ); + record->add ( getSlot( "_spreadingConf" , (int)_spreadingConf ) ); + record->add ( getSlot( "_spaceMargin" , _spaceMargin ) ); + record->add ( getSlot( "_aspectRatio" , _aspectRatio ) ); + record->add ( getSlot( "_antennaInsertThreshold", _antennaInsertThreshold ) ); + record->add ( getSlot( "_feedNames" , _feedNames ) ); + record->add ( getSlot( "_diodeName" , _diodeName ) ); + record->add ( getSlot( "_bloat" , _bloat ) ); + record->add ( DbU::getValueSlot( "_latchUpDistance", &_latchUpDistance ) ); + record->add ( DbU::getValueSlot( "_antennaMaxWL" , &_antennaMaxWL ) ); return record; } diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 32120a88..0454c1e9 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -19,6 +19,7 @@ #include #include #include "coloquinte/circuit.hxx" +#include "coloquinte/circuit_helper.hxx" #include "coloquinte/legalizer.hxx" #include "vlsisapd/configuration/Configuration.h" #include "vlsisapd/utilities/Dots.h" @@ -39,6 +40,7 @@ #include "hurricane/Vertical.h" #include "hurricane/Horizontal.h" #include "hurricane/RoutingPad.h" +#include "hurricane/NetExternalComponents.h" #include "hurricane/UpdateSession.h" #include "hurricane/viewer/CellWidget.h" #include "hurricane/viewer/CellViewer.h" @@ -55,6 +57,7 @@ namespace { using coloquinte::int_t; using coloquinte::float_t; using coloquinte::point; + using Etesian::EtesianEngine; // Options for both placers unsigned const SteinerModel = 0x0001; @@ -174,6 +177,42 @@ namespace { return Transformation( tx, ty, orient ); } + + uint32_t getOutputSide ( Cell* cell ) + { + static map cache; + + auto icache = cache.find( cell ); + if (icache != cache.end()) return (*icache).second; + + Net* output = NULL; + for ( Net* net : cell->getNets() ) { + if (net->isSupply()) continue; + if (net->getDirection() & Net::Direction::DirOut) { + output = net; + break; + } + } + if (not output) return EtesianEngine::RightSide; + + Box ab = cell->getAbutmentBox(); + DbU::Unit left = ab.getWidth(); + DbU::Unit right = ab.getWidth(); + for ( Component* comp : NetExternalComponents::get(output) ) { + Box bb = comp->getBoundingBox(); + DbU::Unit distance = bb.getXMin() - ab.getXMin(); + left = std::min( left, distance ); + + distance = ab.getXMax() - bb.getXMax(); + right = std::min( right, distance ); + } + + uint32_t flags = (left < right) ? EtesianEngine::LeftSide : EtesianEngine::RightSide; + cache[ cell ] = flags; + return flags; + } + + } // Anonymous namespace. @@ -256,19 +295,24 @@ namespace Etesian { , _block (NULL) , _ySpinSet (false) , _flatDesign (false) - , _surface () - , _circuit () - , _placementLB () - , _placementUB () + , _surface (NULL) + , _circuit (NULL) + , _placementLB (NULL) + , _placementUB (NULL) + , _densityLimits(NULL) , _cellsToIds () , _idsToInsts () + , _idsToNets () , _viewer (NULL) + , _diodeCell (NULL) , _feedCells (this) , _bloatCells (this) + , _area (NULL) , _yspinSlice0 (0) , _sliceHeight (0) , _fixedAbHeight(0) , _fixedAbWidth (0) + , _diodeCount (0) { } @@ -283,6 +327,13 @@ namespace Etesian { cmess2 << " o ISPD benchmark <" << getCell()->getName() << ">, no feed cells will be added." << endl; } else { + _diodeCell = DataBase::getDB()->getCell( getConfiguration()->getDiodeName() );; + if (not _diodeCell) { + cerr << Warning( "EtesianEngine::_postCreate() Unable to find \"%s\" diode cell." + , getConfiguration()->getDiodeName().c_str() + ) << endl; + } + _bloatCells.select( getConfiguration()->getBloat() ); string feedNames = getConfiguration()->getFeedNames(); @@ -330,23 +381,53 @@ namespace Etesian { void EtesianEngine::_preDestroy () { - cdebug_log(129,1) << "EtesianEngine::_preDestroy()" << endl; + cdebug_log(120,1) << "EtesianEngine::_preDestroy()" << endl; cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <" << getCell()->getName() << ">" << endl; Super::_preDestroy(); - cdebug.log(129,-1); + cdebug.log(120,-1); } EtesianEngine::~EtesianEngine () { + clearColoquinte(); + delete _area; delete _configuration; } + void EtesianEngine::clearColoquinte () + { + cmess1 << " o Clearing Coloquinte data-structures on <" << getCell()->getName() << ">" << endl; + + delete _surface; + delete _circuit; + delete _placementLB; + delete _placementUB; + delete _densityLimits; + + unordered_map emptyCellsToIds; + _cellsToIds.swap( emptyCellsToIds ); + + vector emptyIdsToInsts; + _idsToInsts.swap( emptyIdsToInsts ); + + vector emptyIdsToNets; + _idsToNets.swap( emptyIdsToNets ); + + _surface = NULL; + _circuit = NULL; + _placementLB = NULL; + _placementUB = NULL; + _densityLimits = NULL; + _diodeCount = 0; + } + + const Name& EtesianEngine::getName () const { return _toolName; } @@ -645,7 +726,7 @@ namespace Etesian { instances[instanceId].attributes = 0; _cellsToIds.insert( make_pair(getString(instance->getName()),instanceId) ); - _idsToInsts.push_back( instance ); + _idsToInsts.push_back( make_tuple(instance,0,0) ); // cerr << "FIXED id=" << instanceId // << " " << instance << " size:(" << xsize << " " << ysize // << ") pos:(" << xpos << " " << ypos << ")" << endl; @@ -719,7 +800,7 @@ namespace Etesian { } _cellsToIds.insert( make_pair(instanceName,instanceId) ); - _idsToInsts.push_back( instance ); + _idsToInsts.push_back( make_tuple(instance,0,0) ); ++instanceId; dots.dot(); } @@ -767,6 +848,7 @@ namespace Etesian { vector nets ( netsNb ); vector pins; + _idsToNets.resize( netsNb ); unsigned int netId = 0; for ( Net* net : getCell()->getNets() ) @@ -781,6 +863,7 @@ namespace Etesian { dots.dot(); nets[netId] = temporary_net( netId, 1 ); + _idsToNets[netId] = make_tuple( net, _cellsToIds.size(), 0 ); //cerr << "+ " << net << endl; @@ -822,6 +905,14 @@ namespace Etesian { } } else { pins.push_back( temporary_pin( point(xpin,ypin), (*iid).second, netId ) ); + Net* rpNet = NULL; + Plug* plug = dynamic_cast( rp->getPlugOccurrence().getEntity() ); + if (plug) { + rpNet = plug->getMasterNet(); + if (rpNet->getDirection() & Net::Direction::DirOut) { + std::get<1>( _idsToNets[netId] ) = (*iid).second; + } + } } //cerr << "| " << rp << " pos:(" << xpin << " " << ypin << ")" << endl; @@ -831,16 +922,18 @@ namespace Etesian { } dots.finish( Dots::Reset ); - _surface = box( (int_t)(topAb.getXMin() / vpitch) - , (int_t)(topAb.getXMax() / vpitch) - , (int_t)(topAb.getYMin() / hpitch) - , (int_t)(topAb.getYMax() / hpitch) - ); - _circuit = netlist( instances, nets, pins ); - _circuit.selfcheck(); - _placementLB.positions_ = positions; - _placementLB.orientations_ = orientations; - _placementUB = _placementLB; + _densityLimits = new coloquinte::density_restrictions (); + _surface = new box( (int_t)(topAb.getXMin() / vpitch) + , (int_t)(topAb.getXMax() / vpitch) + , (int_t)(topAb.getYMin() / hpitch) + , (int_t)(topAb.getYMax() / hpitch) + ); + _circuit = new netlist( instances, nets, pins ); + _circuit->selfcheck(); + _placementLB = new coloquinte::placement_t (); + _placementLB->positions_ = positions; + _placementLB->orientations_ = orientations; + _placementUB = new coloquinte::placement_t ( *_placementLB ); return instancesNb-fixedNb; } @@ -890,18 +983,18 @@ namespace Etesian { // Perform a very quick legalization pass cmess2 << " o Simple legalization." << endl; - auto first_legalizer = region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB); + auto first_legalizer = region_distribution::uniform_density_distribution(*_surface, *_circuit, *_placementLB); first_legalizer.selfcheck(); - get_rough_legalization( _circuit, _placementUB, first_legalizer); + get_rough_legalization( *_circuit, *_placementUB, first_legalizer); - _placementLB = _placementUB; + *_placementLB = *_placementUB; // Early topology-independent solution with a star model + negligible pulling forces to avoid dumb solutions // Spreads well to help subsequent optimization passes cmess2 << " o Star (*) Optimization." << endl; - auto solv = get_star_linear_system( _circuit, _placementLB, 1.0, 0, 10) // Limit the number of pins: don't want big awful nets with high weight - + get_pulling_forces( _circuit, _placementUB, 1000000.0); - solve_linear_system( _circuit, _placementLB, solv, 200 ); + auto solv = get_star_linear_system( *_circuit, *_placementLB, 1.0, 0, 10) // Limit the number of pins: don't want big awful nets with high weight + + get_pulling_forces( *_circuit, *_placementUB, 1000000.0); + solve_linear_system( *_circuit, *_placementLB, solv, 200 ); _progressReport2(" [---]" ); } @@ -911,8 +1004,8 @@ namespace Etesian { using namespace coloquinte::gp; // Create a legalizer and bipartition it until we have sufficient precision auto legalizer = (options & ForceUniformDensity) != 0 ? - region_distribution::uniform_density_distribution (_surface, _circuit, _placementLB, _densityLimits) - : region_distribution::full_density_distribution (_surface, _circuit, _placementLB, _densityLimits); + region_distribution::uniform_density_distribution (*_surface, *_circuit, *_placementLB, *_densityLimits) + : region_distribution::full_density_distribution (*_surface, *_circuit, *_placementLB, *_densityLimits); while(legalizer.region_dimensions().x > 2*legalizer.region_dimensions().y) legalizer.x_bipartition(); while(2*legalizer.region_dimensions().x < legalizer.region_dimensions().y) @@ -927,9 +1020,9 @@ namespace Etesian { legalizer.selfcheck(); } // Keep the orientation between LB and UB - _placementUB = _placementLB; + *_placementUB = *_placementLB; // Update UB - get_rough_legalization( _circuit, _placementUB, legalizer ); + get_rough_legalization( *_circuit, *_placementUB, legalizer ); } @@ -942,11 +1035,12 @@ namespace Etesian { { using namespace coloquinte::gp; + bool antennaDone = false; float_t penaltyIncrease = minInc; - float_t linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); + float_t linearDisruption = get_mean_linear_disruption(*_circuit, *_placementLB, *_placementUB); float_t pullingForce = initPenalty; - float_t upperWL = static_cast(get_HPWL_wirelength(_circuit, _placementUB)), - lowerWL = static_cast(get_HPWL_wirelength(_circuit, _placementLB)); + float_t upperWL = static_cast(get_HPWL_wirelength(*_circuit, *_placementUB)), + lowerWL = static_cast(get_HPWL_wirelength(*_circuit, *_placementLB)); float_t prevOptRatio = lowerWL / upperWL; index_t i=0; @@ -957,32 +1051,37 @@ namespace Etesian { ostringstream label; label.str(""); - label << " [" << setw(3) << setfill('0') << i << setfill(' ') << "] Bipart."; + label << " [" << setw(3) << setfill('0') << i << setfill(' ') << "] " + << setw(5) << setprecision(4) << linearDisruption << "% Bipart."; _progressReport1(label.str() ); - upperWL = static_cast(get_HPWL_wirelength(_circuit, _placementUB)); + upperWL = static_cast(get_HPWL_wirelength(*_circuit, *_placementUB)); //float_t legRatio = lowerWL / upperWL; // Get the system to optimize (tolerance, maximum and minimum pin counts) // and the pulling forces (threshold distance) auto opt_problem = (options & SteinerModel) ? - get_RSMT_linear_system ( _circuit, _placementLB, minDisruption, 2, 100000 ) - : get_HPWLF_linear_system ( _circuit, _placementLB, minDisruption, 2, 100000 ); + get_RSMT_linear_system ( *_circuit, *_placementLB, minDisruption, 2, 100000 ) + : get_HPWLF_linear_system ( *_circuit, *_placementLB, minDisruption, 2, 100000 ); auto solv = opt_problem - + get_linear_pulling_forces( _circuit, _placementUB, _placementLB, pullingForce, 2.0f * linearDisruption); - solve_linear_system( _circuit, _placementLB, solv, 200 ); // 200 iterations - _progressReport2(" Linear." ); + + get_linear_pulling_forces( *_circuit + , *_placementUB + , *_placementLB + , pullingForce + , 2.0f * linearDisruption); + solve_linear_system( *_circuit, *_placementLB, solv, 200 ); // 200 iterations + _progressReport2(" Linear." ); if(options & UpdateLB) - _updatePlacement( _placementLB ); + _updatePlacement( _placementUB ); // Optimize orientation sometimes if (i%5 == 0) { - optimize_exact_orientations( _circuit, _placementLB ); - _progressReport2(" Orient." ); + optimize_exact_orientations( *_circuit, *_placementLB ); + _progressReport2(" Orient." ); } - lowerWL = static_cast(get_HPWL_wirelength(_circuit, _placementLB)); + lowerWL = static_cast(get_HPWL_wirelength(*_circuit, *_placementLB)); float_t optRatio = lowerWL / upperWL; /* @@ -1000,8 +1099,13 @@ namespace Etesian { pullingForce += penaltyIncrease; prevOptRatio = optRatio; - linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); + linearDisruption = get_mean_linear_disruption(*_circuit, *_placementLB, *_placementUB); ++i; + + if ((linearDisruption < getAntennaInsertThreshold()*100.0) and not antennaDone) { + antennaProtect(); + antennaDone = true; + } // First way to exit the loop: UB and LB difference is <10% // Second way to exit the loop: the legalization is close enough to the previous result } while (linearDisruption > minDisruption and prevOptRatio <= 0.9); @@ -1023,52 +1127,94 @@ namespace Etesian { label.str(""); label << " [" << setw(3) << setfill('0') << i << setfill(' ') << "]"; - optimize_x_orientations( _circuit, _placementUB ); // Don't disrupt VDD/VSS connections in a row + optimize_x_orientations( *_circuit, *_placementUB ); // Don't disrupt VDD/VSS connections in a row _progressReport1(label.str() + " Oriented ......." ); if(options & UpdateDetailed) _updatePlacement( _placementUB ); - auto legalizer = legalize( _circuit, _placementUB, _surface, sliceHeight ); - coloquinte::dp::get_result( _circuit, legalizer, _placementUB ); + auto legalizer = legalize( *_circuit, *_placementUB, *_surface, sliceHeight ); + coloquinte::dp::get_result( *_circuit, legalizer, *_placementUB ); _progressReport1(" Legalized ......" ); if(options & UpdateDetailed) _updatePlacement( _placementUB ); - row_compatible_orientation( _circuit, legalizer, true ); - swaps_global_HPWL( _circuit, legalizer, 3, 4 ); - coloquinte::dp::get_result( _circuit, legalizer, _placementUB ); + row_compatible_orientation( *_circuit, legalizer, true ); + swaps_global_HPWL( *_circuit, legalizer, 3, 4 ); + coloquinte::dp::get_result( *_circuit, legalizer, *_placementUB ); _progressReport1(" Global Swaps ..." ); if(options & UpdateDetailed) _updatePlacement( _placementUB ); if(options & SteinerModel) - OSRP_noncvx_RSMT( _circuit, legalizer ); + OSRP_noncvx_RSMT( *_circuit, legalizer ); else - OSRP_convex_HPWL( _circuit, legalizer ); - coloquinte::dp::get_result( _circuit, legalizer, _placementUB ); + OSRP_convex_HPWL( *_circuit, legalizer ); + coloquinte::dp::get_result( *_circuit, legalizer, *_placementUB ); _progressReport1(" Row Optimization" ); if(options & UpdateDetailed) _updatePlacement( _placementUB ); if(options & SteinerModel) - swaps_row_noncvx_RSMT( _circuit, legalizer, effort+2 ); + swaps_row_noncvx_RSMT( *_circuit, legalizer, effort+2 ); else - swaps_row_convex_HPWL( _circuit, legalizer, effort+2 ); - coloquinte::dp::get_result( _circuit, legalizer, _placementUB ); + swaps_row_convex_HPWL( *_circuit, legalizer, effort+2 ); + coloquinte::dp::get_result( *_circuit, legalizer, *_placementUB ); _progressReport1(" Local Swaps ...." ); if(options & UpdateDetailed) _updatePlacement( _placementUB ); if (i == iterations-1) { - //swaps_row_convex_RSMT( _circuit, legalizer, 4 ); - row_compatible_orientation( _circuit, legalizer, true ); - coloquinte::dp::get_result( _circuit, legalizer, _placementUB ); - verify_placement_legality( _circuit, _placementUB, _surface ); + //swaps_row_convex_RSMT( *_circuit, legalizer, 4 ); + row_compatible_orientation( *_circuit, legalizer, true ); + coloquinte::dp::get_result( *_circuit, legalizer, *_placementUB ); + verify_placement_legality( *_circuit, *_placementUB, *_surface ); _progressReport1(" Final Legalize ." ); } } - _placementLB = _placementUB; // In case we run other passes - _updatePlacement( _placementUB ); + *_placementLB = *_placementUB; // In case we run other passes + _updatePlacement( _placementUB, FinalStage ); + } + + + void EtesianEngine::antennaProtect () + { + DbU::Unit maxWL = getAntennaMaxWL(); + if (not maxWL) return; + + cmess1 << " o Inserting antenna effect protection." << endl; + uint32_t count = 0; + int_t diodeWidth = _diodeCell->getAbutmentBox().getWidth() / getSliceStep(); + cdebug_log(122,0) << "diodeWidth=" << diodeWidth << "p" << endl; + + for ( coloquinte::index_t inet=0 ; inet < _circuit->net_cnt() ; ++inet ) { + DbU::Unit rsmt = toDbU( coloquinte::get_RSMT_length( *_circuit, *_placementUB, inet ) ); + size_t idriver = std::get<1>( _idsToNets[inet] ); + if (idriver >= _cellsToIds.size()) continue; + + Instance* instance = std::get<0>( _idsToInsts[idriver] ); + string masterName = getString( instance->getMasterCell()->getName() ); + uint32_t drivePower = 1; + if (masterName.substr(masterName.size()-3,2) == "_x") { + drivePower = std::stoi( masterName.substr(masterName.size()-1) ); + } + + if (rsmt > drivePower*maxWL) { + Net* net = std::get<0>( _idsToNets[inet] ); + cdebug_log(122,0) << "| Net [" << inet << "] \"" << net->getName() << "\" may have antenna effect, " + << DbU::getValueString(rsmt) + << " drive=" << drivePower + << " \"" << masterName << "\"" + << endl; + std::get<2>( _idsToNets [inet ] ) |= NeedsDiode; + std::get<2>( _idsToInsts[idriver] ) |= NeedsDiode; + std::get<1>( _idsToInsts[idriver] ) = inet; + coloquinte::point cell_size = _circuit->get_cell_size(idriver); + cell_size.x += diodeWidth; + _circuit->set_cell_size( idriver, cell_size ); + ++count; + } + } + cmess1 << ::Dots::asInt( " - Inserted diodes", count ) << endl; } @@ -1163,17 +1309,18 @@ namespace Etesian { cmess1 << " o Detailed Placement." << endl; detailedPlace(detailedIterations, detailedEffort, detailedOptions); + Breakpoint::stop( 100, "Before adding feeds." ); cmess2 << " o Adding feed cells." << endl; - readSlices(); + toHurricane(); //addFeeds(); cmess1 << " o Placement finished." << endl; stopMeasures(); printMeasures(); cmess1 << ::Dots::asString - ( " - HPWL", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_HPWL_wirelength(_circuit,_placementUB )*getSliceStep() ) ) << endl; + ( " - HPWL", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_HPWL_wirelength(*_circuit,*_placementUB )*getSliceStep() ) ) << endl; cmess1 << ::Dots::asString - ( " - RMST", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_RSMT_wirelength(_circuit,_placementUB )*getSliceStep() ) ) << endl; + ( " - RMST", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_RSMT_wirelength(*_circuit,*_placementUB )*getSliceStep() ) ) << endl; UpdateSession::open(); for ( Net* net : getCell()->getNets() ) { @@ -1202,12 +1349,12 @@ namespace Etesian { } cmess2 << label - << " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementUB ) - << " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementUB ) + << " HPWL=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_HPWL_wirelength( *_circuit, *_placementUB ))) + << " RMST=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_RSMT_wirelength( *_circuit, *_placementUB ))) << endl; cparanoid << indent - << " L-Dsrpt:" << setw(8) << coloquinte::gp::get_mean_linear_disruption ( _circuit, _placementLB, _placementUB ) - << " Q-Dsrpt:" << setw(8) << coloquinte::gp::get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB ) + << " L-Dsrpt=" << setw(8) << coloquinte::gp::get_mean_linear_disruption ( *_circuit, *_placementLB, *_placementUB ) + << " Q-Dsrpt=" << setw(8) << coloquinte::gp::get_mean_quadratic_disruption( *_circuit, *_placementLB, *_placementUB ) << endl; } @@ -1222,13 +1369,13 @@ namespace Etesian { } cmess2 << label - << " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementLB ) - << " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementLB ) + << " HPWL=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_HPWL_wirelength( *_circuit, *_placementLB ))) + << " RMST=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_RSMT_wirelength( *_circuit, *_placementLB ))) << endl; } - void EtesianEngine::_updatePlacement ( const coloquinte::placement_t& placement ) + void EtesianEngine::_updatePlacement ( const coloquinte::placement_t* placement, uint32_t flags ) { UpdateSession::open(); @@ -1236,6 +1383,8 @@ namespace Etesian { if (getBlockInstance()) topTransformation = getBlockInstance()->getTransformation(); topTransformation.invert(); + vector< tuple > diodeMasters; + for ( Occurrence occurrence : getCell()->getTerminalNetlistInstanceOccurrences(getBlockInstance()) ) { DbU::Unit hpitch = getSliceStep(); @@ -1254,29 +1403,106 @@ namespace Etesian { if (instance->getPlacementStatus() == Instance::PlacementStatus::FIXED) continue; - point position = placement.positions_[(*iid).second]; - Transformation trans = toTransformation( position - , placement.orientations_[(*iid).second] - , instance->getMasterCell() - , hpitch - , vpitch - ); + uint32_t outputSide = getOutputSide( instance->getMasterCell() ); + point position = placement->positions_[(*iid).second]; + Transformation cellTrans = toTransformation( position + , placement->orientations_[(*iid).second] + , instance->getMasterCell() + , hpitch + , vpitch + ); + topTransformation.applyOn( cellTrans ); //cerr << "Setting <" << instanceName << " @" << instancePosition << endl; + if ((flags & FinalStage) and (std::get<2>(_idsToInsts[(*iid).second]) & NeedsDiode)) { + Transformation diodeTrans; + + if (outputSide & RightSide) { + DbU::Unit dx = instance ->getMasterCell()->getAbutmentBox().getWidth(); + if ( (cellTrans.getOrientation() == Transformation::Orientation::R2) + or (cellTrans.getOrientation() == Transformation::Orientation::MX)) + dx = -dx; + diodeTrans = Transformation( cellTrans.getTx() + dx + , cellTrans.getTy() + , cellTrans.getOrientation() ); + } else { + DbU::Unit dx = _diodeCell->getAbutmentBox().getWidth(); + if ( (cellTrans.getOrientation() == Transformation::Orientation::R2) + or (cellTrans.getOrientation() == Transformation::Orientation::MX)) + dx = -dx; + diodeTrans = cellTrans; + cellTrans = Transformation( diodeTrans.getTx() + dx + , diodeTrans.getTy() + , diodeTrans.getOrientation() ); + } + + diodeMasters.push_back( make_tuple( occurrence + , std::get<1>(_idsToInsts[(*iid).second]) + , diodeTrans )); + } + // This is temporary as it's not trans-hierarchic: we ignore the positions // of all the intermediary instances. - topTransformation.applyOn( trans ); - instance->setTransformation( trans ); + instance->setTransformation( cellTrans ); instance->setPlacementStatus( Instance::PlacementStatus::PLACED ); } } + if (_diodeCell) { + Net* diodeOutput = NULL; + for ( Net* net : _diodeCell->getNets() ) { + if (net->isSupply() or not net->isExternal()) continue; + diodeOutput = net; + break; + } + + for ( auto diodeInfos : diodeMasters ) { + Net* topNet = std::get<0>( _idsToNets[ std::get<1>(diodeInfos) ] ); + Instance* instance = static_cast( std::get<0>(diodeInfos).getEntity() ); + Cell* ownerCell = instance->getCell(); + Instance* diode = _createDiode( ownerCell ); + diode->setTransformation( std::get<2>( diodeInfos )); + diode->setPlacementStatus( Instance::PlacementStatus::PLACED ); + + Net* driverOutput = NULL; + for ( Net* net : instance->getMasterCell()->getNets() ) { + if (net->isSupply() or not net->isExternal()) continue; + if (net->getDirection() & Net::Direction::DirOut) { + driverOutput = net; + break; + } + } + + if (diodeOutput and driverOutput) { + cdebug_log(122,0) << "Bind:" << endl; + Plug* diodePlug = diode ->getPlug( diodeOutput ); + Plug* driverPlug = instance->getPlug( driverOutput ); + diodePlug->setNet( driverPlug->getNet() ); + + cdebug_log(122,0) << " Driver net=" << topNet << endl; + cdebug_log(122,0) << " " << instance << " @" << instance->getTransformation() << endl; + cdebug_log(122,0) << " " << diode << " @" << diode ->getTransformation() << endl; + cdebug_log(122,0) << " topNet->getCell():" << topNet->getCell() << endl; + cdebug_log(122,0) << " " << std::get<0>(diodeInfos).getPath() << endl; + Path path = std::get<0>(diodeInfos).getPath(); + RoutingPad::create( topNet, Occurrence(diodePlug,path), RoutingPad::BiggestArea ); + } + } + } + UpdateSession::close(); if (_viewer) _viewer->getCellWidget()->refresh(); } + Instance* EtesianEngine::_createDiode ( Cell* owner ) + { + if (not _diodeCell) return NULL; + return Instance::create( owner, string("diode_")+getString(_getNewDiodeId()), _diodeCell ); + } + + string EtesianEngine::_getTypeName () const { return "Etesian::EtesianEngine"; } @@ -1295,6 +1521,8 @@ namespace Etesian { if (record) { record->add( getSlot( "_configuration", _configuration ) ); + record->add( getSlot( "_area" , _area ) ); + record->add( getSlot( "_diodeCount" , _diodeCount ) ); } return record; } diff --git a/etesian/src/Placement.cpp b/etesian/src/Placement.cpp index 28e2f218..ab189df1 100644 --- a/etesian/src/Placement.cpp +++ b/etesian/src/Placement.cpp @@ -14,16 +14,12 @@ // +-----------------------------------------------------------------+ -#include -#include -#include #include "hurricane/Error.h" #include "hurricane/Warning.h" #include "hurricane/DataBase.h" #include "hurricane/UpdateSession.h" #include "hurricane/Plug.h" #include "hurricane/Path.h" -#include "hurricane/Instance.h" #include "hurricane/Library.h" #include "hurricane/viewer/CellWidget.h" #include "hurricane/viewer/CellViewer.h" @@ -32,242 +28,40 @@ #include "etesian/EtesianEngine.h" -namespace { +namespace Etesian { using namespace std; using Hurricane::tab; using Hurricane::Warning; using Hurricane::Error; - using Hurricane::DbU; - using Hurricane::Box; - using Hurricane::Interval; - using Hurricane::DBo; - using Hurricane::Occurrence; - using Hurricane::Instance; using Hurricane::Path; using Hurricane::Transformation; using Hurricane::DataBase; - using Hurricane::Cell; using Hurricane::Library; + using Hurricane::UpdateSession; using CRL::AllianceFramework; using CRL::CatalogExtension; using CRL::getTransformation; using Etesian::EtesianEngine; -// ------------------------------------------------------------------- -// Class : "::TieDatas". - - class TieDatas { - public: - inline TieDatas ( Cell* cell=NULL, DbU::Unit leftDistance=0, DbU::Unit rightDistance=0 ); - inline Cell* getCell () const; - inline DbU::Unit getLeftDistance () const; - inline DbU::Unit getRightDistance() const; - private: - Cell* _cell; - DbU::Unit _leftDistance; - DbU::Unit _rightDistance; - }; - - - inline TieDatas::TieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance ) - : _cell (cell) - , _leftDistance (leftDistance) - , _rightDistance(rightDistance) - { } - - inline Cell* TieDatas::getCell () const { return _cell; } - inline DbU::Unit TieDatas::getLeftDistance () const { return _leftDistance; } - inline DbU::Unit TieDatas::getRightDistance() const { return _rightDistance; } - - -// ------------------------------------------------------------------- -// Class : "::TieLUT". - - class TieLUT { - public: - inline TieLUT (); - inline const TieDatas* getTieDatas ( Cell* ) const; - inline DbU::Unit getLeftDistance ( Cell* ) const; - inline DbU::Unit getRightDistance ( Cell* ) const; - inline void addTieDatas ( Cell*, DbU::Unit leftDistance, DbU::Unit rightDistance ); - private: - map< Cell*, TieDatas, DBo::CompareById > _tieLut; - }; - - - inline TieLUT::TieLUT () - : _tieLut() - { } - - - inline void TieLUT::addTieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance ) - { - const TieDatas* datas = getTieDatas( cell ); - if (datas) { - cerr << Error( "TieLUT::addTieDatas(): Duplicate datas for % (ignoreds)." - , getString(cell).c_str() - ) << endl; - } - _tieLut[ cell ] = TieDatas( cell, leftDistance, rightDistance ); - } - - - inline const TieDatas* TieLUT::getTieDatas ( Cell* cell ) const - { - auto iDatas = _tieLut.find( cell ); - return (iDatas != _tieLut.end()) ? &((*iDatas).second) : NULL; - } - - - inline DbU::Unit TieLUT::getLeftDistance ( Cell* cell ) const - { - const TieDatas* datas = getTieDatas( cell ); - return (datas) ? datas->getLeftDistance() : 0; - } - - - inline DbU::Unit TieLUT::getRightDistance ( Cell* cell ) const - { - const TieDatas* datas = getTieDatas( cell ); - return (datas) ? datas->getRightDistance() : 0; - } - - // ------------------------------------------------------------------- // Class : "::Tile". - class Area; - class Slice; - - class Tile { - public: - inline Tile ( DbU::Unit xMin, DbU::Unit width, const Occurrence& ); - inline bool isFixed () const; - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - inline DbU::Unit getWidth () const; - inline Cell* getMasterCell () const; - inline Instance* getInstance () const; - inline const Occurrence& getOccurrence () const; - inline void translate ( DbU::Unit ); - private: - DbU::Unit _xMin; - DbU::Unit _width; - Occurrence _occurrence; - }; - - inline Tile::Tile ( DbU::Unit xMin, DbU::Unit width, const Occurrence& occurrence ) - : _xMin(xMin), _width(width), _occurrence(occurrence) - { } - - inline DbU::Unit Tile::getXMin () const { return _xMin; } - inline DbU::Unit Tile::getXMax () const { return _xMin+_width; } - inline DbU::Unit Tile::getWidth () const { return _width; } - inline const Occurrence& Tile::getOccurrence () const { return _occurrence; } - inline Instance* Tile::getInstance () const { return static_cast( _occurrence.getEntity() ); } - inline Cell* Tile::getMasterCell () const { return getInstance()->getMasterCell(); } - - inline bool Tile::isFixed () const - { return getInstance()->getPlacementStatus() == Instance::PlacementStatus::FIXED; } - - - inline void Tile::translate ( DbU::Unit dx ) + Record* Tile::_getRecord () const { - cdebug_log(121,0) << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << endl; - Instance* instance = getInstance(); - Transformation reference = instance->getTransformation(); - Transformation transf = Transformation( reference.getTx() + dx - , reference.getTy() - , reference.getOrientation() ); - instance->setTransformation( transf ); - _xMin += dx; + Record* record = new Record(getString(this)); + record->add( getSlot( "_occurrence", _occurrence ) ); + record->add( DbU::getValueSlot( "_xMin" , &_xMin ) ); + record->add( DbU::getValueSlot( "_width", &_width ) ); + return record; } -// ------------------------------------------------------------------- -// Class : "::Hole". - - class Area; - class Slice; - - - class Hole { - public: - inline Hole ( DbU::Unit xMin, DbU::Unit width ); - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - inline DbU::Unit getWidth () const; - private: - DbU::Unit _xMin; - DbU::Unit _width; - }; - - inline Hole::Hole ( DbU::Unit xMin, DbU::Unit width ) - : _xMin(xMin), _width(width) - { } - - inline DbU::Unit Hole::getXMin () const { return _xMin; } - inline DbU::Unit Hole::getXMax () const { return _xMin+_width; } - inline DbU::Unit Hole::getWidth () const { return _width; } - - -// ------------------------------------------------------------------- -// Class : "::SubSlice". - - class SubSlice { - public: - SubSlice ( Slice*, const list::iterator& beginTile ); - inline const list::iterator getBeginTile () const; - inline const list::iterator getEndTile () const; - inline DbU::Unit getYBottom () const; - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - DbU::Unit getAverageChunk ( size_t& ) const; - void insertTies ( DbU::Unit latchUpMax ); - private: - Slice* _slice; - list::iterator _beginTile; - list::iterator _endTile; - }; - - inline const list::iterator SubSlice::getBeginTile () const { return _beginTile; } - inline const list::iterator SubSlice::getEndTile () const { return _endTile; } - - // ------------------------------------------------------------------- // Class : "::Slice". - class Slice { - public: - Slice ( Area*, DbU::Unit ybottom ); - inline DbU::Unit getYBottom () const; - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - inline Interval getXSpan () const; - inline Area* getArea () const; - inline EtesianEngine* getEtesian () const; - inline size_t getSpinSlice0 () const; - inline DbU::Unit getLeftDistance ( Cell* cell ) const; - inline DbU::Unit getRightDistance ( Cell* cell ) const; - bool validate ( DbU::Unit latchUpMax ) const; - inline list& getTiles (); - void merge ( const Occurrence&, const Box& ); - void addFeeds ( size_t islice ); - void fillHole ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit ybottom, size_t yspin ); - void buildSubSlices (); - void showSubSlices (); - void insertTies ( DbU::Unit latchUpMax ); - string _getString () const; - private: - Area* _area; - DbU::Unit _ybottom; - list _tiles; - vector _subSlices; - }; - Slice::Slice ( Area* area, DbU::Unit ybottom ) : _area (area) @@ -388,7 +182,7 @@ namespace { void Slice::addFeeds ( size_t islice ) { if (_tiles.empty()) { - fillHole( getXMin(), getXMax(), getYBottom(), islice%2 ); + fillHole( _tiles.end(), getXMin(), getXMax(), getYBottom(), islice%2 ); return; } @@ -398,21 +192,27 @@ namespace { // Hole before the first chunk. if ((*itile).getXMin() > getXMin()) { - fillHole( getXMin(), (*itile).getXMin(), getYBottom(), (islice+getSpinSlice0())%2 ); + fillHole( itile, getXMin(), (*itile).getXMin(), getYBottom(), (islice+getSpinSlice0())%2 ); } - for ( ; itilenext != _tiles.end() ; ++itile, ++itilenext ) { - fillHole( (*itile).getXMax(), (*itilenext).getXMin(), getYBottom(), (islice+getSpinSlice0())%2 ); + while ( itilenext != _tiles.end() ) { + fillHole( itilenext, (*itile).getXMax(), (*itilenext).getXMin(), getYBottom(), (islice+getSpinSlice0())%2 ); + itile = itilenext; + ++itilenext; } // Hole after the last chunk. if ((*itile).getXMax() < getXMax()) { - fillHole( (*itile).getXMax(), getXMax(), getYBottom(), (islice+getSpinSlice0())%2 ); + fillHole( _tiles.end(), (*itile).getXMax(), getXMax(), getYBottom(), (islice+getSpinSlice0())%2 ); } } - void Slice::fillHole ( DbU::Unit xmin, DbU::Unit xmax, DbU::Unit ybottom, size_t yspin ) + void Slice::fillHole ( std::list::iterator before + , DbU::Unit xmin + , DbU::Unit xmax + , DbU::Unit ybottom + , size_t yspin ) { Cell* feed = getEtesian()->getFeedCells().getBiggestFeed(); if (feed == NULL) { @@ -438,52 +238,65 @@ namespace { if (feed == NULL) break; } - Instance::create ( getEtesian()->getBlockCell() - , getEtesian()->getFeedCells().getUniqueInstanceName().c_str() - , feed - , getTransformation( feed->getAbutmentBox() - , xtie - , _ybottom - , (yspin)?Transformation::Orientation::MY - :Transformation::Orientation::ID - ) - , Instance::PlacementStatus::PLACED - ); - + Instance* instance = Instance::create + ( getEtesian()->getBlockCell() + , getEtesian()->getFeedCells().getUniqueInstanceName().c_str() + , feed + , getTransformation( feed->getAbutmentBox() + , xtie + , _ybottom + , (yspin)?Transformation::Orientation::MY + :Transformation::Orientation::ID + ) + , Instance::PlacementStatus::PLACED + ); + _tiles.insert( before + , Tile( xtie, feed->getAbutmentBox().getWidth(), Occurrence(instance) )); xtie += feedWidth; } } + + Instance* Slice::createDiodeUnder ( const Box& diodeArea ) + { + Cell* diode = getEtesian()->getDiodeCell(); + if (diode == NULL) { + cerr << Error("Slice::createDiodeUnder(): No diode cell has been registered, ignoring.") << endl; + return NULL; + } + Cell* feed = getEtesian()->getFeedCells().getBiggestFeed(); + if (feed == NULL) { + cerr << Error("Slice::createDiodeUnder(): No feed has been registered, ignoring.") << endl; + return NULL; + } + + Instance* diodeInst = NULL; + for ( auto iTile=_tiles.begin() ; iTile != _tiles.end() ; ++iTile ) { + if ((*iTile).getXMax() < diodeArea.getXMin()) continue; + if ((*iTile).getXMax() >= diodeArea.getXMax()) break; + if ((*iTile).getMasterCell() != feed) continue; + diodeInst = (*iTile).getInstance(); + diodeInst->setMasterCell( diode ); + break; + } + return diodeInst; + } + + + Record* Slice::_getRecord () const + { + Record* record = new Record(getString(this)); + record->add( getSlot( "_area" , _area ) ); + record->add( DbU::getValueSlot( "_ybottom", &_ybottom ) ); + record->add( getSlot( "_tiles" , &_tiles ) ); + record->add( getSlot( "_subSlices" , &_subSlices ) ); + return record; + } + // ------------------------------------------------------------------- // Class : "::Area". - class Area { - public: - Area ( EtesianEngine* ); - ~Area (); - inline EtesianEngine* getEtesian () const; - inline size_t getSpinSlice0 () const; - inline void setSpinSlice0 ( size_t ); - inline DbU::Unit getXMin () const; - inline DbU::Unit getXMax () const; - inline DbU::Unit getLeftDistance ( Cell* cell ) const; - inline DbU::Unit getRightDistance ( Cell* cell ) const; - bool validate ( DbU::Unit latchUpMax ) const; - void merge ( const Occurrence&, const Box& ); - void addFeeds (); - void buildSubSlices (); - void showSubSlices (); - void insertTies ( DbU::Unit latchUpMax ); - private: - EtesianEngine* _etesian; - TieLUT _tieLut; - Box _cellAb; - DbU::Unit _sliceHeight; - vector _slices; - size_t _spinSlice0; - }; - Area::Area ( EtesianEngine* etesian ) : _etesian (etesian) @@ -505,6 +318,10 @@ namespace { if (masterCell) { _tieLut.addTieDatas( masterCell, DbU::fromMicrons(1.28), DbU::fromMicrons(11.7) ); } + masterCell = library->getCell( "dio_x0" ); + if (masterCell) { + _tieLut.addTieDatas( masterCell, DbU::fromMicrons(6.5), DbU::fromMicrons(6.5) ); + } } } } @@ -517,15 +334,6 @@ namespace { } - inline EtesianEngine* Area::getEtesian () const { return _etesian; } - inline size_t Area::getSpinSlice0 () const { return _spinSlice0; } - inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; } - inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); } - inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); } - inline DbU::Unit Area::getLeftDistance ( Cell* cell ) const { return _tieLut.getLeftDistance(cell); } - inline DbU::Unit Area::getRightDistance ( Cell* cell ) const { return _tieLut.getRightDistance(cell); } - - bool Area::validate ( DbU::Unit latchUpMax ) const { bool validated = true; @@ -573,6 +381,19 @@ namespace { validate( latchUpMax ); } + + Record* Area::_getRecord () const + { + Record* record = new Record(getString(this)); + record->add( getSlot( "_etesian" , _etesian ) ); + record->add( getSlot( "_tieLut" , &_tieLut ) ); + record->add( getSlot( "_cellAb" , _cellAb ) ); + record->add( DbU::getValueSlot( "_sliceHeight", &_sliceHeight ) ); + record->add( getSlot( "_slices" , &_slices ) ); + record->add( getSlot( "_spinSlice0" , _spinSlice0 ) ); + return record; + } + SubSlice::SubSlice ( Slice* slice, const list::iterator& beginTile ) : _slice(slice) @@ -586,14 +407,6 @@ namespace { } } - inline DbU::Unit SubSlice::getYBottom () const { return _slice->getYBottom(); } - - inline DbU::Unit SubSlice::getXMin () const - { return (_beginTile == _slice->getTiles().begin()) ? _slice->getXMin() : (*_beginTile).getXMin(); } - - inline DbU::Unit SubSlice::getXMax () const - { return (_endTile == _slice->getTiles().end ()) ? _slice->getXMax() : (*_endTile).getXMax(); } - DbU::Unit SubSlice::getAverageChunk ( size_t& count ) const { @@ -755,31 +568,23 @@ namespace { cdebug_tabw(121,-2); } + + Instance* Area::createDiodeUnder ( const Box& diodeArea ) + { + DbU::Unit y = diodeArea.getYCenter(); - inline DbU::Unit Slice::getYBottom () const { return _ybottom; } - inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); } - inline DbU::Unit Slice::getXMax () const { return _area->getXMax(); } - inline DbU::Unit Slice::getLeftDistance ( Cell* cell ) const { return _area->getLeftDistance(cell); } - inline DbU::Unit Slice::getRightDistance ( Cell* cell ) const { return _area->getRightDistance(cell); } - inline Interval Slice::getXSpan () const { return Interval( getXMin(), getXMax() ); } - inline Area* Slice::getArea () const { return _area; } - inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); } - inline size_t Slice::getSpinSlice0 () const { return getArea()->getSpinSlice0(); } - inline list& Slice::getTiles () { return _tiles; } + if ((y < _cellAb.getYMin()) or (y >= _cellAb.getYMax())) return NULL; + if (not diodeArea.intersect(_cellAb)) return NULL; + + size_t islice = (y - _cellAb.getYMin()) / _sliceHeight; + return _slices[islice]->createDiodeUnder( diodeArea ); + } -} // Anonymous namespace. +// ------------------------------------------------------------------- +// Class : "::EtesianEngine". - -namespace Etesian { - - - using Hurricane::DataBase; - using Hurricane::UpdateSession; - using Hurricane::Occurrence; - - - void EtesianEngine::readSlices () + void EtesianEngine::toHurricane () { if (not getFeedCells().feedNumbers()) { cerr << Warning( "EtesianEngine::readSlices(): No feed cells available, skipping." ) << endl; @@ -788,10 +593,11 @@ namespace Etesian { UpdateSession::open(); - Area area ( this ); + if (_area) delete _area; + _area = new Area ( this ); Box topCellAb = getBlockCell()->getAbutmentBox(); - area.setSpinSlice0( _yspinSlice0 ); + _area->setSpinSlice0( _yspinSlice0 ); if (getBlockInstance()) { Transformation toBlockTransf = getBlockInstance()->getTransformation(); @@ -803,7 +609,7 @@ namespace Etesian { toBlockTransf.applyOn( overlapAb ); overlapAb = topCellAb.getIntersection( overlapAb ); if (not overlapAb.isEmpty()) { - area.merge( Occurrence(instance), overlapAb ); + _area->merge( Occurrence(instance), overlapAb ); } } } @@ -831,19 +637,19 @@ namespace Etesian { continue; } - area.merge( occurrence, instanceAb ); + _area->merge( occurrence, instanceAb ); } - area.buildSubSlices(); - area.showSubSlices(); + _area->buildSubSlices(); + _area->showSubSlices(); if (getConfiguration()->getLatchUpDistance()) { Cell* feed = getFeedCells().getBiggestFeed(); DbU::Unit tieSpacing = getConfiguration()->getLatchUpDistance()*2 - feed->getAbutmentBox().getWidth(); if (feed != NULL) tieSpacing -= feed->getAbutmentBox().getWidth(); - area.insertTies( tieSpacing ); + _area->insertTies( tieSpacing ); } - area.addFeeds(); + _area->addFeeds(); UpdateSession::close(); diff --git a/etesian/src/PyEtesianEngine.cpp b/etesian/src/PyEtesianEngine.cpp index 21a8f3c6..a9159e3f 100644 --- a/etesian/src/PyEtesianEngine.cpp +++ b/etesian/src/PyEtesianEngine.cpp @@ -71,6 +71,7 @@ extern "C" { DirectVoidMethod(EtesianEngine,etesian,setDefaultAb) DirectVoidMethod(EtesianEngine,etesian,resetPlacement) + DirectVoidMethod(EtesianEngine,etesian,clearColoquinte) DirectSetLongAttribute (PyEtesianEngine_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine) DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine) DirectSetDoubleAttribute(PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine) @@ -233,6 +234,8 @@ extern "C" { , "Override the configuration aspect ratio parameter value." } , { "resetPlacement" , (PyCFunction)PyEtesianEngine_resetPlacement , METH_NOARGS , "Compute and set the abutment box using the aspect ratio and the space margin." } + , { "clearColoquinte" , (PyCFunction)PyEtesianEngine_clearColoquinte , METH_NOARGS + , "De-allocate the Coloquinte related data structures." } , { "place" , (PyCFunction)PyEtesianEngine_place , METH_NOARGS , "Run the placer (Etesian)." } , { "destroy" , (PyCFunction)PyEtesianEngine_destroy , METH_NOARGS diff --git a/etesian/src/etesian/Configuration.h b/etesian/src/etesian/Configuration.h index 9d6a49fe..406924f0 100644 --- a/etesian/src/etesian/Configuration.h +++ b/etesian/src/etesian/Configuration.h @@ -55,27 +55,30 @@ namespace Etesian { class Configuration { public: // Constructor & Destructor. - Configuration ( const RoutingGauge* rg=NULL, const CellGauge* cg=NULL ); - ~Configuration (); - Configuration* clone () const; - // Methods. - inline RoutingGauge* getGauge () const; - inline CellGauge* getCellGauge () const; - inline Effort getPlaceEffort () const; - inline GraphicUpdate getUpdateConf () const; - inline Density getSpreadingConf () const; - inline bool getRoutingDriven () const; - inline double getSpaceMargin () const; - inline double getAspectRatio () const; - inline string getFeedNames () const; - inline string getBloat () const; - inline DbU::Unit getLatchUpDistance () const; - inline void setSpaceMargin ( double ); - inline void setAspectRatio ( double ); - void print ( Cell* ) const; - Record* _getRecord () const; - string _getString () const; - string _getTypeName () const; + Configuration ( const RoutingGauge* rg=NULL, const CellGauge* cg=NULL ); + ~Configuration (); + Configuration* clone () const; + // Methods. + inline RoutingGauge* getGauge () const; + inline CellGauge* getCellGauge () const; + inline Effort getPlaceEffort () const; + inline GraphicUpdate getUpdateConf () const; + inline Density getSpreadingConf () const; + inline bool getRoutingDriven () const; + inline double getSpaceMargin () const; + inline double getAspectRatio () const; + inline double getAntennaInsertThreshold () const; + inline string getFeedNames () const; + inline string getDiodeName () const; + inline string getBloat () const; + inline DbU::Unit getLatchUpDistance () const; + inline DbU::Unit getAntennaMaxWL () const; + inline void setSpaceMargin ( double ); + inline void setAspectRatio ( double ); + void print ( Cell* ) const; + Record* _getRecord () const; + string _getString () const; + string _getTypeName () const; protected: // Attributes. RoutingGauge* _rg; @@ -86,28 +89,34 @@ namespace Etesian { bool _routingDriven; double _spaceMargin; double _aspectRatio; + double _antennaInsertThreshold; string _feedNames; + string _diodeName; string _bloat; DbU::Unit _latchUpDistance; + DbU::Unit _antennaMaxWL; private: Configuration ( const Configuration& ); Configuration& operator= ( const Configuration& ); }; - inline RoutingGauge* Configuration::getGauge () const { return _rg; } - inline CellGauge* Configuration::getCellGauge () const { return _cg; } - inline Effort Configuration::getPlaceEffort () const { return _placeEffort; } - inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; } - inline Density Configuration::getSpreadingConf () const { return _spreadingConf; } - inline bool Configuration::getRoutingDriven () const { return _routingDriven; } - inline double Configuration::getSpaceMargin () const { return _spaceMargin; } - inline double Configuration::getAspectRatio () const { return _aspectRatio; } - inline string Configuration::getFeedNames () const { return _feedNames; } - inline string Configuration::getBloat () const { return _bloat; } - inline DbU::Unit Configuration::getLatchUpDistance () const { return _latchUpDistance; } - inline void Configuration::setSpaceMargin ( double margin ) { _spaceMargin = margin; } - inline void Configuration::setAspectRatio ( double ratio ) { _aspectRatio = ratio; } + inline RoutingGauge* Configuration::getGauge () const { return _rg; } + inline CellGauge* Configuration::getCellGauge () const { return _cg; } + inline Effort Configuration::getPlaceEffort () const { return _placeEffort; } + inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; } + inline Density Configuration::getSpreadingConf () const { return _spreadingConf; } + inline bool Configuration::getRoutingDriven () const { return _routingDriven; } + inline double Configuration::getSpaceMargin () const { return _spaceMargin; } + inline double Configuration::getAspectRatio () const { return _aspectRatio; } + inline double Configuration::getAntennaInsertThreshold () const { return _antennaInsertThreshold; } + inline string Configuration::getFeedNames () const { return _feedNames; } + inline string Configuration::getDiodeName () const { return _diodeName; } + inline string Configuration::getBloat () const { return _bloat; } + inline DbU::Unit Configuration::getLatchUpDistance () const { return _latchUpDistance; } + inline DbU::Unit Configuration::getAntennaMaxWL () const { return _antennaMaxWL; } + inline void Configuration::setSpaceMargin ( double margin ) { _spaceMargin = margin; } + inline void Configuration::setAspectRatio ( double ratio ) { _aspectRatio = ratio; } } // Etesian namespace. diff --git a/etesian/src/etesian/EtesianEngine.h b/etesian/src/etesian/EtesianEngine.h index 9115fa4f..5c06c828 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -15,6 +15,7 @@ #pragma once +#include #include #include #include "coloquinte/circuit.hxx" @@ -34,6 +35,7 @@ namespace Hurricane { #include "etesian/Configuration.h" #include "etesian/FeedCells.h" #include "etesian/BloatCells.h" +#include "etesian/Placement.h" namespace Etesian { @@ -52,56 +54,70 @@ namespace Etesian { class EtesianEngine : public CRL::ToolEngine { public: - typedef ToolEngine Super; + static const uint32_t NeedsDiode = (1<<0); + static const uint32_t FinalStage = (1<<1); + static const uint32_t RightSide = (1<<2); + static const uint32_t LeftSide = (1<<3); public: - static const Name& staticGetName (); - static EtesianEngine* create ( Cell* ); - static EtesianEngine* get ( const Cell* ); - public: - virtual Configuration* getConfiguration (); - virtual const Configuration* getConfiguration () const; - virtual const Name& getName () const; - inline RoutingGauge* getGauge () const; - inline CellGauge* getCellGauge () const; - inline DbU::Unit getHorizontalPitch () const; - inline DbU::Unit getVerticalPitch () const; - inline DbU::Unit getSliceHeight () const; - inline DbU::Unit getSliceStep () const; - inline DbU::Unit getFixedAbHeight () const; - inline DbU::Unit getFixedAbWidth () const; - inline Effort getPlaceEffort () const; - inline GraphicUpdate getUpdateConf () const; - inline Density getSpreadingConf () const; - inline double getSpaceMargin () const; - inline double getAspectRatio () const; - inline const FeedCells& getFeedCells () const; - inline Hurricane::CellViewer* getViewer () const; - inline void setViewer ( Hurricane::CellViewer* ); - inline Cell* getBlockCell () const; - inline Instance* getBlockInstance () const; - inline void setBlock ( Instance* ); - inline void setFixedAbHeight ( DbU::Unit ); - inline void setFixedAbWidth ( DbU::Unit ); - inline void setSpaceMargin ( double ); - inline void setAspectRatio ( double ); - void setDefaultAb (); - void adjustSliceHeight (); - void resetPlacement (); - void loadLeafCellLayouts (); - size_t toColoquinte (); - void preplace (); - void roughLegalize ( float minDisruption, unsigned options ); - void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 ); - void detailedPlace ( int iterations, int effort, unsigned options=0 ); - void place (); - inline void useFeed ( Cell* ); - size_t findYSpin (); - void addFeeds (); - void readSlices (); - inline void selectBloat ( std::string ); - virtual Record* _getRecord () const; - virtual std::string _getString () const; - virtual std::string _getTypeName () const; + typedef ToolEngine Super; + typedef std::tuple NetInfos; + typedef std::tuple InstanceInfos; + public: + static const Name& staticGetName (); + static EtesianEngine* create ( Cell* ); + static EtesianEngine* get ( const Cell* ); + public: + virtual Configuration* getConfiguration (); + virtual const Configuration* getConfiguration () const; + virtual const Name& getName () const; + inline RoutingGauge* getGauge () const; + inline CellGauge* getCellGauge () const; + inline DbU::Unit getHorizontalPitch () const; + inline DbU::Unit getVerticalPitch () const; + inline DbU::Unit getSliceHeight () const; + inline DbU::Unit getSliceStep () const; + inline DbU::Unit getFixedAbHeight () const; + inline DbU::Unit getFixedAbWidth () const; + inline Effort getPlaceEffort () const; + inline GraphicUpdate getUpdateConf () const; + inline Density getSpreadingConf () const; + inline double getSpaceMargin () const; + inline double getAspectRatio () const; + inline double getAntennaInsertThreshold () const; + inline DbU::Unit getAntennaMaxWL () const; + inline DbU::Unit getLatchUpDistance () const; + inline const FeedCells& getFeedCells () const; + inline Cell* getDiodeCell () const; + inline Hurricane::CellViewer* getViewer () const; + inline void setViewer ( Hurricane::CellViewer* ); + inline Cell* getBlockCell () const; + inline Instance* getBlockInstance () const; + inline void setBlock ( Instance* ); + inline void setFixedAbHeight ( DbU::Unit ); + inline void setFixedAbWidth ( DbU::Unit ); + inline void setSpaceMargin ( double ); + inline void setAspectRatio ( double ); + void setDefaultAb (); + void adjustSliceHeight (); + void resetPlacement (); + void clearColoquinte (); + void loadLeafCellLayouts (); + inline DbU::Unit toDbU ( int64_t ) const; + size_t toColoquinte (); + void preplace (); + void roughLegalize ( float minDisruption, unsigned options ); + void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 ); + void detailedPlace ( int iterations, int effort, unsigned options=0 ); + void antennaProtect (); + void place (); + inline void useFeed ( Cell* ); + size_t findYSpin (); + void addFeeds (); + void toHurricane (); + inline void selectBloat ( std::string ); + virtual Record* _getRecord () const; + virtual std::string _getString () const; + virtual std::string _getTypeName () const; private: // Attributes. static Name _toolName; @@ -111,20 +127,24 @@ namespace Etesian { bool _placed; bool _ySpinSet; bool _flatDesign; - coloquinte::box _surface; - coloquinte::netlist _circuit; - coloquinte::placement_t _placementLB; - coloquinte::placement_t _placementUB; - coloquinte::density_restrictions _densityLimits; + coloquinte::box* _surface; + coloquinte::netlist* _circuit; + coloquinte::placement_t* _placementLB; + coloquinte::placement_t* _placementUB; + coloquinte::density_restrictions* _densityLimits; std::unordered_map _cellsToIds; - std::vector _idsToInsts; + std::vector _idsToInsts; + std::vector _idsToNets; Hurricane::CellViewer* _viewer; + Cell* _diodeCell; FeedCells _feedCells; BloatCells _bloatCells; + Area* _area; size_t _yspinSlice0; DbU::Unit _sliceHeight; DbU::Unit _fixedAbHeight; DbU::Unit _fixedAbWidth; + uint32_t _diodeCount; protected: // Constructors & Destructors. @@ -136,39 +156,47 @@ namespace Etesian { EtesianEngine ( const EtesianEngine& ); EtesianEngine& operator= ( const EtesianEngine& ); private: - void _updatePlacement ( const coloquinte::placement_t& ); + inline uint32_t _getNewDiodeId (); + Instance* _createDiode ( Cell* ); + void _updatePlacement ( const coloquinte::placement_t*, uint32_t flags=0 ); void _progressReport1 ( string label ) const; void _progressReport2 ( string label ) const; }; // Inline Functions. - inline void EtesianEngine::setViewer ( Hurricane::CellViewer* viewer ) { _viewer = viewer; } - inline Hurricane::CellViewer* EtesianEngine::getViewer () const { return _viewer; } - inline RoutingGauge* EtesianEngine::getGauge () const { return getConfiguration()->getGauge(); } - inline CellGauge* EtesianEngine::getCellGauge () const { return getConfiguration()->getCellGauge(); } - inline DbU::Unit EtesianEngine::getHorizontalPitch () const { return getGauge()->getHorizontalPitch(); } - inline DbU::Unit EtesianEngine::getVerticalPitch () const { return getGauge()->getVerticalPitch(); } - inline DbU::Unit EtesianEngine::getSliceHeight () const { return _sliceHeight; } - inline DbU::Unit EtesianEngine::getSliceStep () const { return getCellGauge()->getSliceStep(); } - inline DbU::Unit EtesianEngine::getFixedAbHeight () const { return _fixedAbHeight; } - inline DbU::Unit EtesianEngine::getFixedAbWidth () const { return _fixedAbWidth; } - inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); } - inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); } - inline Density EtesianEngine::getSpreadingConf () const { return getConfiguration()->getSpreadingConf(); } - inline double EtesianEngine::getSpaceMargin () const { return getConfiguration()->getSpaceMargin(); } - inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); } - inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); } - inline const FeedCells& EtesianEngine::getFeedCells () const { return _feedCells; } - inline void EtesianEngine::selectBloat ( std::string profile ) { _bloatCells.select(profile); } - - inline Cell* EtesianEngine::getBlockCell () const { return (_block) ? _block->getMasterCell() : getCell(); } - inline Instance* EtesianEngine::getBlockInstance () const { return _block; } - inline void EtesianEngine::setBlock ( Instance* block ) { _block = block; _placed = _block->getMasterCell()->isPlaced(); } - inline void EtesianEngine::setFixedAbHeight ( DbU::Unit abHeight ) { _fixedAbHeight = abHeight; } - inline void EtesianEngine::setFixedAbWidth ( DbU::Unit abWidth ) { _fixedAbWidth = abWidth; } - inline void EtesianEngine::setSpaceMargin ( double margin ) { getConfiguration()->setSpaceMargin(margin); } - inline void EtesianEngine::setAspectRatio ( double ratio ) { getConfiguration()->setAspectRatio(ratio); } + inline void EtesianEngine::setViewer ( Hurricane::CellViewer* viewer ) { _viewer = viewer; } + inline Hurricane::CellViewer* EtesianEngine::getViewer () const { return _viewer; } + inline RoutingGauge* EtesianEngine::getGauge () const { return getConfiguration()->getGauge(); } + inline CellGauge* EtesianEngine::getCellGauge () const { return getConfiguration()->getCellGauge(); } + inline DbU::Unit EtesianEngine::getHorizontalPitch () const { return getGauge()->getHorizontalPitch(); } + inline DbU::Unit EtesianEngine::getVerticalPitch () const { return getGauge()->getVerticalPitch(); } + inline DbU::Unit EtesianEngine::getSliceHeight () const { return _sliceHeight; } + inline DbU::Unit EtesianEngine::getSliceStep () const { return getCellGauge()->getSliceStep(); } + inline DbU::Unit EtesianEngine::getFixedAbHeight () const { return _fixedAbHeight; } + inline DbU::Unit EtesianEngine::getFixedAbWidth () const { return _fixedAbWidth; } + inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); } + inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); } + inline Density EtesianEngine::getSpreadingConf () const { return getConfiguration()->getSpreadingConf(); } + inline double EtesianEngine::getSpaceMargin () const { return getConfiguration()->getSpaceMargin(); } + inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); } + inline double EtesianEngine::getAntennaInsertThreshold () const { return getConfiguration()->getAntennaInsertThreshold(); } + inline DbU::Unit EtesianEngine::getAntennaMaxWL () const { return getConfiguration()->getAntennaMaxWL(); } + inline DbU::Unit EtesianEngine::getLatchUpDistance () const { return getConfiguration()->getLatchUpDistance(); } + inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); } + inline const FeedCells& EtesianEngine::getFeedCells () const { return _feedCells; } + inline Cell* EtesianEngine::getDiodeCell () const { return _diodeCell; } + inline void EtesianEngine::selectBloat ( std::string profile ) { _bloatCells.select(profile); } + + inline Cell* EtesianEngine::getBlockCell () const { return (_block) ? _block->getMasterCell() : getCell(); } + inline Instance* EtesianEngine::getBlockInstance () const { return _block; } + inline void EtesianEngine::setBlock ( Instance* block ) { _block = block; _placed = _block->getMasterCell()->isPlaced(); } + inline void EtesianEngine::setFixedAbHeight ( DbU::Unit abHeight ) { _fixedAbHeight = abHeight; } + inline void EtesianEngine::setFixedAbWidth ( DbU::Unit abWidth ) { _fixedAbWidth = abWidth; } + inline void EtesianEngine::setSpaceMargin ( double margin ) { getConfiguration()->setSpaceMargin(margin); } + inline void EtesianEngine::setAspectRatio ( double ratio ) { getConfiguration()->setAspectRatio(ratio); } + inline DbU::Unit EtesianEngine::toDbU ( int64_t v ) const { return v*getSliceStep(); } + inline uint32_t EtesianEngine::_getNewDiodeId () { return _diodeCount++; } // Variables. extern const char* missingEtesian; diff --git a/etesian/src/etesian/Placement.h b/etesian/src/etesian/Placement.h new file mode 100644 index 00000000..330c896a --- /dev/null +++ b/etesian/src/etesian/Placement.h @@ -0,0 +1,322 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2020-2020, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | E t e s i a n - A n a l y t i c P l a c e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./Placement.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include +#include +#include "hurricane/Box.h" +#include "hurricane/Interval.h" +#include "hurricane/Instance.h" +#include "hurricane/Occurrence.h" + + +namespace Etesian { + + using Hurricane::Error; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Box; + using Hurricane::Interval; + using Hurricane::DBo; + using Hurricane::Cell; + using Hurricane::Instance; + using Hurricane::Transformation; + using Hurricane::Occurrence; + class EtesianEngine; + + +// ------------------------------------------------------------------- +// Class : "::TieDatas". + + class TieDatas { + public: + inline TieDatas ( Cell* cell=NULL, DbU::Unit leftDistance=0, DbU::Unit rightDistance=0 ); + inline Cell* getCell () const; + inline DbU::Unit getLeftDistance () const; + inline DbU::Unit getRightDistance() const; + private: + Cell* _cell; + DbU::Unit _leftDistance; + DbU::Unit _rightDistance; + }; + + + inline TieDatas::TieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance ) + : _cell (cell) + , _leftDistance (leftDistance) + , _rightDistance(rightDistance) + { } + + inline Cell* TieDatas::getCell () const { return _cell; } + inline DbU::Unit TieDatas::getLeftDistance () const { return _leftDistance; } + inline DbU::Unit TieDatas::getRightDistance() const { return _rightDistance; } + + +// ------------------------------------------------------------------- +// Class : "::TieLUT". + + class TieLUT { + public: + inline TieLUT (); + inline const TieDatas* getTieDatas ( Cell* ) const; + inline DbU::Unit getLeftDistance ( Cell* ) const; + inline DbU::Unit getRightDistance ( Cell* ) const; + inline void addTieDatas ( Cell*, DbU::Unit leftDistance, DbU::Unit rightDistance ); + private: + std::map< Cell*, TieDatas, DBo::CompareById > _tieLut; + }; + + + inline TieLUT::TieLUT () + : _tieLut() + { } + + + inline void TieLUT::addTieDatas ( Cell* cell, DbU::Unit leftDistance, DbU::Unit rightDistance ) + { + const TieDatas* datas = getTieDatas( cell ); + if (datas) { + std::cerr << Error( "TieLUT::addTieDatas(): Duplicate datas for % (ignoreds)." + , getString(cell).c_str() + ) << std::endl; + } + _tieLut[ cell ] = TieDatas( cell, leftDistance, rightDistance ); + } + + + inline const TieDatas* TieLUT::getTieDatas ( Cell* cell ) const + { + auto iDatas = _tieLut.find( cell ); + return (iDatas != _tieLut.end()) ? &((*iDatas).second) : NULL; + } + + + inline DbU::Unit TieLUT::getLeftDistance ( Cell* cell ) const + { + const TieDatas* datas = getTieDatas( cell ); + return (datas) ? datas->getLeftDistance() : 0; + } + + + inline DbU::Unit TieLUT::getRightDistance ( Cell* cell ) const + { + const TieDatas* datas = getTieDatas( cell ); + return (datas) ? datas->getRightDistance() : 0; + } + + +// ------------------------------------------------------------------- +// Class : "::Tile". + + class Area; + class Slice; + + + class Tile { + public: + inline Tile ( DbU::Unit xMin, DbU::Unit width, const Occurrence& ); + inline bool isFixed () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () const; + inline DbU::Unit getWidth () const; + inline Cell* getMasterCell () const; + inline Instance* getInstance () const; + inline const Occurrence& getOccurrence () const; + inline void translate ( DbU::Unit ); + inline std::string _getString () const; + Record* _getRecord () const; + private: + DbU::Unit _xMin; + DbU::Unit _width; + Occurrence _occurrence; + }; + + inline Tile::Tile ( DbU::Unit xMin, DbU::Unit width, const Occurrence& occurrence ) + : _xMin(xMin), _width(width), _occurrence(occurrence) + { } + + inline DbU::Unit Tile::getXMin () const { return _xMin; } + inline DbU::Unit Tile::getXMax () const { return _xMin+_width; } + inline DbU::Unit Tile::getWidth () const { return _width; } + inline const Occurrence& Tile::getOccurrence () const { return _occurrence; } + inline Instance* Tile::getInstance () const { return static_cast( _occurrence.getEntity() ); } + inline Cell* Tile::getMasterCell () const { return getInstance()->getMasterCell(); } + + inline bool Tile::isFixed () const + { return getInstance()->getPlacementStatus() == Instance::PlacementStatus::FIXED; } + + + inline void Tile::translate ( DbU::Unit dx ) + { + cdebug_log(121,0) << " Tile::translate(), dx:" << DbU::getValueString(dx) << ", " << _occurrence << std::endl; + Instance* instance = getInstance(); + Transformation reference = instance->getTransformation(); + Transformation transf = Transformation( reference.getTx() + dx + , reference.getTy() + , reference.getOrientation() ); + instance->setTransformation( transf ); + _xMin += dx; + } + + + inline std::string Tile::_getString () const + { + string s = "getName()) + + "\">"; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "::SubSlice". + + class SubSlice { + public: + SubSlice ( Slice*, const std::list::iterator& beginTile ); + inline const std::list::iterator getBeginTile () const; + inline const std::list::iterator getEndTile () const; + inline DbU::Unit getYBottom () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () const; + DbU::Unit getAverageChunk ( size_t& ) const; + void insertTies ( DbU::Unit latchUpMax ); + private: + Slice* _slice; + std::list::iterator _beginTile; + std::list::iterator _endTile; + }; + + inline const std::list::iterator SubSlice::getBeginTile () const { return _beginTile; } + inline const std::list::iterator SubSlice::getEndTile () const { return _endTile; } + + +// ------------------------------------------------------------------- +// Class : "::Slice". + + class Slice { + public: + Slice ( Area*, DbU::Unit ybottom ); + inline DbU::Unit getYBottom () const; + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () const; + inline Interval getXSpan () const; + inline Area* getArea () const; + inline EtesianEngine* getEtesian () const; + inline size_t getSpinSlice0 () const; + inline DbU::Unit getLeftDistance ( Cell* cell ) const; + inline DbU::Unit getRightDistance ( Cell* cell ) const; + bool validate ( DbU::Unit latchUpMax ) const; + inline std::list& getTiles (); + void merge ( const Occurrence&, const Box& ); + void addFeeds ( size_t islice ); + void fillHole ( std::list::iterator before + , DbU::Unit xmin + , DbU::Unit xmax + , DbU::Unit ybottom + , size_t yspin ); + void buildSubSlices (); + void showSubSlices (); + void insertTies ( DbU::Unit latchUpMax ); + Instance* createDiodeUnder ( const Box& ); + inline std::string _getString () const; + Record* _getRecord () const; + private: + Area* _area; + DbU::Unit _ybottom; + std::list _tiles; + std::vector _subSlices; + }; + + + inline std::string Slice::_getString () const + { + string s = ""; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "::Area". + + class Area { + public: + Area ( EtesianEngine* ); + ~Area (); + inline EtesianEngine* getEtesian () const; + inline size_t getSpinSlice0 () const; + inline void setSpinSlice0 ( size_t ); + inline DbU::Unit getXMin () const; + inline DbU::Unit getXMax () const; + inline DbU::Unit getLeftDistance ( Cell* cell ) const; + inline DbU::Unit getRightDistance ( Cell* cell ) const; + bool validate ( DbU::Unit latchUpMax ) const; + void merge ( const Occurrence&, const Box& ); + void addFeeds (); + void buildSubSlices (); + void showSubSlices (); + void insertTies ( DbU::Unit latchUpMax ); + Instance* createDiodeUnder ( const Box& ); + inline std::string _getString () const; + Record* _getRecord () const; + private: + EtesianEngine* _etesian; + TieLUT _tieLut; + Box _cellAb; + DbU::Unit _sliceHeight; + std::vector _slices; + size_t _spinSlice0; + }; + + + inline EtesianEngine* Area::getEtesian () const { return _etesian; } + inline size_t Area::getSpinSlice0 () const { return _spinSlice0; } + inline void Area::setSpinSlice0 ( size_t spinSlice0 ) { _spinSlice0 = spinSlice0; } + inline DbU::Unit Area::getXMin () const { return _cellAb.getXMin(); } + inline DbU::Unit Area::getXMax () const { return _cellAb.getXMax(); } + inline DbU::Unit Area::getLeftDistance ( Cell* cell ) const { return _tieLut.getLeftDistance(cell); } + inline DbU::Unit Area::getRightDistance ( Cell* cell ) const { return _tieLut.getRightDistance(cell); } + inline string Area::_getString () const { return ""; } + + + inline DbU::Unit SubSlice::getYBottom () const { return _slice->getYBottom(); } + + inline DbU::Unit SubSlice::getXMin () const + { return (_beginTile == _slice->getTiles().begin()) ? _slice->getXMin() : (*_beginTile).getXMin(); } + + inline DbU::Unit SubSlice::getXMax () const + { return (_endTile == _slice->getTiles().end ()) ? _slice->getXMax() : (*_endTile).getXMax(); } + + + inline DbU::Unit Slice::getYBottom () const { return _ybottom; } + inline DbU::Unit Slice::getXMin () const { return _area->getXMin(); } + inline DbU::Unit Slice::getXMax () const { return _area->getXMax(); } + inline DbU::Unit Slice::getLeftDistance ( Cell* cell ) const { return _area->getLeftDistance(cell); } + inline DbU::Unit Slice::getRightDistance ( Cell* cell ) const { return _area->getRightDistance(cell); } + inline Interval Slice::getXSpan () const { return Interval( getXMin(), getXMax() ); } + inline Area* Slice::getArea () const { return _area; } + inline EtesianEngine* Slice::getEtesian () const { return getArea()->getEtesian(); } + inline size_t Slice::getSpinSlice0 () const { return getArea()->getSpinSlice0(); } + inline std::list& Slice::getTiles () { return _tiles; } + + +} // Etesian namespace. + + +INSPECTOR_PR_SUPPORT(Etesian::Tile); +INSPECTOR_P_SUPPORT(Etesian::Slice); +INSPECTOR_P_SUPPORT(Etesian::Area);