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 )
conf = chip.Configuration.loadConfiguration( cell, editor )
conf.chipValidate()
if not conf.validated: return False
placeChip = chip.Chip.PlaceRoute( conf )

View File

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

View File

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

View File

@ -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,31 +563,31 @@ 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()
self.cell = cell
@ -523,14 +605,13 @@ 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._loadIoPadGauge( chipConfigDict )
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' )
@ -538,12 +619,17 @@ class ChipConf ( object ):
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()
@ -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 )

View File

@ -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._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.
self.pads = [ ]
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,22 +85,43 @@ 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 ):
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() )
@ -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 )

View File

@ -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
pads = []
pads.append( Instance.create( self.chip
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.groundPadCount
, self.getCell('pvssick_px') ) )
ioNet.pads.append( Instance.create( self.chip
, ioNet.padInstanceName + '_o_%d' % self.groundPadCount
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
pads = [ ]
pads.append( Instance.create( self.chip
, 'p_' + ioNet.padInstanceName + 'ick_%d' % self.powerPadCount
, self.getCell('pvddick_px') ) )
ioNet.pads.append( Instance.create( self.chip
, ioNet.padInstanceName + '_o_%d' % self.powerPadCount
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
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: