# 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, '-' )