Support for gf180mcu native I/O pads.
* Bug: In CRL/technos.node180.gf180mcu_c4m.iolib.py, remove the VDD and VSS ring terminals in the pad as only *some* of the have it. Assume that it is a bug from GF. The power rail will still be ok as it connect by abutment (with the filler & other I/O pads). * New: In cumulus.plugins.block.configuration.py, added support for iterable I/O pad specifications in ioPads argument. * New: In cumulus.plugins.core2chip.core2chip.py, add support for any number of control signals on I/O pads. Not fully implemented yet, as we only allow to hard-wire them either to one or zero. Raise an error if _connect() fails to find a master net, so we don't fail strangely later...
This commit is contained in:
parent
4420da664e
commit
9274c21c14
|
@ -181,7 +181,7 @@ def _routing ():
|
|||
cfg.katana.globalRipupLimit = 5
|
||||
cfg.katana.globalRipupLimit = [1, None]
|
||||
cfg.katana.longGlobalRipupLimit = 5
|
||||
cfg.chip.padCoreSide = 'South'
|
||||
cfg.chip.padCoreSide = 'North'
|
||||
# Plugins setup
|
||||
cfg.clockTree.minimumSide = u(5.04) * 6
|
||||
cfg.clockTree.buffer = 'gf180mcu_fd_sc_mcu9t5v0__clkbuf_2'
|
||||
|
|
|
@ -99,6 +99,10 @@ def _routing():
|
|||
)
|
||||
af.addCellGauge(cg)
|
||||
af.setCellGauge('StdCell3V3Lib')
|
||||
lg5 = af.getRoutingGauge('StdCell3V3Lib').getLayerGauge( 5 )
|
||||
lg5.setType( CRL.RoutingLayerGauge.PowerSupply )
|
||||
env = af.getEnvironment()
|
||||
env.setRegister( '.*sff.*' )
|
||||
|
||||
# Place & Route setup
|
||||
with CfgCache(priority=Cfg.Parameter.Priority.ConfigurationFile) as cfg:
|
||||
|
@ -162,17 +166,8 @@ def _routing():
|
|||
cfg.katana.globalRipupLimit = 5
|
||||
cfg.katana.globalRipupLimit = [1, None]
|
||||
cfg.katana.longGlobalRipupLimit = 5
|
||||
cfg.chip.padCoreSide = 'South'
|
||||
|
||||
# Plugins setup
|
||||
with CfgCache(priority=Cfg.Parameter.Priority.ConfigurationFile) as cfg:
|
||||
cfg.viewer.minimumSize = 500
|
||||
cfg.viewer.pixelThreshold = 10
|
||||
cfg.chip.block.rails.count = 5
|
||||
cfg.chip.block.rails.hWidth = u(2.68)
|
||||
cfg.chip.block.rails.vWidth = u(2.68)
|
||||
cfg.chip.block.rails.hSpacing = u(0.7)
|
||||
cfg.chip.block.rails.vSpacing = u(0.7)
|
||||
cfg.clockTree.minimumSide = l(600)
|
||||
cfg.clockTree.buffer = 'buf_x1'
|
||||
cfg.clockTree.placerEngine = 'Etesian'
|
||||
|
|
|
@ -27,8 +27,9 @@ def _routing ():
|
|||
cfg.chip.block.rails.vWidth = u(30.0)
|
||||
cfg.chip.block.rails.hSpacing = u( 6.0)
|
||||
cfg.chip.block.rails.vSpacing = u( 6.0)
|
||||
cfg.chip.padCorner = 'gf180mcu_fd_io__cor_5lm'
|
||||
cfg.chip.padSpacers = 'gf180mcu_fd_io__fill10_5lm,gf180mcu_fd_io__fill5_5lm,gf180mcu_fd_io__fill1_5lm'
|
||||
#cfg.chip.padCorner = 'gf180mcu_fd_io__cor'
|
||||
#cfg.chip.padSpacers = 'gf180mcu_fd_io__fill10,gf180mcu_fd_io__fill5,gf180mcu_fd_io__fill1'
|
||||
cfg.chip.padCoreSide = 'North'
|
||||
af = AllianceFramework.get()
|
||||
cg = CellGauge.create( 'LEF.GF_IO_Site'
|
||||
, 'Metal2' # pin layer name.
|
||||
|
@ -57,7 +58,6 @@ def _loadIoLib ( pdkDir ):
|
|||
print( ' o Setup GF180MCU I/O library in {}.'.format( ioLib.getName() ))
|
||||
io.vprint( 1, ' o Setup GF180MCU I/O library in {}.'.format( ioLib.getName() ))
|
||||
cellsDir = pdkDir / 'libraries' / 'gf180mcu_fd_io' / 'latest' / 'cells'
|
||||
print( cellsDir )
|
||||
for lefFile in cellsDir.glob( '*/*_5lm.lef' ):
|
||||
print( lefFile )
|
||||
gdsFile = lefFile.with_suffix( '.gds' )
|
||||
|
@ -65,6 +65,12 @@ def _loadIoLib ( pdkDir ):
|
|||
Gds.setTopCellName( gdsFile.stem[:-4] )
|
||||
Gds.load( ioLib, gdsFile.as_posix(), Gds.Layer_0_IsBoundary|Gds.NoBlockages )
|
||||
LefImport.load( lefFile.as_posix() )
|
||||
# Demote the VDD/VSS nets until we understand how that works.
|
||||
for cell in ioLib.getCells():
|
||||
for net in cell.getNets():
|
||||
if net.getName() in ('VDD', 'VSS'):
|
||||
net.setExternal( False )
|
||||
net.setGlobal( False )
|
||||
af.wrapLibrary( ioLib, 1 )
|
||||
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/niolib.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/libresocio.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/sky130.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/core2chip/gf180mcu.py
|
||||
)
|
||||
set ( pyPluginChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/__init__.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/constants.py
|
||||
|
|
|
@ -284,7 +284,6 @@ def setupGf180mcu_c4m ( checkToolkit=None
|
|||
cfg.misc.verboseLevel2 = True
|
||||
cfg.etesian.graphics = 3
|
||||
cfg.etesian.spaceMargin = 0.10
|
||||
cfg.anabatic.topRoutingLayer = 'metal6'
|
||||
cfg.katana.eventsLimit = 4000000
|
||||
af = CRL.AllianceFramework.get()
|
||||
lg5 = af.getRoutingGauge('StdCell3V3Lib').getLayerGauge( 5 )
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import sys
|
||||
import re
|
||||
import os.path
|
||||
import collections
|
||||
from operator import itemgetter
|
||||
from ... import Cfg
|
||||
from ...Hurricane import DataBase, Breakpoint, DbU, Box, Transformation, \
|
||||
|
@ -1449,7 +1450,22 @@ class BlockConf ( GaugeConf ):
|
|||
for ioPinSpec in self.ioPinsArg:
|
||||
self.ioPins.append( IoPin( *ioPinSpec ) )
|
||||
for line in range(len(self.ioPadsArg)):
|
||||
self.chipConf.addIoPad( self.ioPadsArg[line], line )
|
||||
bits = []
|
||||
if not isinstance(self.ioPadsArg[line][-1],str) \
|
||||
and isinstance(self.ioPadsArg[line][-1],collections.Iterable):
|
||||
bits = self.ioPadsArg[line][-1]
|
||||
elif isinstance(self.ioPadsArg[line][-1],int):
|
||||
bits = range( self.ioPadsArg[line][-1] )
|
||||
if bits != []:
|
||||
for bit in bits:
|
||||
spec = [ self.ioPadsArg[line][0]
|
||||
, self.ioPadsArg[line][1]
|
||||
]
|
||||
for i in range( 2, len(self.ioPadsArg[line])-1 ):
|
||||
spec.append( self.ioPadsArg[line][i].format( bit ))
|
||||
self.chipConf.addIoPad( spec, line )
|
||||
else:
|
||||
self.chipConf.addIoPad( self.ioPadsArg[line], line )
|
||||
trace( 550, ',-' )
|
||||
|
||||
@property
|
||||
|
|
|
@ -693,11 +693,11 @@ class Corona ( object ):
|
|||
if plug.getMasterNet().isGlobal():
|
||||
net = self.conf.cell.getNet( plug.getMasterNet().getName() )
|
||||
if not net:
|
||||
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "%s" is not connected and there is no global net (in pad \"%s").' \
|
||||
% plug.getMasterNet().getName(), padCell.getName() )
|
||||
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "{}" is not connected and there is no global net (in pad "{}").' \
|
||||
.format( plug.getMasterNet().getName(), padCell.getName() ))
|
||||
else:
|
||||
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \
|
||||
% plug.getMasterNet().getName(), padCell.getName() )
|
||||
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "{}" is neither connected nor global (in pad "{}").' \
|
||||
.format( plug.getMasterNet().getName(), padCell.getName() ))
|
||||
if net:
|
||||
self.padRails.append( ( net
|
||||
, component.getLayer()
|
||||
|
|
|
@ -375,6 +375,7 @@ class IoPad ( object ):
|
|||
or self.nets[0].chipExtNetName.startswith('io_in') \
|
||||
or self.nets[0].chipExtNetName.startswith('io_out')
|
||||
if hasEnable:
|
||||
trace( 550, '\tself.nets = {}\n'.format( self.nets ))
|
||||
if len(self.nets) < 2:
|
||||
enableNet = self.coreToChip.newEnableForNet( self.nets[0] )
|
||||
self.nets.append( self.coreToChip.getIoNet( enableNet ) )
|
||||
|
@ -387,6 +388,7 @@ class IoPad ( object ):
|
|||
connexions.append( ( self.nets[0].chipIntNet , padInfo.inputNet ) )
|
||||
connexions.append( ( self.coreToChip.newDummyNet(), padInfo.outputNet ) )
|
||||
if hasEnable:
|
||||
trace( 550, '\tenable Pad={} <-> {}\n'.format( padInfo.enableNet, self.nets[1].chipIntNet ))
|
||||
connexions.append( ( self.nets[1].chipIntNet, padInfo.enableNet ) )
|
||||
elif (self.direction == IoPad.TRI_OUT) and (len(self.nets) < 2):
|
||||
self.nets[0].setFlags( IoNet.DoExtNet )
|
||||
|
@ -415,6 +417,11 @@ class IoPad ( object ):
|
|||
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
|
||||
connexions.append( ( self.nets[1].chipIntNet, padInfo.outputNet ) )
|
||||
connexions.append( ( self.nets[2].chipIntNet, padInfo.enableNet ) )
|
||||
for controlInfo in padInfo.controlNets:
|
||||
controlNet = self.coreToChip.newControlForPad( self.ioPadConf, controlInfo )
|
||||
self.nets.append( self.coreToChip.getIoNet( controlNet ) )
|
||||
self.nets[-1].buildNets()
|
||||
connexions.append( ( self.nets[-1].chipIntNet, controlInfo.name ) )
|
||||
if not self.coreToChip.useHarness():
|
||||
self.pads.append( Instance.create( self.coreToChip.chip
|
||||
, self.padInstanceName
|
||||
|
@ -448,13 +455,21 @@ class CoreToChip ( object ):
|
|||
to the core actually bearing information.
|
||||
"""
|
||||
|
||||
class IoControlInfo ( object ):
|
||||
|
||||
def __init__ ( self, name, defaultState ):
|
||||
self.name = name
|
||||
self.defaultState = defaultState
|
||||
pass
|
||||
|
||||
class IoPadInfo ( object ):
|
||||
|
||||
def __init__ ( self, flags, padName, padNet, coreNets ):
|
||||
self.flags = flags
|
||||
self.name = padName
|
||||
self.padNet = padNet
|
||||
self.coreNets = coreNets
|
||||
def __init__ ( self, flags, padName, padNet, coreNets, controlNets=[] ):
|
||||
self.flags = flags
|
||||
self.name = padName
|
||||
self.padNet = padNet
|
||||
self.coreNets = coreNets
|
||||
self.controlNets = [ CoreToChip.IoControlInfo( net[0], net[1] ) for net in controlNets ]
|
||||
return
|
||||
|
||||
@property
|
||||
|
@ -508,6 +523,10 @@ class CoreToChip ( object ):
|
|||
if not masterNetO: masterNet = instance.getMasterCell().getNet( chipNet.getName() )
|
||||
elif isinstance(masterNetO,Net): masterNet = masterNetO
|
||||
else: masterNet = instance.getMasterCell().getNet( masterNetO )
|
||||
if not masterNet:
|
||||
raise ErrorMessage( 1, [ 'CoreToChip._connect(): No net "{}" in cell "{}".' \
|
||||
.format( masterNetO, instance.getMasterCell().getName() )
|
||||
] )
|
||||
instance.getPlug( masterNet ).setNet( chipNet )
|
||||
return
|
||||
|
||||
|
@ -571,6 +590,22 @@ class CoreToChip ( object ):
|
|||
self.dummyNetCount += 1
|
||||
return dummy
|
||||
|
||||
def newControlNet ( self, controlName, constantType ):
|
||||
"""
|
||||
Create a new control signal, in *core* cell, to control the associated I/O pad.
|
||||
The control signal is tied to a constant value, either zero or one.
|
||||
|
||||
:param controlName: The name of the control net *in the core cell*.
|
||||
:param constantType: Whether the control signal is set to zero or one.
|
||||
"""
|
||||
instance = self.conf.constantsConf.createInstance( self.core, constantType )
|
||||
control = Net.create( self.core, controlName )
|
||||
control.setExternal ( True )
|
||||
control.setDirection( Net.Direction.OUT )
|
||||
getPlugByName( instance, self.conf.constantsConf.output(constantType) ).setNet( control )
|
||||
self.conf.addClonedCell( self.conf.core )
|
||||
return control
|
||||
|
||||
def newEnableForNet ( self, ioNet ):
|
||||
"""
|
||||
Create a new enable signal, in *core* cell, to control the associated I/O pad.
|
||||
|
@ -582,13 +617,16 @@ class CoreToChip ( object ):
|
|||
else:
|
||||
raise ErrorMessage( 2, 'CoreToChip.newEnableForNet(): Net "{}" is neither IN nor OUT.' \
|
||||
.format(ioNet.coreNet.getName()) )
|
||||
instance = self.conf.constantsConf.createInstance( self.core, constantType )
|
||||
enable = Net.create( self.core, ioNet.enableNetName )
|
||||
enable.setExternal ( True )
|
||||
enable.setDirection( Net.Direction.OUT )
|
||||
getPlugByName( instance, self.conf.constantsConf.output(constantType) ).setNet( enable )
|
||||
self.conf.addClonedCell( self.conf.core )
|
||||
return enable
|
||||
return self.newControlNet( ioNet.enableNetName, constantType )
|
||||
|
||||
def newControlForPad ( self, ioPadInfo, ioControlInfo ):
|
||||
"""
|
||||
Create a new control signal, in *core* cell, to control the associated I/O pad.
|
||||
This is to be used for all I/O pads controls nets, save the "enable" signal.
|
||||
"""
|
||||
constantType = ConstantsConf.ONE if ioControlInfo.defaultState else ConstantsConf.ZERO
|
||||
controlNetName = '{}_{}'.format( ioPadInfo.instanceName, ioControlInfo.name )
|
||||
return self.newControlNet( controlNetName, constantType )
|
||||
|
||||
def getIoNet ( self, coreNet ):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,248 @@
|
|||
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) Sorbonne Université 2020-2023, All Rights Reserved
|
||||
#
|
||||
# +-----------------------------------------------------------------+
|
||||
# | C O R I O L I S |
|
||||
# | C u m u l u s - P y t h o n T o o l s |
|
||||
# | |
|
||||
# | Author : Jean-Paul CHAPUT |
|
||||
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./plugins/core2chip/libresocio.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
"""
|
||||
Core2Chip configuration for the Global Foudries 180nm I/O pad library (GF180MCU).
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from ...Hurricane import DbU, DataBase, UpdateSession, Breakpoint, \
|
||||
Transformation , Instance , Net
|
||||
from ...CRL import Catalog, AllianceFramework
|
||||
from ...helpers import trace
|
||||
from ...helpers.io import ErrorMessage, WarningMessage
|
||||
from ...helpers.overlay import CfgCache
|
||||
from .core2chip import CoreToChip as BaseCoreToChip, IoNet, IoPad
|
||||
|
||||
|
||||
class CoreToChip ( BaseCoreToChip ):
|
||||
"""
|
||||
Provide pad-specific part for GF180MCU I/O pads (works in real mode).
|
||||
"""
|
||||
rePadType = re.compile(r'(?P<type>.+)_(?P<index>[\d]+)$')
|
||||
|
||||
def __init__ ( self, core ):
|
||||
with CfgCache() as cfg:
|
||||
cfg.chip.useAbstractPads = False
|
||||
self.ioPadNames = { 'in' :'gf180mcu_fd_io__in_s'
|
||||
, 'bidir' :'gf180mcu_fd_io__bi_t'
|
||||
, 'analog' :'gf180mcu_fd_io__asig_5p0'
|
||||
, 'vdd' :'gf180mcu_fd_io__dvdd'
|
||||
, 'vss' :'gf180mcu_fd_io__dvss'
|
||||
, 'corner' :'gf180mcu_fd_io__cor'
|
||||
, 'spacer1' :'gf180mcu_fd_io__fill1'
|
||||
, 'spacer5' :'gf180mcu_fd_io__fill5'
|
||||
, 'spacer10' :'gf180mcu_fd_io__fill10'
|
||||
}
|
||||
BaseCoreToChip.__init__ ( self, core )
|
||||
self.ringNetNames = { 'DVDD' : None
|
||||
, 'DVSS' : None
|
||||
#, 'VDD' : None
|
||||
#, 'VSS' : None
|
||||
}
|
||||
self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.IN
|
||||
, self.ioPadNames['in']
|
||||
, 'PAD', ['Y'], [ ( 'PU' , False )
|
||||
, ( 'PD' , False )
|
||||
] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.BIDIR
|
||||
, self.ioPadNames['bidir']
|
||||
, 'PAD', ['A', 'Y', 'OE'], [ ( 'SL' , True )
|
||||
, ( 'CS' , True )
|
||||
, ( 'PU' , False )
|
||||
, ( 'PD' , False )
|
||||
, ( 'PDRV0', False )
|
||||
, ( 'PDRV1', False )
|
||||
, ( 'IE' , True )
|
||||
] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.ANALOG
|
||||
, self.ioPadNames['analog']
|
||||
, 'ASIG5V', ['asig5v'] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.CORNER
|
||||
, self.ioPadNames['corner']
|
||||
, None, [] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.FILLER
|
||||
, self.ioPadNames['spacer1']
|
||||
, None, [] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.FILLER
|
||||
, self.ioPadNames['spacer5']
|
||||
, None, [] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.FILLER
|
||||
, self.ioPadNames['spacer10']
|
||||
, None, [] )
|
||||
]
|
||||
self.cornerCount = 0
|
||||
self.spacerCount = 0
|
||||
self.padSpacers = []
|
||||
self._getPadLib()
|
||||
return
|
||||
|
||||
def _getPadLib ( self ):
|
||||
"""
|
||||
Check that the I/O pad library is present and pre-load the spacer cells.
|
||||
"""
|
||||
def _cmpPad ( pad ):
|
||||
"""Used to sort I/O pads by decreasing width."""
|
||||
return pad.getAbutmentBox().getWidth()
|
||||
|
||||
self.padLib = AllianceFramework.get().getLibrary( "iolib" )
|
||||
if not self.padLib:
|
||||
message = [ 'CoreToChip.libresocio._getPadLib(): Unable to find Alliance "iolib" library' ]
|
||||
raise ErrorMessage( 1, message )
|
||||
for ioPadInfo in self.ioPadInfos:
|
||||
if ioPadInfo.flags & IoPad.FILLER:
|
||||
spacerCell = self.padLib.getCell( ioPadInfo.name )
|
||||
if spacerCell: self.padSpacers.append( spacerCell )
|
||||
else:
|
||||
raise ErrorMessage( 1, 'CoreToChip.gf180mcu._getPadLib(): Missing spacer cell "{}"'.format(spacerName) )
|
||||
self.padSpacers = sorted( self.padSpacers, key=_cmpPad, reverse=True )
|
||||
|
||||
def getNetType ( self, netName ):
|
||||
if netName.lower().startswith('vss') or netName.lower().startswith('dvss'): return Net.Type.GROUND
|
||||
if netName.lower().startswith('vdd') or netName.lower().startswith('dvdd'): return Net.Type.POWER
|
||||
return Net.Type.LOGICAL
|
||||
|
||||
def isGlobal ( self, netName ):
|
||||
if netName in self.ringNetNames: return True
|
||||
return False
|
||||
|
||||
def getCell ( self, masterCellName ):
|
||||
#cell = self.padLib.getCell( masterCellName )
|
||||
cell = AllianceFramework.get().getCell( masterCellName, Catalog.State.Views )
|
||||
if not cell:
|
||||
raise ErrorMessage( 1, 'libresocio.getCell(): I/O pad library "%s" does not contain cell named "%s"' \
|
||||
% (self.padLib.getName(),masterCellName) )
|
||||
return cell
|
||||
|
||||
def _buildAllGroundPads ( self, ioPadConf ):
|
||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||
padNet = 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 )
|
||||
self.icore.getPlug( coreNet ).setNet( coronaNet )
|
||||
if not chipNet:
|
||||
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName )
|
||||
chipNet.setExternal( True )
|
||||
chipNet.setType ( Net.Type.GROUND )
|
||||
if not padNet:
|
||||
padNet = Net.create( self.chip, ioPadConf.padSupplyNetName )
|
||||
padNet.setExternal( True )
|
||||
padNet.setType ( Net.Type.GROUND )
|
||||
coronaPlug = self.icorona.getPlug( coronaNet )
|
||||
if not coronaPlug.getNet():
|
||||
coronaPlug.setNet( chipNet )
|
||||
self.ringNetNames['DVSS' ] = chipNet
|
||||
#self.ringNetNames['VSS' ] = padNet
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_iovss_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['vss']) ) )
|
||||
#self._connect( ioPadConf.pads[0], chipNet, 'VSS' )
|
||||
self._connect( ioPadConf.pads[0], padNet , 'DVSS' )
|
||||
self.groundPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
|
||||
def _buildAllPowerPads ( self, ioPadConf ):
|
||||
trace( 550, ',+', '\tgf180mcu.CoreToChip()\n' )
|
||||
trace( 550, '\tcoreSupplyNetName="{}"\n'.format( ioPadConf.coreSupplyNetName ))
|
||||
trace( 550, '\tpadSupplyNetName ="{}"\n'.format( ioPadConf.padSupplyNetName ))
|
||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||
padNet = 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 )
|
||||
self.icore.getPlug( coreNet ).setNet( coronaNet )
|
||||
if not chipNet:
|
||||
chipNet = Net.create( self.chip, ioPadConf.coreSupplyNetName )
|
||||
chipNet.setExternal( True )
|
||||
chipNet.setType ( Net.Type.POWER )
|
||||
self.icorona.getPlug( coronaNet ).setNet( chipNet )
|
||||
trace( 550, '\tchipNet ="{}"\n'.format( chipNet ))
|
||||
if not padNet:
|
||||
padNet = Net.create( self.chip, ioPadConf.padSupplyNetName )
|
||||
padNet.setExternal( True )
|
||||
padNet.setType ( Net.Type.POWER )
|
||||
self.ringNetNames['DVDD'] = chipNet
|
||||
#self.ringNetNames['VDD'] = padNet
|
||||
trace( 550, '\tpadNet ="{}"\n'.format( padNet ))
|
||||
ioPadConf.pads.append( Instance.create( self.chip
|
||||
, 'p_iovdd_{}'.format(ioPadConf.index)
|
||||
, self.getCell(self.ioPadNames['vdd']) ) )
|
||||
#self._connect( ioPadConf.pads[0], chipNet, 'VDD' )
|
||||
self._connect( ioPadConf.pads[0], padNet , 'DVDD' )
|
||||
self.powerPadCount += 1
|
||||
self.chipPads += ioPadConf.pads
|
||||
trace( 550, '-,' )
|
||||
|
||||
def _buildClockPads ( self, ioPadConf ):
|
||||
"""For "GF180MCU" there is no specialized clock I/O pad. So do nothing."""
|
||||
pass
|
||||
|
||||
def _connectClocks ( self ):
|
||||
"""For "GF180MCU" there is no pad internal clock ring. So do nothing."""
|
||||
pass
|
||||
|
||||
def hasCornerCell ( self ):
|
||||
"""Overload of CoreToChip, YES we have dedicated corner cells."""
|
||||
return True
|
||||
|
||||
def hasFillerCells ( self ):
|
||||
"""Overload of CoreToChip, YES we have dedicated filler cells."""
|
||||
return True
|
||||
|
||||
def getCornerCell ( self ):
|
||||
"""Return the model of corner cell."""
|
||||
return self.getCell( self.ioPadNames['corner'] )
|
||||
|
||||
def createSpacer ( self, gapWidth ):
|
||||
"""Return a new instance of spacer cell."""
|
||||
spacerCell = None
|
||||
for candidate in self.padSpacers:
|
||||
if gapWidth >= candidate.getAbutmentBox().getWidth():
|
||||
spacerCell = candidate
|
||||
break
|
||||
if not spacerCell:
|
||||
return None
|
||||
spacer = Instance.create( self.chip
|
||||
, 'pad_spacer_{}'.format( self.spacerCount )
|
||||
, spacerCell )
|
||||
self.spacerCount += 1
|
||||
#self._connect( spacer, self.ringNetNames['vddring'], 'vddring' )
|
||||
self._connect( spacer, self.ringNetNames['DVDD'], 'DVDD' )
|
||||
#self._connect( spacer, self.ringNetNames['gndring'], 'gndring' )
|
||||
self._connect( spacer, self.ringNetNames['DVSS'], 'DVSS' )
|
||||
return spacer
|
||||
|
||||
def createCorner ( self, instanceName=None ):
|
||||
"""Return a new instance of corner cell."""
|
||||
if instanceName is None:
|
||||
instanceName = 'pad_corner_{}'.format( self.cornerCount )
|
||||
corner = Instance.create( self.chip, instanceName, self.getCornerCell() )
|
||||
self.cornerCount += 1
|
||||
self._connect( corner, self.ringNetNames['DVDD'], 'DVDD' )
|
||||
#self._connect( corner, self.ringNetNames['vddcore'], 'vddcore' )
|
||||
self._connect( corner, self.ringNetNames['DVSS'], 'DVSS' )
|
||||
#self._connect( corner, self.ringNetNames['gndcore'], 'gndcore' )
|
||||
return corner
|
Loading…
Reference in New Issue