diff --git a/cumulus/src/plugins/alpha/block/block.py b/cumulus/src/plugins/alpha/block/block.py index 25530744..2c02da74 100644 --- a/cumulus/src/plugins/alpha/block/block.py +++ b/cumulus/src/plugins/alpha/block/block.py @@ -24,7 +24,7 @@ from Hurricane import Breakpoint, DbU, Box, Transformation, Point, \ Cell, Instance import CRL from CRL import RoutingLayerGauge -from helpers import trace, dots +from helpers import trace, dots, l, u, n from helpers.io import ErrorMessage, WarningMessage, catch from helpers.overlay import UpdateSession import Etesian @@ -32,15 +32,15 @@ import Anabatic import Katana import plugins.rsave from plugins import getParameter -from alpha.macro.macro import Macro -from alpha.block import timing -from alpha.block.spares import Spares -from alpha.block.clocktree import ClockTree -#from alpha.block.hfns1 import BufferTree -#from alpha.block.hfns2 import BufferTree -#from alpha.block.hfns3 import BufferTree -from alpha.block.hfns4 import BufferTree -from alpha.block.configuration import IoPin, BlockConf, GaugeConf +from plugins.alpha.macro.macro import Macro +from plugins.alpha.block import timing +from plugins.alpha.block.spares import Spares +from plugins.alpha.block.clocktree import ClockTree +#from plugins.alpha.block.hfns1 import BufferTree +#from plugins.alpha.block.hfns2 import BufferTree +#from plugins.alpha.block.hfns3 import BufferTree +from plugins.alpha.block.hfns4 import BufferTree +from plugins.alpha.block.configuration import IoPin, BlockConf, GaugeConf timing.staticInit() @@ -297,17 +297,18 @@ class Block ( object ): Create a Block object. The only parameter ``conf`` must be a BlockConf object which contains the complete block configuration. """ - self.flags = 0 - self.conf = conf - self.spares = Spares( self ) - self.clockTrees = [] - self.hfnTrees = [] - self.blockInstances = [] - self.sides = { IoPin.WEST : Side( self.conf, IoPin.WEST ) - , IoPin.EAST : Side( self.conf, IoPin.EAST ) - , IoPin.SOUTH : Side( self.conf, IoPin.SOUTH ) - , IoPin.NORTH : Side( self.conf, IoPin.NORTH ) - } + self.flags = 0 + self.conf = conf + self.spares = Spares( self ) + self.clockTrees = [] + self.hfnTrees = [] + self.blockInstances = [] + self.placeHolderCount = 0 + self.sides = { IoPin.WEST : Side( self.conf, IoPin.WEST ) + , IoPin.EAST : Side( self.conf, IoPin.EAST ) + , IoPin.SOUTH : Side( self.conf, IoPin.SOUTH ) + , IoPin.NORTH : Side( self.conf, IoPin.NORTH ) + } if not self.conf.cell.getAbutmentBox().isEmpty(): isBuilt = True for instance in self.conf.cell.getInstances(): @@ -604,6 +605,7 @@ class Block ( object ): coreTransf.applyOn( macroPosition ) xoffset = macroPosition.getX() - pnrAb.getXMin() xpitch = self.conf.vDeepRG.getPitch() + print( 'X placement pitch: {}'.format(DbU.getValueString(xpitch)) ) print( 'Original X offset: {}'.format(DbU.getValueString(xoffset)) ) if xoffset % xpitch: xoffset += xpitch - (xoffset % xpitch) @@ -627,6 +629,33 @@ class Block ( object ): , Transformation.Orientation.ID ) , Instance.PlacementStatus.FIXED ) + def addPlaceHolder ( self, area, inCore=False ): + if area.isEmpty(): + print( ErrorMessage( 1, 'Block.addPlaceHolder(): Request for an empty place holder area.' )) + return + af = CRL.AllianceFramework.get() + phCellName = 'placeholder_{}'.format(self.placeHolderCount) + placeHolder = Cell.create( af.getLibrary(0), phCellName ) + if inCore: + self.conf.icore.getTransformation().applyOn( area ) + pitchedArea = Box( self.conf.toXPitch(area.getXMin(),True) + , self.conf.toYSlice(area.getYMin(),True) + , self.conf.toXPitch(area.getXMax()) + , self.conf.toYSlice(area.getYMax()) ) + placeHolder.setAbutmentBox( Box( u(0.0) + , u(0.0) + , pitchedArea.getWidth() + , pitchedArea.getHeight() )) + print( 'pitchedArea={}'.format(pitchedArea) ) + placeHolder.setTerminalNetlist( True ) + instance = Instance.create( self.conf.cellPnR, phCellName, placeHolder ) + instance.setTransformation( Transformation( pitchedArea.getXMin() + , pitchedArea.getYMin() + , Transformation.Orientation.ID ) ) + instance.setPlacementStatus( Instance.PlacementStatus.FIXED ) + self.placeHolderCount += 1 + return instance + def route ( self ): routedCell = self.conf.corona if self.conf.isCoreBlock else self.conf.cell self.katana = Katana.KatanaEngine.create( routedCell ) diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index 11cf0163..f0735123 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -1239,3 +1239,27 @@ class BlockConf ( GaugeConf ): self.cell.setName( self.cell.getName()+'_r' ) rsave( self.cell, CRL.Catalog.State.Physical|flags ) return + + def toXPitch ( self, x, superior=False ): + """ + Returns the coordinate of the pitch immediately inferior to X. + Compute in the "P&R cell" coordinate system which may be core + or corona. + """ + area = self.cellPnR.getAbutmentBox() + modulo = (x - area.getXMin()) % self.sliceStep + if modulo and superior: + x += self.sliceStep + return x - modulo + + def toYSlice ( self, y, superior=False ): + """ + Returns the coordinate of the slice immediately inferior to Y. + Compute in the "P&R cell" coordinate system which may be core + or corona. + """ + area = self.cellPnR.getAbutmentBox() + modulo = (y - area.getYMin()) % self.sliceHeight + if modulo and superior: + y += self.sliceHeight + return y - modulo diff --git a/cumulus/src/plugins/alpha/block/spares.py b/cumulus/src/plugins/alpha/block/spares.py index a6c54d50..0fbe8096 100644 --- a/cumulus/src/plugins/alpha/block/spares.py +++ b/cumulus/src/plugins/alpha/block/spares.py @@ -308,6 +308,7 @@ class QuadTree ( object ): self.pool = BufferPool( self ) self.plugs = [] self.rtag = rtag + self.rleafX = [ area.getXCenter() ] def destroy ( self ): if self.bl: self.bl.destroy() @@ -481,6 +482,17 @@ class QuadTree ( object ): for leaf in self.leafs: leaf.rselectBuffer( column, row, flags ) trace( 540, '-' ) + def _mergeLeafX ( self, leafX ): + for x in leafX: + if not (x in self.rleafX): + self.rleafX.append( x ) + self.rleafX.sort() + + def _upMergeLeafX ( self ): + if self.parent: + self.parent._mergeLeafX( self.rleafX ) + self.parent._upMergeLeafX() + def partition ( self ): """ Build one level of the quad-tree, if the side of the area is bigger than @@ -584,6 +596,8 @@ class QuadTree ( object ): for leaf in self.leafs: trace( 540, '\tLeaf rtag:"{}"\n'.format(leaf.rtag) ) leaf.rpartition() + else: + self._upMergeLeafX() trace( 540, '-' ) if self.isRoot(): self._rsetMaxDepth() @@ -804,6 +818,11 @@ class Spares ( object ): self.quadTree = None self.strayBuffers = [] + @property + def rleafX ( self ): + if self.quadTree: return self.quadTree.rleafX + return [] + def reset ( self ): self.quadTree.destroy() for buffer in self.strayBuffers: @@ -908,6 +927,9 @@ class Spares ( object ): with UpdateSession(): self.quadTree = QuadTree.create( self ) #self._addCapTies() + print( "X Centers of the QuadTree leaf" ) + for x in self.quadTree.rleafX: + print( '| {}'.format(DbU.getValueString(x) )) trace( 540, '-' ) def rshowPoolUse ( self ): diff --git a/cumulus/src/plugins/alpha/chip/chip.py b/cumulus/src/plugins/alpha/chip/chip.py index dc18849c..75bc44a4 100644 --- a/cumulus/src/plugins/alpha/chip/chip.py +++ b/cumulus/src/plugins/alpha/chip/chip.py @@ -82,7 +82,7 @@ class Chip ( Block ): self.conf.chip.setAbutmentBox( self.conf.chipAb ) trace( 550, '\tSet chip ab:{}\n'.format(self.conf.chip.getAbutmentBox()) ) trace( 550, '\tUsing core ab:{}\n'.format(self.conf.core.getAbutmentBox()) ) - self.padsCorona = plugins.alpha.chip.pads.Corona( self.conf ) + self.padsCorona = plugins.alpha.chip.pads.Corona( self ) self.conf.validated = self.padsCorona.validate() if not self.conf.validated: return False @@ -112,10 +112,11 @@ class Chip ( Block ): y = y - (y % self.conf.sliceHeight) self.conf.icore.setTransformation ( Transformation(x,y,Transformation.Orientation.ID) ) self.conf.icore.setPlacementStatus( Instance.PlacementStatus.FIXED ) - self.padsCorona.doPowerLayout() self.conf.refresh() def doConnectCore ( self ): + if self.padsCorona: + self.padsCorona.doPowerLayout() if self.conf.routingGauge.hasPowerSupply(): power = plugins.alpha.chip.powerplane.Builder( self.conf ) power.connectPower() diff --git a/cumulus/src/plugins/alpha/chip/pads.py b/cumulus/src/plugins/alpha/chip/pads.py index ebdec34b..2f724a61 100644 --- a/cumulus/src/plugins/alpha/chip/pads.py +++ b/cumulus/src/plugins/alpha/chip/pads.py @@ -780,7 +780,7 @@ class CoreWire ( object ): class Corona ( object ): - def __init__ ( self, conf ): + def __init__ ( self, chip ): def _cmpPad ( pad1, pad2): width1 = pad1.getAbutmentBox().getWidth() @@ -797,7 +797,7 @@ class Corona ( object ): duplicateds.append( [ position, padInstance ] ) return duplicateds - self.conf = conf + self.chip = chip self.conf.validated = False self.northPads = _dupPads( self.conf.chipConf.northPads ) self.southPads = _dupPads( self.conf.chipConf.southPads ) @@ -838,6 +838,9 @@ class Corona ( object ): if self.conf.cfg.chip.minPadSpacing is None: self.conf.cfg.chip.minPadSpacing = 0 + @property + def conf ( self ): return self.chip.conf + @property def supplyRailWidth ( self ): return self.conf.cfg.chip.supplyRailWidth @@ -1212,9 +1215,6 @@ class Corona ( object ): with UpdateSession(): capViaWidth = self.conf.vDeepRG.getPitch()*3 coreAb = self.conf.coreAb - stripesNb = int( (coreAb.getWidth() - 8*capViaWidth + self.supplyRailWidth) \ - / self.supplyRailPitch - 1 ) - offset = (coreAb.getWidth() - self.supplyRailPitch*(stripesNb-1)) / 2 powerNet = None groundNet = None chipPowerNet = None @@ -1251,31 +1251,59 @@ class Corona ( object ): else: raise ErrorMessage( 1, 'pads.Corona.doPowerLayout(): No ground net found in "{}"' \ .format(corona.getName()) ) + icore = self.conf.icore xcore = icore.getTransformation().getTx() - trace( 550, '\ticoreAb={}\n'.format(icore.getAbutmentBox()) ) - print( 'capViaWidth={}'.format(DbU.getValueString(capViaWidth))) stripeSpecs = [] - for i in range(stripesNb+4): + stripesNb = int( (coreAb.getWidth() - 8*capViaWidth + self.supplyRailWidth) \ + / self.supplyRailPitch - 1 ) + offset = (coreAb.getWidth() - self.supplyRailPitch*(stripesNb-1)) / 2 + stripeSpecs.append( [ xcore + capViaWidth/2 , capViaWidth ] ) + stripeSpecs.append( [ xcore + 2*capViaWidth + capViaWidth/2 , capViaWidth ] ) + if self.chip.spares: + rleafX = self.chip.spares.rleafX + spacing = (rleafX[1] - rleafX[0]) / 2 + stepOffset = 0 + step = 1 + trace( 550, '\trleafX\n' ) + for i in range(len(rleafX)): + trace( 550, '\t| rleafX[{}] = {}\n'.format(i,DbU.getValueString(rleafX[i]))) + if spacing < self.supplyRailPitch: + stepOffset = 1 + step = 2 + spacing = (rleafX[2] - rleafX[0]) / 2 + if step == 1: + stripeSpecs.append( [ rleafX[0] - spacing, self.supplyRailWidth ] ) + trace( 550, '\tstripe[N/A] @{}\n'.format(DbU.getValueString(stripeSpecs[-1][0]))) + else: + stripeSpecs.append( [ rleafX[0], self.supplyRailWidth ] ) + trace( 550, '\tstripe[N/A] @{}\n'.format(DbU.getValueString(stripeSpecs[-1][0]))) + for i in range( stepOffset, len(rleafX)-stepOffset, step ): + if step == 1: + stripeSpecs.append( [ rleafX[i], self.supplyRailWidth ] ) + trace( 550, '\tstripe[{}] @{}\n'.format(i,DbU.getValueString(stripeSpecs[-1][0]))) + stripeSpecs.append( [ rleafX[i] + spacing, self.supplyRailWidth ] ) + trace( 550, '\tstripe[{}] @{}\n'.format(i,DbU.getValueString(stripeSpecs[-1][0]))) + else: + for i in range(stripesNb): + stripeSpecs.append( [ xcore + offset + i*self.supplyRailPitch + , self.supplyRailWidth + ] ) + stripeSpecs.append( [ xcore + coreAb.getWidth() - 2*capViaWidth + capViaWidth/2 , capViaWidth ] ) + stripeSpecs.append( [ xcore + coreAb.getWidth() - capViaWidth/2 , capViaWidth ] ) + + trace( 550, '\ticoreAb={}\n'.format(icore.getAbutmentBox()) ) + trace( 550, '\tcapViaWidth={}\n'.format(DbU.getValueString(capViaWidth))) + for i in range(len(stripeSpecs)): if i % 2: - coronaNet = groundNet - chipNet = chipGroundNet - else: - coronaNet = powerNet chipNet = chipPowerNet - if i < 2: - axis = xcore + 2*i*capViaWidth + capViaWidth/2 - width = capViaWidth - elif i >= stripesNb+2: - axis = xcore + coreAb.getWidth() - 2*(i-stripesNb-1)*capViaWidth + capViaWidth/2 - width = capViaWidth + coronaNet = powerNet else: - axis = xcore + offset + (i-2)*self.supplyRailPitch - width = self.supplyRailWidth - stripeSpecs.append( [ chipNet, coronaNet, axis, width ] ) - for chipNet, coronaNet, axis, width in stripeSpecs: - self._supplyToPad( chipNet, coronaNet, axis, width, North ) - self._supplyToPad( chipNet, coronaNet, axis, width, South ) + chipNet = chipGroundNet + coronaNet = groundNet + trace( 550, '\tstripe[{}] @{}\n'.format(i,DbU.getValueString(stripeSpecs[i][0]))) + self._supplyToPad( chipNet, coronaNet, stripeSpecs[i][0], stripeSpecs[i][1], North ) + self._supplyToPad( chipNet, coronaNet, stripeSpecs[i][0], stripeSpecs[i][1], South ) #for istripe in range(stripesNb): # trace( 550, '\tistripe={}\n'.format(istripe) ) # axis = xcore + offset + istripe*self.supplyRailPitch diff --git a/cumulus/src/plugins/alpha/chip/powerplane.py b/cumulus/src/plugins/alpha/chip/powerplane.py index c0e48acf..ec7328cc 100644 --- a/cumulus/src/plugins/alpha/chip/powerplane.py +++ b/cumulus/src/plugins/alpha/chip/powerplane.py @@ -448,7 +448,7 @@ class Builder ( object ): if layer.isSymbolic(): layer = layer.getBasicLayer() query.setBasicLayer( layer ) - trace( 550, ',+', 'query.doQuery() {}'.format(layer) ) + trace( 550, ',+', '\tquery.doQuery() {}\n'.format(layer) ) query.doQuery() trace( 550, '-' ) self.activePlane = None diff --git a/cumulus/src/plugins/alpha/macro/macro.py b/cumulus/src/plugins/alpha/macro/macro.py index c85e83ae..8fe7bf23 100644 --- a/cumulus/src/plugins/alpha/macro/macro.py +++ b/cumulus/src/plugins/alpha/macro/macro.py @@ -22,7 +22,7 @@ from Hurricane import Breakpoint, DbU, Box, Transformation, Point, \ Box, Path, Layer, Occurrence, Net, \ NetExternalComponents, RoutingPad, Pad, \ Horizontal, Vertical, Contact, Pin, Plug, \ - Cell, Instance + Cell, Instance, Rectilinear import CRL from CRL import RoutingLayerGauge from helpers import trace, dots @@ -40,10 +40,12 @@ class Macro ( object ): processeds macros so they are modified only once. """ + trace( 550, '\tStatic init of Macro\n' ) LUT = {} @staticmethod def lookup ( macroCell ): + trace( 550, '\tMacro.lookup() on {}\n'.format(macroCell) ) if Macro.LUT.has_key(macroCell): return Macro.LUT[ macroCell ] return None @@ -68,6 +70,7 @@ class Macro ( object ): macro = Macro.lookup( macroCell ) if macro is not None: + trace( 550, '\tReusing macro wrapper {}\n'.format(macroCell) ) return macro return Macro( macroCell, gaugeName, hMargin, vMargin ) @@ -112,12 +115,53 @@ class Macro ( object ): that are half free and half occluded by the block itself may cause (stupid) deadlock to appear. """ + trace( 550, '\tMacro.__init__() {}\n'.format(macroCell) ) self.cell = macroCell Macro.LUT[ self.cell ] = self af = CRL.AllianceFramework.get() ab = self.cell.getAbutmentBox() - self.rg = af.getRoutingGauge( gaugeName ) + self.rg = af.getRoutingGauge( gaugeName ) + gaugeMetal2 = self.rg.getLayerGauge( 1 ) + gaugeMetal3 = self.rg.getLayerGauge( 2 ) + gaugeMetal4 = self.rg.getLayerGauge( 3 ) + blockageMetal2 = gaugeMetal2.getBlockageLayer() + blockageMetal3 = gaugeMetal3.getBlockageLayer() + blockageMetal4 = gaugeMetal4.getBlockageLayer() + minSpacingMetal2 = gaugeMetal2.getLayer().getMinimalSpacing() + minSpacingMetal3 = gaugeMetal3.getLayer().getMinimalSpacing() + minSpacingMetal4 = gaugeMetal4.getLayer().getMinimalSpacing() + if self.cell.getName() == 'SPBlock_512W64B8W': + print( ' o Ad-hoc blockage patch for "{}".'.format(self.cell.getName()) ) + for net in self.cell.getNets(): + for component in net.getComponents(): + if isinstance(component,Rectilinear) and component.getLayer() == blockageMetal2: + bb = component.getBoundingBox() + bb.inflate( minSpacingMetal2/2 ) + Horizontal.create( component.getNet() + , blockageMetal2 + , bb.getYCenter() + , bb.getHeight() + , bb.getXMin() + , bb.getXMax() ) + elif isinstance(component,Rectilinear) and component.getLayer() == blockageMetal3: + bb = component.getBoundingBox() + bb.inflate( 2*minSpacingMetal3, minSpacingMetal3/2 ) + Vertical.create( component.getNet() + , blockageMetal3 + , bb.getXCenter() + , bb.getWidth() + , bb.getYMin() + , bb.getYMax() ) + elif isinstance(component,Rectilinear) and component.getLayer() == blockageMetal4: + bb = component.getBoundingBox() + bb.inflate( minSpacingMetal4/2 ) + Horizontal.create( component.getNet() + , blockageMetal4 + , bb.getYCenter() + , bb.getHeight() + , bb.getXMin() + , bb.getXMax() ) self.innerAb = ab sliceHeight = af.getCellGauge( gaugeName ).getSliceHeight() westPins = []