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.append( ClockTree(self.spares,clockNet,len(self.clockTrees)) )
|
||||||
self.clockTrees[-1].buildHTree()
|
self.clockTrees[-1].buildHTree()
|
||||||
trace( 550, '-' )
|
trace( 550, '-' )
|
||||||
|
Breakpoint.stop( 100, 'Block.addClockTrees() on {} done.'.format(self.conf.cellPnR) )
|
||||||
|
|
||||||
def splitClocks ( self ):
|
def splitClocks ( self ):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -104,41 +104,66 @@ class ClockTree ( object ):
|
||||||
hLeafDepth = gaugeConf.horizontalDepth
|
hLeafDepth = gaugeConf.horizontalDepth
|
||||||
if gaugeConf.horizontalDepth > 2 and (gaugeConf.horizontalDepth > gaugeConf.verticalDepth):
|
if gaugeConf.horizontalDepth > 2 and (gaugeConf.horizontalDepth > gaugeConf.verticalDepth):
|
||||||
hLeafDepth = gaugeConf.horizontalDepth - 2
|
hLeafDepth = gaugeConf.horizontalDepth - 2
|
||||||
leftSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer , bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
blContact = None
|
||||||
rightSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer , bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
brContact = None
|
||||||
|
tlContact = None
|
||||||
|
trContact = None
|
||||||
|
leftContact = None
|
||||||
|
rigthContact = None
|
||||||
|
if qt.bl:
|
||||||
blContact = gaugeConf.rpAccessByPlugName( qt.bl.buffer, bufferConf.input , ckNet )
|
blContact = gaugeConf.rpAccessByPlugName( qt.bl.buffer, bufferConf.input , ckNet )
|
||||||
|
if qt.br:
|
||||||
brContact = gaugeConf.rpAccessByPlugName( qt.br.buffer, bufferConf.input , ckNet )
|
brContact = gaugeConf.rpAccessByPlugName( qt.br.buffer, bufferConf.input , ckNet )
|
||||||
|
if qt.tl:
|
||||||
tlContact = gaugeConf.rpAccessByPlugName( qt.tl.buffer, bufferConf.input , ckNet )
|
tlContact = gaugeConf.rpAccessByPlugName( qt.tl.buffer, bufferConf.input , ckNet )
|
||||||
|
if qt.tr:
|
||||||
trContact = gaugeConf.rpAccessByPlugName( qt.tr.buffer, bufferConf.input , ckNet )
|
trContact = gaugeConf.rpAccessByPlugName( qt.tr.buffer, bufferConf.input , ckNet )
|
||||||
leftContact = gaugeConf.createContact( ckNet, blContact.getX(), leftSourceContact.getY(), 0 )
|
if qt.bl or qt.tl:
|
||||||
rightContact = gaugeConf.createContact( ckNet, brContact.getX(), rightSourceContact.getY(), 0 )
|
leafContact = blContact if brContact else tlContact
|
||||||
|
leftSourceContact = gaugeConf.rpAccessByPlugName( qt.buffer, bufferConf.output, ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
|
||||||
leftSourceX = gaugeConf.getNearestVerticalTrack ( leftSourceContact.getX(), 0 )
|
leftSourceX = gaugeConf.getNearestVerticalTrack ( leftSourceContact.getX(), 0 )
|
||||||
leftSourceY = gaugeConf.getNearestHorizontalTrack( leftSourceContact.getY(), 0 )
|
leftSourceY = gaugeConf.getNearestHorizontalTrack( leftSourceContact.getY(), 0 )
|
||||||
rightSourceX = gaugeConf.getNearestVerticalTrack ( rightSourceContact.getX(), 0 )
|
leftContact = gaugeConf.createContact( ckNet, leafContact.getX(), leftSourceContact.getY(), 0 )
|
||||||
rightSourceY = gaugeConf.getNearestHorizontalTrack( rightSourceContact.getY(), 0 )
|
|
||||||
leftX = gaugeConf.getNearestVerticalTrack( leftContact.getX(), 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( 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 .setX( leftX )
|
||||||
leftContact .setY( leftSourceY )
|
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.setX( rightX )
|
||||||
rightContact.setY( rightSourceY )
|
rightContact.setY( rightSourceY )
|
||||||
|
if qt.bl or qt.tl:
|
||||||
gaugeConf.createHorizontal( leftContact, leftSourceContact, leftSourceY , 0 )
|
gaugeConf.createHorizontal( leftContact, leftSourceContact, leftSourceY , 0 )
|
||||||
|
if qt.br or qt.tr:
|
||||||
gaugeConf.createHorizontal( rightSourceContact, rightContact, rightSourceY, 0 )
|
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 ( 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 )
|
gaugeConf.createVertical ( trContact, rightContact, rightX, 0 )
|
||||||
|
if qt.br:
|
||||||
|
gaugeConf.setStackPosition( brContact, rightX, blY )
|
||||||
|
gaugeConf.createVertical ( rightContact, brContact, rightX, 0 )
|
||||||
if qt.isRoot():
|
if qt.isRoot():
|
||||||
ckNet = self.clockNet
|
ckNet = self.clockNet
|
||||||
if not self.spares.conf.isCoreBlock:
|
if not self.spares.conf.isCoreBlock:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#
|
|
||||||
# This file is part of the Coriolis Software.
|
# This file is part of the Coriolis Software.
|
||||||
# Copyright (c) SU 2020-2020, All Rights Reserved
|
# Copyright (c) SU 2020-2020, All Rights Reserved
|
||||||
#
|
#
|
||||||
|
@ -253,10 +253,43 @@ class QuadTree ( object ):
|
||||||
else:
|
else:
|
||||||
area = Box( area )
|
area = Box( area )
|
||||||
spares.conf.icore.getTransformation().applyOn( area )
|
spares.conf.icore.getTransformation().applyOn( area )
|
||||||
root = QuadTree( spares, None, area )
|
root = QuadTree._create( spares, None, area, 'root', raiseError=True )
|
||||||
root.rpartition()
|
root.rpartition()
|
||||||
return root
|
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' ):
|
def __init__ ( self, spares, parent, area, rtag='root' ):
|
||||||
self.spares = spares
|
self.spares = spares
|
||||||
self.area = area
|
self.area = area
|
||||||
|
@ -474,14 +507,14 @@ class QuadTree ( object ):
|
||||||
|
|
||||||
if aspectRatio < 0.5:
|
if aspectRatio < 0.5:
|
||||||
self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 )
|
self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 )
|
||||||
self.bl = QuadTree( self.spares
|
self.bl = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.area.getXMin()
|
, Box( self.area.getXMin()
|
||||||
, self.area.getYMin()
|
, self.area.getYMin()
|
||||||
, self.area.getXMax()
|
, self.area.getXMax()
|
||||||
, self.ycut )
|
, self.ycut )
|
||||||
, 'bl' )
|
, 'bl' )
|
||||||
self.tl = QuadTree( self.spares
|
self.tl = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.area.getXMin()
|
, Box( self.area.getXMin()
|
||||||
, self.ycut
|
, self.ycut
|
||||||
|
@ -493,14 +526,14 @@ class QuadTree ( object ):
|
||||||
return True
|
return True
|
||||||
elif aspectRatio > 2.0:
|
elif aspectRatio > 2.0:
|
||||||
self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth()/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
|
, self
|
||||||
, Box( self.area.getXMin()
|
, Box( self.area.getXMin()
|
||||||
, self.area.getYMin()
|
, self.area.getYMin()
|
||||||
, self.xcut
|
, self.xcut
|
||||||
, self.area.getYMax() )
|
, self.area.getYMax() )
|
||||||
, 'bl' )
|
, 'bl' )
|
||||||
self.br = QuadTree( self.spares
|
self.br = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.xcut
|
, Box( self.xcut
|
||||||
, self.area.getYMin()
|
, self.area.getYMin()
|
||||||
|
@ -513,28 +546,28 @@ class QuadTree ( object ):
|
||||||
|
|
||||||
self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 )
|
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.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth ()/2 )
|
||||||
self.bl = QuadTree( self.spares
|
self.bl = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.area.getXMin()
|
, Box( self.area.getXMin()
|
||||||
, self.area.getYMin()
|
, self.area.getYMin()
|
||||||
, self.xcut
|
, self.xcut
|
||||||
, self.ycut )
|
, self.ycut )
|
||||||
, 'bl' )
|
, 'bl' )
|
||||||
self.br = QuadTree( self.spares
|
self.br = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.xcut
|
, Box( self.xcut
|
||||||
, self.area.getYMin()
|
, self.area.getYMin()
|
||||||
, self.area.getXMax()
|
, self.area.getXMax()
|
||||||
, self.ycut )
|
, self.ycut )
|
||||||
, 'br' )
|
, 'br' )
|
||||||
self.tl = QuadTree( self.spares
|
self.tl = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.area.getXMin()
|
, Box( self.area.getXMin()
|
||||||
, self.ycut
|
, self.ycut
|
||||||
, self.xcut
|
, self.xcut
|
||||||
, self.area.getYMax() )
|
, self.area.getYMax() )
|
||||||
, 'tl' )
|
, 'tl' )
|
||||||
self.tr = QuadTree( self.spares
|
self.tr = QuadTree._create( self.spares
|
||||||
, self
|
, self
|
||||||
, Box( self.xcut
|
, Box( self.xcut
|
||||||
, self.ycut
|
, self.ycut
|
||||||
|
@ -658,11 +691,21 @@ class QuadTree ( object ):
|
||||||
if self.isVBipart():
|
if self.isVBipart():
|
||||||
if position.getY() < self.ycut: return self.bl.getLeafUnder(position)
|
if position.getY() < self.ycut: return self.bl.getLeafUnder(position)
|
||||||
return self.tl.getLeafUnder(position)
|
return self.tl.getLeafUnder(position)
|
||||||
|
leaf = None
|
||||||
if position.getX() < self.xcut:
|
if position.getX() < self.xcut:
|
||||||
if position.getY() < self.ycut: return self.bl.getLeafUnder(position)
|
if position.getY() < self.ycut: leaf = self.bl
|
||||||
return self.tl.getLeafUnder(position)
|
else: leaf = self.tl
|
||||||
if position.getY() < self.ycut: return self.br.getLeafUnder(position)
|
else:
|
||||||
return self.tr.getLeafUnder(position)
|
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 ):
|
def getFreeLeafUnder ( self, area, attractor=None ):
|
||||||
"""
|
"""
|
||||||
|
@ -867,7 +910,7 @@ class Spares ( object ):
|
||||||
, DbU.getValueString(7*self.conf.sliceHeight ) ))
|
, DbU.getValueString(7*self.conf.sliceHeight ) ))
|
||||||
with UpdateSession():
|
with UpdateSession():
|
||||||
self.quadTree = QuadTree.create( self )
|
self.quadTree = QuadTree.create( self )
|
||||||
self._addCapTies()
|
#self._addCapTies()
|
||||||
trace( 540, '-' )
|
trace( 540, '-' )
|
||||||
|
|
||||||
def rshowPoolUse ( self ):
|
def rshowPoolUse ( self ):
|
||||||
|
|
Loading…
Reference in New Issue