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
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# 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".
|
||||
|
||||
|
@ -1190,6 +1259,7 @@ class BlockConf ( GaugeConf ):
|
|||
self.bufferConf = BufferConf( self.framework )
|
||||
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
||||
self.feedsConf = FeedsConf( self.framework, self.cfg )
|
||||
self.powersConf = PowersConf( self.framework, self.cfg )
|
||||
self.chipConf = ChipConf( self )
|
||||
self.bColumns = 2
|
||||
self.bRows = 2
|
||||
|
@ -1217,6 +1287,7 @@ class BlockConf ( GaugeConf ):
|
|||
self.cfg.etesian.spaceMargin = None
|
||||
self.cfg.etesian.latchUpDistance = None
|
||||
self.cfg.block.spareSide = None
|
||||
self.cfg.block.vRailsPeriod = None
|
||||
self.cfg.katana.dumpMeasures = None
|
||||
self.etesian = None
|
||||
self.katana = None
|
||||
|
@ -1286,6 +1357,9 @@ class BlockConf ( GaugeConf ):
|
|||
def createFeed ( self ):
|
||||
return self.feedsConf.createFeed( self.cellPnR )
|
||||
|
||||
def createPower ( self ):
|
||||
return self.powersConf.createPower( self.cellPnR )
|
||||
|
||||
def setDeltaAb ( self, dx1, dy1, dx2, dy2 ):
|
||||
self.deltaAb = [ dx1, dy1, dx2, dy2 ]
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ class BufferPool ( object ):
|
|||
self.selectedIndexes = []
|
||||
for i in range(self.rows*self.columns):
|
||||
self.buffers.append( [ 0, None ] )
|
||||
self._xRight = None
|
||||
self._createBuffers()
|
||||
|
||||
@property
|
||||
|
@ -171,6 +172,10 @@ class BufferPool ( object ):
|
|||
instance.setTransformation( transf )
|
||||
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||
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()
|
||||
trBufAb = self.buffers[-1][1].getAbutmentBox()
|
||||
self.area = Box( blBufAb.getXMin(), blBufAb.getYMin()
|
||||
|
@ -779,6 +784,32 @@ class QuadTree ( object ):
|
|||
position = plugOccurrence.getBoundingBox().getCenter()
|
||||
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 ):
|
||||
return self.area.contains( plugOccurrence.getBoundingBox().getCenter() )
|
||||
|
||||
|
@ -1020,6 +1051,44 @@ class Spares ( object ):
|
|||
trace( 540, "\tX Centers of the QuadTree leaf\n" )
|
||||
for x in self.quadTree.rleafX:
|
||||
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, '-' )
|
||||
|
||||
def rshowPoolUse ( self ):
|
||||
|
|
Loading…
Reference in New Issue