Support for non complete clock-tree to fill every nook and cranny.
* Change: In Cumulus/plugins.block.spares, allow the QuadTree to have only *some* of it's four childs (BL, TL, TR, BR). Modify QuandTree.getLeafUnder() so when there is no leaf under the point, due to an incomplete tree, we get the closer leaf. Leaf are suppressed when their center points (where the buffers are to be put) are under a FIXED Instance (that is, an opaque block). Those opaque blocks (or macro blocks) must be put *on the periphery* of the design, because the closer they got to the center, the larger the chunks of QuadTree that are removeds. * Change: In Cumulus/plugins.block.clocktree, based on the spare QuadTree changes, can now build a clock-tree with some of the leaf missing. Should find a way to compensate for the missing leaf wires & buffer (dummies).
This commit is contained in:
parent
f4891a0aee
commit
9dc0040703
|
@ -438,6 +438,7 @@ class Block ( object ):
|
|||
self.clockTrees.append( ClockTree(self.spares,clockNet,len(self.clockTrees)) )
|
||||
self.clockTrees[-1].buildHTree()
|
||||
trace( 550, '-' )
|
||||
Breakpoint.stop( 100, 'Block.addClockTrees() on {} done.'.format(self.conf.cellPnR) )
|
||||
|
||||
def splitClocks ( self ):
|
||||
"""
|
||||
|
|
|
@ -104,41 +104,66 @@ class ClockTree ( object ):
|
|||
hLeafDepth = gaugeConf.horizontalDepth
|
||||
if gaugeConf.horizontalDepth > 2 and (gaugeConf.horizontalDepth > gaugeConf.verticalDepth):
|
||||
hLeafDepth = gaugeConf.horizontalDepth - 2
|
||||
leftSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer , bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
rightSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer , bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
blContact = None
|
||||
brContact = None
|
||||
tlContact = None
|
||||
trContact = None
|
||||
leftContact = None
|
||||
rigthContact = None
|
||||
if qt.bl:
|
||||
blContact = gaugeConf.rpAccessByPlugName( qt.bl.buffer, bufferConf.input , ckNet )
|
||||
if qt.br:
|
||||
brContact = gaugeConf.rpAccessByPlugName( qt.br.buffer, bufferConf.input , ckNet )
|
||||
if qt.tl:
|
||||
tlContact = gaugeConf.rpAccessByPlugName( qt.tl.buffer, bufferConf.input , ckNet )
|
||||
if qt.tr:
|
||||
trContact = gaugeConf.rpAccessByPlugName( qt.tr.buffer, bufferConf.input , ckNet )
|
||||
leftContact = gaugeConf.createContact( ckNet, blContact.getX(), leftSourceContact.getY(), 0 )
|
||||
rightContact = gaugeConf.createContact( ckNet, brContact.getX(), rightSourceContact.getY(), 0 )
|
||||
if qt.bl or qt.tl:
|
||||
leafContact = blContact if brContact else tlContact
|
||||
leftSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer, bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
leftSourceX = gaugeConf.getNearestVerticalTrack ( leftSourceContact.getX(), 0 )
|
||||
leftSourceY = gaugeConf.getNearestHorizontalTrack( leftSourceContact.getY(), 0 )
|
||||
rightSourceX = gaugeConf.getNearestVerticalTrack ( rightSourceContact.getX(), 0 )
|
||||
rightSourceY = gaugeConf.getNearestHorizontalTrack( rightSourceContact.getY(), 0 )
|
||||
leftContact = gaugeConf.createContact( ckNet, leafContact.getX(), leftSourceContact.getY(), 0 )
|
||||
leftX = gaugeConf.getNearestVerticalTrack( leftContact.getX(), 0 )
|
||||
rightX = gaugeConf.getNearestVerticalTrack ( rightContact.getX(), 0 )
|
||||
tlY = gaugeConf.getTrack( tlContact.getY(), hLeafDepth, 0 )
|
||||
blY = gaugeConf.getTrack( blContact.getY(), hLeafDepth, 0 )
|
||||
#tlY = gaugeConf.getNearestHorizontalTrack( tlContact.getY(), 0 )
|
||||
#blY = gaugeConf.getNearestHorizontalTrack( blContact.getY(), 0 )
|
||||
trace( 550, '\tblY:{}\n'.format( DbU.getValueString(blY) ))
|
||||
gaugeConf.setStackPosition( leftSourceContact, leftSourceX, leftSourceY )
|
||||
gaugeConf.setStackPosition( rightSourceContact, rightSourceX, rightSourceY )
|
||||
gaugeConf.setStackPosition( tlContact, leftX, tlY )
|
||||
gaugeConf.setStackPosition( blContact, leftX, blY )
|
||||
gaugeConf.setStackPosition( trContact, rightX, tlY )
|
||||
gaugeConf.setStackPosition( brContact, rightX, blY )
|
||||
leftContact .setX( leftX )
|
||||
leftContact .setY( leftSourceY )
|
||||
if qt.br or qt.tr:
|
||||
leafContact = brContact if brContact else trContact
|
||||
rightSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer, bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||
rightSourceX = gaugeConf.getNearestVerticalTrack( rightSourceContact.getX(), 0 )
|
||||
rightSourceY = gaugeConf.getNearestHorizontalTrack( rightSourceContact.getY(), 0 )
|
||||
rightContact = gaugeConf.createContact( ckNet, leafContact.getX(), rightSourceContact.getY(), 0 )
|
||||
rightX = gaugeConf.getNearestVerticalTrack( rightContact.getX(), 0 )
|
||||
gaugeConf.setStackPosition( rightSourceContact, rightSourceX, rightSourceY )
|
||||
rightContact.setX( rightX )
|
||||
rightContact.setY( rightSourceY )
|
||||
if qt.bl or qt.tl:
|
||||
gaugeConf.createHorizontal( leftContact, leftSourceContact, leftSourceY , 0 )
|
||||
if qt.br or qt.tr:
|
||||
gaugeConf.createHorizontal( rightSourceContact, rightContact, rightSourceY, 0 )
|
||||
gaugeConf.createVertical ( leftContact , blContact , leftX , 0 )
|
||||
if tlContact:
|
||||
tlY = gaugeConf.getTrack( tlContact.getY(), hLeafDepth, 0 )
|
||||
elif trContact:
|
||||
tlY = gaugeConf.getTrack( trContact.getY(), hLeafDepth, 0 )
|
||||
if blContact:
|
||||
blY = gaugeConf.getTrack( blContact.getY(), hLeafDepth, 0 )
|
||||
trace( 550, '\tblY:{}\n'.format( DbU.getValueString(blY) ))
|
||||
elif brContact:
|
||||
blY = gaugeConf.getTrack( brContact.getY(), hLeafDepth, 0 )
|
||||
trace( 550, '\tblY:{}\n'.format( DbU.getValueString(blY) ))
|
||||
if qt.tl:
|
||||
gaugeConf.setStackPosition( tlContact, leftX, tlY )
|
||||
gaugeConf.createVertical ( tlContact, leftContact, leftX, 0 )
|
||||
gaugeConf.createVertical ( rightContact , brContact , rightX , 0 )
|
||||
if qt.bl:
|
||||
gaugeConf.setStackPosition( blContact, leftX, blY )
|
||||
gaugeConf.createVertical ( leftContact, blContact, leftX, 0 )
|
||||
if qt.tr:
|
||||
gaugeConf.setStackPosition( trContact, rightX, tlY )
|
||||
gaugeConf.createVertical ( trContact, rightContact, rightX, 0 )
|
||||
if qt.br:
|
||||
gaugeConf.setStackPosition( brContact, rightX, blY )
|
||||
gaugeConf.createVertical ( rightContact, brContact, rightX, 0 )
|
||||
if qt.isRoot():
|
||||
ckNet = self.clockNet
|
||||
if not self.spares.conf.isCoreBlock:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#
|
||||
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) SU 2020-2020, All Rights Reserved
|
||||
#
|
||||
|
@ -253,10 +253,43 @@ class QuadTree ( object ):
|
|||
else:
|
||||
area = Box( area )
|
||||
spares.conf.icore.getTransformation().applyOn( area )
|
||||
root = QuadTree( spares, None, area )
|
||||
root = QuadTree._create( spares, None, area, 'root', raiseError=True )
|
||||
root.rpartition()
|
||||
return root
|
||||
|
||||
@staticmethod
|
||||
def isUsedArea ( spares, area, rtag, raiseError ):
|
||||
centerArea = Box( area.getCenter() )
|
||||
sliceHeight = spares.conf.sliceHeight
|
||||
centerArea.inflate( 4*sliceHeight, sliceHeight )
|
||||
trace( 540, '\tQuadTree.isUnderArea(): {} {} of {}\n'.format(rtag,centerArea,spares.conf.cell) )
|
||||
trace( 540, '\t{}\n'.format( spares.conf.cellPnR ))
|
||||
for occurrence in spares.conf.cellPnR.getTerminalNetlistInstanceOccurrencesUnder( centerArea ):
|
||||
if not isinstance(occurrence.getEntity(),Instance):
|
||||
continue
|
||||
instance = occurrence.getEntity()
|
||||
masterCell = instance.getMasterCell()
|
||||
if not masterCell.isTerminalNetlist():
|
||||
continue
|
||||
trace( 540, '\t| Overlap {}\n'.format(occurrence.getEntity()) )
|
||||
if raiseError:
|
||||
raise Error%essage( 1, [ 'QuadTree.create(): Unable to create QuadTree under area {}' \
|
||||
.format(area)
|
||||
, 'Area center is under fixed block {}' .format()
|
||||
] )
|
||||
return True
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _create ( spares, parent, area, rtag, raiseError=False ):
|
||||
childRtag = parent.rtag+'_'+rtag if parent else rtag
|
||||
if QuadTree.isUsedArea( spares, area, childRtag, raiseError ):
|
||||
return None
|
||||
qt = QuadTree( spares, parent, area, childRtag )
|
||||
return qt
|
||||
|
||||
def __init__ ( self, spares, parent, area, rtag='root' ):
|
||||
self.spares = spares
|
||||
self.area = area
|
||||
|
@ -474,14 +507,14 @@ class QuadTree ( object ):
|
|||
|
||||
if aspectRatio < 0.5:
|
||||
self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 )
|
||||
self.bl = QuadTree( self.spares
|
||||
self.bl = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.area.getXMin()
|
||||
, self.area.getYMin()
|
||||
, self.area.getXMax()
|
||||
, self.ycut )
|
||||
, 'bl' )
|
||||
self.tl = QuadTree( self.spares
|
||||
self.tl = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.area.getXMin()
|
||||
, self.ycut
|
||||
|
@ -493,14 +526,14 @@ class QuadTree ( object ):
|
|||
return True
|
||||
elif aspectRatio > 2.0:
|
||||
self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth()/2 )
|
||||
self.bl = QuadTree( self.spares
|
||||
self.bl = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.area.getXMin()
|
||||
, self.area.getYMin()
|
||||
, self.xcut
|
||||
, self.area.getYMax() )
|
||||
, 'bl' )
|
||||
self.br = QuadTree( self.spares
|
||||
self.br = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.xcut
|
||||
, self.area.getYMin()
|
||||
|
@ -513,28 +546,28 @@ class QuadTree ( object ):
|
|||
|
||||
self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 )
|
||||
self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth ()/2 )
|
||||
self.bl = QuadTree( self.spares
|
||||
self.bl = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.area.getXMin()
|
||||
, self.area.getYMin()
|
||||
, self.xcut
|
||||
, self.ycut )
|
||||
, 'bl' )
|
||||
self.br = QuadTree( self.spares
|
||||
self.br = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.xcut
|
||||
, self.area.getYMin()
|
||||
, self.area.getXMax()
|
||||
, self.ycut )
|
||||
, 'br' )
|
||||
self.tl = QuadTree( self.spares
|
||||
self.tl = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.area.getXMin()
|
||||
, self.ycut
|
||||
, self.xcut
|
||||
, self.area.getYMax() )
|
||||
, 'tl' )
|
||||
self.tr = QuadTree( self.spares
|
||||
self.tr = QuadTree._create( self.spares
|
||||
, self
|
||||
, Box( self.xcut
|
||||
, self.ycut
|
||||
|
@ -658,11 +691,21 @@ class QuadTree ( object ):
|
|||
if self.isVBipart():
|
||||
if position.getY() < self.ycut: return self.bl.getLeafUnder(position)
|
||||
return self.tl.getLeafUnder(position)
|
||||
leaf = None
|
||||
if position.getX() < self.xcut:
|
||||
if position.getY() < self.ycut: return self.bl.getLeafUnder(position)
|
||||
return self.tl.getLeafUnder(position)
|
||||
if position.getY() < self.ycut: return self.br.getLeafUnder(position)
|
||||
return self.tr.getLeafUnder(position)
|
||||
if position.getY() < self.ycut: leaf = self.bl
|
||||
else: leaf = self.tl
|
||||
else:
|
||||
if position.getY() < self.ycut: leaf = self.br
|
||||
else: leaf = self.tr
|
||||
if not leaf:
|
||||
dx = abs( position.getX() - self.xcut )
|
||||
dy = abs( position.getY() - self.ycut )
|
||||
if self.tr and ((dx < dy) or not leaf): leaf = self.tr
|
||||
if self.tl and ((dx < dy) or not leaf): leaf = self.tl
|
||||
if self.br and ((dx >= dy) or not leaf): leaf = self.br
|
||||
if self.bl and ((dx >= dy) or not leaf): leaf = self.bl
|
||||
return leaf.getLeafUnder(position)
|
||||
|
||||
def getFreeLeafUnder ( self, area, attractor=None ):
|
||||
"""
|
||||
|
@ -867,7 +910,7 @@ class Spares ( object ):
|
|||
, DbU.getValueString(7*self.conf.sliceHeight ) ))
|
||||
with UpdateSession():
|
||||
self.quadTree = QuadTree.create( self )
|
||||
self._addCapTies()
|
||||
#self._addCapTies()
|
||||
trace( 540, '-' )
|
||||
|
||||
def rshowPoolUse ( self ):
|
||||
|
|
Loading…
Reference in New Issue