Change SkyWater130 Caravel harness connecting strategy.
* Change: In cumulus/plugins/core2chip, instead of the user providing an explicit mapping towards the harness I/O pins, we expect that the core block must have I/O pins with names matching thoses of the harness. That way, connections are automatically made. * Change: In cumulus/plugins/block/htree, if the root signal of the H-Tree is a bit from a vector (like "io_in(0)"), then remove the vector index notation on all the stem name of all the sub-nets. Done by the unbitify() function: "io_in(0)" => "io_in_bit0".
This commit is contained in:
parent
76d468f6d5
commit
ae1f08f039
|
@ -661,7 +661,8 @@ class IoPadConf ( object ):
|
|||
reSpecialPads = re.compile( r'^(?P<type>.+)_(?P<index>[\d+])$' )
|
||||
m = reSpecialPads.match( self.instanceName )
|
||||
else:
|
||||
self.flags |= IoPadConf.ALL_POWER
|
||||
if self.instanceName is not None:
|
||||
self.flags |= IoPadConf.ALL_POWER
|
||||
if m:
|
||||
self.index = m.group('index')
|
||||
if m.group('type') == 'allpower': self.flags |= IoPadConf.ALL_POWER
|
||||
|
@ -771,6 +772,8 @@ class ChipConf ( object ):
|
|||
if attr == 'ioPadGauge' and value is not None:
|
||||
self.blockConf._loadIoPadGauge( value )
|
||||
|
||||
def ioPadsCount ( self ): return len(self.padInstances)
|
||||
|
||||
def addIoPad ( self, spec, specNb ):
|
||||
"""
|
||||
Add an I/O pad specification. The spec argument must be of the form:
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import sys
|
||||
import os.path
|
||||
import re
|
||||
import Cfg
|
||||
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
|
||||
Path, Layer, Occurrence, Net, HyperNet, \
|
||||
|
@ -31,6 +32,16 @@ from plugins.alpha.block.configuration import GaugeConf
|
|||
from plugins.alpha.block.spares import Spares
|
||||
|
||||
|
||||
def unbitify ( rawName ):
|
||||
"""
|
||||
Remove the bit indexation from the net name, if any.
|
||||
"""
|
||||
p = re.compile( r'(?P<name>.+)\((?P<index>\d+)\)' )
|
||||
m = p.match( rawName )
|
||||
if not m: return rawName
|
||||
return '{}_bit{}'.format( m.group('name'), m.group('index') )
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Class : "htree.HTree".
|
||||
|
||||
|
@ -223,7 +234,7 @@ class HTree ( object ):
|
|||
buffers of the leafs of the QuadTree.
|
||||
"""
|
||||
qt = self.spares.quadTree
|
||||
qt.bufferTag = self.treeNet.getName()
|
||||
qt.bufferTag = unbitify( self.treeNet.getName() )
|
||||
qt.runselect()
|
||||
qt.rselectBuffer( self.treeIndex
|
||||
, self.treeIndex
|
||||
|
@ -239,7 +250,7 @@ class HTree ( object ):
|
|||
"""
|
||||
bufferConf = self.spares.conf.bufferConf
|
||||
quadTree = self.spares.quadTree
|
||||
quadTree.bufferTag = self.treeNet.getName()
|
||||
quadTree.bufferTag = unbitify( self.treeNet.getName() )
|
||||
quadTree.runselect()
|
||||
quadTree.rselectBuffer( self.treeIndex, self.treeIndex, self.flags)
|
||||
with UpdateSession():
|
||||
|
|
|
@ -574,7 +574,7 @@ class ChipConf ( BlockConf ):
|
|||
net = self.corona.getNet( masterNet.getName() )
|
||||
if not net:
|
||||
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Missing global net "{}" at corona level.' \
|
||||
.format(asterNet.getName()) )
|
||||
.format(masterNet.getName()) )
|
||||
self._validated = False
|
||||
continue
|
||||
if netType == Net.Type.GROUND:
|
||||
|
|
|
@ -57,7 +57,7 @@ from plugins.checks import oneDriver
|
|||
from plugins.alpha.utils import getPlugByName
|
||||
from plugins.alpha.block.block import Block
|
||||
from plugins.alpha.block.configuration import BlockConf, IoPadConf, ConstantsConf
|
||||
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Class : "IoNet".
|
||||
|
@ -155,7 +155,10 @@ class IoNet ( object ):
|
|||
@property
|
||||
def chipExtNetName ( self ):
|
||||
if self._chipExtNetName is not None: return self._chipExtNetName
|
||||
if self._flags & IoNet.IsEnable: return 'None'
|
||||
if self._flags & IoNet.IsEnable:
|
||||
if self.coreToChip.useHarness():
|
||||
return 'io_oeb({})'.format( self._index )
|
||||
return 'None'
|
||||
if self.chipExtNet: return self.chipExtNet.getName()
|
||||
s = self._name
|
||||
if self._flags & IoNet.IsElem: s += '({})'.format(self._index)
|
||||
|
@ -209,7 +212,7 @@ class IoNet ( object ):
|
|||
self.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName )
|
||||
self.chipIntNet = self.chipExtNet
|
||||
if not self.chipExtNet:
|
||||
raise ErrorMessage( 1, 'IoNet.buildNets(): Not harness net "{}" to connect core net "{}".' \
|
||||
raise ErrorMessage( 1, 'IoNet.buildNets(): No harness net "{}" to connect core net "{}".' \
|
||||
.format( self.chipExtNetName, self.coreNet.getName() ))
|
||||
# Chip "internal" net, connect Corona instance net to I/O inside the chip.
|
||||
if not self.chipIntNet:
|
||||
|
@ -285,7 +288,7 @@ class IoPad ( object ):
|
|||
def __str__ ( self ):
|
||||
s = '<IoPad "{}" '.format(self.padInstanceName)
|
||||
for ioNet in self.nets:
|
||||
s += ' {}'.format(ioNet.coreNetName)
|
||||
s += ' "{}" <-> "{}"'.format(ioNet.coreNetName,ioNet.chipExtNetName)
|
||||
s += ' direction={}'.format(self.direction)
|
||||
s += '>'
|
||||
return s
|
||||
|
@ -630,33 +633,28 @@ class CoreToChip ( object ):
|
|||
|
||||
def _buildCoreGroundPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to core ground signals."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||
|
||||
def _buildIoGroundPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to pad internal ground signals."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||
|
||||
def _buildAllGroundPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to ground signals for core and pads."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||
|
||||
def _buildCorePowerPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to core power signals."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||
|
||||
def _buildIoPowerPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to pad internal power signals."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||
|
||||
def _buildAllPowerPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to power signals for core and pads."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded, on {}' \
|
||||
.format(ioPadConf) )
|
||||
|
||||
def _buildClockPads ( self, ioPadConf ):
|
||||
"""Build I/O pad relateds to clock signals."""
|
||||
|
@ -665,7 +663,6 @@ class CoreToChip ( object ):
|
|||
|
||||
def _connectClocks ( self ):
|
||||
"""Connect inner clocks signal to the corona (towards the core) ."""
|
||||
if self.useHarness(): return
|
||||
raise NotImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' )
|
||||
|
||||
def _loadHarness ( self ):
|
||||
|
@ -704,29 +701,37 @@ class CoreToChip ( object ):
|
|||
ioPads = []
|
||||
clockIoNets = []
|
||||
for ioPadConf in self.conf.chipConf.padInstances:
|
||||
if self.useHarness():
|
||||
ioPadConf.flags = IoPadConf.BIDIR
|
||||
trace( 550, ',+', '\tioPadConf={}\n'.format( ioPadConf ))
|
||||
if ioPadConf.isAllPower():
|
||||
self._buildAllPowerPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isCorePower():
|
||||
self._buildCorePowerPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isIoPower():
|
||||
self._buildIoPowerPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isAllGround():
|
||||
self._buildAllGroundPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isCoreGround():
|
||||
self._buildCoreGroundPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isIoGround():
|
||||
self._buildIoGroundPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if ioPadConf.isClock():
|
||||
self._buildClockPads( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
continue
|
||||
if self.useHarness():
|
||||
ioPadConf.flags = IoPadConf.BIDIR
|
||||
ioPadConf.udata = IoPad( self, ioPadConf )
|
||||
for netName in ioPadConf.nets:
|
||||
if netName is None: continue
|
||||
|
@ -741,12 +746,14 @@ class CoreToChip ( object ):
|
|||
else:
|
||||
if ioPadConf.isBidir() or ioPadConf.isTristate():
|
||||
if coreNet.getName() == ioPadConf.enableNetName:
|
||||
trace( 550, '\tFlag core net name "{}" as enable\n'.format( coreNet.getName() ))
|
||||
ioNet.setEnable( True )
|
||||
if not ioNet.isEnable():
|
||||
if not ioNet.isEnable() and not self.conf.useHarness:
|
||||
trace( 550, '\tForce pad net name to "{}"\n'.format( ioPadConf.padNetName ))
|
||||
ioNet.chipExtNetName = ioPadConf.padNetName
|
||||
ioPadConf.udata.addNet( ioNet )
|
||||
ioPads.append( ioPadConf )
|
||||
trace( 550, '-' )
|
||||
trace( 550, '\tProcessed all IoPadConf, looking for orphaned core nets...\n' )
|
||||
for coreNet in self.core.getNets():
|
||||
if not coreNet.isExternal(): continue
|
||||
|
@ -771,8 +778,6 @@ class CoreToChip ( object ):
|
|||
#trace( 550, '\tNon-configured core net {}, adding {}\n'.format(coreNet,directPad) )
|
||||
for ioPad in ioPads:
|
||||
ioPad.udata.createPad()
|
||||
#if self.useHarness():
|
||||
# self._connectCorona()
|
||||
else:
|
||||
self._connectRing()
|
||||
self._connectClocks()
|
||||
|
|
|
@ -33,6 +33,93 @@ from plugins.alpha.core2chip.core2chip import CoreToChip as BaseCoreToChip, \
|
|||
IoNet, IoPad
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Class : "MatchHarnessIos".
|
||||
|
||||
class MatchHarnessIos ( object ):
|
||||
"""
|
||||
In case the connections of the core to the I/O pins are not specified
|
||||
(empty ioPadsSpecs list), try to guess the connection by names.
|
||||
|
||||
.. note:: Currently, only matching with the (io_in,io_out,io_oeb),
|
||||
power and clock are supported.
|
||||
"""
|
||||
|
||||
def __init__ ( self, coreToChip ):
|
||||
self.coreToChip = coreToChip
|
||||
self.digitalIos = []
|
||||
for i in range(38):
|
||||
self.digitalIos.append( [None, None, None] )
|
||||
self.clock = None
|
||||
self.digitalVdd = None
|
||||
self.digitalVss = None
|
||||
|
||||
@property
|
||||
def conf ( self ): return self.coreToChip.conf
|
||||
|
||||
def matchCore ( self ):
|
||||
print( ' o Using implicit Caravel harness connections.' )
|
||||
reIoIn = re.compile( r'^(?P<name>\w+)\((?P<index>\d+)\)$' )
|
||||
for net in self.conf.core.getNets():
|
||||
if not net.isExternal(): continue
|
||||
if net.isClock():
|
||||
self.clock = net
|
||||
continue
|
||||
if net.isPower():
|
||||
self.digitalVdd = net
|
||||
continue
|
||||
if net.isGround():
|
||||
self.digitalVss = net
|
||||
continue
|
||||
m = reIoIn.match( net.getName() )
|
||||
if m:
|
||||
index = int( m.group('index') )
|
||||
if index >= 38:
|
||||
continue
|
||||
if m.group('name') == 'io_in':
|
||||
self.digitalIos[ index ][0] = net
|
||||
elif m.group('name') == 'io_out':
|
||||
self.digitalIos[ index ][1] = net
|
||||
elif m.group('name') == 'io_oeb':
|
||||
self.digitalIos[ index ][2] = net
|
||||
else:
|
||||
print( WarningMessage('Unable to match "{}" into harness net.'.format( net.getName() )))
|
||||
else:
|
||||
print( WarningMessage('Unable to match "{}" into harness net.'.format( net.getName() )))
|
||||
if self.digitalVdd:
|
||||
self.conf.chipConf.addIoPad( (None, None, 'power_0', 'vccd1', self.digitalVdd.getName()), 0 )
|
||||
else:
|
||||
print( WarningMessage('Missing digital power net in "{}".'.format(self.conf.core.getName())) )
|
||||
if self.digitalVss:
|
||||
self.conf.chipConf.addIoPad( (None, None, 'ground_0', 'vssd1', self.digitalVss.getName()), 0 )
|
||||
else:
|
||||
print( WarningMessage('Missing digital ground net in "{}".'.format(self.conf.core.getName())) )
|
||||
if self.clock:
|
||||
self.conf.chipConf.addIoPad( (None, None, None, 'user_clock2', self.clock.getName()), 0 )
|
||||
else:
|
||||
print( WarningMessage('Missing digital clock net in "{}".'.format(self.conf.core.getName())) )
|
||||
for i in range(38):
|
||||
ioNets = self.digitalIos[ i ]
|
||||
if ioNets[0] and ioNets[1] and ioNets[2]:
|
||||
self.conf.chipConf.addIoPad( ( None, None, None, ioNets[0].getName()
|
||||
, ioNets[0].getName()
|
||||
, ioNets[1].getName()
|
||||
, ioNets[2].getName() ), 0 )
|
||||
elif ioNets[0] and not ioNets[1] and not ioNets[2]:
|
||||
self.conf.chipConf.addIoPad( ( None, None, None, ioNets[0].getName()
|
||||
, ioNets[0].getName() ), 0 )
|
||||
elif not ioNets[0] and not ioNets[1] and ioNets[2]:
|
||||
self.conf.chipConf.addIoPad( ( None, None, None, ioNets[2].getName()
|
||||
, ioNets[2].getName() ), 0 )
|
||||
elif not ioNets[0] and not ioNets[1] and not ioNets[2]:
|
||||
continue
|
||||
else:
|
||||
print( WarningMessage( [ 'Incomplete digital connexion to I/O pad "{}".'.format(index)
|
||||
, '* In :{}'.format( ioNets[0] )
|
||||
, '* Out:{}'.format( ioNets[1] )
|
||||
, '* OEb:{}'.format( ioNets[2] ) ]))
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Class : "sky130.CoreToChip"
|
||||
|
||||
|
@ -70,6 +157,8 @@ class CoreToChip ( BaseCoreToChip ):
|
|||
, 'pad', ['pad', 'padres'] )
|
||||
]
|
||||
self._getPadLib()
|
||||
if self.conf.chipConf.ioPadsCount() == 0:
|
||||
MatchHarnessIos( self ).matchCore()
|
||||
return
|
||||
|
||||
def _getPadLib ( self ):
|
||||
|
@ -88,80 +177,47 @@ class CoreToChip ( BaseCoreToChip ):
|
|||
raise NotImplementedError( 'coreToChip.getCell(): Harness does not provides I/O pad cells.' )
|
||||
|
||||
def _buildCoreGroundPads ( self, ioPadConf ):
|
||||
trace( 550, '\tsky130.CoreToChip._buildGroundPowerPads()\n' )
|
||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.padSupplyNetName )
|
||||
if not coronaNet:
|
||||
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
|
||||
coronaNet.setExternal( True )
|
||||
coronaNet.setGlobal ( True )
|
||||
coronaNet.setType ( Net.Type.GROUND )
|
||||
coronaNet.setExternal ( True )
|
||||
coronaNet.setGlobal ( True )
|
||||
coronaNet.setDirection( Net.Direction.IN )
|
||||
coronaNet.setType ( Net.Type.GROUND )
|
||||
self.icore.getPlug( coreNet ).setNet( coronaNet )
|
||||
trace( 550, '\tCreated corona ground net: {}\n'.format(coronaNet) )
|
||||
if not chipNet:
|
||||
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName )
|
||||
chipNet.setExternal( True )
|
||||
chipNet.setType ( Net.Type.GROUND )
|
||||
raise ErrorMessage( 1, 'Harness do not provide ground net ""{}' \
|
||||
.format( ioPadConf.padSupplyNetName ))
|
||||
coronaPlug = self.icorona.getPlug( coronaNet )
|
||||
if not coronaPlug.getNet():
|
||||
coronaPlug.setNet( chipNet )
|
||||
self.ringNetNames['vss'] = chipNet
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_vss_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['vss']) ) )
|
||||
self._connect( ioPadConf.pads[0], chipNet, 'vss' )
|
||||
self.groundPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
|
||||
def _buildIoGroundPads ( self, ioPadConf ):
|
||||
padNet = self.chip.getNet( ioPadConf.padSupplyNetName )
|
||||
if not padNet:
|
||||
padNet = Net.create( self.chip, ioPadConf.padSupplyNetName )
|
||||
padNet.setExternal( True )
|
||||
padNet.setType ( Net.Type.GROUND )
|
||||
self.ringNetNames['iovss'] = padNet
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_iovss_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['iovss']) ) )
|
||||
self._connect( ioPadConf.pads[0], padNet , 'iovss' )
|
||||
self.groundPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
|
||||
def _buildCorePowerPads ( self, ioPadConf ):
|
||||
trace( 550, '\tsky130.CoreToChip._buildCorePowerPads()\n' )
|
||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.padSupplyNetName )
|
||||
if not coronaNet:
|
||||
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
|
||||
coronaNet.setExternal( True )
|
||||
coronaNet.setGlobal ( True )
|
||||
coronaNet.setType ( Net.Type.POWER )
|
||||
coronaNet.setExternal ( True )
|
||||
coronaNet.setGlobal ( True )
|
||||
coronaNet.setDirection( Net.Direction.IN )
|
||||
coronaNet.setType ( Net.Type.POWER )
|
||||
self.icore.getPlug( coreNet ).setNet( coronaNet )
|
||||
trace( 550, '\tCreated corona power net: {}\n'.format(coronaNet) )
|
||||
if not chipNet:
|
||||
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName )
|
||||
chipNet.setExternal( True )
|
||||
chipNet.setType ( Net.Type.POWER )
|
||||
raise ErrorMessage( 1, 'Harness do not provide power net ""{}' \
|
||||
.format( ioPadConf.padSupplyNetName ))
|
||||
self.icorona.getPlug( coronaNet ).setNet( chipNet )
|
||||
self.ringNetNames['vdd'] = chipNet
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_vdd_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['vdd']) ) )
|
||||
self._connect( ioPadConf.pads[0], chipNet, 'vdd' )
|
||||
coronaPlug = self.icorona.getPlug( coronaNet )
|
||||
if not coronaPlug.getNet():
|
||||
coronaPlug.setNet( chipNet )
|
||||
self.powerPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
|
||||
def _buildIoPowerPads ( self, ioPadConf ):
|
||||
padNet = self.chip .getNet( ioPadConf.padSupplyNetName )
|
||||
if not padNet:
|
||||
padNet = Net.create( self.chip, ioPadConf.padSupplyNetName )
|
||||
padNet.setExternal( True )
|
||||
padNet.setType ( Net.Type.POWER )
|
||||
self.ringNetNames['iovdd'] = padNet
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_iovdd_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['iovdd']) ) )
|
||||
self._connect( ioPadConf.pads[0], padNet , 'iovdd' )
|
||||
self.powerPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
|
||||
def _buildClockPads ( self, ioPadConf ):
|
||||
"""For "Sky130" there is no specialized clock I/O pad. So do nothing."""
|
||||
|
|
Loading…
Reference in New Issue