Added support for Tristate and bidir pads in CoreToChip.
* New: In Cumulus/plugins/CoreToChip, added support for Tristate ouput pads and bidirectional pads. Added capability to name the I/O pad instance and their external terminals so we can override the default naming scheme. Mandatory anyway for bidirectional and tristate I/O pad as we cannot guess the core net grouping (in/out/enable). Support is available for symbolic CMOS and AMS c35b4 (but not published due to NDA). * Change: In Cumulus/plugins/chip/Configuration.py, the configuration file is now named simply "ioring.py" instead of being prefixed by the design name. As a consequence we can have only one chip per directory. But now all the tools, for any design in that directory can peek datas into it.
This commit is contained in:
parent
acc3a38f60
commit
86c4e9cb17
|
@ -67,6 +67,7 @@ def ScriptMain ( **kw ):
|
||||||
cell, editor = plugins.kwParseMain( **kw )
|
cell, editor = plugins.kwParseMain( **kw )
|
||||||
|
|
||||||
conf = chip.Configuration.loadConfiguration( cell, editor )
|
conf = chip.Configuration.loadConfiguration( cell, editor )
|
||||||
|
conf.chipValidate()
|
||||||
if not conf.validated: return False
|
if not conf.validated: return False
|
||||||
|
|
||||||
placeChip = chip.Chip.PlaceRoute( conf )
|
placeChip = chip.Chip.PlaceRoute( conf )
|
||||||
|
|
|
@ -68,6 +68,7 @@ def ScriptMain ( **kw ):
|
||||||
|
|
||||||
cell, editor = plugins.kwParseMain( **kw )
|
cell, editor = plugins.kwParseMain( **kw )
|
||||||
conf = chip.Configuration.loadConfiguration( cell, editor )
|
conf = chip.Configuration.loadConfiguration( cell, editor )
|
||||||
|
conf.chipValidate()
|
||||||
if not conf.validated: return False
|
if not conf.validated: return False
|
||||||
|
|
||||||
prChip = chip.Chip.PlaceRoute( conf )
|
prChip = chip.Chip.PlaceRoute( conf )
|
||||||
|
|
|
@ -51,7 +51,7 @@ def ScriptMain ( **kw ):
|
||||||
raise ErrorMessage( 1, 'CoreToChip_cmos.ScriptMain(): No cell (core) loaded in the editor yet.' )
|
raise ErrorMessage( 1, 'CoreToChip_cmos.ScriptMain(): No cell (core) loaded in the editor yet.' )
|
||||||
|
|
||||||
chip_cmos = core2chip.cmos.cmos( cell )
|
chip_cmos = core2chip.cmos.cmos( cell )
|
||||||
chip_cmos.buildChip( 'chip' )
|
chip_cmos.buildChip()
|
||||||
|
|
||||||
if editor: editor.setCell( chip_cmos.chip )
|
if editor: editor.setCell( chip_cmos.chip )
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,82 @@ def destroyNetComponents ( net ):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Class : "IoPadConf".
|
||||||
|
|
||||||
|
class IoPadConf ( object ):
|
||||||
|
# self._datas is a table of 6 elements, the five first coming from
|
||||||
|
# the configuration itself. Direction are taken from the core point
|
||||||
|
# of view.
|
||||||
|
#
|
||||||
|
# Meaning of the table element's:
|
||||||
|
#
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | Index | Type |
|
||||||
|
# +=========+===========================================================+
|
||||||
|
# | 0 | Pad instance name |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | 1 | Pad connected signal name. |
|
||||||
|
# | | The name of the external signal at chip level |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | 2 | The name of the signal going *from* the pad to the core. |
|
||||||
|
# | | OUT direction in the core |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | 3 | The name of the signal going *to* the pad from the core. |
|
||||||
|
# | | IN direction in core |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | 4 | The enable signal, coming from the core |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
# | 5 | The IoPad associated object. It is set to None initially |
|
||||||
|
# +---------+-----------------------------------------------------------+
|
||||||
|
|
||||||
|
def __init__ ( self, datas ):
|
||||||
|
if not isinstance(datas,list):
|
||||||
|
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" parameter is not a list.'
|
||||||
|
, str(datas) ] )
|
||||||
|
if len(datas) < 3 and len(datas) > 5:
|
||||||
|
raise ErrorMessage( 1, [ 'IoPadConf.__init__(): The "datas" list must have between 3 to 5 elements.'
|
||||||
|
, str(datas) ] )
|
||||||
|
|
||||||
|
self._datas = datas
|
||||||
|
self._datas.append( None )
|
||||||
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def padInstanceName ( self ): return self._datas[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def padNetName ( self ): return self._datas[1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fromCoreNet ( self ): return self._datas[2]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def toCoreNet ( self ): return self._datas[3]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enableNet ( self ): return self._datas[-2]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nets ( self ): return self._datas[2:-1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def udata ( self ): return self._datas[-1]
|
||||||
|
|
||||||
|
@udata.setter
|
||||||
|
def udata ( self, data ): self._datas[-1] = data
|
||||||
|
|
||||||
|
def isTristate ( self ): return len(self._datas) == 5
|
||||||
|
def isBidir ( self ): return len(self._datas) == 6
|
||||||
|
|
||||||
|
def __repr__ ( self ):
|
||||||
|
s = '<IoPadConf %s pad:%s from:%s' % (self.padInstanceName,self.padNetName,self.fromCoreNet)
|
||||||
|
if self.isBidir():
|
||||||
|
s += ' to:%s en:%s' % (self.toCoreNet,self.enableNet)
|
||||||
|
s += '>'
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# Class : "Configuration.GaugeConf".
|
# Class : "Configuration.GaugeConf".
|
||||||
|
|
||||||
|
@ -448,9 +524,15 @@ class ChipConf ( object ):
|
||||||
return useClockTree
|
return useClockTree
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _readChipName( chipConfigDict ):
|
||||||
|
if chipConfigDict.has_key('chip.name'): return chipConfigDict['chip.name']
|
||||||
|
return 'chip'
|
||||||
|
|
||||||
|
|
||||||
def _loadIoPadGauge ( self, chipConfigDict ):
|
def _loadIoPadGauge ( self, chipConfigDict ):
|
||||||
if not chipConfigDict.has_key('pads.ioPadGauge'):
|
if not chipConfigDict.has_key('pads.ioPadGauge'):
|
||||||
raise ErrorMessage( 1, 'The IO pad gauge configuration paramater "pads.ioPadGauge" is missing.' )
|
#raise ErrorMessage( 1, 'The IO pad gauge configuration parameter "pads.ioPadGauge" is missing.' )
|
||||||
return
|
return
|
||||||
self.gaugeConf._loadIoPadGauge( chipConfigDict['pads.ioPadGauge'] )
|
self.gaugeConf._loadIoPadGauge( chipConfigDict['pads.ioPadGauge'] )
|
||||||
return
|
return
|
||||||
|
@ -481,31 +563,31 @@ class ChipConf ( object ):
|
||||||
% (i,keyword) )
|
% (i,keyword) )
|
||||||
continue
|
continue
|
||||||
|
|
||||||
instance = self.cell.getInstance( instanceName )
|
padList.append( [ position, instanceName ] )
|
||||||
if not instance:
|
|
||||||
raise ErrorMessage( 1, 'The pad [%d] (%s) of list %s do not exists in netlist (skipped).'
|
|
||||||
% (i,instanceName,keyword) )
|
|
||||||
continue
|
|
||||||
|
|
||||||
if (instance.getMasterCell().getAbutmentBox().getHeight() != self.gaugeConf.getIoPadHeight()):
|
|
||||||
raise ErrorMessage( 1, 'The pad [%d] (%s) of list %s is not an instance of a pad cell (skipped).'
|
|
||||||
% (i,instanceName,keyword) )
|
|
||||||
continue
|
|
||||||
|
|
||||||
padList.append( [ position, instance ] )
|
|
||||||
|
|
||||||
return padList
|
return padList
|
||||||
|
|
||||||
|
|
||||||
|
def _readPadInstances ( self, chipConfigDict ):
|
||||||
|
if not chipConfigDict.has_key('pads.instances'): return [ ]
|
||||||
|
|
||||||
|
padInstancesConf = chipConfigDict['pads.instances']
|
||||||
|
if not isinstance(padInstancesConf,list):
|
||||||
|
raise ErrorMessage( 1, 'The "%s" entry is not a list.' )
|
||||||
|
return [ ]
|
||||||
|
|
||||||
|
padInstances = [ ]
|
||||||
|
for entry in padInstancesConf:
|
||||||
|
padInstances.append( IoPadConf( entry ) )
|
||||||
|
return padInstances
|
||||||
|
|
||||||
|
|
||||||
def __init__ ( self, chipConfigDict, cell, viewer=None ):
|
def __init__ ( self, chipConfigDict, cell, viewer=None ):
|
||||||
trace( 550, '\tONE LAMBDA = %s\n' % DbU.getValueString(DbU.fromLambda(1.0)) )
|
trace( 550, '\tONE LAMBDA = %s\n' % DbU.getValueString(DbU.fromLambda(1.0)) )
|
||||||
|
|
||||||
if not isinstance(chipConfigDict,dict):
|
if not isinstance(chipConfigDict,dict):
|
||||||
raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' )
|
raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' )
|
||||||
|
|
||||||
self.chipMode = True
|
|
||||||
if len(chipConfigDict.keys()) == 0: self.chipMode = False
|
|
||||||
|
|
||||||
self.validated = True
|
self.validated = True
|
||||||
self.gaugeConf = GaugeConf()
|
self.gaugeConf = GaugeConf()
|
||||||
self.cell = cell
|
self.cell = cell
|
||||||
|
@ -523,32 +605,36 @@ class ChipConf ( object ):
|
||||||
self.coronaVss = None
|
self.coronaVss = None
|
||||||
self.coronaCk = None
|
self.coronaCk = None
|
||||||
self.blockageNet = None
|
self.blockageNet = None
|
||||||
|
|
||||||
if self.chipMode:
|
|
||||||
self._loadIoPadGauge( chipConfigDict )
|
|
||||||
|
|
||||||
self.coronas = []
|
self.coronas = []
|
||||||
self.cores = []
|
self.cores = []
|
||||||
if self.chipMode:
|
|
||||||
self.padsHavePosition = False
|
|
||||||
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.useClockTree = ChipConf._readClockTree( chipConfigDict )
|
|
||||||
|
|
||||||
minHCorona = self.railsNb*(self.hRailWidth + self.hRailSpace) + self.hRailSpace
|
self._loadIoPadGauge( chipConfigDict )
|
||||||
minVCorona = self.railsNb*(self.vRailWidth + self.vRailSpace) + self.vRailSpace
|
|
||||||
if minHCorona > minVCorona: self.minCorona = minHCorona*2
|
|
||||||
else: self.minCorona = minVCorona*2
|
|
||||||
|
|
||||||
self.checkPads()
|
self.padsHavePosition = False
|
||||||
self.checkCorona()
|
self.padInstances = self._readPadInstances( chipConfigDict )
|
||||||
self.computeChipSize()
|
self.southPads = self._readPads( chipConfigDict, 'pads.south' )
|
||||||
#self.checkChipSize()
|
self.northPads = self._readPads( chipConfigDict, 'pads.north' )
|
||||||
self.findPowerAndClockNets()
|
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.useClockTree = ChipConf._readClockTree( chipConfigDict )
|
||||||
|
self.chipName = ChipConf._readChipName ( 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
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def chipValidate ( self ):
|
||||||
|
self.checkPads()
|
||||||
|
self.checkCorona()
|
||||||
|
self.computeChipSize()
|
||||||
|
#self.checkChipSize()
|
||||||
|
self.findPowerAndClockNets()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -857,24 +943,42 @@ class ChipConf ( object ):
|
||||||
|
|
||||||
def checkPads ( self ):
|
def checkPads ( self ):
|
||||||
|
|
||||||
def contains ( padList, pad ):
|
def contains ( padList, side, padInstance ):
|
||||||
for padPair in padList:
|
for i in range(len(padList)):
|
||||||
if padPair[1] == pad: return True
|
if padList[i][1] == padInstance.getName():
|
||||||
|
if (padInstance.getMasterCell().getAbutmentBox().getHeight() != self.gaugeConf.getIoPadHeight()):
|
||||||
|
raise ErrorMessage( 1, 'The pad [%d] %s (%s) on %s side is not an instance of a pad cell.'
|
||||||
|
% (i,padInstance.getName(),padInstance.getModel().getName(),side) )
|
||||||
|
padList[i][1] = padInstance
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def checkNotFounds ( padList, side ):
|
||||||
|
for i in range(len(padList)):
|
||||||
|
if not isinstance(padList[i][1],Instance):
|
||||||
|
print ErrorMessage( 1, 'The pad [%d] (%s) of list %s do not exists in netlist (skipped).'
|
||||||
|
% (i,padList[i][1],side) )
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
af = CRL.AllianceFramework.get()
|
af = CRL.AllianceFramework.get()
|
||||||
cellPads = []
|
cellPads = []
|
||||||
for instance in self.cell.getInstances():
|
for instance in self.cell.getInstances():
|
||||||
if contains(self.southPads,instance): continue
|
if contains(self.southPads,'south',instance): continue
|
||||||
if contains(self.northPads,instance): continue
|
if contains(self.northPads,'north',instance): continue
|
||||||
if contains(self.eastPads ,instance): continue
|
if contains(self.eastPads ,'east' ,instance): continue
|
||||||
if contains(self.westPads ,instance): continue
|
if contains(self.westPads ,'west' ,instance): continue
|
||||||
if (instance.getMasterCell().getAbutmentBox().getHeight() == self.gaugeConf.getIoPadHeight()):
|
if (instance.getMasterCell().getAbutmentBox().getHeight() == self.gaugeConf.getIoPadHeight()):
|
||||||
raise ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % instance.getName() )
|
raise ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % instance.getName() )
|
||||||
self.validated = False
|
self.validated = False
|
||||||
else:
|
else:
|
||||||
self.coronas.append( instance )
|
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:
|
if len(self.coronas) > 1:
|
||||||
message = [ 'Chip "%s" have more than one corona:' % self.cell.getName() ]
|
message = [ 'Chip "%s" have more than one corona:' % self.cell.getName() ]
|
||||||
for i in range(len(self.coronas)):
|
for i in range(len(self.coronas)):
|
||||||
|
@ -1117,7 +1221,8 @@ class ChipConf ( object ):
|
||||||
def loadConfiguration ( cell, viewer=None ):
|
def loadConfiguration ( cell, viewer=None ):
|
||||||
sys.path.append( os.getcwd() )
|
sys.path.append( os.getcwd() )
|
||||||
|
|
||||||
confFile = cell.getName()+'_ioring'
|
#confFile = cell.getName()+'_ioring'
|
||||||
|
confFile = 'ioring'
|
||||||
if not os.path.isfile(confFile+'.py'):
|
if not os.path.isfile(confFile+'.py'):
|
||||||
raise ErrorMessage( 1, 'ChipPlugin configuration file <%s.py> is missing.' % confFile )
|
raise ErrorMessage( 1, 'ChipPlugin configuration file <%s.py> is missing.' % confFile )
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ from CRL import Catalog
|
||||||
from CRL import AllianceFramework
|
from CRL import AllianceFramework
|
||||||
from helpers import netDirectionToStr
|
from helpers import netDirectionToStr
|
||||||
from helpers.io import ErrorMessage
|
from helpers.io import ErrorMessage
|
||||||
|
import chip.Chip
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -30,30 +31,45 @@ from helpers.io import ErrorMessage
|
||||||
|
|
||||||
class IoNet ( object ):
|
class IoNet ( object ):
|
||||||
|
|
||||||
|
IsElem = 0x0001
|
||||||
|
IsEnable = 0x0002
|
||||||
|
IsBidir = 0x0004
|
||||||
reVHDLVector = re.compile( r'(?P<name>[^(]*)\((?P<index>[\d]+)\)$' )
|
reVHDLVector = re.compile( r'(?P<name>[^(]*)\((?P<index>[\d]+)\)$' )
|
||||||
|
|
||||||
def __init__ ( self, coreToChip, coreNet ):
|
def __init__ ( self, coreToChip, coreNet ):
|
||||||
self.coreToChip = coreToChip
|
self.coreToChip = coreToChip
|
||||||
self.coreNet = coreNet
|
self._flags = 0
|
||||||
self.coronaNet = None # Corona net going from core to corona.
|
self._chipExtNetName = None # In the case of bidir pad, force external net name.
|
||||||
self.chipIntNet = None # Chip net going from corona to I/O pad.
|
self.coreNet = coreNet
|
||||||
self.chipExtNet = None # Chip net going from I/O pad to the outside world.
|
self.coronaNet = None # Corona net going from core to corona.
|
||||||
self.pads = [ ]
|
self.chipIntNet = None # Chip net going from corona to I/O pad.
|
||||||
|
self.chipExtNet = None # Chip net going from I/O pad to the outside world.
|
||||||
|
|
||||||
m = IoNet.reVHDLVector.match( self.coreNet.getName() )
|
m = IoNet.reVHDLVector.match( self.coreNet.getName() )
|
||||||
if m:
|
if m:
|
||||||
self._isElem = True
|
self._flags |= IoNet.IsElem
|
||||||
self._name = m.group('name')
|
self._name = m.group('name')
|
||||||
self._index = m.group('index')
|
self._index = m.group('index')
|
||||||
else:
|
else:
|
||||||
self._isElem = False
|
|
||||||
self._name = self.coreNet.getName()
|
self._name = self.coreNet.getName()
|
||||||
self._index = 0
|
self._index = 0
|
||||||
|
|
||||||
self._type = self.coreToChip.getNetType( self._name )
|
self._type = self.coreToChip.getNetType( self._name )
|
||||||
return
|
return
|
||||||
|
|
||||||
def isElem ( self ): return self._isElem
|
def __repr__ ( self ):
|
||||||
|
s = '<IoNet "%s" ext:' % self.coreNet.getName()
|
||||||
|
if self.chipExtNet: s += self.chipExtNet.getName()
|
||||||
|
else: s += 'None'
|
||||||
|
s += ' int:'
|
||||||
|
if self.chipIntNet: s += self.chipIntNet.getName()
|
||||||
|
else: s += 'None'
|
||||||
|
s += '>'
|
||||||
|
return s
|
||||||
|
|
||||||
|
def isElem ( self ): return self._flags & IoNet.IsElem
|
||||||
|
def isEnable ( self ): return self._flags & IoNet.IsEnable
|
||||||
|
def isBidir ( self ): return self._flags & IoNet.IsBidir
|
||||||
|
|
||||||
def isGlobal ( self ): return self.isGlobal( self._name )
|
def isGlobal ( self ): return self.isGlobal( self._name )
|
||||||
|
|
||||||
|
@ -69,25 +85,46 @@ class IoNet ( object ):
|
||||||
@property
|
@property
|
||||||
def coronaNetName ( self ):
|
def coronaNetName ( self ):
|
||||||
s = self._name + '_core'
|
s = self._name + '_core'
|
||||||
if self._isElem: s += '(' + self._index + ')'
|
if self._flags & IoNet.IsElem: s += '(' + self._index + ')'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def padNetName ( self ):
|
def padNetName ( self ):
|
||||||
|
if self._chipExtNetName is not None: return self._chipExtNetName
|
||||||
|
|
||||||
s = self._name
|
s = self._name
|
||||||
if self._isElem: s += '(' + self._index + ')'
|
if self._flags & IoNet.IsElem: s += '(' + self._index + ')'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@padNetName.setter
|
||||||
|
def padNetName ( self, name ): self._chipExtNetName = name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def padInstanceName ( self ):
|
def padInstanceName ( self ):
|
||||||
s = self._name
|
s = self._name
|
||||||
if self._isElem: s += '_' + self._index
|
if self._flags & IoNet.IsElem: s += '_' + self._index
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def setChipExtNetName ( self, name ): self.chipExtNetName = name
|
||||||
|
|
||||||
|
def setEnable ( self, state ):
|
||||||
|
if state == True: self._flags |= IoNet.IsEnable
|
||||||
|
else: self._flags &= ~IoNet.IsEnable
|
||||||
|
return
|
||||||
|
|
||||||
|
def setBidir ( self, state ):
|
||||||
|
if state == True: self._flags |= IoNet.IsBidir
|
||||||
|
else: self._flags &= ~IoNet.IsBidir
|
||||||
|
return
|
||||||
|
|
||||||
def buildNets ( self ):
|
def buildNets ( self ):
|
||||||
self.chipExtNet = Net.create( self.coreToChip.chip, self.padNetName )
|
if self.chipIntNet != None: return
|
||||||
self.chipExtNet.setExternal ( True )
|
|
||||||
self.chipExtNet.setDirection( self.coreNet.getDirection() )
|
if not self.isBidir () \
|
||||||
|
or (not self.isEnable() and self.coreNet.getDirection() == Net.Direction.OUT):
|
||||||
|
self.chipExtNet = Net.create( self.coreToChip.chip, self.padNetName )
|
||||||
|
self.chipExtNet.setExternal ( True )
|
||||||
|
self.chipExtNet.setDirection( self.coreNet.getDirection() )
|
||||||
|
|
||||||
self.chipIntNet = Net.create( self.coreToChip.chip, self.coronaNetName )
|
self.chipIntNet = Net.create( self.coreToChip.chip, self.coronaNetName )
|
||||||
|
|
||||||
|
@ -110,6 +147,110 @@ class IoNet ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Class : "IoPad".
|
||||||
|
|
||||||
|
|
||||||
|
class IoPad ( object ):
|
||||||
|
|
||||||
|
IN = 0x0001
|
||||||
|
OUT = 0x0002
|
||||||
|
BIDIR = 0x0004
|
||||||
|
TRI_OUT = 0x0008
|
||||||
|
UNSUPPORTED = 0x0010
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def directionToStr ( direction ):
|
||||||
|
if direction == IoPad.IN: return "IN"
|
||||||
|
if direction == IoPad.OUT: return "OUT"
|
||||||
|
if direction == IoPad.BIDIR: return "BIDIR"
|
||||||
|
if direction == IoPad.TRI_OUT: return "TRI_OUT"
|
||||||
|
if direction == IoPad.UNSUPPORTED: return "UNSUPPORTED"
|
||||||
|
return "Invalid value"
|
||||||
|
|
||||||
|
|
||||||
|
def __init__ ( self, coreToChip, padInstanceName ):
|
||||||
|
self.coreToChip = coreToChip
|
||||||
|
self.padInstanceName = padInstanceName
|
||||||
|
self.direction = 0
|
||||||
|
self.nets = [ ]
|
||||||
|
self.pads = [ ]
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def __str__ ( self ):
|
||||||
|
s = '<IoPad "%s" ' % self.padInstanceName
|
||||||
|
for ioNet in self.nets:
|
||||||
|
s += ' %s' % ioNet.coreNetName
|
||||||
|
s += '>'
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def addNet ( self, ioNet ):
|
||||||
|
self.nets.append( ioNet )
|
||||||
|
if len(self.nets) == 1:
|
||||||
|
if self.nets[0].coreNet.getDirection() == Net.Direction.IN: self.direction = IoPad.IN
|
||||||
|
elif self.nets[0].coreNet.getDirection() == Net.Direction.OUT: self.direction = IoPad.OUT
|
||||||
|
else:
|
||||||
|
raise ErrorMessage( 1, 'IoPad.addNet(): Unsupported direction %d (%s) for core net "%s" in I/O pad \"%s\".' \
|
||||||
|
% ( self.nets[0].coreNet.getDirection()
|
||||||
|
, netDirectionToStr(self.nets[0].coreNet.getDirection())
|
||||||
|
, self.nets[0].coreNet.getName()
|
||||||
|
, self.padInstanceName ) )
|
||||||
|
elif len(self.nets) == 2:
|
||||||
|
self.direction = IoPad.TRI_OUT
|
||||||
|
elif len(self.nets) == 3:
|
||||||
|
self.direction = IoPad.BIDIR
|
||||||
|
else:
|
||||||
|
message = [ 'IoPad.addNet(): More than three core nets on I/O pad "%s".' % self.padInstanceName ]
|
||||||
|
for ioNet in self.nets:
|
||||||
|
message += [ "%s" % ioNet.coreNet ]
|
||||||
|
raise ErrorMessage( 1, message )
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def createPad ( self ):
|
||||||
|
fromCoreNet = None
|
||||||
|
toCoreNet = None
|
||||||
|
enableNet = None
|
||||||
|
|
||||||
|
for ioNet in self.nets:
|
||||||
|
ioNet.buildNets()
|
||||||
|
if self.direction == IoPad.TRI_OUT:
|
||||||
|
if ioNet.isEnable(): enableNet = ioNet
|
||||||
|
else: fromCoreNet = ioNet
|
||||||
|
elif self.direction == IoPad.BIDIR:
|
||||||
|
if ioNet.coreNet.getDirection() == Net.Direction.IN: toCoreNet = ioNet
|
||||||
|
if ioNet.coreNet.getDirection() == Net.Direction.OUT:
|
||||||
|
if ioNet.isEnable(): enableNet = ioNet
|
||||||
|
else: fromCoreNet = ioNet
|
||||||
|
else:
|
||||||
|
fromCoreNet = ioNet
|
||||||
|
|
||||||
|
if not self.coreToChip.ioPadInfos.has_key(self.direction):
|
||||||
|
raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction %d (%s) for pad "%s".' \
|
||||||
|
% (self.direction
|
||||||
|
,IoPad.directionToStr(self.direction)
|
||||||
|
,self.padInstanceName) )
|
||||||
|
padInfo = self.coreToChip.ioPadInfos[ self.direction ]
|
||||||
|
|
||||||
|
self.pads.append( Instance.create( self.coreToChip.chip
|
||||||
|
, self.padInstanceName
|
||||||
|
, self.coreToChip.getCell(padInfo.name) ) )
|
||||||
|
|
||||||
|
CoreToChip._connect( self.pads[0], fromCoreNet.chipExtNet, padInfo.padNet )
|
||||||
|
CoreToChip._connect( self.pads[0], fromCoreNet.chipIntNet, padInfo.coreNets[0] )
|
||||||
|
|
||||||
|
if toCoreNet: CoreToChip._connect( self.pads[0], toCoreNet.chipIntNet, padInfo.coreNets[-2] )
|
||||||
|
if enableNet: CoreToChip._connect( self.pads[0], enableNet.chipIntNet, padInfo.coreNets[-1] )
|
||||||
|
|
||||||
|
self.coreToChip._connectRing( self.pads[0] )
|
||||||
|
self.coreToChip.chipPads += self.pads
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# Class : "CoreToChip".
|
# Class : "CoreToChip".
|
||||||
|
|
||||||
|
@ -147,8 +288,9 @@ class CoreToChip ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
def __init__ ( self, core ):
|
def __init__ ( self, core ):
|
||||||
|
self.conf = chip.Configuration.loadConfiguration( core )
|
||||||
self.ringNetNames = [ ]
|
self.ringNetNames = [ ]
|
||||||
self.ioPads = { }
|
self.ioPadInfos = { }
|
||||||
self.chipPads = [ ]
|
self.chipPads = [ ]
|
||||||
self.padLib = None
|
self.padLib = None
|
||||||
self.core = core
|
self.core = core
|
||||||
|
@ -156,11 +298,29 @@ class CoreToChip ( object ):
|
||||||
self.corona = None
|
self.corona = None
|
||||||
self.icorona = None
|
self.icorona = None
|
||||||
self.icore = None
|
self.icore = None
|
||||||
|
self._ioNets = { }
|
||||||
self.powerPadCount = 0
|
self.powerPadCount = 0
|
||||||
self.groundPadCount = 0
|
self.groundPadCount = 0
|
||||||
self.clockPadCount = 0
|
self.clockPadCount = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def hasIoNet ( self, netName ):
|
||||||
|
if self._ioNets.has_key(netName): return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def getIoNet ( self, coreNet ):
|
||||||
|
if isinstance(coreNet,str):
|
||||||
|
if self._ioNets.has_key(coreNet): return self._ioNet[ coreNet ]
|
||||||
|
raise ErrorMessage( 1, 'CoreToChip.getIoNet(): Cannot lookup net "%s" by name.' % coreNet )
|
||||||
|
|
||||||
|
if not self._ioNets.has_key(coreNet.getName()):
|
||||||
|
self._ioNets[ coreNet.getName() ] = IoNet( self, coreNet )
|
||||||
|
|
||||||
|
return self._ioNets[ coreNet.getName() ]
|
||||||
|
|
||||||
|
|
||||||
def _connectRing ( self, padInstance ):
|
def _connectRing ( self, padInstance ):
|
||||||
for ringNetName in self.ringNetNames:
|
for ringNetName in self.ringNetNames:
|
||||||
if isinstance(ringNetName,tuple):
|
if isinstance(ringNetName,tuple):
|
||||||
|
@ -179,12 +339,13 @@ class CoreToChip ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _buildStandardPad ( self, ioNet ):
|
def _buildStandardPad ( self, ioNet ):
|
||||||
if not self.ioPads.has_key(ioNet.coreNet.getDirection()):
|
if not self.ioPadInfos.has_key(ioNet.coreNet.getDirection()):
|
||||||
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d for core net "%s".' \
|
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \
|
||||||
% (netDirectionToStr(ioNet.coreNet.getDirection())
|
% (ioNet.coreNet.getDirection()
|
||||||
|
,netDirectionToStr(ioNet.coreNet.getDirection())
|
||||||
,ioNet.coreNet.getName()) )
|
,ioNet.coreNet.getName()) )
|
||||||
|
|
||||||
padInfo = self.ioPads[ ioNet.coreNet.getDirection() ]
|
padInfo = self.ioPadInfos[ ioNet.coreNet.getDirection() ]
|
||||||
|
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
ioNet.pads.append( Instance.create( self.chip
|
||||||
, ioNet.padInstanceName
|
, ioNet.padInstanceName
|
||||||
|
@ -204,29 +365,69 @@ class CoreToChip ( object ):
|
||||||
def _buildClockPads ( self, ioNet ):
|
def _buildClockPads ( self, ioNet ):
|
||||||
raise ErrorMessage( 1, 'coreToChip._buildClockPads(): This method must be overloaded.' )
|
raise ErrorMessage( 1, 'coreToChip._buildClockPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
def buildChip ( self, chipName ):
|
def buildChip ( self ):
|
||||||
af = AllianceFramework.get()
|
af = AllianceFramework.get()
|
||||||
|
|
||||||
UpdateSession.open()
|
UpdateSession.open()
|
||||||
|
|
||||||
self.chip = af.createCell( chipName )
|
self.chip = af.createCell( self.conf.chipName )
|
||||||
self.corona = af.createCell( 'corona' )
|
self.corona = af.createCell( 'corona' )
|
||||||
self.icore = Instance.create( self.corona, 'core' , self.core )
|
self.icore = Instance.create( self.corona, 'core' , self.core )
|
||||||
self.icorona = Instance.create( self.chip , 'corona', self.corona )
|
self.icorona = Instance.create( self.chip , 'corona', self.corona )
|
||||||
|
|
||||||
self._buildRingNets()
|
self._buildRingNets()
|
||||||
|
|
||||||
|
ioPads = [ ]
|
||||||
clockIoNets = [ ]
|
clockIoNets = [ ]
|
||||||
|
|
||||||
|
for padConf in self.conf.padInstances:
|
||||||
|
padConf.udata = IoPad( self, padConf.padInstanceName )
|
||||||
|
|
||||||
|
for netName in padConf.nets:
|
||||||
|
coreNet = self.core.getNet(netName)
|
||||||
|
if not coreNet:
|
||||||
|
raise ErrorMessage( 1, 'CoreToChip.buildChip(): "%s" doesn\'t have a "%s" net.'
|
||||||
|
% (self.core.getName(),netName) )
|
||||||
|
ioNet = self.getIoNet( coreNet )
|
||||||
|
ioNet.padNetName = padConf.padNetName
|
||||||
|
|
||||||
|
if padConf.isBidir() or padConf.isTristate():
|
||||||
|
ioNet.setBidir( True )
|
||||||
|
if coreNet.getName() == padConf.enableNet:
|
||||||
|
ioNet.setEnable( True )
|
||||||
|
|
||||||
|
padConf.udata.addNet( ioNet )
|
||||||
|
ioPads.append( padConf )
|
||||||
|
|
||||||
for coreNet in self.core.getNets():
|
for coreNet in self.core.getNets():
|
||||||
if not coreNet.isExternal(): continue
|
if not coreNet.isExternal(): continue
|
||||||
|
|
||||||
ioNet = IoNet( self, coreNet )
|
# Case of special nets (power, ground & clocks).
|
||||||
ioNet.buildNets()
|
if coreNet.isPower():
|
||||||
|
self._buildPowerPads( IoNet( self, coreNet ) )
|
||||||
|
continue
|
||||||
|
elif coreNet.isGround():
|
||||||
|
self._buildGroundPads( IoNet( self, coreNet ) )
|
||||||
|
continue
|
||||||
|
elif coreNet.isClock():
|
||||||
|
clockIoNets.append( IoNet( self, coreNet ) )
|
||||||
|
continue
|
||||||
|
|
||||||
if coreNet.isPower(): self._buildPowerPads ( ioNet )
|
if self.hasIoNet(coreNet.getName()):
|
||||||
elif coreNet.isGround(): self._buildGroundPads ( ioNet )
|
continue
|
||||||
elif coreNet.isClock(): clockIoNets.append( ioNet )
|
|
||||||
else: self._buildStandardPad( ioNet )
|
# Remaining non configured Standard I/O pads.
|
||||||
|
ioNet = IoNet( self, coreNet )
|
||||||
|
directPad = chip.Configuration.IoPadConf( [ ioNet.padInstanceName
|
||||||
|
, ioNet.padNetName
|
||||||
|
, ioNet.coreNetName
|
||||||
|
] )
|
||||||
|
directPad.udata = IoPad( self, directPad.padInstanceName )
|
||||||
|
directPad.udata.addNet( ioNet )
|
||||||
|
ioPads.append( directPad )
|
||||||
|
|
||||||
|
for ioPad in ioPads:
|
||||||
|
ioPad.udata.createPad()
|
||||||
|
|
||||||
for clockIoNet in clockIoNets:
|
for clockIoNet in clockIoNets:
|
||||||
self._buildClockPads( clockIoNet )
|
self._buildClockPads( clockIoNet )
|
||||||
|
|
|
@ -26,6 +26,7 @@ import Viewer
|
||||||
from CRL import Catalog
|
from CRL import Catalog
|
||||||
from CRL import AllianceFramework
|
from CRL import AllianceFramework
|
||||||
from helpers.io import ErrorMessage
|
from helpers.io import ErrorMessage
|
||||||
|
from core2chip.CoreToChip import IoPad
|
||||||
from core2chip.CoreToChip import CoreToChip
|
from core2chip.CoreToChip import CoreToChip
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,8 +35,10 @@ class cmos ( CoreToChip ):
|
||||||
def __init__ ( self, core ):
|
def __init__ ( self, core ):
|
||||||
CoreToChip.__init__ ( self, core )
|
CoreToChip.__init__ ( self, core )
|
||||||
self.ringNetNames = [ 'vsse', 'vssi', 'vdde', 'vddi', ('cki', 'ck') ]
|
self.ringNetNames = [ 'vsse', 'vssi', 'vdde', 'vddi', ('cki', 'ck') ]
|
||||||
self.ioPads = { Net.Direction.IN : CoreToChip.IoPadInfo( 'pi_px', 'pad', ['t',] )
|
self.ioPadInfos = { IoPad.IN : CoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] )
|
||||||
, Net.Direction.OUT : CoreToChip.IoPadInfo( 'po_px', 'pad', ['i',] )
|
, IoPad.OUT : CoreToChip.IoPadInfo( 'po_px' , 'pad', ['i',] )
|
||||||
|
, IoPad.TRI_OUT : CoreToChip.IoPadInfo( 'pot_px' , 'pad', ['i', 'b' ] )
|
||||||
|
, IoPad.BIDIR : CoreToChip.IoPadInfo( 'piot_px', 'pad', ['i', 't', 'b' ] )
|
||||||
}
|
}
|
||||||
self._getPadLib()
|
self._getPadLib()
|
||||||
return
|
return
|
||||||
|
@ -68,6 +71,7 @@ class cmos ( CoreToChip ):
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
def _buildGroundPads ( self, ioNet ):
|
def _buildGroundPads ( self, ioNet ):
|
||||||
|
ioNet.buildNets()
|
||||||
vssi = self.chip.getNet( 'vssi' )
|
vssi = self.chip.getNet( 'vssi' )
|
||||||
vssi.setExternal( True )
|
vssi.setExternal( True )
|
||||||
vssi.setGlobal ( True )
|
vssi.setGlobal ( True )
|
||||||
|
@ -82,22 +86,24 @@ class cmos ( CoreToChip ):
|
||||||
vsse.merge( ioNet.chipExtNet )
|
vsse.merge( ioNet.chipExtNet )
|
||||||
ioNet.chipExtNet = vsse
|
ioNet.chipExtNet = vsse
|
||||||
|
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
pads = []
|
||||||
, ioNet.padInstanceName + '_i_%d' % self.groundPadCount
|
pads.append( Instance.create( self.chip
|
||||||
, self.getCell('pvssick_px') ) )
|
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.groundPadCount
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
, self.getCell('pvssick_px') ) )
|
||||||
, ioNet.padInstanceName + '_o_%d' % self.groundPadCount
|
pads.append( Instance.create( self.chip
|
||||||
, self.getCell('pvsseck_px') ) )
|
, 'p_' + ioNet.padInstanceName + 'eck_%d' % self.groundPadCount
|
||||||
|
, self.getCell('pvsseck_px') ) )
|
||||||
|
|
||||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, 'vssi' )
|
CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vssi' )
|
||||||
CoreToChip._connect( ioNet.pads[1], ioNet.chipExtNet, 'vsse' )
|
CoreToChip._connect( pads[1], ioNet.chipExtNet, 'vsse' )
|
||||||
|
|
||||||
for pad in ioNet.pads: self._connectRing( pad )
|
for pad in pads: self._connectRing( pad )
|
||||||
self.groundPadCount += 1
|
self.groundPadCount += 1
|
||||||
self.chipPads += ioNet.pads
|
self.chipPads += pads
|
||||||
return
|
return
|
||||||
|
|
||||||
def _buildPowerPads ( self, ioNet ):
|
def _buildPowerPads ( self, ioNet ):
|
||||||
|
ioNet.buildNets()
|
||||||
vddi = self.chip.getNet( 'vddi' )
|
vddi = self.chip.getNet( 'vddi' )
|
||||||
vddi.setExternal( True )
|
vddi.setExternal( True )
|
||||||
vddi.setGlobal ( True )
|
vddi.setGlobal ( True )
|
||||||
|
@ -112,31 +118,34 @@ class cmos ( CoreToChip ):
|
||||||
vdde.merge( ioNet.chipExtNet )
|
vdde.merge( ioNet.chipExtNet )
|
||||||
ioNet.chipExtNet = vdde
|
ioNet.chipExtNet = vdde
|
||||||
|
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
pads = [ ]
|
||||||
, ioNet.padInstanceName + '_i_%d' % self.powerPadCount
|
pads.append( Instance.create( self.chip
|
||||||
, self.getCell('pvddick_px') ) )
|
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.powerPadCount
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
, self.getCell('pvddick_px') ) )
|
||||||
, ioNet.padInstanceName + '_o_%d' % self.powerPadCount
|
pads.append( Instance.create( self.chip
|
||||||
, self.getCell('pvddeck_px') ) )
|
, 'p_' + ioNet.padInstanceName + 'eck_%d' % self.powerPadCount
|
||||||
|
, self.getCell('pvddeck_px') ) )
|
||||||
|
|
||||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, 'vddi' )
|
CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vddi' )
|
||||||
CoreToChip._connect( ioNet.pads[1], ioNet.chipExtNet, 'vdde' )
|
CoreToChip._connect( pads[1], ioNet.chipExtNet, 'vdde' )
|
||||||
|
|
||||||
for pad in ioNet.pads: self._connectRing( pad )
|
for pad in pads: self._connectRing( pad )
|
||||||
self.powerPadCount += 1
|
self.powerPadCount += 1
|
||||||
self.chipPads += ioNet.pads
|
self.chipPads += pads
|
||||||
return
|
return
|
||||||
|
|
||||||
def _buildClockPads ( self, ioNet ):
|
def _buildClockPads ( self, ioNet ):
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
ioNet.buildNets()
|
||||||
, ioNet.padInstanceName + '_%d' % self.clockPadCount
|
pads = [ ]
|
||||||
, self.getCell('pck_px') ) )
|
pads.append( Instance.create( self.chip
|
||||||
|
, 'p_' + ioNet.padInstanceName + '_%d' % self.clockPadCount
|
||||||
|
, self.getCell('pck_px') ) )
|
||||||
|
|
||||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipExtNet, 'pad' )
|
CoreToChip._connect( pads[0], ioNet.chipExtNet, 'pad' )
|
||||||
|
|
||||||
for pad in ioNet.pads: self._connectRing( pad )
|
for pad in pads: self._connectRing( pad )
|
||||||
self.clockPadCount += 1
|
self.clockPadCount += 1
|
||||||
self.chipPads += ioNet.pads
|
self.chipPads += pads
|
||||||
|
|
||||||
p = re.compile( r'pv[ds]{2}[ei]ck_px' )
|
p = re.compile( r'pv[ds]{2}[ei]ck_px' )
|
||||||
for pad in self.chipPads:
|
for pad in self.chipPads:
|
||||||
|
|
Loading…
Reference in New Issue