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:
Jean-Paul Chaput 2021-12-17 15:58:57 +01:00
parent 76d468f6d5
commit ae1f08f039
5 changed files with 150 additions and 75 deletions

View File

@ -661,7 +661,8 @@ class IoPadConf ( object ):
reSpecialPads = re.compile( r'^(?P<type>.+)_(?P<index>[\d+])$' ) reSpecialPads = re.compile( r'^(?P<type>.+)_(?P<index>[\d+])$' )
m = reSpecialPads.match( self.instanceName ) m = reSpecialPads.match( self.instanceName )
else: else:
self.flags |= IoPadConf.ALL_POWER if self.instanceName is not None:
self.flags |= IoPadConf.ALL_POWER
if m: if m:
self.index = m.group('index') self.index = m.group('index')
if m.group('type') == 'allpower': self.flags |= IoPadConf.ALL_POWER 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: if attr == 'ioPadGauge' and value is not None:
self.blockConf._loadIoPadGauge( value ) self.blockConf._loadIoPadGauge( value )
def ioPadsCount ( self ): return len(self.padInstances)
def addIoPad ( self, spec, specNb ): def addIoPad ( self, spec, specNb ):
""" """
Add an I/O pad specification. The spec argument must be of the form: Add an I/O pad specification. The spec argument must be of the form:

View File

@ -15,6 +15,7 @@
import sys import sys
import os.path import os.path
import re
import Cfg import Cfg
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \ from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
Path, Layer, Occurrence, Net, HyperNet, \ Path, Layer, Occurrence, Net, HyperNet, \
@ -31,6 +32,16 @@ from plugins.alpha.block.configuration import GaugeConf
from plugins.alpha.block.spares import Spares 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". # Class : "htree.HTree".
@ -223,7 +234,7 @@ class HTree ( object ):
buffers of the leafs of the QuadTree. buffers of the leafs of the QuadTree.
""" """
qt = self.spares.quadTree qt = self.spares.quadTree
qt.bufferTag = self.treeNet.getName() qt.bufferTag = unbitify( self.treeNet.getName() )
qt.runselect() qt.runselect()
qt.rselectBuffer( self.treeIndex qt.rselectBuffer( self.treeIndex
, self.treeIndex , self.treeIndex
@ -239,7 +250,7 @@ class HTree ( object ):
""" """
bufferConf = self.spares.conf.bufferConf bufferConf = self.spares.conf.bufferConf
quadTree = self.spares.quadTree quadTree = self.spares.quadTree
quadTree.bufferTag = self.treeNet.getName() quadTree.bufferTag = unbitify( self.treeNet.getName() )
quadTree.runselect() quadTree.runselect()
quadTree.rselectBuffer( self.treeIndex, self.treeIndex, self.flags) quadTree.rselectBuffer( self.treeIndex, self.treeIndex, self.flags)
with UpdateSession(): with UpdateSession():

View File

@ -574,7 +574,7 @@ class ChipConf ( BlockConf ):
net = self.corona.getNet( masterNet.getName() ) net = self.corona.getNet( masterNet.getName() )
if not net: if not net:
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Missing global net "{}" at corona level.' \ raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Missing global net "{}" at corona level.' \
.format(asterNet.getName()) ) .format(masterNet.getName()) )
self._validated = False self._validated = False
continue continue
if netType == Net.Type.GROUND: if netType == Net.Type.GROUND:

View File

@ -57,7 +57,7 @@ from plugins.checks import oneDriver
from plugins.alpha.utils import getPlugByName from plugins.alpha.utils import getPlugByName
from plugins.alpha.block.block import Block from plugins.alpha.block.block import Block
from plugins.alpha.block.configuration import BlockConf, IoPadConf, ConstantsConf from plugins.alpha.block.configuration import BlockConf, IoPadConf, ConstantsConf
# ------------------------------------------------------------------- # -------------------------------------------------------------------
# Class : "IoNet". # Class : "IoNet".
@ -155,7 +155,10 @@ class IoNet ( object ):
@property @property
def chipExtNetName ( self ): def chipExtNetName ( self ):
if self._chipExtNetName is not None: return self._chipExtNetName 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() if self.chipExtNet: return self.chipExtNet.getName()
s = self._name s = self._name
if self._flags & IoNet.IsElem: s += '({})'.format(self._index) 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.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName )
self.chipIntNet = self.chipExtNet self.chipIntNet = self.chipExtNet
if not 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() )) .format( self.chipExtNetName, self.coreNet.getName() ))
# Chip "internal" net, connect Corona instance net to I/O inside the chip. # Chip "internal" net, connect Corona instance net to I/O inside the chip.
if not self.chipIntNet: if not self.chipIntNet:
@ -285,7 +288,7 @@ class IoPad ( object ):
def __str__ ( self ): def __str__ ( self ):
s = '<IoPad "{}" '.format(self.padInstanceName) s = '<IoPad "{}" '.format(self.padInstanceName)
for ioNet in self.nets: for ioNet in self.nets:
s += ' {}'.format(ioNet.coreNetName) s += ' "{}" <-> "{}"'.format(ioNet.coreNetName,ioNet.chipExtNetName)
s += ' direction={}'.format(self.direction) s += ' direction={}'.format(self.direction)
s += '>' s += '>'
return s return s
@ -630,33 +633,28 @@ class CoreToChip ( object ):
def _buildCoreGroundPads ( self, ioPadConf ): def _buildCoreGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to core ground signals.""" """Build I/O pad relateds to core ground signals."""
if self.useHarness(): return
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildIoGroundPads ( self, ioPadConf ): def _buildIoGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to pad internal ground signals.""" """Build I/O pad relateds to pad internal ground signals."""
if self.useHarness(): return
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildAllGroundPads ( self, ioPadConf ): def _buildAllGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to ground signals for core and pads.""" """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.' ) raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildCorePowerPads ( self, ioPadConf ): def _buildCorePowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to core power signals.""" """Build I/O pad relateds to core power signals."""
if self.useHarness(): return
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
def _buildIoPowerPads ( self, ioPadConf ): def _buildIoPowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to pad internal power signals.""" """Build I/O pad relateds to pad internal power signals."""
if self.useHarness(): return
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
def _buildAllPowerPads ( self, ioPadConf ): def _buildAllPowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to power signals for core and pads.""" """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, on {}' \
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' ) .format(ioPadConf) )
def _buildClockPads ( self, ioPadConf ): def _buildClockPads ( self, ioPadConf ):
"""Build I/O pad relateds to clock signals.""" """Build I/O pad relateds to clock signals."""
@ -665,7 +663,6 @@ class CoreToChip ( object ):
def _connectClocks ( self ): def _connectClocks ( self ):
"""Connect inner clocks signal to the corona (towards the core) .""" """Connect inner clocks signal to the corona (towards the core) ."""
if self.useHarness(): return
raise NotImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' )
def _loadHarness ( self ): def _loadHarness ( self ):
@ -704,29 +701,37 @@ class CoreToChip ( object ):
ioPads = [] ioPads = []
clockIoNets = [] clockIoNets = []
for ioPadConf in self.conf.chipConf.padInstances: for ioPadConf in self.conf.chipConf.padInstances:
if self.useHarness(): trace( 550, ',+', '\tioPadConf={}\n'.format( ioPadConf ))
ioPadConf.flags = IoPadConf.BIDIR
if ioPadConf.isAllPower(): if ioPadConf.isAllPower():
self._buildAllPowerPads( ioPadConf ) self._buildAllPowerPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isCorePower(): if ioPadConf.isCorePower():
self._buildCorePowerPads( ioPadConf ) self._buildCorePowerPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isIoPower(): if ioPadConf.isIoPower():
self._buildIoPowerPads( ioPadConf ) self._buildIoPowerPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isAllGround(): if ioPadConf.isAllGround():
self._buildAllGroundPads( ioPadConf ) self._buildAllGroundPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isCoreGround(): if ioPadConf.isCoreGround():
self._buildCoreGroundPads( ioPadConf ) self._buildCoreGroundPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isIoGround(): if ioPadConf.isIoGround():
self._buildIoGroundPads( ioPadConf ) self._buildIoGroundPads( ioPadConf )
trace( 550, '-' )
continue continue
if ioPadConf.isClock(): if ioPadConf.isClock():
self._buildClockPads( ioPadConf ) self._buildClockPads( ioPadConf )
trace( 550, '-' )
continue continue
if self.useHarness():
ioPadConf.flags = IoPadConf.BIDIR
ioPadConf.udata = IoPad( self, ioPadConf ) ioPadConf.udata = IoPad( self, ioPadConf )
for netName in ioPadConf.nets: for netName in ioPadConf.nets:
if netName is None: continue if netName is None: continue
@ -741,12 +746,14 @@ class CoreToChip ( object ):
else: else:
if ioPadConf.isBidir() or ioPadConf.isTristate(): if ioPadConf.isBidir() or ioPadConf.isTristate():
if coreNet.getName() == ioPadConf.enableNetName: if coreNet.getName() == ioPadConf.enableNetName:
trace( 550, '\tFlag core net name "{}" as enable\n'.format( coreNet.getName() ))
ioNet.setEnable( True ) 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 )) trace( 550, '\tForce pad net name to "{}"\n'.format( ioPadConf.padNetName ))
ioNet.chipExtNetName = ioPadConf.padNetName ioNet.chipExtNetName = ioPadConf.padNetName
ioPadConf.udata.addNet( ioNet ) ioPadConf.udata.addNet( ioNet )
ioPads.append( ioPadConf ) ioPads.append( ioPadConf )
trace( 550, '-' )
trace( 550, '\tProcessed all IoPadConf, looking for orphaned core nets...\n' ) trace( 550, '\tProcessed all IoPadConf, looking for orphaned core nets...\n' )
for coreNet in self.core.getNets(): for coreNet in self.core.getNets():
if not coreNet.isExternal(): continue if not coreNet.isExternal(): continue
@ -771,8 +778,6 @@ class CoreToChip ( object ):
#trace( 550, '\tNon-configured core net {}, adding {}\n'.format(coreNet,directPad) ) #trace( 550, '\tNon-configured core net {}, adding {}\n'.format(coreNet,directPad) )
for ioPad in ioPads: for ioPad in ioPads:
ioPad.udata.createPad() ioPad.udata.createPad()
#if self.useHarness():
# self._connectCorona()
else: else:
self._connectRing() self._connectRing()
self._connectClocks() self._connectClocks()

View File

@ -33,6 +33,93 @@ from plugins.alpha.core2chip.core2chip import CoreToChip as BaseCoreToChip, \
IoNet, IoPad 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" # Class : "sky130.CoreToChip"
@ -70,6 +157,8 @@ class CoreToChip ( BaseCoreToChip ):
, 'pad', ['pad', 'padres'] ) , 'pad', ['pad', 'padres'] )
] ]
self._getPadLib() self._getPadLib()
if self.conf.chipConf.ioPadsCount() == 0:
MatchHarnessIos( self ).matchCore()
return return
def _getPadLib ( self ): def _getPadLib ( self ):
@ -88,80 +177,47 @@ class CoreToChip ( BaseCoreToChip ):
raise NotImplementedError( 'coreToChip.getCell(): Harness does not provides I/O pad cells.' ) raise NotImplementedError( 'coreToChip.getCell(): Harness does not provides I/O pad cells.' )
def _buildCoreGroundPads ( self, ioPadConf ): def _buildCoreGroundPads ( self, ioPadConf ):
trace( 550, '\tsky130.CoreToChip._buildGroundPowerPads()\n' )
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName ) coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName ) coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName ) chipNet = self.chip .getNet( ioPadConf.padSupplyNetName )
if not coronaNet: if not coronaNet:
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName ) coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
coronaNet.setExternal( True ) coronaNet.setExternal ( True )
coronaNet.setGlobal ( True ) coronaNet.setGlobal ( True )
coronaNet.setType ( Net.Type.GROUND ) coronaNet.setDirection( Net.Direction.IN )
coronaNet.setType ( Net.Type.GROUND )
self.icore.getPlug( coreNet ).setNet( coronaNet ) self.icore.getPlug( coreNet ).setNet( coronaNet )
trace( 550, '\tCreated corona ground net: {}\n'.format(coronaNet) )
if not chipNet: if not chipNet:
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName ) raise ErrorMessage( 1, 'Harness do not provide ground net ""{}' \
chipNet.setExternal( True ) .format( ioPadConf.padSupplyNetName ))
chipNet.setType ( Net.Type.GROUND )
coronaPlug = self.icorona.getPlug( coronaNet ) coronaPlug = self.icorona.getPlug( coronaNet )
if not coronaPlug.getNet(): if not coronaPlug.getNet():
coronaPlug.setNet( chipNet ) 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.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 ): def _buildCorePowerPads ( self, ioPadConf ):
trace( 550, '\tsky130.CoreToChip._buildCorePowerPads()\n' )
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName ) coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName ) coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName ) chipNet = self.chip .getNet( ioPadConf.padSupplyNetName )
if not coronaNet: if not coronaNet:
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName ) coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
coronaNet.setExternal( True ) coronaNet.setExternal ( True )
coronaNet.setGlobal ( True ) coronaNet.setGlobal ( True )
coronaNet.setType ( Net.Type.POWER ) coronaNet.setDirection( Net.Direction.IN )
coronaNet.setType ( Net.Type.POWER )
self.icore.getPlug( coreNet ).setNet( coronaNet ) self.icore.getPlug( coreNet ).setNet( coronaNet )
trace( 550, '\tCreated corona power net: {}\n'.format(coronaNet) )
if not chipNet: if not chipNet:
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName ) raise ErrorMessage( 1, 'Harness do not provide power net ""{}' \
chipNet.setExternal( True ) .format( ioPadConf.padSupplyNetName ))
chipNet.setType ( Net.Type.POWER )
self.icorona.getPlug( coronaNet ).setNet( chipNet ) self.icorona.getPlug( coronaNet ).setNet( chipNet )
self.ringNetNames['vdd'] = chipNet coronaPlug = self.icorona.getPlug( coronaNet )
ioPadConf.pads.append( Instance.create( self.chip if not coronaPlug.getNet():
, 'p_vdd_{}'.format(ioPadConf.index) coronaPlug.setNet( chipNet )
, self.getCell(self.ioPadNames['vdd']) ) )
self._connect( ioPadConf.pads[0], chipNet, 'vdd' )
self.powerPadCount += 1 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 ): def _buildClockPads ( self, ioPadConf ):
"""For "Sky130" there is no specialized clock I/O pad. So do nothing.""" """For "Sky130" there is no specialized clock I/O pad. So do nothing."""