From 86c4e9cb1740f1ade59d3e0a4fdef4dbd2af9e02 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Thu, 8 Aug 2019 00:57:19 +0200 Subject: [PATCH] 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. --- cumulus/src/plugins/ChipPlace.py | 1 + cumulus/src/plugins/ChipRoute.py | 1 + cumulus/src/plugins/CoreToChip_cmos.py | 2 +- cumulus/src/plugins/chip/Configuration.py | 199 +++++++++++---- cumulus/src/plugins/core2chip/CoreToChip.py | 257 +++++++++++++++++--- cumulus/src/plugins/core2chip/cmos.py | 65 ++--- 6 files changed, 421 insertions(+), 104 deletions(-) diff --git a/cumulus/src/plugins/ChipPlace.py b/cumulus/src/plugins/ChipPlace.py index df293ea2..8b3814e7 100644 --- a/cumulus/src/plugins/ChipPlace.py +++ b/cumulus/src/plugins/ChipPlace.py @@ -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 ) diff --git a/cumulus/src/plugins/ChipRoute.py b/cumulus/src/plugins/ChipRoute.py index 5590f462..e39d112a 100644 --- a/cumulus/src/plugins/ChipRoute.py +++ b/cumulus/src/plugins/ChipRoute.py @@ -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 ) diff --git a/cumulus/src/plugins/CoreToChip_cmos.py b/cumulus/src/plugins/CoreToChip_cmos.py index 168a030c..edcf7e9b 100644 --- a/cumulus/src/plugins/CoreToChip_cmos.py +++ b/cumulus/src/plugins/CoreToChip_cmos.py @@ -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 ) diff --git a/cumulus/src/plugins/chip/Configuration.py b/cumulus/src/plugins/chip/Configuration.py index 3d953597..cbcd7b08 100644 --- a/cumulus/src/plugins/chip/Configuration.py +++ b/cumulus/src/plugins/chip/Configuration.py @@ -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 = ' 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 ) diff --git a/cumulus/src/plugins/core2chip/CoreToChip.py b/cumulus/src/plugins/core2chip/CoreToChip.py index a4667b4b..fe5f3c91 100644 --- a/cumulus/src/plugins/core2chip/CoreToChip.py +++ b/cumulus/src/plugins/core2chip/CoreToChip.py @@ -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[^(]*)\((?P[\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 = '