From 9dc0040703cf017f0fde9f0b7f96f7830c467ad6 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Mon, 29 Mar 2021 16:49:00 +0200 Subject: [PATCH] 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). --- cumulus/src/plugins/alpha/block/block.py | 1 + cumulus/src/plugins/alpha/block/clocktree.py | 95 +++++++---- cumulus/src/plugins/alpha/block/spares.py | 169 ++++++++++++------- 3 files changed, 167 insertions(+), 98 deletions(-) diff --git a/cumulus/src/plugins/alpha/block/block.py b/cumulus/src/plugins/alpha/block/block.py index 02f2c6e4..25530744 100644 --- a/cumulus/src/plugins/alpha/block/block.py +++ b/cumulus/src/plugins/alpha/block/block.py @@ -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 ): """ diff --git a/cumulus/src/plugins/alpha/block/clocktree.py b/cumulus/src/plugins/alpha/block/clocktree.py index 6b93c18e..7f31852b 100644 --- a/cumulus/src/plugins/alpha/block/clocktree.py +++ b/cumulus/src/plugins/alpha/block/clocktree.py @@ -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 = gaugeConf.rpAccessByPlugName( qt.bl.buffer, bufferConf.input , ckNet ) - brContact = gaugeConf.rpAccessByPlugName( qt.br.buffer, bufferConf.input , ckNet ) - tlContact = gaugeConf.rpAccessByPlugName( qt.tl.buffer, bufferConf.input , ckNet ) - 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 ) - leftSourceX = gaugeConf.getNearestVerticalTrack ( leftSourceContact.getX(), 0 ) - leftSourceY = gaugeConf.getNearestHorizontalTrack( leftSourceContact.getY(), 0 ) - rightSourceX = gaugeConf.getNearestVerticalTrack ( rightSourceContact.getX(), 0 ) - rightSourceY = gaugeConf.getNearestHorizontalTrack( rightSourceContact.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 ) - rightContact.setX( rightX ) - rightContact.setY( rightSourceY ) - gaugeConf.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 ) - gaugeConf.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 ) - gaugeConf.createVertical ( leftContact , blContact , leftX , 0 ) - gaugeConf.createVertical ( tlContact , leftContact , leftX , 0 ) - gaugeConf.createVertical ( rightContact , brContact , rightX , 0 ) - gaugeConf.createVertical ( trContact , rightContact , rightX , 0 ) + 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 ) + 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 ) + leftContact = gaugeConf.createContact( ckNet, leafContact.getX(), leftSourceContact.getY(), 0 ) + leftX = gaugeConf.getNearestVerticalTrack( leftContact.getX(), 0 ) + gaugeConf.setStackPosition( leftSourceContact, leftSourceX, leftSourceY ) + 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 ) + 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 ) + 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: diff --git a/cumulus/src/plugins/alpha/block/spares.py b/cumulus/src/plugins/alpha/block/spares.py index 7dbc88e3..da6d564b 100644 --- a/cumulus/src/plugins/alpha/block/spares.py +++ b/cumulus/src/plugins/alpha/block/spares.py @@ -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,73 +507,73 @@ 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 - , Box( self.area.getXMin() - , self.area.getYMin() - , self.area.getXMax() - , self.ycut ) - , 'bl' ) - self.tl = QuadTree( self.spares - , self - , Box( self.area.getXMin() - , self.ycut - , self.area.getXMax() - , self.area.getYMax() ) - , 'tl' ) + self.bl = QuadTree._create( self.spares + , self + , Box( self.area.getXMin() + , self.area.getYMin() + , self.area.getXMax() + , self.ycut ) + , 'bl' ) + self.tl = QuadTree._create( self.spares + , self + , Box( self.area.getXMin() + , self.ycut + , self.area.getXMax() + , self.area.getYMax() ) + , 'tl' ) trace( 540, '\tVertical bi-partition @Y:{}\n'.format(DbU.getValueString(self.ycut)) ) trace( 540, '-' ) return True elif aspectRatio > 2.0: self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth()/2 ) - self.bl = QuadTree( self.spares - , self - , Box( self.area.getXMin() - , self.area.getYMin() - , self.xcut - , self.area.getYMax() ) - , 'bl' ) - self.br = QuadTree( self.spares - , self - , Box( self.xcut - , self.area.getYMin() - , self.area.getXMax() - , self.area.getYMax() ) - , 'br' ) + self.bl = QuadTree._create( self.spares + , self + , Box( self.area.getXMin() + , self.area.getYMin() + , self.xcut + , self.area.getYMax() ) + , 'bl' ) + self.br = QuadTree._create( self.spares + , self + , Box( self.xcut + , self.area.getYMin() + , self.area.getXMax() + , self.area.getYMax() ) + , 'br' ) trace( 540, '\tHorizontal bi-partition @X:{}\n'.format(DbU.getValueString(self.xcut)) ) trace( 540, '-' ) return True 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 - , Box( self.area.getXMin() - , self.area.getYMin() - , self.xcut - , self.ycut ) - , 'bl' ) - self.br = QuadTree( self.spares - , self - , Box( self.xcut - , self.area.getYMin() - , self.area.getXMax() - , self.ycut ) - , 'br' ) - self.tl = QuadTree( self.spares - , self - , Box( self.area.getXMin() - , self.ycut - , self.xcut - , self.area.getYMax() ) - , 'tl' ) - self.tr = QuadTree( self.spares - , self - , Box( self.xcut - , self.ycut - , self.area.getXMax() - , self.area.getYMax() ) - , 'tr' ) + self.bl = QuadTree._create( self.spares + , self + , Box( self.area.getXMin() + , self.area.getYMin() + , self.xcut + , self.ycut ) + , 'bl' ) + self.br = QuadTree._create( self.spares + , self + , Box( self.xcut + , self.area.getYMin() + , self.area.getXMax() + , self.ycut ) + , 'br' ) + self.tl = QuadTree._create( self.spares + , self + , Box( self.area.getXMin() + , self.ycut + , self.xcut + , self.area.getYMax() ) + , 'tl' ) + self.tr = QuadTree._create( self.spares + , self + , Box( self.xcut + , self.ycut + , self.area.getXMax() + , self.area.getYMax() ) + , 'tr' ) trace( 540, '\tQuadri-partition @X:{} + @Y:{}\n'\ .format(DbU.getValueString(self.xcut),DbU.getValueString(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 ):