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:
Jean-Paul Chaput 2019-08-08 00:57:19 +02:00
parent acc3a38f60
commit 86c4e9cb17
6 changed files with 421 additions and 104 deletions

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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: