No longer straight route the root of a H-Tree.
* Change: In cumulus/plugins.block.HTree._rrouteHTree(), make the non-routing of the root net the default policy. Straight routing can still be activated with the use of Spares.ROUTE_ROOT_NET.
This commit is contained in:
parent
0f636912e0
commit
c595a8e73e
|
@ -185,7 +185,9 @@ class HTree ( object ):
|
|||
self._connectLeaf( qt.br, ckNet, rightContact, brContact, rightX, blY )
|
||||
if qt.isRoot():
|
||||
ckNet = self.treeNet
|
||||
if not self.spares.conf.isCoreBlock and ckNet.isExternal():
|
||||
if not self.spares.conf.isCoreBlock \
|
||||
and ckNet.isExternal() \
|
||||
and (self.flags & Spares.ROUTE_ROOT_NET):
|
||||
trace( 550, '\tRemoving any previous pin...\n' )
|
||||
pins = []
|
||||
for pin in ckNet.getPins(): pins.append( pin )
|
||||
|
|
|
@ -892,7 +892,7 @@ class QuadTree ( object ):
|
|||
class Spares ( object ):
|
||||
"""
|
||||
Manages all the spare buffer over a Cell abutment box. Used for clock tree
|
||||
synthesis (CTS) and high fanout net synthesis (HFS). 4 buffers are created
|
||||
synthesis (CTS) and high fanout net synthesis (HNFS). 4 buffers are created
|
||||
in each pool. Pools are set in a regular matrix over the whole abutment box.
|
||||
Excess area is put in the topmost and rightmost pools.
|
||||
"""
|
||||
|
@ -901,6 +901,7 @@ class Spares ( object ):
|
|||
CHECK_USED = 0x00010000
|
||||
MARK_USED = 0x00020000
|
||||
HEAVY_LEAF_LOAD = 0x00040000
|
||||
ROUTE_ROOT_NET = 0x00080000
|
||||
|
||||
def __init__ ( self, block ):
|
||||
self.conf = block.conf
|
||||
|
|
|
@ -0,0 +1,711 @@
|
|||
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) Sorbonne Université 2014-2021, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C u m u l u s - P y t h o n T o o l s |
|
||||
# | |
|
||||
# | Author : Jean-Paul CHAPUT |
|
||||
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./plugins/chip/configuration.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import Cfg
|
||||
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
|
||||
Path, Layer, Occurrence, Net, RoutingPad, \
|
||||
Horizontal, Vertical, Contact, Pin, Plug, \
|
||||
Instance
|
||||
import CRL
|
||||
from CRL import RoutingLayerGauge
|
||||
from helpers import trace
|
||||
from helpers.utils import classdecorator
|
||||
from helpers.overlay import UpdateSession
|
||||
from helpers.io import ErrorMessage, WarningMessage, \
|
||||
vprint, catch
|
||||
import plugins.chip
|
||||
from plugins.alpha.block.configuration import BlockConf
|
||||
|
||||
__all__ = [ 'ChipConf' ]
|
||||
|
||||
|
||||
plugins.alpha.chip.importConstants( globals() )
|
||||
af = CRL.AllianceFramework.get()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Class : "Configuration.ChipConf".
|
||||
|
||||
class ChipConf ( BlockConf ):
|
||||
|
||||
@staticmethod
|
||||
def _toSymbolic ( u, rounding ):
|
||||
"""
|
||||
Pitch the coordinates ``u`` to the symbolic grid, according
|
||||
to ``rounding`` (Superior or Inferior).
|
||||
"""
|
||||
oneLambda = DbU.fromLambda( 1.0 )
|
||||
remainder = u % oneLambda
|
||||
if remainder:
|
||||
if rounding == Superior: u = u + (oneLambda - remainder)
|
||||
else: u = u - remainder
|
||||
return u
|
||||
|
||||
@staticmethod
|
||||
def toSymbolic ( v, rounding ):
|
||||
"""
|
||||
Pitch the coordinates of object ``v`` to the symbolic grid,
|
||||
according to ``rounding``. Were ``v`` can be:
|
||||
|
||||
* A scalar, then rounding is Inferior or Superior.
|
||||
* A Box, then rounding is:
|
||||
|
||||
* Inwards: the pitched box will be fully enclosed in the
|
||||
original box.
|
||||
* Outwards: the pitched box will fully enclose the original
|
||||
box.
|
||||
"""
|
||||
if isinstance(v,int): return ChipConf._toSymbolic( v, rounding )
|
||||
if isinstance(v,Box):
|
||||
if rounding & Inwards:
|
||||
roundings = [ Superior
|
||||
, Superior
|
||||
, Inferior
|
||||
, Inferior ]
|
||||
else:
|
||||
roundings = [ Inferior
|
||||
, Inferior
|
||||
, Superior
|
||||
, Superior ]
|
||||
xMin = ChipConf._toSymbolic( v.getXMin(), roundings[0] )
|
||||
yMin = ChipConf._toSymbolic( v.getYMin(), roundings[1] )
|
||||
xMax = ChipConf._toSymbolic( v.getXMax(), roundings[2] )
|
||||
yMax = ChipConf._toSymbolic( v.getYMax(), roundings[3] )
|
||||
return Box( xMin, yMin, xMax, yMax )
|
||||
return v
|
||||
|
||||
def __init__ ( self, cell, ioPins=[], ioPads=[] ):
|
||||
trace( 550, ',+', 'ChipConf.__init__(): "{}"'.format(cell.getName()) )
|
||||
super(ChipConf,self).__init__( cell, ioPins, ioPads )
|
||||
#trace( 550, '\tONE LAMBDA = %s\n' % DbU.getValueString(DbU.fromLambda(1.0)) )
|
||||
self.validated = True
|
||||
# Block Corona parameters (triggers loading from disk).
|
||||
self.cfg.chip.padCoreSide = None
|
||||
self.cfg.chip.supplyRailWidth = None
|
||||
self.cfg.chip.supplyRailPitch = None
|
||||
self.cfg.chip.block.rails.count = None
|
||||
self.cfg.chip.block.rails.hWidth = None
|
||||
self.cfg.chip.block.rails.vWidth = None
|
||||
self.cfg.chip.block.rails.hSpacing = None
|
||||
self.cfg.chip.block.rails.vSpacing = None
|
||||
self._railsCount = self.cfg.chip.block.rails.count
|
||||
# Global Net names.
|
||||
self.blockageName = "blockagenet"
|
||||
# Global Nets.
|
||||
self.coronaVdd = None
|
||||
self.coronaVss = None
|
||||
self.coronaCks = []
|
||||
self.blockageNet = None
|
||||
self.padsHavePosition = False
|
||||
self.chipLogos = []
|
||||
trace( 550, '-' )
|
||||
|
||||
@property
|
||||
def padCoreSide ( self ):
|
||||
return self.cfg.chip.padCoreSide
|
||||
|
||||
@property
|
||||
def railsCount ( self ):
|
||||
return self._railsCount
|
||||
|
||||
@railsCount.setter
|
||||
def railsCount ( self, count ):
|
||||
self._railsCount = count
|
||||
|
||||
@property
|
||||
def hRailWidth ( self ):
|
||||
return self.cfg.chip.block.rails.hWidth
|
||||
|
||||
@property
|
||||
def vRailWidth ( self ):
|
||||
return self.cfg.chip.block.rails.vWidth
|
||||
|
||||
@property
|
||||
def hRailSpace ( self ):
|
||||
return self.cfg.chip.block.rails.hSpacing
|
||||
|
||||
@property
|
||||
def vRailSpace ( self ):
|
||||
return self.cfg.chip.block.rails.vSpacing
|
||||
|
||||
def computeCoronaBorder ( self ):
|
||||
global af
|
||||
if self.useClockTree:
|
||||
clockNets = []
|
||||
for net in self.cellPnR.getNets():
|
||||
if net.isClock():
|
||||
clockNets.append( net )
|
||||
self.railsCount = self.cfg.chip.block.rails.count + len(clockNets)
|
||||
trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) )
|
||||
hRailsSize = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace
|
||||
if hRailsSize % self.sliceHeight:
|
||||
hRailsSize += self.sliceHeight - (hRailsSize % self.sliceHeight)
|
||||
self.minHCorona = hRailsSize + self.sliceHeight
|
||||
vRailsSize = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace
|
||||
if vRailsSize % self.sliceHeight:
|
||||
vRailsSize += self.sliceHeight - (vRailsSize % self.sliceHeight)
|
||||
self.minVCorona = vRailsSize + self.sliceHeight
|
||||
|
||||
def chipValidate ( self ):
|
||||
#self.checkPads()
|
||||
#self.checkCorona()
|
||||
#self.computeChipSize()
|
||||
#self.checkChipSize()
|
||||
self.findPowerAndClockNets()
|
||||
return
|
||||
|
||||
def getInstanceAb ( self, instance ):
|
||||
ab = instance.getMasterCell().getAbutmentBox()
|
||||
instance.getTransformation().applyOn( ab )
|
||||
if instance.getCell() == self.chip: return ab
|
||||
if instance.getCell() != self.corona:
|
||||
raise ErrorMessage( 1, 'ChipConf.getInstanceAb(): Instance "{}" neither belong to chip or corona.' \
|
||||
.format(instance.getName()) )
|
||||
return ab
|
||||
self.icorona.getTransformation().applyOn( ab )
|
||||
return ab
|
||||
|
||||
def setupICore ( self ):
|
||||
"""
|
||||
Setup the abutment box of the *core* master cell and position it's unique
|
||||
instance (*icore*) in the center of the *corona* master cell.
|
||||
"""
|
||||
with UpdateSession():
|
||||
trace( 550, ',+', '\tChipConf.setupICore()\n' )
|
||||
ab = self.getInstanceAb( self.icorona )
|
||||
if ab.isEmpty():
|
||||
raise ErrorMessage( 1, 'ChipConf.setupICore(): Attempt to setup core *before* corona.' )
|
||||
return
|
||||
#ab.inflate( -gapX1, -gapY1, -gapX2, -gapY2 )
|
||||
ab = self.toSymbolic( ab, Inwards )
|
||||
trace( 550, '\tself.coreAb:{}\n'.format(self.coreAb) )
|
||||
if self.core.getAbutmentBox().isEmpty():
|
||||
if not self.coreAb.isEmpty():
|
||||
trace( 550, '\tUsing user-defined CORE size:{}\n'.format(self.coreSize) )
|
||||
ab = self.coreAb
|
||||
else:
|
||||
ab.inflate( -self.minHCorona, -self.minVCorona )
|
||||
self.coreSize = (ab.getWidth(), ab.getHeight())
|
||||
trace( 550, '\tSetting CORE abutment box:{}\n'.format(ab) )
|
||||
self.core.setAbutmentBox( Box( 0, 0, ab.getWidth(), ab.getHeight() ) )
|
||||
self.coreSize = ( self.coreSize[0] - self.coreSize[0] % self.sliceStep
|
||||
, self.coreSize[1] - self.coreSize[1] % self.sliceHeight )
|
||||
self.core.setAbutmentBox( Box( 0, 0, self.coreAb.getWidth(), self.coreAb.getHeight() ) )
|
||||
trace( 550, '\tCORE ab:{}\n'.format(self.coreAb) )
|
||||
coreX = (self.coronaAb.getWidth () - self.coreAb.getWidth ()) // 2
|
||||
trace( 550, '\tCore X, {} '.format(DbU.getValueString(coreX)) )
|
||||
coreX = coreX - (coreX % self.sliceHeight)
|
||||
trace( 550, ' adjusted on {}, {}\n'.format( DbU.getValueString(self.sliceHeight)
|
||||
, DbU.getValueString(coreX)) )
|
||||
coreY = (self.coronaAb.getHeight() - self.coreAb.getHeight()) // 2
|
||||
coreY = coreY - (coreY % self.sliceHeight)
|
||||
self.icore.setTransformation( Transformation( coreX, coreY, Transformation.Orientation.ID ) )
|
||||
self.icore.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||
trace( 550, '-' )
|
||||
|
||||
def getCoronaNet ( self, chipNet ):
|
||||
for plug in chipNet.getPlugs():
|
||||
if plug.getInstance() == self.icorona:
|
||||
return plug.getMasterNet()
|
||||
return None
|
||||
|
||||
def toRoutingGauge ( self, uMin, uMax, layer ):
|
||||
trace( 550, ',+', '\ttoRoutingGauge() [{} {}] {}\n' \
|
||||
.format(DbU.getValueString(uMin), DbU.getValueString(uMax), layer) )
|
||||
ab = self.corona.getAbutmentBox()
|
||||
lg = None
|
||||
mask = layer.getMask()
|
||||
for layerGauge in self.routingGauge.getLayerGauges():
|
||||
if layerGauge.getLayer().getMask() == mask:
|
||||
lg = layerGauge
|
||||
trace( 550, '\tUsing layer gauge {}\n'.format(lg) )
|
||||
break
|
||||
if uMax < uMin: uMin, uMax = uMax, uMin
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
abMin = ab.getYMin()
|
||||
abMax = ab.getYMax()
|
||||
else:
|
||||
abMin = ab.getXMin()
|
||||
abMax = ab.getXMax()
|
||||
if uMin <= abMin:
|
||||
shiftRight = abMin - uMin + lg.getPitch()
|
||||
uMin += shiftRight
|
||||
uMax += shiftRight
|
||||
if uMax >= abMax:
|
||||
shiftLeft = uMax - abMax + lg.getPitch()
|
||||
uMin -= shiftLeft
|
||||
uMax -= shiftLeft
|
||||
iTrackMin = lg.getTrackIndex( abMin, abMax, uMin, RoutingLayerGauge.Superior )
|
||||
iTrackMax = lg.getTrackIndex( abMin, abMax, uMax, RoutingLayerGauge.Inferior )
|
||||
if iTrackMax < iTrackMin: iTrackMax = iTrackMin
|
||||
uTrackMin = lg.getTrackPosition( abMin, iTrackMin )
|
||||
uTrackMax = lg.getTrackPosition( abMin, iTrackMax )
|
||||
axis = (uTrackMax + uTrackMin) // 2
|
||||
width = (iTrackMax - iTrackMin) * lg.getPitch() + lg.getWireWidth()
|
||||
if self.routingGauge.isSymbolic():
|
||||
trace( 550, '\tRoutingGauge is symbolic, adjust on lambda.\n' )
|
||||
oneLambda = DbU.fromLambda( 1.0 )
|
||||
if axis % oneLambda:
|
||||
axis -= oneLambda // 2
|
||||
width -= oneLambda
|
||||
trace( 550, '\t[{} {}] -> [{} {}]\n'.format( iTrackMin
|
||||
, iTrackMax
|
||||
, DbU.getValueString(uTrackMin)
|
||||
, DbU.getValueString(uTrackMax) ) )
|
||||
trace( 550, '\taxis: {:.1f}L {}\n'.format(DbU.toLambda(axis ), DbU.getValueString(axis )) )
|
||||
trace( 550, '\twidth: {:.1f}L {}\n'.format(DbU.toLambda(width), DbU.getValueString(width)) )
|
||||
else:
|
||||
axis = (uMax + uMin) // 2
|
||||
width = (uMax - uMin)
|
||||
trace( 550, '-' )
|
||||
return axis, width
|
||||
|
||||
def toCoronaPitchInChip ( self, uCore, layer ):
|
||||
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {:.1f}L {}\n' \
|
||||
.format(DbU.toLambda(uCore), DbU.getValueString(uCore)) )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
lg = None
|
||||
mask = layer.getMask()
|
||||
for layerGauge in self.routingGauge.getLayerGauges():
|
||||
if layerGauge.getLayer().getMask() == mask:
|
||||
lg = layerGauge
|
||||
break
|
||||
if not lg:
|
||||
trace( 550, '-' )
|
||||
return 0
|
||||
trace( 550, '\t{}\n'.format(lg) )
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
uCorona = uCore - coronaAb.getYMin()
|
||||
else:
|
||||
uCorona = uCore - coronaAb.getXMin()
|
||||
uCorona, width = self.toRoutingGauge( uCorona, uCorona, layer )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {:.1f}L {}\n' \
|
||||
.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
uCore = uCorona + coronaAb.getYMin()
|
||||
else:
|
||||
uCore = uCorona + coronaAb.getXMin()
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {:.1f}L {}\n'.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCore: {:.1f}L {}\n'.format(DbU.toLambda(uCore ), DbU.getValueString(uCore )) )
|
||||
trace( 550, '-' )
|
||||
return uCore
|
||||
|
||||
def coronaHorizontal ( self, chipNet, layer, chipY, width, chipXMin, chipXMax ):
|
||||
trace( 550, ',+', '\tChipConf.coronaHorizontal\n' )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
coronaNet = self.getCoronaNet ( chipNet )
|
||||
if not coronaNet: return None
|
||||
coronaY = chipY - coronaAb.getYMin()
|
||||
dxMin = ChipConf.toSymbolic( chipXMin - coronaAb.getXMin(), Superior )
|
||||
dxMax = ChipConf.toSymbolic( chipXMax - coronaAb.getXMin(), Inferior )
|
||||
trace( 550, '\t| chipNet: {} {}\n'.format(chipNet, layer) )
|
||||
trace( 550, '\t| Real\n' )
|
||||
trace( 550, '\t| axis: {}\n'.format(DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| width:{}\n'.format(DbU.getValueString(width)) )
|
||||
trace( 550, '\t| dxMin:{} ({:.1f}L)\n' \
|
||||
.format( DbU.getValueString(chipXMin - coronaAb.getXMin())
|
||||
, DbU.toLambda(chipXMin - coronaAb.getXMin()) ) )
|
||||
trace( 550, '\t| dxMax:{}\n'.format(DbU.getValueString(chipXMax - coronaAb.getXMin())) )
|
||||
coronaY, width = self.toRoutingGauge( coronaY - width//2, coronaY + width//2, layer )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaY), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| width:{:.1f}L or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
trace( 550, '\t| dxMin:{:.1f}L\n'.format(DbU.toLambda(dxMin)) )
|
||||
trace( 550, '\t| dxMax:{:.1f}L\n'.format(DbU.toLambda(dxMax)) )
|
||||
h = Horizontal.create( coronaNet, layer, coronaY, width, dxMin, dxMax )
|
||||
trace( 550, '\t| {}\n'.format(h) )
|
||||
trace( 550, '-' )
|
||||
return h
|
||||
|
||||
def coronaVertical ( self, chipNet, layer, chipX, width, chipYMin, chipYMax ):
|
||||
trace( 550, ',+', '\tChipConf.coronaVertical\n' )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
coronaNet = self.getCoronaNet( chipNet )
|
||||
if not coronaNet: return None
|
||||
coronaX = chipX - coronaAb.getXMin()
|
||||
dyMin = ChipConf.toSymbolic( chipYMin - coronaAb.getYMin(), Superior )
|
||||
dyMax = ChipConf.toSymbolic( chipYMax - coronaAb.getYMin(), Inferior )
|
||||
trace( 550, '\t| chipNet: {} {}\n'.format(chipNet, layer) )
|
||||
trace( 550, '\t| Real\n' )
|
||||
trace( 550, '\t| axis: {}\n'.format(DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| width:{}\n'.format(DbU.getValueString(width)) )
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width//2, coronaX + width//2, layer )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaX), DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| width:{:.1f}L or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
v = Vertical.create( coronaNet, layer, coronaX, width, dyMin, dyMax )
|
||||
trace( 550, '\t| {}\n'.format(v) )
|
||||
trace( 550, '-' )
|
||||
return v
|
||||
|
||||
def coronaContact ( self, chipNet, layer, chipX, chipY, width, height, flags=0 ):
|
||||
trace( 550, ',+', '\tChipConf.coronaContact\n' )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
coronaNet = self.getCoronaNet( chipNet )
|
||||
if not coronaNet: return None
|
||||
coronaX = chipX - coronaAb.getXMin()
|
||||
coronaY = chipY - coronaAb.getYMin()
|
||||
trace( 550, '\t| chipNet: {} {}\n'.format(chipNet,layer) )
|
||||
trace( 550, '\t| Real\n' )
|
||||
trace( 550, '\t| center: {:>12} {:>12}\n'.format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {:>12} {:>12}\n'.format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
topLayer = layer.getTop()
|
||||
botLayer = layer.getBottom()
|
||||
if self.isHorizontal(topLayer):
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width //2, coronaX + width //2, botLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height//2, coronaY + height//2, topLayer )
|
||||
else:
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width //2, coronaX + width //2, topLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height//2, coronaY + height//2, botLayer )
|
||||
if not (flags & OnHorizontalPitch):
|
||||
trace( 550, '\tNot on horizontal routing pitch, Y on lambda only.\n' )
|
||||
coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), Superior )
|
||||
if not (flags & OnVerticalPitch ):
|
||||
trace( 550, '\tNot on vertical routing pitch, X on lambda only.\n' )
|
||||
coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), Superior )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| X axis: {:>12.1f}L or {:>12}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| Y axis: {:>12.1f}L or {:>12}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| center: {:>12} {:>12}\n' .format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {:>12} {:>12}\n' .format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
c = Contact.create( coronaNet
|
||||
, layer
|
||||
, coronaX
|
||||
, coronaY
|
||||
, width
|
||||
, height
|
||||
)
|
||||
trace( 550, '\t| {}\n'.format(c) )
|
||||
trace( 550, '-' )
|
||||
return c
|
||||
|
||||
def getViaPitch ( self, viaLayer ):
|
||||
topLayer = viaLayer.getTop()
|
||||
if topLayer.isSymbolic():
|
||||
topLayer = topLayer.getBasicLayer()
|
||||
topEnclosure = viaLayer.getEnclosure( topLayer, Layer.EnclosureH|Layer.EnclosureV )
|
||||
topPitch = 2*topEnclosure + viaLayer.getMinimalSize() + topLayer.getMinimalSpacing()
|
||||
botLayer = viaLayer.getBottom()
|
||||
if botLayer.isSymbolic():
|
||||
botLayer = botLayer.getBasicLayer()
|
||||
botEnclosure = viaLayer.getEnclosure( botLayer, Layer.EnclosureH|Layer.EnclosureV )
|
||||
botPitch = 2*botEnclosure + viaLayer.getMinimalSize() + botLayer.getMinimalSpacing()
|
||||
viaPitch = max( topPitch, botPitch )
|
||||
trace( 550, '\tgetViaPitch of {}: {}\n'.format(viaLayer.getName(),DbU.getValueString(viaPitch)) )
|
||||
trace( 550, '\t| minimal size of {}: {}\n'.format(viaLayer.getName(),DbU.getValueString(viaLayer.getMinimalSize())) )
|
||||
trace( 550, '\t| enclosure of {}: {}\n'.format(topLayer.getName(),DbU.getValueString(topEnclosure)) )
|
||||
trace( 550, '\t| enclosure of {}: {}\n'.format(botLayer.getName(),DbU.getValueString(botEnclosure)) )
|
||||
return viaPitch
|
||||
|
||||
def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
|
||||
trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
|
||||
viaPitch = self.getViaPitch( layer )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
coronaNet = self.getCoronaNet( chipNet )
|
||||
if not coronaNet: return None
|
||||
trace( 550, '\t| chipNet: {} {}\n'.format(chipNet, layer) )
|
||||
coronaX = chipX - coronaAb.getXMin()
|
||||
coronaY = chipY - coronaAb.getYMin()
|
||||
topLayer = layer.getTop()
|
||||
if self.isHorizontal(topLayer):
|
||||
coronaX, width = self.toRoutingGauge( coronaX, coronaX, layer.getBottom() )
|
||||
coronaY, height = self.toRoutingGauge( coronaY, coronaY, topLayer )
|
||||
else:
|
||||
coronaX, width = self.toRoutingGauge( coronaX, coronaX, topLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY, coronaY, layer.getBottom() )
|
||||
if not (flags & OnHorizontalPitch):
|
||||
trace( 550, '\tNot on horizontal routing pitch, Y on lambda only.\n' )
|
||||
coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), Superior )
|
||||
if not (flags & OnVerticalPitch ):
|
||||
trace( 550, '\tNot on vertical routing pitch, X on lambda only.\n' )
|
||||
coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), Superior )
|
||||
contacts = []
|
||||
xContact = coronaX - viaPitch * (array[0]-1)//2
|
||||
yContact = coronaY - viaPitch * (array[1]-1)//2
|
||||
contactSize = layer.getMinimalSize()
|
||||
trace( 550, '\txContact:{} yContact:{}\n'.format(DbU.getValueString(xContact),DbU.getValueString(yContact)) )
|
||||
for i in range(array[0]):
|
||||
for j in range(array[1]):
|
||||
c = Contact.create( coronaNet
|
||||
, layer
|
||||
, xContact + i*viaPitch
|
||||
, yContact + j*viaPitch
|
||||
, contactSize
|
||||
, contactSize
|
||||
)
|
||||
trace( 550, '\t+ {}\n'.format(c) )
|
||||
contacts.append( c )
|
||||
trace( 550, '-' )
|
||||
return contacts
|
||||
|
||||
def coronaPin ( self, chipNet, count, direction, layer, chipX, chipY, width, height ):
|
||||
trace( 550, ',+', '\tChipConf.coronaPin\n' )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
coronaNet = self.getCoronaNet( chipNet )
|
||||
if not coronaNet: return None
|
||||
coronaX = chipX - coronaAb.getXMin()
|
||||
coronaY = chipY - coronaAb.getYMin()
|
||||
trace( 550, '\t| chipNet: {} ({}) {}\n'.format(chipNet, count, layer) )
|
||||
trace( 550, '\t| Real\n' )
|
||||
trace( 550, '\t| center: {} {}\n'.format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {} {}\n'.format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
topLayer = layer.getTop()
|
||||
if self.isHorizontal(topLayer):
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width //2, coronaX + width //2, layer.getBottom() )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height//2, coronaY + height//2, topLayer )
|
||||
else:
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width //2, coronaX + width //2, topLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height//2, coronaY + height//2, layer.getBottom() )
|
||||
if direction == Pin.Direction.NORTH or direction == Pin.Direction.SOUTH:
|
||||
trace( 550, '\tEast/West not on horizontal routing pitch, Y on lambda only.\n' )
|
||||
coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), Superior )
|
||||
if direction == Pin.Direction.EAST or direction == Pin.Direction.WEST:
|
||||
trace( 550, '\tNorth/South not on vertical routing pitch, X on lambda only.\n' )
|
||||
coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), Superior )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| X axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| Y axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| center: {} {}\n' .format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {} {}\n' .format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
c = Pin.create( coronaNet
|
||||
, '{}.{}'.format(coronaNet.getName(),count)
|
||||
, direction
|
||||
, Pin.PlacementStatus.FIXED
|
||||
, layer
|
||||
, coronaX
|
||||
, coronaY
|
||||
, width
|
||||
, height
|
||||
)
|
||||
trace( 550, '\t| {}\n'.format(c) )
|
||||
trace( 550, '-' )
|
||||
return c
|
||||
|
||||
def checkPads ( self ):
|
||||
|
||||
def contains ( padList, side, padInstance ):
|
||||
for i in range(len(padList)):
|
||||
if padList[i][1] == padInstance.getName():
|
||||
if (padInstance.getMasterCell().getAbutmentBox().getHeight() != self.ioPadHeight):
|
||||
raise ErrorMessage( 1, 'The pad [{}] {} ({}) on {} side is not an instance of a pad cell.' \
|
||||
.format(i,padInstance.getName(),padInstance.getMasterCell().getName(),side) )
|
||||
padList[i][1] = padInstance
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkNotFounds ( padList, side ):
|
||||
for i in range(len(padList)):
|
||||
if not isinstance(padList[i][1],Instance):
|
||||
print( ErrorMessage( 1, 'The pad [{}] ({}) of list {} do not exists in netlist (skipped).'
|
||||
.format(i,padList[i][1],side) ))
|
||||
return
|
||||
|
||||
global af
|
||||
cellPads = []
|
||||
for instance in self.chip.getInstances():
|
||||
if contains(self.southPads,'south',instance): continue
|
||||
if contains(self.northPads,'north',instance): continue
|
||||
if contains(self.eastPads ,'east' ,instance): continue
|
||||
if contains(self.westPads ,'west' ,instance): continue
|
||||
if (instance.getMasterCell().getAbutmentBox().getHeight() == self.ioPadHeight):
|
||||
raise ErrorMessage( 1, 'Pad "{}" is not on any side (N/S/E/W).'.format(instance.getName()) )
|
||||
self.validated = False
|
||||
else:
|
||||
self.coronas.append( instance )
|
||||
checkNotFounds( self.southPads, 'south' )
|
||||
checkNotFounds( self.northPads, 'north' )
|
||||
checkNotFounds( self.eastPads , 'east' )
|
||||
checkNotFounds( self.westPads , 'west' )
|
||||
if len(self.coronas) > 1:
|
||||
message = [ 'Chip "{}" have more than one corona:'.format(self.chip.getName()) ]
|
||||
for i in range(len(self.coronas)):
|
||||
message.append( '{}: {}'.format(i,self.coronas[i].getName()) )
|
||||
raise ErrorMessage( 1, message )
|
||||
self.validated = False
|
||||
if len(self.coronas) < 1:
|
||||
raise ErrorMessage( 1, 'Chip "{}" doesn\'t seems to have a corona.' \
|
||||
.format(self.chip.getName()) )
|
||||
self.validated = False
|
||||
else:
|
||||
for instance in self.corona.getInstances():
|
||||
self.cores.append( instance )
|
||||
if len(self.cores) > 1:
|
||||
message = [ 'Chip "{}" have more than one core:'.format(self.chip.getName()) ]
|
||||
for i in range(len(self.cores)):
|
||||
message.append( '{}: {}'.format(i,self.cores[i].getName()) )
|
||||
raise ErrorMessage( 1, message )
|
||||
self.validated = False
|
||||
|
||||
if len(self.cores) < 1:
|
||||
raise ErrorMessage( 1, 'Chip "{} doesn\'t seems to have a core.' \
|
||||
.format(self.chip.getName()) )
|
||||
self.validated = False
|
||||
return
|
||||
|
||||
def findPowerAndClockNets ( self ):
|
||||
if self.icore:
|
||||
for plug in self.icore.getPlugs():
|
||||
masterNet = plug.getMasterNet()
|
||||
netType = masterNet.getType()
|
||||
if netType != Net.Type.POWER \
|
||||
and netType != Net.Type.GROUND \
|
||||
and netType != Net.Type.CLOCK:
|
||||
continue
|
||||
net = plug.getNet()
|
||||
if not net:
|
||||
net = self.corona.getNet( masterNet.getName() )
|
||||
if not net:
|
||||
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Missing global net "{}" at corona level.' \
|
||||
.format(asterNet.getName()) )
|
||||
self._validated = False
|
||||
continue
|
||||
if netType == Net.Type.GROUND:
|
||||
if self.coronaVss and self.coronaVss != net:
|
||||
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple ground nets "{}" and "{}" at corona level.' \
|
||||
.format(self.coronaVss.getName(), net.getName()) )
|
||||
self._validated = False
|
||||
continue
|
||||
else:
|
||||
self.coronaVss = net
|
||||
|
||||
if netType == Net.Type.POWER:
|
||||
if self.coronaVdd and self.coronaVdd != net:
|
||||
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple power nets "{}" and "{}" at corona level.' \
|
||||
.format(self.coronaVdd.getName(), net.getName()) )
|
||||
self._validated = False
|
||||
continue
|
||||
else:
|
||||
self.coronaVdd = net
|
||||
|
||||
if netType == Net.Type.CLOCK:
|
||||
if not net in self.coronaCks:
|
||||
self.coronaCks.append( net )
|
||||
vprint( 2, ' - Using clock "{}".'.format(net.getName()) )
|
||||
for net in self.corona.getNets():
|
||||
if net.getType() == Net.Type.BLOCKAGE:
|
||||
self.blockageNet = net
|
||||
self.blockageName = net.getName()
|
||||
if not self.blockageNet:
|
||||
self.blockageNet = Net.create( self.corona, self.blockageName )
|
||||
self.blockageNet.setType( Net.Type.BLOCKAGE )
|
||||
return
|
||||
|
||||
def checkChipSize ( self ):
|
||||
if self.chipSize[0] % self.sliceStep:
|
||||
print( WarningMessage( 'ChipConf.checkChipSize(): Width of "{}" ({})is not on sliceStep ({}), ajusted.' \
|
||||
.format( self.chipConf.name
|
||||
, DbU.getValueString(self.chipSize[0])
|
||||
, DbU.getValueString(self.sliceStep))) )
|
||||
adjust = self.sliceStep - self.chipSize[0] % self.sliceStep
|
||||
self.chipSize = (self.chipSize[0] + adjust, self.chipSize[1])
|
||||
if self.chipSize[1] % self.sliceStep:
|
||||
print( WarningMessage( 'ChipConf.checkChipSize(): Height of "{}" ({})is not on sliceStep ({}), ajusted.' \
|
||||
.format( self.chipConf.name
|
||||
, DbU.getValueString(self.chipSize[1])
|
||||
, DbU.getValueString(self.sliceStep))) )
|
||||
adjust = self.sliceStep - self.chipSize[1] % self.sliceStep
|
||||
self.chipSize = (self.chipSize[0], self.chipSize[1] + adjust)
|
||||
|
||||
#if self._coreSize.isEmpty(): return
|
||||
#
|
||||
#minWidth = self._coreSize.getWidth () + self._minCorona + 2*self._padHeight
|
||||
#minHeight = self._coreSize.getHeight() + self._minCorona + 2*self._padHeight
|
||||
#
|
||||
#if self._chipSize.getWidth() < minWidth:
|
||||
# raise ErrorMessage( 1, 'Core is too wide to fit into the chip. Needs: %d, but has %d' \
|
||||
# % ( DbU.toLambda(minWidth), DbU.toLambda(self._chipSize.getWidth()) ) )
|
||||
# self._validated = False
|
||||
#
|
||||
#if self._chipSize.getHeight() < minHeight:
|
||||
# raise ErrorMessage( 1, 'Core is too wide to fit into the chip. Needs: %d, but has %d' \
|
||||
# % ( DbU.toLambda(minHeight), DbU.toLambda(self._chipSize.getHeight()) ) )
|
||||
# self._validated = False
|
||||
return
|
||||
|
||||
def checkCorona ( self ):
|
||||
trace( 550, ',+', 'Configuration.checkCorona()\n' )
|
||||
netPads = {}
|
||||
for plug in self.icorona.getPlugs():
|
||||
padNet = plug.getNet()
|
||||
coronaNet = plug.getMasterNet()
|
||||
if not padNet and coronaNet.isGlobal():
|
||||
padNet = self.chip.getNet( coronaNet.getName() )
|
||||
if padNet:
|
||||
if not padNet in netPads:
|
||||
trace( 550, '\t{:>20} <-> {:<20}\n'.format(padNet.getName(),coronaNet.getName()) )
|
||||
netPads[ padNet ] = coronaNet
|
||||
else:
|
||||
raise ErrorMessage( 1, 'ChipConf.checkCorona(): Corona nets "{}" and "{}" connected to the same pad net "{}".' \
|
||||
.format(coronaNet.getName(),netPads[padNet].getName(),padNet.getName()) )
|
||||
self._validated = False
|
||||
trace( 550, '-' )
|
||||
return
|
||||
|
||||
def computeChipSize ( self ):
|
||||
|
||||
def getSideLength ( pads ):
|
||||
sideLength = self.ioPadHeight * 2
|
||||
for pad in pads: sideLength += pad.getMasterCell().getAbutmentBox().getWidth()
|
||||
return sideLength
|
||||
|
||||
if not self.chipSize.isEmpty(): return
|
||||
southPadsLength = getSideLength( self.southPads )
|
||||
northPadsLength = getSideLength( self.northPads )
|
||||
eastPadsLength = getSideLength( self.eastPads )
|
||||
westPadsLength = getSideLength( self.westPads )
|
||||
horizontalPads = max( len(self.southPads), len(self.northPads) )
|
||||
verticalPads = max( len(self.eastPads ), len(self.westPads ) )
|
||||
self.chipSize = ( max( southPadsLength, northPadsLength )
|
||||
, max( westPadsLength, eastPadsLength ) )
|
||||
|
||||
def setupCorona ( self, gapX1, gapY1, gapX2, gapY2 ):
|
||||
ab = self.chip.getAbutmentBox()
|
||||
ab.inflate ( -gapX1, -gapY1, -gapX2, -gapY2 )
|
||||
ab.inflate ( - self.ioPadHeight )
|
||||
ab.translate( - self.ioPadHeight, - self.ioPadHeight)
|
||||
ab = self.toSymbolic( ab, Inwards )
|
||||
|
||||
self. corona.setAbutmentBox( Box( 0, 0, ab.getWidth(), ab.getHeight() ) )
|
||||
self.icorona.setTransformation(
|
||||
Transformation( self.toSymbolic( self.ioPadHeight + ab.getXMin(), Superior )
|
||||
, self.toSymbolic( self.ioPadHeight + ab.getYMin(), Superior )
|
||||
, Transformation.Orientation.ID ) )
|
||||
self.icorona.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||
self.setRoutingBb( self.corona.getAbutmentBox() )
|
||||
|
||||
def setupCore ( self, gapX1, gapY1, gapX2, gapY2 ):
|
||||
trace( 550, ',+', '\tChipConf.setupCore()\n' )
|
||||
ab = self.getInstanceAb( self.icorona )
|
||||
if ab.isEmpty():
|
||||
raise ErrorMessage( 1, 'ChipConf.setupCore(): Attempt to setup core *before* corona.' )
|
||||
return
|
||||
ab.inflate( -gapX1, -gapY1, -gapX2, -gapY2 )
|
||||
ab = self.toSymbolic( ab, Inwards )
|
||||
tracee( 550, '\tself.coreAb:{}\n'.format(self.coreAb) )
|
||||
if not self.coreAb.isEmpty():
|
||||
trace( 550, '\tUsing user-defined CORE size:{}\n'.format(self.coreSize) )
|
||||
ab = self.coreAb
|
||||
trace( 550, '\tSetting CORE abutment box:{}\n'.format(ab) )
|
||||
self.core.setAbutmentBox( Box( 0, 0, ab.getWidth(), ab.getHeight() ) )
|
||||
self.icore.setTransformation(
|
||||
Transformation( ChipConf.toSymbolic(ab.getXMin(),Inferior) - self.icorona.getTransformation().getTx()
|
||||
, ChipConf.toSymbolic(ab.getYMin(),Inferior) - self.icorona.getTransformation().getTy()
|
||||
, Transformation.Orientation.ID ) )
|
||||
self.icore.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||
trace( 550, '-' )
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) Sorbonne Université 2014-2021, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C u m u l u s - P y t h o n T o o l s |
|
||||
# | |
|
||||
# | Author : Jean-Paul CHAPUT |
|
||||
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./plugins/chip/chip.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
import os.path
|
||||
import optparse
|
||||
import math
|
||||
import cProfile
|
||||
import pstats
|
||||
import Cfg
|
||||
import Hurricane
|
||||
from Hurricane import DataBase, DbU ,Point, Transformation, Box, \
|
||||
Path, Occurrence, UpdateSession, Breakpoint, \
|
||||
Net, RoutingPad, Contact, Horizontal, Vertical, \
|
||||
Instance, HyperNet, Query
|
||||
import Viewer
|
||||
import CRL
|
||||
from CRL import RoutingLayerGauge
|
||||
import helpers
|
||||
from helpers import trace
|
||||
from helpers.io import ErrorMessage, WarningMessage
|
||||
from helpers.overlay import UpdateSession
|
||||
import Etesian
|
||||
import Anabatic
|
||||
import Katana
|
||||
import Unicorn
|
||||
import plugins
|
||||
import plugins.rsave
|
||||
from plugins.alpha.block.block import Block
|
||||
import plugins.alpha.chip.pads
|
||||
import plugins.alpha.chip.power
|
||||
import plugins.alpha.chip.powerplane
|
||||
import plugins.alpha.chip.corona
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Class : "chip.Chip"
|
||||
|
||||
class Chip ( Block ):
|
||||
|
||||
def __init__ ( self, conf ):
|
||||
super(Chip,self).__init__( conf )
|
||||
|
||||
def validate ( self ):
|
||||
self.conf.validated = True
|
||||
coreAb = self.conf.core.getAbutmentBox()
|
||||
if (not coreAb.isEmpty()):
|
||||
if coreAb.getWidth () <= self.conf.coreAb.getWidth() \
|
||||
and coreAb.getHeight() <= self.conf.coreAb.getHeight():
|
||||
self.conf.coreSize = (coreAb.getWidth(), coreAb.getHeight())
|
||||
else:
|
||||
raise ErrorMessage( 1, [ 'Core "{}" already have an abutment box, bigger than the requested one:' \
|
||||
.format(self.conf.core.getName())
|
||||
, " Cell abutment box: {}".format(coreAb)
|
||||
, " Maximum abutment box: {}".format(self.conf.coreAb) ] )
|
||||
self.conf.validated = False
|
||||
return self.conf.validated
|
||||
|
||||
def doChipFloorplan ( self ):
|
||||
print( ' - Chip has {} north pads.'.format(len(self.conf.chipConf.northPads)) )
|
||||
print( ' - Chip has {} south pads.'.format(len(self.conf.chipConf.southPads)) )
|
||||
print( ' - Chip has {} east pads.' .format(len(self.conf.chipConf.eastPads )) )
|
||||
print( ' - Chip has {} west pads.' .format(len(self.conf.chipConf.westPads )) )
|
||||
self.conf.computeCoronaBorder()
|
||||
self.conf.chipValidate()
|
||||
if not self.conf.validated:
|
||||
raise ErrorMessage( 1, 'chip.doChipFloorplan(): Chip is not valid, aborting.' )
|
||||
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 )
|
||||
self.conf.validated = self.padsCorona.validate()
|
||||
if not self.conf.validated:
|
||||
return False
|
||||
self.padsCorona.doLayout()
|
||||
self.validate()
|
||||
minHCorona = self.conf.minHCorona
|
||||
minVCorona = self.conf.minVCorona
|
||||
innerBb = Box( self.conf.coreAb )
|
||||
innerBb.inflate( minHCorona, minVCorona )
|
||||
coronaAb = self.conf.corona.getAbutmentBox()
|
||||
if innerBb.getWidth() > coronaAb.getWidth():
|
||||
raise ErrorMessage( 1, 'Core is too wide to fit into the corona, needs {} but only has {}.' \
|
||||
.format( DbU.getValueString(innerBb .getWidth())
|
||||
, DbU.getValueString(coronaAb.getWidth()) ) )
|
||||
if innerBb.getHeight() > coronaAb.getHeight():
|
||||
raise ErrorMessage( 1, 'Core is too tall to fit into the corona, needs {} but only has {}.' \
|
||||
.format( DbU.getValueString(innerBb .getHeight())
|
||||
, DbU.getValueString(coronaAb.getHeight()) ) )
|
||||
with UpdateSession():
|
||||
self.conf.core.setAbutmentBox( self.conf.coreAb )
|
||||
x = (coronaAb.getWidth () - self.conf.coreAb.getWidth ()) // 2
|
||||
y = (coronaAb.getHeight() - self.conf.coreAb.getHeight()) // 2
|
||||
trace( 550, '\tCore X, {} '.format(DbU.getValueString(x)) )
|
||||
x = x - (x % self.conf.sliceHeight)
|
||||
trace( 550, ' adjusted on {}, {}\n'.format( DbU.getValueString(self.conf.sliceHeight)
|
||||
, DbU.getValueString(x)) )
|
||||
y = y - (y % self.conf.sliceHeight)
|
||||
self.conf.icore.setTransformation ( Transformation(x,y,Transformation.Orientation.ID) )
|
||||
self.conf.icore.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||
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()
|
||||
#power.connectHTrees( self.hTrees )
|
||||
power.doLayout()
|
||||
Breakpoint.stop( 101, 'After Query power.' )
|
||||
else:
|
||||
power = plugins.alpha.chip.power.Builder( self.conf )
|
||||
power.connectPower()
|
||||
power.connectClocks()
|
||||
power.doLayout()
|
||||
self.conf.refresh()
|
||||
corona = plugins.alpha.chip.corona.Builder( power )
|
||||
corona.connectPads( self.padsCorona )
|
||||
corona.connectCore()
|
||||
corona.doLayout()
|
||||
self.conf.refresh()
|
||||
|
||||
def doPnR ( self ):
|
||||
super(Chip,self).doPnR()
|
||||
self.conf.refresh( self.conf.chip )
|
||||
return self.conf.validated
|
||||
|
||||
def save ( self, flags=0 ):
|
||||
if not self.conf.validated:
|
||||
raise ErrorMessage( 1, 'chip.save(): Chip is not valid, aborting.' )
|
||||
views = CRL.Catalog.State.Logical
|
||||
if self.conf.routingGauge.isSymbolic():
|
||||
views = views | CRL.Catalog.State.Physical
|
||||
super(Chip,self).save( flags )
|
Loading…
Reference in New Issue