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 )
|
||||
|
||||
conf = chip.Configuration.loadConfiguration( cell, editor )
|
||||
conf.chipValidate()
|
||||
if not conf.validated: return False
|
||||
|
||||
placeChip = chip.Chip.PlaceRoute( conf )
|
||||
|
|
|
@ -68,6 +68,7 @@ def ScriptMain ( **kw ):
|
|||
|
||||
cell, editor = plugins.kwParseMain( **kw )
|
||||
conf = chip.Configuration.loadConfiguration( cell, editor )
|
||||
conf.chipValidate()
|
||||
if not conf.validated: return False
|
||||
|
||||
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.' )
|
||||
|
||||
chip_cmos = core2chip.cmos.cmos( cell )
|
||||
chip_cmos.buildChip( 'chip' )
|
||||
chip_cmos.buildChip()
|
||||
|
||||
if editor: editor.setCell( chip_cmos.chip )
|
||||
|
||||
|
|
|
@ -108,6 +108,82 @@ def destroyNetComponents ( net ):
|
|||
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".
|
||||
|
||||
|
@ -448,9 +524,15 @@ class ChipConf ( object ):
|
|||
return useClockTree
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _readChipName( chipConfigDict ):
|
||||
if chipConfigDict.has_key('chip.name'): return chipConfigDict['chip.name']
|
||||
return 'chip'
|
||||
|
||||
|
||||
def _loadIoPadGauge ( self, chipConfigDict ):
|
||||
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
|
||||
self.gaugeConf._loadIoPadGauge( chipConfigDict['pads.ioPadGauge'] )
|
||||
return
|
||||
|
@ -481,30 +563,30 @@ class ChipConf ( object ):
|
|||
% (i,keyword) )
|
||||
continue
|
||||
|
||||
instance = self.cell.getInstance( 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 ] )
|
||||
padList.append( [ position, instanceName ] )
|
||||
|
||||
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 ):
|
||||
trace( 550, '\tONE LAMBDA = %s\n' % DbU.getValueString(DbU.fromLambda(1.0)) )
|
||||
|
||||
if not isinstance(chipConfigDict,dict):
|
||||
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.gaugeConf = GaugeConf()
|
||||
|
@ -523,32 +605,36 @@ class ChipConf ( object ):
|
|||
self.coronaVss = None
|
||||
self.coronaCk = None
|
||||
self.blockageNet = None
|
||||
|
||||
if self.chipMode:
|
||||
self._loadIoPadGauge( chipConfigDict )
|
||||
|
||||
self.coronas = []
|
||||
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 )
|
||||
|
||||
self._loadIoPadGauge( 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.checkCorona()
|
||||
self.computeChipSize()
|
||||
#self.checkChipSize()
|
||||
self.findPowerAndClockNets()
|
||||
self.padsHavePosition = False
|
||||
self.padInstances = self._readPadInstances( chipConfigDict )
|
||||
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 )
|
||||
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
|
||||
|
||||
|
||||
|
@ -857,24 +943,42 @@ class ChipConf ( object ):
|
|||
|
||||
def checkPads ( self ):
|
||||
|
||||
def contains ( padList, pad ):
|
||||
for padPair in padList:
|
||||
if padPair[1] == pad: return True
|
||||
def contains ( padList, side, padInstance ):
|
||||
for i in range(len(padList)):
|
||||
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
|
||||
|
||||
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()
|
||||
cellPads = []
|
||||
for instance in self.cell.getInstances():
|
||||
if contains(self.southPads,instance): continue
|
||||
if contains(self.northPads,instance): continue
|
||||
if contains(self.eastPads ,instance): continue
|
||||
if contains(self.westPads ,instance): continue
|
||||
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.gaugeConf.getIoPadHeight()):
|
||||
raise ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % 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 "%s" have more than one corona:' % self.cell.getName() ]
|
||||
for i in range(len(self.coronas)):
|
||||
|
@ -1117,7 +1221,8 @@ class ChipConf ( object ):
|
|||
def loadConfiguration ( cell, viewer=None ):
|
||||
sys.path.append( os.getcwd() )
|
||||
|
||||
confFile = cell.getName()+'_ioring'
|
||||
#confFile = cell.getName()+'_ioring'
|
||||
confFile = 'ioring'
|
||||
if not os.path.isfile(confFile+'.py'):
|
||||
raise ErrorMessage( 1, 'ChipPlugin configuration file <%s.py> is missing.' % confFile )
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ from CRL import Catalog
|
|||
from CRL import AllianceFramework
|
||||
from helpers import netDirectionToStr
|
||||
from helpers.io import ErrorMessage
|
||||
import chip.Chip
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
@ -30,30 +31,45 @@ from helpers.io import ErrorMessage
|
|||
|
||||
class IoNet ( object ):
|
||||
|
||||
IsElem = 0x0001
|
||||
IsEnable = 0x0002
|
||||
IsBidir = 0x0004
|
||||
reVHDLVector = re.compile( r'(?P<name>[^(]*)\((?P<index>[\d]+)\)$' )
|
||||
|
||||
def __init__ ( self, coreToChip, coreNet ):
|
||||
self.coreToChip = coreToChip
|
||||
self.coreNet = coreNet
|
||||
self.coronaNet = None # Corona net going from core to corona.
|
||||
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.
|
||||
self.pads = [ ]
|
||||
self.coreToChip = coreToChip
|
||||
self._flags = 0
|
||||
self._chipExtNetName = None # In the case of bidir pad, force external net name.
|
||||
self.coreNet = coreNet
|
||||
self.coronaNet = None # Corona net going from core to corona.
|
||||
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() )
|
||||
if m:
|
||||
self._isElem = True
|
||||
self._flags |= IoNet.IsElem
|
||||
self._name = m.group('name')
|
||||
self._index = m.group('index')
|
||||
else:
|
||||
self._isElem = False
|
||||
self._name = self.coreNet.getName()
|
||||
self._index = 0
|
||||
|
||||
self._type = self.coreToChip.getNetType( self._name )
|
||||
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 )
|
||||
|
||||
|
@ -69,25 +85,46 @@ class IoNet ( object ):
|
|||
@property
|
||||
def coronaNetName ( self ):
|
||||
s = self._name + '_core'
|
||||
if self._isElem: s += '(' + self._index + ')'
|
||||
if self._flags & IoNet.IsElem: s += '(' + self._index + ')'
|
||||
return s
|
||||
|
||||
@property
|
||||
def padNetName ( self ):
|
||||
if self._chipExtNetName is not None: return self._chipExtNetName
|
||||
|
||||
s = self._name
|
||||
if self._isElem: s += '(' + self._index + ')'
|
||||
if self._flags & IoNet.IsElem: s += '(' + self._index + ')'
|
||||
return s
|
||||
|
||||
@padNetName.setter
|
||||
def padNetName ( self, name ): self._chipExtNetName = name
|
||||
|
||||
@property
|
||||
def padInstanceName ( self ):
|
||||
s = self._name
|
||||
if self._isElem: s += '_' + self._index
|
||||
if self._flags & IoNet.IsElem: s += '_' + self._index
|
||||
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 ):
|
||||
self.chipExtNet = Net.create( self.coreToChip.chip, self.padNetName )
|
||||
self.chipExtNet.setExternal ( True )
|
||||
self.chipExtNet.setDirection( self.coreNet.getDirection() )
|
||||
if self.chipIntNet != None: return
|
||||
|
||||
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 )
|
||||
|
||||
|
@ -110,6 +147,110 @@ class IoNet ( object ):
|
|||
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".
|
||||
|
||||
|
@ -147,8 +288,9 @@ class CoreToChip ( object ):
|
|||
return
|
||||
|
||||
def __init__ ( self, core ):
|
||||
self.conf = chip.Configuration.loadConfiguration( core )
|
||||
self.ringNetNames = [ ]
|
||||
self.ioPads = { }
|
||||
self.ioPadInfos = { }
|
||||
self.chipPads = [ ]
|
||||
self.padLib = None
|
||||
self.core = core
|
||||
|
@ -156,11 +298,29 @@ class CoreToChip ( object ):
|
|||
self.corona = None
|
||||
self.icorona = None
|
||||
self.icore = None
|
||||
self._ioNets = { }
|
||||
self.powerPadCount = 0
|
||||
self.groundPadCount = 0
|
||||
self.clockPadCount = 0
|
||||
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 ):
|
||||
for ringNetName in self.ringNetNames:
|
||||
if isinstance(ringNetName,tuple):
|
||||
|
@ -179,12 +339,13 @@ class CoreToChip ( object ):
|
|||
return
|
||||
|
||||
def _buildStandardPad ( self, ioNet ):
|
||||
if not self.ioPads.has_key(ioNet.coreNet.getDirection()):
|
||||
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d for core net "%s".' \
|
||||
% (netDirectionToStr(ioNet.coreNet.getDirection())
|
||||
if not self.ioPadInfos.has_key(ioNet.coreNet.getDirection()):
|
||||
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \
|
||||
% (ioNet.coreNet.getDirection()
|
||||
,netDirectionToStr(ioNet.coreNet.getDirection())
|
||||
,ioNet.coreNet.getName()) )
|
||||
|
||||
padInfo = self.ioPads[ ioNet.coreNet.getDirection() ]
|
||||
padInfo = self.ioPadInfos[ ioNet.coreNet.getDirection() ]
|
||||
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName
|
||||
|
@ -204,29 +365,69 @@ class CoreToChip ( object ):
|
|||
def _buildClockPads ( self, ioNet ):
|
||||
raise ErrorMessage( 1, 'coreToChip._buildClockPads(): This method must be overloaded.' )
|
||||
|
||||
def buildChip ( self, chipName ):
|
||||
def buildChip ( self ):
|
||||
af = AllianceFramework.get()
|
||||
|
||||
UpdateSession.open()
|
||||
|
||||
self.chip = af.createCell( chipName )
|
||||
self.chip = af.createCell( self.conf.chipName )
|
||||
self.corona = af.createCell( 'corona' )
|
||||
self.icore = Instance.create( self.corona, 'core' , self.core )
|
||||
self.icorona = Instance.create( self.chip , 'corona', self.corona )
|
||||
|
||||
self._buildRingNets()
|
||||
|
||||
ioPads = [ ]
|
||||
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():
|
||||
if not coreNet.isExternal(): continue
|
||||
|
||||
ioNet = IoNet( self, coreNet )
|
||||
ioNet.buildNets()
|
||||
# Case of special nets (power, ground & clocks).
|
||||
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 )
|
||||
elif coreNet.isGround(): self._buildGroundPads ( ioNet )
|
||||
elif coreNet.isClock(): clockIoNets.append( ioNet )
|
||||
else: self._buildStandardPad( ioNet )
|
||||
if self.hasIoNet(coreNet.getName()):
|
||||
continue
|
||||
|
||||
# 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:
|
||||
self._buildClockPads( clockIoNet )
|
||||
|
|
|
@ -26,6 +26,7 @@ import Viewer
|
|||
from CRL import Catalog
|
||||
from CRL import AllianceFramework
|
||||
from helpers.io import ErrorMessage
|
||||
from core2chip.CoreToChip import IoPad
|
||||
from core2chip.CoreToChip import CoreToChip
|
||||
|
||||
|
||||
|
@ -34,8 +35,10 @@ class cmos ( CoreToChip ):
|
|||
def __init__ ( self, core ):
|
||||
CoreToChip.__init__ ( self, core )
|
||||
self.ringNetNames = [ 'vsse', 'vssi', 'vdde', 'vddi', ('cki', 'ck') ]
|
||||
self.ioPads = { Net.Direction.IN : CoreToChip.IoPadInfo( 'pi_px', 'pad', ['t',] )
|
||||
, Net.Direction.OUT : CoreToChip.IoPadInfo( 'po_px', 'pad', ['i',] )
|
||||
self.ioPadInfos = { IoPad.IN : CoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] )
|
||||
, 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()
|
||||
return
|
||||
|
@ -68,6 +71,7 @@ class cmos ( CoreToChip ):
|
|||
return cell
|
||||
|
||||
def _buildGroundPads ( self, ioNet ):
|
||||
ioNet.buildNets()
|
||||
vssi = self.chip.getNet( 'vssi' )
|
||||
vssi.setExternal( True )
|
||||
vssi.setGlobal ( True )
|
||||
|
@ -82,22 +86,24 @@ class cmos ( CoreToChip ):
|
|||
vsse.merge( ioNet.chipExtNet )
|
||||
ioNet.chipExtNet = vsse
|
||||
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName + '_i_%d' % self.groundPadCount
|
||||
, self.getCell('pvssick_px') ) )
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName + '_o_%d' % self.groundPadCount
|
||||
, self.getCell('pvsseck_px') ) )
|
||||
pads = []
|
||||
pads.append( Instance.create( self.chip
|
||||
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.groundPadCount
|
||||
, self.getCell('pvssick_px') ) )
|
||||
pads.append( Instance.create( self.chip
|
||||
, 'p_' + ioNet.padInstanceName + 'eck_%d' % self.groundPadCount
|
||||
, self.getCell('pvsseck_px') ) )
|
||||
|
||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, 'vssi' )
|
||||
CoreToChip._connect( ioNet.pads[1], ioNet.chipExtNet, 'vsse' )
|
||||
CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vssi' )
|
||||
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.chipPads += ioNet.pads
|
||||
self.chipPads += pads
|
||||
return
|
||||
|
||||
def _buildPowerPads ( self, ioNet ):
|
||||
ioNet.buildNets()
|
||||
vddi = self.chip.getNet( 'vddi' )
|
||||
vddi.setExternal( True )
|
||||
vddi.setGlobal ( True )
|
||||
|
@ -112,31 +118,34 @@ class cmos ( CoreToChip ):
|
|||
vdde.merge( ioNet.chipExtNet )
|
||||
ioNet.chipExtNet = vdde
|
||||
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName + '_i_%d' % self.powerPadCount
|
||||
, self.getCell('pvddick_px') ) )
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName + '_o_%d' % self.powerPadCount
|
||||
, self.getCell('pvddeck_px') ) )
|
||||
pads = [ ]
|
||||
pads.append( Instance.create( self.chip
|
||||
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.powerPadCount
|
||||
, self.getCell('pvddick_px') ) )
|
||||
pads.append( Instance.create( self.chip
|
||||
, 'p_' + ioNet.padInstanceName + 'eck_%d' % self.powerPadCount
|
||||
, self.getCell('pvddeck_px') ) )
|
||||
|
||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, 'vddi' )
|
||||
CoreToChip._connect( ioNet.pads[1], ioNet.chipExtNet, 'vdde' )
|
||||
CoreToChip._connect( pads[0], ioNet.chipIntNet, 'vddi' )
|
||||
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.chipPads += ioNet.pads
|
||||
self.chipPads += pads
|
||||
return
|
||||
|
||||
def _buildClockPads ( self, ioNet ):
|
||||
ioNet.pads.append( Instance.create( self.chip
|
||||
, ioNet.padInstanceName + '_%d' % self.clockPadCount
|
||||
, self.getCell('pck_px') ) )
|
||||
ioNet.buildNets()
|
||||
pads = [ ]
|
||||
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.chipPads += ioNet.pads
|
||||
self.chipPads += pads
|
||||
|
||||
p = re.compile( r'pv[ds]{2}[ei]ck_px' )
|
||||
for pad in self.chipPads:
|
||||
|
|
Loading…
Reference in New Issue