Add support of vertical power rails made of powmid cells in Block.
* New: In cumulus/plugins.block.congiguration: New PowersConf config sub-object to store characteristics of the "powmid_x0" cell. The name of the Cell with which to build the vertical power rails is given though the cfg parameter: "cfg.etesian.cell.power" * New: In cumulus/plugins.block.spares, add support for creating vertical power lines along with the buffers pools of the H-Trees. At most, one vertical power rail will be put exactly at the right edge of the buffer pool of each leaf QuadTree. We can reduce that number, using the parameter: "cfg.block.vRailsPeriod = N" Which give the ratio to use (one over N QuadTree leaf). WARNING: This may not work if the QuadTree is "dented" not in a corner but in the *middle* of the side. Needs to be improved and/or checked.
This commit is contained in:
parent
df972b7250
commit
b1b67d18e6
|
@ -1001,6 +1001,75 @@ class FeedsConf ( object ):
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Class : "configuration.PowersConf".
|
||||||
|
|
||||||
|
class PowersConf ( object ):
|
||||||
|
"""
|
||||||
|
Store informations about power cells to build vertical power rails in
|
||||||
|
technologies with low number of routing layers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__ ( self, framework, cfg ):
|
||||||
|
trace( 550, ',+', '\tPowersConf.__init__()\n' )
|
||||||
|
cfg.etesian.cell.power = None
|
||||||
|
self.power = None
|
||||||
|
powerName = cfg.etesian.cell.power
|
||||||
|
self.count = 0
|
||||||
|
if cfg.etesian.cell.power:
|
||||||
|
self.power = framework.getCell( powerName, CRL.Catalog.State.Views )
|
||||||
|
if not self.power:
|
||||||
|
print( WarningMessage( 'PowersConf.__init__(): Power cell "{}" not found in library (skipped).' \
|
||||||
|
.format(powerName)) )
|
||||||
|
trace( 550, '-' )
|
||||||
|
return
|
||||||
|
|
||||||
|
def createPower ( self, cell ):
|
||||||
|
instance = Instance.create( cell, 'power_{}'.format(self.count), self.power )
|
||||||
|
self.count += 1
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def columnAt ( self, cell, x, y, orient, sliceCount ):
|
||||||
|
"""
|
||||||
|
In ``cell``, build a column which bottom is at ``transf`` position and
|
||||||
|
span over ``sliceCount`` slices.
|
||||||
|
"""
|
||||||
|
sliceHeight = self.power.getAbutmentBox().getHeight()
|
||||||
|
if orient == Transformation.Orientation.ID:
|
||||||
|
offset = 1
|
||||||
|
orients = ( Transformation.Orientation.ID, Transformation.Orientation.MX )
|
||||||
|
elif orient == Transformation.Orientation.MX:
|
||||||
|
offset = 1
|
||||||
|
orients = ( Transformation.Orientation.MX, Transformation.Orientation.ID )
|
||||||
|
elif orient == Transformation.Orientation.R2:
|
||||||
|
y += sliceHeight
|
||||||
|
offset = 0
|
||||||
|
orients = ( Transformation.Orientation.R2, Transformation.Orientation.MY )
|
||||||
|
elif orient == Transformation.Orientation.MY:
|
||||||
|
y += sliceHeight
|
||||||
|
offset = 0
|
||||||
|
orients = ( Transformation.Orientation.MY, Transformation.Orientation.R2 )
|
||||||
|
else:
|
||||||
|
raise ErrorMessage( [ 'PowersConf.columnAt(): Rotations are not allowed for power columns, in "{}".' \
|
||||||
|
.format(cell.getName())
|
||||||
|
, ' (@{}, sliceCount:{})' \
|
||||||
|
.format(orient,sliceCount)
|
||||||
|
] )
|
||||||
|
|
||||||
|
for islice in range(sliceCount):
|
||||||
|
instance = Instance.create( cell, 'power_{}'.format(self.count), self.power )
|
||||||
|
instance.setTransformation( Transformation( x
|
||||||
|
, y
|
||||||
|
, orients[ islice%2 ] ))
|
||||||
|
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||||
|
if (islice+offset) % 2:
|
||||||
|
y += 2*sliceHeight
|
||||||
|
self.count += 1
|
||||||
|
|
||||||
|
def resetPowerCount ( self ):
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Class : "configuration.IoPin".
|
# Class : "configuration.IoPin".
|
||||||
|
|
||||||
|
@ -1190,6 +1259,7 @@ class BlockConf ( GaugeConf ):
|
||||||
self.bufferConf = BufferConf( self.framework )
|
self.bufferConf = BufferConf( self.framework )
|
||||||
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
||||||
self.feedsConf = FeedsConf( self.framework, self.cfg )
|
self.feedsConf = FeedsConf( self.framework, self.cfg )
|
||||||
|
self.powersConf = PowersConf( self.framework, self.cfg )
|
||||||
self.chipConf = ChipConf( self )
|
self.chipConf = ChipConf( self )
|
||||||
self.bColumns = 2
|
self.bColumns = 2
|
||||||
self.bRows = 2
|
self.bRows = 2
|
||||||
|
@ -1217,6 +1287,7 @@ class BlockConf ( GaugeConf ):
|
||||||
self.cfg.etesian.spaceMargin = None
|
self.cfg.etesian.spaceMargin = None
|
||||||
self.cfg.etesian.latchUpDistance = None
|
self.cfg.etesian.latchUpDistance = None
|
||||||
self.cfg.block.spareSide = None
|
self.cfg.block.spareSide = None
|
||||||
|
self.cfg.block.vRailsPeriod = None
|
||||||
self.cfg.katana.dumpMeasures = None
|
self.cfg.katana.dumpMeasures = None
|
||||||
self.etesian = None
|
self.etesian = None
|
||||||
self.katana = None
|
self.katana = None
|
||||||
|
@ -1286,6 +1357,9 @@ class BlockConf ( GaugeConf ):
|
||||||
def createFeed ( self ):
|
def createFeed ( self ):
|
||||||
return self.feedsConf.createFeed( self.cellPnR )
|
return self.feedsConf.createFeed( self.cellPnR )
|
||||||
|
|
||||||
|
def createPower ( self ):
|
||||||
|
return self.powersConf.createPower( self.cellPnR )
|
||||||
|
|
||||||
def setDeltaAb ( self, dx1, dy1, dx2, dy2 ):
|
def setDeltaAb ( self, dx1, dy1, dx2, dy2 ):
|
||||||
self.deltaAb = [ dx1, dy1, dx2, dy2 ]
|
self.deltaAb = [ dx1, dy1, dx2, dy2 ]
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ class BufferPool ( object ):
|
||||||
self.selectedIndexes = []
|
self.selectedIndexes = []
|
||||||
for i in range(self.rows*self.columns):
|
for i in range(self.rows*self.columns):
|
||||||
self.buffers.append( [ 0, None ] )
|
self.buffers.append( [ 0, None ] )
|
||||||
|
self._xRight = None
|
||||||
self._createBuffers()
|
self._createBuffers()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -171,6 +172,10 @@ class BufferPool ( object ):
|
||||||
instance.setTransformation( transf )
|
instance.setTransformation( transf )
|
||||||
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||||
length += instance.getMasterCell().getAbutmentBox().getWidth()
|
length += instance.getMasterCell().getAbutmentBox().getWidth()
|
||||||
|
if self._xRight is None:
|
||||||
|
self._xRight = x + length
|
||||||
|
else:
|
||||||
|
self._xRight = max( self._xRight, x+length )
|
||||||
blBufAb = self.buffers[ 0][1].getAbutmentBox()
|
blBufAb = self.buffers[ 0][1].getAbutmentBox()
|
||||||
trBufAb = self.buffers[-1][1].getAbutmentBox()
|
trBufAb = self.buffers[-1][1].getAbutmentBox()
|
||||||
self.area = Box( blBufAb.getXMin(), blBufAb.getYMin()
|
self.area = Box( blBufAb.getXMin(), blBufAb.getYMin()
|
||||||
|
@ -779,6 +784,32 @@ class QuadTree ( object ):
|
||||||
position = plugOccurrence.getBoundingBox().getCenter()
|
position = plugOccurrence.getBoundingBox().getCenter()
|
||||||
self.getLeafUnder(position).plugs.append( plugOccurrence )
|
self.getLeafUnder(position).plugs.append( plugOccurrence )
|
||||||
|
|
||||||
|
def getBottomLeafs ( self, bottoms=[] ):
|
||||||
|
"""
|
||||||
|
Recursively build a list of all the QuadTree leaf cells at the bottom
|
||||||
|
of the tree. Sorted left to right by X position.
|
||||||
|
"""
|
||||||
|
if self.isLeaf():
|
||||||
|
bottoms.append( self )
|
||||||
|
return
|
||||||
|
if self.bl: self.bl.getBottomLeafs( bottoms )
|
||||||
|
elif self.tl: self.tl.getBottomLeafs( bottoms )
|
||||||
|
if self.br: self.br.getBottomLeafs( bottoms )
|
||||||
|
elif self.tr: self.tr.getBottomLeafs( bottoms )
|
||||||
|
|
||||||
|
def getTopLeafs ( self, tops=[] ):
|
||||||
|
"""
|
||||||
|
Recursively build a list of all the QuadTree leaf cells at the top
|
||||||
|
of the tree. Sorted left to right by X position.
|
||||||
|
"""
|
||||||
|
if self.isLeaf():
|
||||||
|
tops.append( self )
|
||||||
|
return
|
||||||
|
if self.tl: self.tl.getTopLeafs( tops )
|
||||||
|
elif self.bl: self.bl.getTopLeafs( tops )
|
||||||
|
if self.tr: self.tr.getTopLeafs( tops )
|
||||||
|
elif self.br: self.br.getTopLeafs( tops )
|
||||||
|
|
||||||
def isUnderArea ( self, plugOccurrence ):
|
def isUnderArea ( self, plugOccurrence ):
|
||||||
return self.area.contains( plugOccurrence.getBoundingBox().getCenter() )
|
return self.area.contains( plugOccurrence.getBoundingBox().getCenter() )
|
||||||
|
|
||||||
|
@ -1020,6 +1051,44 @@ class Spares ( object ):
|
||||||
trace( 540, "\tX Centers of the QuadTree leaf\n" )
|
trace( 540, "\tX Centers of the QuadTree leaf\n" )
|
||||||
for x in self.quadTree.rleafX:
|
for x in self.quadTree.rleafX:
|
||||||
trace( 540, '\t| {}\n'.format(DbU.getValueString(x) ))
|
trace( 540, '\t| {}\n'.format(DbU.getValueString(x) ))
|
||||||
|
self._buildPower()
|
||||||
|
trace( 540, '-' )
|
||||||
|
|
||||||
|
def _buildPower ( self ):
|
||||||
|
trace( 540, '+', '\tSpares._buildPower()\n' )
|
||||||
|
if not self.conf.powersConf.power: return
|
||||||
|
bottoms = []
|
||||||
|
self.quadTree.getBottomLeafs( bottoms )
|
||||||
|
trace( 540, '\tBottom leafs of the QuadTree:\n' )
|
||||||
|
for leaf in bottoms:
|
||||||
|
trace( 540, '\t| {} xRight={}\n'.format( leaf, DbU.getValueString(leaf.pool._xRight) ))
|
||||||
|
tops = []
|
||||||
|
self.quadTree.getTopLeafs( tops )
|
||||||
|
trace( 540, '\tTop leafs of the QuadTree:\n' )
|
||||||
|
for leaf in tops:
|
||||||
|
trace( 540, '\t| {} xRight={}\n'.format( leaf, DbU.getValueString(leaf.pool._xRight) ))
|
||||||
|
if len(tops) != len(bottoms):
|
||||||
|
print( ErrorMessage( 2, 'Spares._buildPower(): Discrepency between QuadTree top and bottom leafs lists, {} vs {}.'
|
||||||
|
.format( len(tops), len(bottoms) )))
|
||||||
|
trace( 540, '-' )
|
||||||
|
return
|
||||||
|
vRailsPeriod = self.conf.cfg.block.vRailsPeriod
|
||||||
|
if vRailsPeriod is None:
|
||||||
|
vRailsPeriod = 1
|
||||||
|
if vRailsPeriod == 0:
|
||||||
|
trace( 540, '-' )
|
||||||
|
return
|
||||||
|
sliceHeight = self.conf.sliceHeight
|
||||||
|
for column in range(len(bottoms)):
|
||||||
|
if column % vRailsPeriod: continue
|
||||||
|
x = bottoms[column].pool._xRight
|
||||||
|
y = bottoms[column].area.getYMin()
|
||||||
|
ymax = tops [column].area.getYMax() - sliceHeight
|
||||||
|
while y <= ymax:
|
||||||
|
power = self.conf.createPower()
|
||||||
|
power.setTransformation ( self._getTransformation(x,y) )
|
||||||
|
power.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||||
|
y += sliceHeight
|
||||||
trace( 540, '-' )
|
trace( 540, '-' )
|
||||||
|
|
||||||
def rshowPoolUse ( self ):
|
def rshowPoolUse ( self ):
|
||||||
|
|
Loading…
Reference in New Issue