684 lines
25 KiB
Python
684 lines
25 KiB
Python
# -*- explicit-buffer-name: "Configuration.py<cumulus/src/plugins/chip>" -*-
|
|
#
|
|
# This file is part of the Coriolis Software.
|
|
# Copyright (c) UPMC 2014-2014, 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@asim.lip6.fr |
|
|
# | =============================================================== |
|
|
# | Python : "./plugins/chip/Configuration.py" |
|
|
# +-----------------------------------------------------------------+
|
|
|
|
|
|
import sys
|
|
import os.path
|
|
import Cfg
|
|
from Hurricane import DbU
|
|
from Hurricane import Box
|
|
from Hurricane import Transformation
|
|
from Hurricane import Box
|
|
from Hurricane import Path
|
|
from Hurricane import Occurrence
|
|
from Hurricane import Net
|
|
from Hurricane import RoutingPad
|
|
from Hurricane import Contact
|
|
from Hurricane import Horizontal
|
|
from Hurricane import Vertical
|
|
from Hurricane import Plug
|
|
from Hurricane import Instance
|
|
import CRL
|
|
from CRL import RoutingLayerGauge
|
|
from helpers import trace
|
|
from helpers import ErrorMessage
|
|
from helpers import WarningMessage
|
|
from plugins import getParameter
|
|
|
|
|
|
def breakpoint ( editor, level, message ):
|
|
if editor:
|
|
editor.fit()
|
|
editor.refresh()
|
|
Breakpoint.stop( level, message )
|
|
return
|
|
|
|
|
|
def getPlugByName ( instance, netName ):
|
|
masterCell = instance.getMasterCell()
|
|
masterNet = masterCell.getNet( netName )
|
|
if masterNet:
|
|
return instance.getPlug( masterNet )
|
|
return None
|
|
|
|
|
|
def getPlugByNet ( instance, net ):
|
|
for plug in net.getPlugs():
|
|
if plug.getInstance() == instance:
|
|
return plug
|
|
return None
|
|
|
|
|
|
def getRpBb ( instance, netName ):
|
|
bb = Box()
|
|
for net in instance.getMasterCell().getNets():
|
|
if net.isExternal() and net.getName() == netName:
|
|
for component in net.getExternalComponents():
|
|
if isinstance(component,Vertical):
|
|
bb = component.getBoundingBox()
|
|
instance.getTransformation().applyOn( bb )
|
|
return bb
|
|
|
|
|
|
def showNet ( cell, netName ):
|
|
net = cell.getNet(netName)
|
|
if not net:
|
|
print ErrorMessage( 3, 'Cell %s doesn\'t have net %s' % (cell.getName(),netName) )
|
|
return
|
|
|
|
print 'Components of', netName
|
|
for component in net.getComponents():
|
|
print '| ', component, component.getBoundingBox()
|
|
return
|
|
|
|
|
|
def destroyNetComponents ( net ):
|
|
# 1. We cannot iterate over a Hurricane Collection if we are deleting
|
|
# some of it's elements at the same time (could be improved as it
|
|
# is an intrusive map.
|
|
# 2. Lazy programming: as we don't know the destruction order, some
|
|
# components can be deleted by (previous) others so we can endup
|
|
# on dangling Python proxy which send an exception that we catch.
|
|
# 3. Plugs are not destroyed (they cannot as they are part of the
|
|
# Instance). They stay connected to the net.
|
|
toDestroy = []
|
|
for component in net.getComponents():
|
|
if not isinstance(component,Plug):
|
|
toDestroy.append( component )
|
|
for component in toDestroy:
|
|
try:
|
|
component.destroy()
|
|
except:
|
|
pass
|
|
return
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Class : "Configuration.GaugeConf".
|
|
|
|
class GaugeConf ( object ):
|
|
|
|
HAccess = 0x0001
|
|
OffsetRight1 = 0x0002
|
|
OffsetTop1 = 0x0004
|
|
OffsetBottom1 = 0x0008
|
|
|
|
def __init__ ( self ):
|
|
self._cellGauge = None
|
|
self._routingGauge = None
|
|
self._topLayerDepth = 0
|
|
self._plugToRp = { }
|
|
|
|
self._loadRoutingGauge()
|
|
return
|
|
|
|
def getSliceHeight ( self ): return self._cellGauge.getSliceHeight()
|
|
def getSliceStep ( self ): return self._cellGauge.getSliceStep()
|
|
|
|
def _loadRoutingGauge ( self ):
|
|
self._cellGauge = CRL.AllianceFramework.get().getCellGauge()
|
|
self._routingGauge = CRL.AllianceFramework.get().getRoutingGauge()
|
|
|
|
topLayer = Cfg.getParamString('katabatic.topRoutingLayer').asString()
|
|
|
|
self._topLayerDepth = 0
|
|
for layerGauge in self._routingGauge.getLayerGauges():
|
|
if layerGauge.getLayer().getName() == topLayer:
|
|
self._topLayerDepth = layerGauge.getDepth()
|
|
break
|
|
if not self._topLayerDepth:
|
|
print WarningMessage( 'Gauge top layer not defined, using top of gauge (%d).' \
|
|
% self._routingGauge.getDepth() )
|
|
self._topLayerDepth = self._routingGauge.getDepth()
|
|
|
|
self._horizontalDepth = 0
|
|
self._verticalDepth = 0
|
|
for depth in range(0,self._topLayerDepth+1):
|
|
if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal:
|
|
self._horizontalDepth = depth
|
|
if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical:
|
|
self._verticalDepth = depth
|
|
return
|
|
|
|
def _createContact ( self, net, x, y ):
|
|
return Contact.create( net
|
|
, self._routingGauge.getContactLayer(self._horizontalDepth)
|
|
, x, y
|
|
, self._routingGauge.getLayerGauge(self._horizontalDepth).getViaWidth()
|
|
, self._routingGauge.getLayerGauge(self._horizontalDepth).getViaWidth()
|
|
)
|
|
|
|
def _createHorizontal ( self, source, target, y ):
|
|
segment = Horizontal.create( source
|
|
, target
|
|
, self._routingGauge.getRoutingLayer(self._horizontalDepth)
|
|
, y
|
|
, self._routingGauge.getLayerGauge(self._horizontalDepth).getWireWidth()
|
|
)
|
|
trace( 550, segment )
|
|
return segment
|
|
|
|
def _createVertical ( self, source, target, x ):
|
|
segment = Vertical.create( source
|
|
, target
|
|
, self._routingGauge.getRoutingLayer(self._verticalDepth)
|
|
, x
|
|
, self._routingGauge.getLayerGauge(self._verticalDepth).getWireWidth()
|
|
)
|
|
trace( 550, segment )
|
|
return segment
|
|
|
|
def _rpAccess ( self, rp, flags ):
|
|
trace( 550, ',+', '\t_rpAccess() %s\n' % str(rp) )
|
|
|
|
hpitch = self._routingGauge.getLayerGauge(self._horizontalDepth).getPitch()
|
|
hoffset = self._routingGauge.getLayerGauge(self._horizontalDepth).getOffset()
|
|
contact1 = Contact.create( rp, self._routingGauge.getContactLayer(0), 0, 0 )
|
|
midSliceY = contact1.getY() - (contact1.getY() % self._cellGauge.getSliceHeight()) \
|
|
+ self._cellGauge.getSliceHeight() / 2
|
|
midTrackY = midSliceY - ((midSliceY - hoffset) % hpitch)
|
|
dy = midSliceY - contact1.getY()
|
|
|
|
if flags & GaugeConf.OffsetBottom1: dy += hpitch
|
|
if flags & GaugeConf.OffsetTop1: dy -= hpitch
|
|
contact1.setDy( dy )
|
|
|
|
trace( 550, contact1 )
|
|
|
|
if flags & GaugeConf.HAccess: stopDepth = self._horizontalDepth
|
|
else: stopDepth = self._verticalDepth
|
|
|
|
for depth in range(1,stopDepth):
|
|
xoffset = 0
|
|
if flags & GaugeConf.OffsetRight1 and depth == 1:
|
|
xoffset = self._routingGauge.getLayerGauge(depth+1).getPitch()
|
|
contact2 = Contact.create( rp.getNet()
|
|
, self._routingGauge.getContactLayer(depth)
|
|
, contact1.getX() + xoffset
|
|
, contact1.getY()
|
|
, self._routingGauge.getLayerGauge(depth).getViaWidth()
|
|
, self._routingGauge.getLayerGauge(depth).getViaWidth()
|
|
)
|
|
trace( 550, contact2 )
|
|
if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal:
|
|
segment = Horizontal.create( contact1
|
|
, contact2
|
|
, self._routingGauge.getRoutingLayer(depth)
|
|
, contact1.getY()
|
|
, self._routingGauge.getLayerGauge(depth).getWireWidth()
|
|
)
|
|
trace( 550, segment )
|
|
else:
|
|
segment = Vertical.create( contact1
|
|
, contact2
|
|
, self._routingGauge.getRoutingLayer(depth)
|
|
, contact1.getX()
|
|
, self._routingGauge.getLayerGauge(depth).getWireWidth()
|
|
)
|
|
trace( 550, segment )
|
|
contact1 = contact2
|
|
|
|
trace( 550, '-' )
|
|
return contact1
|
|
|
|
def _rpByOccurrence ( self, occurrence, net ):
|
|
plug = occurrence.getEntity()
|
|
if self._plugToRp.has_key(plug):
|
|
rp = self._plugToRp[plug]
|
|
else:
|
|
rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea )
|
|
self._plugToRp[plug] = rp
|
|
|
|
return rp
|
|
|
|
def _rpAccessByOccurrence ( self, occurrence, net, flags ):
|
|
plug = occurrence.getEntity()
|
|
if self._plugToRp.has_key(plug):
|
|
rp = self._plugToRp[plug]
|
|
else:
|
|
rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea )
|
|
self._plugToRp[plug] = rp
|
|
|
|
return self._rpAccess( self._rpByOccurrence(occurrence,net), flags )
|
|
|
|
def _rpByPlug ( self, plug, net ):
|
|
if self._plugToRp.has_key(plug):
|
|
rp = self._plugToRp[plug]
|
|
else:
|
|
occurrence = Occurrence( plug, Path(net.getCell(),'') )
|
|
rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea )
|
|
self._plugToRp[plug] = rp
|
|
|
|
return rp
|
|
|
|
def _rpByPlugName ( self, instance, plugName, net ):
|
|
return self._rpByPlug( getPlugByName(instance,plugName), net )
|
|
|
|
def _rpAccessByPlug ( self, plug, net, flags ):
|
|
return self._rpAccess( self._rpByPlug(plug,net), flags )
|
|
|
|
def _rpAccessByPlugName ( self, instance, plugName, net, flags=0 ):
|
|
return self._rpAccess( self._rpByPlugName(instance,plugName,net), flags )
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Class : "Configuration.GaugeConfWrapper".
|
|
|
|
class GaugeConfWrapper ( object ):
|
|
|
|
def __init__ ( self, conf ):
|
|
#print id(conf), type(conf)
|
|
#if not isinstance(conf,GaugeConf):
|
|
# raise ErrorMessage( 1, 'Attempt to create a GaugeConfWrapper() from non-GaugeConf object.' )
|
|
self._gaugeConf = conf
|
|
return
|
|
|
|
@property
|
|
def gaugeConf ( self ): return self._gaugeConf
|
|
|
|
@property
|
|
def routingGauge ( self ): return self._gaugeConf._routingGauge
|
|
@property
|
|
def topLayerDepth ( self ): return self._gaugeConf._topLayerDepth
|
|
@property
|
|
def horizontalDepth ( self ): return self._gaugeConf._horizontalDepth
|
|
@property
|
|
def verticalDepth ( self ): return self._gaugeConf._verticalDepth
|
|
|
|
def loadRoutingGauge ( self ): self._gaugeConf._loadRoutingGauge()
|
|
|
|
def rpByOccurrence ( self, occurrence, net ):
|
|
return self._gaugeConf._rpByOccurrence ( occurrence, net )
|
|
|
|
def rpByPlugName ( self, instance, plugName, net ):
|
|
return self._gaugeConf._rpByPlugName ( instance, plugName, net )
|
|
|
|
def rpAccess ( self, rp, flags=0 ):
|
|
return self._gaugeConf._rpAccess( rp, flags )
|
|
|
|
def rpAccessByOccurrence ( self, occurrence, net, flags=0 ):
|
|
return self.gaugeConf._rpAccessByOccurrence ( occurrence, net, flags )
|
|
|
|
def rpAccessByPlugName ( self, instance, plugName, net, flags=0 ):
|
|
return self._gaugeConf._rpAccessByPlugName( instance, plugName, net, flags )
|
|
|
|
def createContact ( self, net, x, y ):
|
|
return self._gaugeConf._createContact( net, x, y )
|
|
|
|
def createHorizontal ( self, source, target, y ):
|
|
return self._gaugeConf._createHorizontal( source, target, y )
|
|
|
|
def createVertical ( self, source, target, x ):
|
|
return self._gaugeConf._createVertical( source, target, x )
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Class : "Configuration.ChipConf".
|
|
|
|
class ChipConf ( object ):
|
|
|
|
@staticmethod
|
|
def _readChipSize( chipConfigDict ):
|
|
if not chipConfigDict.has_key('chip.size'): return Box()
|
|
chipSize = chipConfigDict['chip.size']
|
|
if not isinstance(chipSize,tuple):
|
|
print ErrorMessage( 1, 'The Chip size parameter is *not* a tuple.' )
|
|
return Box()
|
|
if len(chipSize) != 2:
|
|
print ErrorMessage( 1, 'The Chip size parameter is *not* a tuple of exactly two items.' )
|
|
return Box()
|
|
return Box( 0, 0, DbU.fromLambda(chipSize[0]), DbU.fromLambda(chipSize[1]) )
|
|
|
|
|
|
@staticmethod
|
|
def _readCoreSize( chipConfigDict ):
|
|
if not chipConfigDict.has_key('core.size'):
|
|
print ErrorMessage( 1, 'The Core size parameter is missing.' )
|
|
return Box()
|
|
coreSize = chipConfigDict['core.size']
|
|
if not isinstance(coreSize,tuple):
|
|
print ErrorMessage( 1, 'The Core size parameter is *not* a tuple.' )
|
|
return Box()
|
|
if len(coreSize) != 2:
|
|
print ErrorMessage( 1, 'The Core size parameter is *not* a tuple of exactly two items.' )
|
|
return Box()
|
|
return Box( 0, 0, DbU.fromLambda(coreSize[0]), DbU.fromLambda(coreSize[1]) )
|
|
|
|
|
|
@staticmethod
|
|
def _readClockTree( chipConfigDict ):
|
|
useClockTree = False
|
|
if chipConfigDict.has_key('chip.clockTree'):
|
|
if chipConfigDict['chip.clockTree']:
|
|
useClockTree = True
|
|
return useClockTree
|
|
|
|
|
|
def _readPads ( self, chipConfigDict, keyword ):
|
|
if not chipConfigDict.has_key(keyword): return []
|
|
padNameList = chipConfigDict[keyword]
|
|
if not isinstance(padNameList,list):
|
|
print ErrorMessage( 1, 'The "%s" entry is not a list.' )
|
|
return []
|
|
|
|
af = CRL.AllianceFramework.get()
|
|
padList = []
|
|
for i in range(len(padNameList)):
|
|
if not isinstance(padNameList[i],str):
|
|
print ErrorMessage( 1, 'The element [%d] of list %s is *not* a string (skipped).'
|
|
% (i,keyword) )
|
|
continue
|
|
|
|
instance = self._cell.getInstance( padNameList[i] )
|
|
if not instance:
|
|
print ErrorMessage( 1, 'The pad [%d] (%s) of list %s do not exists in netlist (skipped).'
|
|
% (i,padNameList[i],keyword) )
|
|
continue
|
|
|
|
if (not af.isPad(instance.getMasterCell().getName())):
|
|
print ErrorMessage( 1, 'The pad [%d] (%s) of list %s is not an instance of a pad cell (skipped).'
|
|
% (i,padNameList[i],keyword) )
|
|
continue
|
|
|
|
padList.append( instance )
|
|
|
|
if not self._clockPad and instance.getMasterCell().getName() == self._pckName:
|
|
self._clockPad = instance
|
|
|
|
if not self._powerPad and instance.getMasterCell().getName() == self._pvddickName:
|
|
self._powerPad = instance
|
|
|
|
return padList
|
|
|
|
|
|
def _guessGlobalNet ( self, name, net ):
|
|
if name == self._vddeName: self._vdde = net
|
|
if name == self._vddiName: self._vddi = net
|
|
if name == self._vsseName: self._vsse = net
|
|
if name == self._vssiName: self._vssi = net
|
|
if name == self._ckiName: self._cki = net
|
|
if name == self._ckoName: self._cko = net
|
|
if name == self._ckName: self._ck = net
|
|
return
|
|
|
|
|
|
def __init__ ( self, chipConfigDict, cell ):
|
|
if not isinstance(chipConfigDict,dict):
|
|
raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' )
|
|
|
|
self._validated = True
|
|
self._cell = cell
|
|
# Block Corona parameters.
|
|
self._railsNb = getParameter('chip','chip.block.rails.count').asInt()
|
|
self._hRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.hWidth' ).asInt() )
|
|
self._vRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.vWidth' ).asInt() )
|
|
self._hRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.hSpacing').asInt() )
|
|
self._vRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.vSpacing').asInt() )
|
|
# Global Pad names.
|
|
self._pckName = getParameter('chip', 'chip.pad.pck' ).asString()
|
|
self._pvddickName = getParameter('chip', 'chip.pad.pvddick').asString()
|
|
self._pvssickName = getParameter('chip', 'chip.pad.pvssick').asString()
|
|
self._pvddeckName = getParameter('chip', 'chip.pad.pvddeck').asString()
|
|
self._pvsseckName = getParameter('chip', 'chip.pad.pvsseck').asString()
|
|
# Global Net names.
|
|
self._vddeName = "vdde"
|
|
self._vddiName = "vddi"
|
|
self._vsseName = "vsse"
|
|
self._vssiName = "vssi"
|
|
self._ckiName = "ck"
|
|
self._ckoName = "cko"
|
|
self._ckName = "pad"
|
|
# Global Nets.
|
|
self._vdde = None
|
|
self._vddi = None
|
|
self._vsse = None
|
|
self._vssi = None
|
|
self._cki = None
|
|
self._cko = None
|
|
self._ck = None
|
|
|
|
self._clockPad = None
|
|
self._powerPad = None
|
|
self._cores = []
|
|
self._southPads = self._readPads( chipConfigDict, 'pads.south' )
|
|
self._northPads = self._readPads( chipConfigDict, 'pads.north' )
|
|
self._eastPads = self._readPads( chipConfigDict, 'pads.east' )
|
|
self._westPads = self._readPads( chipConfigDict, 'pads.west' )
|
|
self._coreSize = ChipConf._readCoreSize( chipConfigDict )
|
|
self._chipSize = ChipConf._readChipSize( chipConfigDict )
|
|
self._padWidth = 0
|
|
self._padHeight = 0
|
|
self._useClockTree = ChipConf._readClockTree( chipConfigDict )
|
|
|
|
minHCorona = self._railsNb*(self._hRailWidth + self._hRailSpace) + self._hRailSpace
|
|
minVCorona = self._railsNb*(self._vRailWidth + self._vRailSpace) + self._vRailSpace
|
|
if minHCorona > minVCorona: self._minCorona = minHCorona*2
|
|
else: self._minCorona = minVCorona*2
|
|
|
|
self.checkPads()
|
|
self.computeChipSize()
|
|
self.findPowerAndClockNets()
|
|
return
|
|
|
|
|
|
def checkPads ( self ):
|
|
af = CRL.AllianceFramework.get()
|
|
cellPads = []
|
|
for instance in self._cell.getInstances():
|
|
if (af.isPad(instance.getMasterCell().getName())):
|
|
cellPads.append( instance )
|
|
else:
|
|
self._cores.append( instance )
|
|
|
|
for pad in cellPads:
|
|
if pad in self._southPads: continue
|
|
if pad in self._northPads: continue
|
|
if pad in self._eastPads: continue
|
|
if pad in self._westPads: continue
|
|
print ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % pad.getName() )
|
|
self._validated = False
|
|
|
|
if len(self._cores) < 1:
|
|
print ErrorMessage( 1, 'Chip "%s" doesn\'t seems to have a core.' % self._cell.getName() )
|
|
self._validated = False
|
|
|
|
if len(self._cores) > 1:
|
|
message = [ 'Chip "%s" have more than one core:' % self._cell.getName() ]
|
|
for i in range(len(self._cores)):
|
|
message.append( '%4d: %s' % (i,self._cores[i].getName()) )
|
|
print ErrorMessage( 1, message )
|
|
self._validated = False
|
|
|
|
return
|
|
|
|
|
|
def findPowerAndClockNets ( self ):
|
|
if self._powerPad:
|
|
for plug in self._powerPad.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._cell.getNet( masterNet.getName() )
|
|
if not net:
|
|
print ErrorMessage( 1, 'Missing global net <%s> at chip level.' % masterNet.getName() )
|
|
self._validated = False
|
|
continue
|
|
self._guessGlobalNet( masterNet.getName(), net )
|
|
|
|
if self._clockPad:
|
|
for plug in self._powerPad.getPlugs():
|
|
masterNet = plug.getMasterNet()
|
|
netType = masterNet.getType()
|
|
net = plug.getNet()
|
|
|
|
if not net:
|
|
net = self._cell.getNet( masterNet.getName() )
|
|
if not net:
|
|
print ErrorMessage( 1, 'Missing global net <%s> at chip level.' % masterNet.getName() )
|
|
self._validated = False
|
|
continue
|
|
|
|
if masterNet.getName() == self._ckName:
|
|
self._guessGlobalNet( masterNet.getName(), net )
|
|
return
|
|
|
|
|
|
def computeChipSize ( self ):
|
|
if not self._clockPad:
|
|
print ErrorMessage( 1, 'There must be at least one pad of model "%s" to be used as reference.' \
|
|
% self._pckName )
|
|
self._validated = False
|
|
return False
|
|
|
|
self._padHeight = self._clockPad.getMasterCell().getAbutmentBox().getHeight()
|
|
self._padWidth = self._clockPad.getMasterCell().getAbutmentBox().getWidth()
|
|
|
|
if not self._chipSize.isEmpty(): return
|
|
|
|
horizontalPads = max( len(self._southPads), len(self._northPads) )
|
|
verticalPads = max( len(self._eastPads ), len(self._westPads ) )
|
|
self._chipSize = Box( 0
|
|
, 0
|
|
, self._padWidth * horizontalPads + 2*self._padHeight
|
|
, self._padWidth * verticalPads + 2*self._padHeight
|
|
)
|
|
return
|
|
|
|
def getSpecialNetRoot ( self, net ):
|
|
if net.getName() == self._vddeName: return self._vdde
|
|
if net.getName() == self._vsseName: return self._vsse
|
|
if net.getType() == Net.Type.POWER: return self._vddi
|
|
if net.getType() == Net.Type.GROUND: return self._vssi
|
|
return None
|
|
|
|
|
|
# -------------------------------------------------------------------
|
|
# Class : "Configuration.ChipConfWrapper".
|
|
|
|
class ChipConfWrapper ( GaugeConfWrapper ):
|
|
|
|
def __init__ ( self, gaugeConf, chipConf ):
|
|
GaugeConfWrapper.__init__( self, gaugeConf )
|
|
|
|
#if not isinstance(chipConf,ChipConf):
|
|
# raise ErrorMessage( 1, 'Attempt to create a ChipConfWrapper() from non-ChipConf object.' )
|
|
self._chipConf = chipConf
|
|
return
|
|
|
|
def isValid ( self ): return self._chipConf._validated
|
|
|
|
@property
|
|
def chipConf ( self ): return self._chipConf
|
|
|
|
def getSliceHeight ( self ): return self._gaugeConf.getSliceHeight()
|
|
def getSliceStep ( self ): return self._gaugeConf.getSliceStep()
|
|
|
|
@property
|
|
def cell ( self ): return self._chipConf._cell
|
|
|
|
# Global Pad names.
|
|
@property
|
|
def pvddeckName ( self ): return self._chipConf._pvddeckName
|
|
@property
|
|
def pvsseckName ( self ): return self._chipConf._pvsseckName
|
|
@property
|
|
def pvddickName ( self ): return self._chipConf._pvddickName
|
|
@property
|
|
def pvssickName ( self ): return self._chipConf._pvssickName
|
|
@property
|
|
def pckName ( self ): return self._chipConf._pckName
|
|
|
|
# Global Net names.
|
|
@property
|
|
def vddeName ( self ): return self._chipConf._vddeName
|
|
@property
|
|
def vsseName ( self ): return self._chipConf._vsseName
|
|
@property
|
|
def vddiName ( self ): return self._chipConf._vddiName
|
|
@property
|
|
def vssiName ( self ): return self._chipConf._vssiName
|
|
@property
|
|
def ckiName ( self ): return self._chipConf._ckiName
|
|
@property
|
|
def ckoName ( self ): return self._chipConf._ckoName
|
|
@property
|
|
def ckName ( self ): return self._chipConf._ckName
|
|
|
|
# Global Nets.
|
|
@property
|
|
def vdde ( self ): return self._chipConf._vdde
|
|
@property
|
|
def vsse ( self ): return self._chipConf._vsse
|
|
@property
|
|
def vddi ( self ): return self._chipConf._vddi
|
|
@property
|
|
def vssi ( self ): return self._chipConf._vssi
|
|
@property
|
|
def cki ( self ): return self._chipConf._cki
|
|
@property
|
|
def cko ( self ): return self._chipConf._cko
|
|
@property
|
|
def ck ( self ): return self._chipConf._ck
|
|
|
|
# Various.
|
|
@property
|
|
def clockPad ( self ): return self._chipConf._clockPad
|
|
@property
|
|
def powerPad ( self ): return self._chipConf._powerPad
|
|
@property
|
|
def cores ( self ): return self._chipConf._cores
|
|
@property
|
|
def southPads ( self ): return self._chipConf._southPads
|
|
@property
|
|
def northPads ( self ): return self._chipConf._northPads
|
|
@property
|
|
def eastPads ( self ): return self._chipConf._eastPads
|
|
@property
|
|
def westPads ( self ): return self._chipConf._westPads
|
|
@property
|
|
def coreSize ( self ): return self._chipConf._coreSize
|
|
@coreSize.setter
|
|
def coreSize ( self, ab ): self._chipConf._coreSize = ab
|
|
@property
|
|
def chipSize ( self ): return self._chipConf._chipSize
|
|
@property
|
|
def minCorona ( self ): return self._chipConf._minCorona
|
|
@property
|
|
def padWidth ( self ): return self._chipConf._padWidth
|
|
@property
|
|
def padHeight ( self ): return self._chipConf._padHeight
|
|
@property
|
|
def useClockTree ( self ): return self._chipConf._useClockTree
|
|
|
|
|
|
def loadConfiguration ( cell ):
|
|
sys.path.append( os.getcwd() )
|
|
|
|
confFile = cell.getName()+'_chip'
|
|
confModule = __import__( confFile, globals(), locals(), confFile )
|
|
|
|
if not confModule.__dict__.has_key('chip'):
|
|
raise WarningMessage( 'Module <%s> do not provides the chip variable, skipped.' \
|
|
% confFile )
|
|
|
|
return ChipConfWrapper( GaugeConf()
|
|
, ChipConf ( confModule.__dict__['chip'], cell ) )
|