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

682 lines
33 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
from Hurricane import DbU
from Hurricane import Box
from Hurricane import Transformation
from Hurricane import Box
from Hurricane import Path
from Hurricane import Layer
from Hurricane import Occurrence
from Hurricane import Net
from Hurricane import RoutingPad
from Hurricane import Horizontal
from Hurricane import Vertical
from Hurricane import Contact
from Hurricane import Pin
from Hurricane import Plug
from Hurricane import 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
from helpers.io import WarningMessage
from helpers.io import catch
from plugins import getParameter
import plugins.chip
from plugins.alpha.block.configuration import BlockConf
plugins.alpha.chip.importConstants( globals() )
# -------------------------------------------------------------------
# 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()) )
print( super(ChipConf,self).__init__ )
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.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.coronaCk = None
self.blockageNet = None
self.padsHavePosition = False
trace( 550, '-' )
@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 ):
if self.useClockTree:
trace( 550, '\tcomputeCoronaBorder() useClockTree: {}\n'.format(self.useClockTree) )
self.railsCount = self.cfg.chip.block.rails.count + 1
trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) )
self.minHCorona = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + self.sliceHeight
self.minVCorona = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + 10*self.sliceStep
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() ) )
trace( 550, '\tCORE ab:{}\n'.format(self.coreAb) )
coreX = (self.coronaAb.getWidth () - self.coreAb.getWidth ()) / 2
coreY = (self.coronaAb.getHeight() - self.coreAb.getHeight()) / 2
coreX = coreX - (coreX % self.sliceStep)
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():
oneLambda = DbU.fromLambda( 1.0 )
if axis % oneLambda:
axis -= oneLambda / 2
width -= oneLambda
trace( 550, '\t[{} {}]\n'.format(iTrackMin, iTrackMax) )
trace( 550, '\taxis: {}l {}\n'.format(DbU.toLambda(axis ), DbU.getValueString(axis )) )
trace( 550, '\twidth: {}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: {}l %s\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: {}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: {}l %s\n'.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
trace( 550, '\ttoCoronaPitchInChip(): uCore: {}l %s\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:{} ({}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: {}l or {}\n'.format(DbU.toLambda(coronaY), DbU.getValueString(coronaY)) )
trace( 550, '\t| width:{}l or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
trace( 550, '\t| dxMin:{}l\n'.format(DbU.toLambda(dxMin)) )
trace( 550, '\t| dxMax:{}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: {} or {}\n'.format(DbU.toLambda(coronaX), DbU.getValueString(coronaX)) )
trace( 550, '\t| width:{} 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()
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 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} or {:>12}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
trace( 550, '\t| Y axis: {:>12} 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 coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
viaPitch = layer.getMinimalSize() + layer.getMinimalSpacing()
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:{}l yContact:{}l\n'.format(DbU.toLambda(xContact),DbU.toLambda(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: {} or {}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
trace( 550, '\t| Y axis: {} 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
af = CRL.AllianceFramework.get()
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 self.coronaCk and self.coronaCk != net:
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple clock nets "{}" and "{}" at corona level.' \
.format(self.coronaCk.getName(), net.getName()) )
self._validated = False
continue
else:
self.coronaCk = net
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 ):
print( 'checkChipSize' )
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 )
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, '-' )