coriolis/cumulus/src/plugins/alpha/chip/configuration.py

712 lines
36 KiB
Python

# This file is part of the Coriolis Software.
# Copyright (c) SU 2014-2020, 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" |
# +-----------------------------------------------------------------+
from __future__ import print_function
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,long): 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
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 netPads.has_key(padNet):
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, '-' )