Add core2chip file for gf180mcu
This is a copy of the sky130 one.
This commit is contained in:
parent
1262f65eec
commit
7b04a76fae
|
@ -74,6 +74,7 @@
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/niolib.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/libresocio.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/sky130.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/gf180mcu.py
|
||||
)
|
||||
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) Sorbonne Université 2020-2021, 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/sky130.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
"""
|
||||
Core2Chip configuration for the Sky130 harness.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from Hurricane import DbU, DataBase, UpdateSession, Breakpoint, \
|
||||
Transformation , Box, Instance , Net, \
|
||||
Contact
|
||||
import Viewer
|
||||
from CRL import Catalog
|
||||
from CRL import AllianceFramework, DefImport
|
||||
from helpers import trace, l, u, n
|
||||
from helpers.io import ErrorMessage, WarningMessage
|
||||
from helpers.overlay import CfgCache, UpdateSession
|
||||
import plugins.alpha.chip
|
||||
from plugins.alpha.block.configuration import IoPin, GaugeConf
|
||||
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"
|
||||
|
||||
class CoreToChip ( BaseCoreToChip ):
|
||||
"""
|
||||
Provide harness-specific part for SkyWater 130 (works in real mode).
|
||||
Emulate the behavior of I/O pads.
|
||||
"""
|
||||
rePadType = re.compile(r'(?P<type>.+)_(?P<index>[\d]+)$')
|
||||
|
||||
def __init__ ( self, core ):
|
||||
self.ioPadNames = { 'bidir' :'IOHarnessInOut'
|
||||
, 'analog':'IOHarnessAnalog'
|
||||
, 'vdd' :'IOHarnessVdd'
|
||||
, 'vss' :'IOHarnessVss'
|
||||
, 'iovdd' :'IOHarnessIOVdd'
|
||||
, 'iovss' :'IOHarnessIOVss'
|
||||
}
|
||||
BaseCoreToChip.__init__ ( self, core )
|
||||
self.conf.useHarness = True
|
||||
self.ringNetNames = { 'vssa2' : None
|
||||
, 'vdda2' : None
|
||||
, 'vssa1' : None
|
||||
, 'vdda1' : None
|
||||
, 'vssd2' : None
|
||||
, 'vccd2' : None
|
||||
, 'vssd1' : None
|
||||
, 'vccd1' : None
|
||||
}
|
||||
self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.BIDIR
|
||||
, self.ioPadNames['bidir']
|
||||
, 'pad', ['io_in', 'io_out', 'io_oeb'] )
|
||||
, BaseCoreToChip.IoPadInfo( IoPad.ANALOG
|
||||
, self.ioPadNames['analog']
|
||||
, 'pad', ['pad', 'padres'] )
|
||||
]
|
||||
self._getPadLib()
|
||||
if self.conf.chipConf.ioPadsCount() == 0:
|
||||
MatchHarnessIos( self ).matchCore()
|
||||
return
|
||||
|
||||
def _getPadLib ( self ):
|
||||
return None
|
||||
|
||||
def getNetType ( self, netName ):
|
||||
if netName.startswith('vss') or netName.startswith('vee'): return Net.Type.GROUND
|
||||
if netName.startswith('vdd') or netName.startswith('vcc'): 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 ):
|
||||
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.padSupplyNetName )
|
||||
if not coronaNet:
|
||||
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
|
||||
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:
|
||||
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.groundPadCount += 1
|
||||
|
||||
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.padSupplyNetName )
|
||||
if not coronaNet:
|
||||
coronaNet = Net.create( self.corona, ioPadConf.coreSupplyNetName )
|
||||
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:
|
||||
raise ErrorMessage( 1, 'Harness do not provide power net ""{}' \
|
||||
.format( ioPadConf.padSupplyNetName ))
|
||||
self.icorona.getPlug( coronaNet ).setNet( chipNet )
|
||||
coronaPlug = self.icorona.getPlug( coronaNet )
|
||||
if not coronaPlug.getNet():
|
||||
coronaPlug.setNet( chipNet )
|
||||
self.powerPadCount += 1
|
||||
|
||||
def _buildClockPads ( self, ioPadConf ):
|
||||
"""For "Sky130" there is no specialized clock I/O pad. So do nothing."""
|
||||
pass
|
||||
|
||||
def _connectClocks ( self ):
|
||||
"""For "Sky130" there is no pad internal clock ring. So do nothing."""
|
||||
pass
|
||||
|
||||
def _loadHarness ( self ):
|
||||
"""
|
||||
Load the DEF file containing the reference harness layout.
|
||||
Remove the supplied internal power grid and slightly shrink
|
||||
the central P&R area so that I/O pins are fully outside of it.
|
||||
"""
|
||||
self.harness = DefImport.load( self.conf.cfg.harness.path )
|
||||
innerAb = self.harness.getAbutmentBox()
|
||||
wholeBb = self.harness.getBoundingBox()
|
||||
filterBb = Box( wholeBb.getXMin(), innerAb.getYMin()
|
||||
, wholeBb.getXMax(), innerAb.getYMax() )
|
||||
components = []
|
||||
for component in self.harness.getComponentsUnder( filterBb ):
|
||||
if component.getNet().isSupply() and filterBb.contains( component.getBoundingBox() ):
|
||||
components.append( component )
|
||||
for instance in self.harness.getInstancesUnder( filterBb ):
|
||||
components.append( instance )
|
||||
with UpdateSession():
|
||||
for component in components:
|
||||
component.destroy()
|
||||
components = []
|
||||
filterBb = Box( innerAb.getXMin(), wholeBb.getYMin()
|
||||
, innerAb.getXMax(), wholeBb.getYMax() )
|
||||
for component in self.harness.getComponentsUnder( filterBb ):
|
||||
if component.getNet().isSupply() and filterBb.contains( component.getBoundingBox() ):
|
||||
components.append( component )
|
||||
for instance in self.harness.getInstancesUnder( filterBb ):
|
||||
components.append( instance )
|
||||
with UpdateSession():
|
||||
for component in components:
|
||||
component.destroy()
|
||||
areaXMin = innerAb.getXMin()
|
||||
areaYMin = innerAb.getYMin()
|
||||
areaXMax = innerAb.getXMax()
|
||||
areaYMax = innerAb.getYMax()
|
||||
for net in self.harness.getNets():
|
||||
if net.isSupply(): continue
|
||||
for component in net.getComponents():
|
||||
trace( 550, '\t| {}\n'.format(component) )
|
||||
bb = component.getBoundingBox()
|
||||
side = None
|
||||
if bb.getXMin() < innerAb.getXMin():
|
||||
areaXMin = max( areaXMin, bb.getXMax() )
|
||||
side = IoPin.WEST
|
||||
if bb.getXMax() > innerAb.getXMax():
|
||||
areaXMax = min( areaXMax, bb.getXMin() )
|
||||
side = IoPin.EAST
|
||||
if bb.getYMin() < innerAb.getYMin():
|
||||
areaYMin = max( areaYMin, bb.getYMax() )
|
||||
side = IoPin.SOUTH
|
||||
if bb.getYMax() > innerAb.getYMax():
|
||||
areaYMax = min( areaYMax, bb.getYMin() )
|
||||
side = IoPin.NORTH
|
||||
trace( 550, '\tside: {} {}\n'.format(side,type(component)) )
|
||||
if side and isinstance(component,Contact):
|
||||
trace( 550, '\tAdded on {} side: {}\n'.format(side,component) )
|
||||
self.conf.chipConf.addHarnessPin( component, side )
|
||||
area = Box( areaXMin, areaYMin, areaXMax, areaYMax )
|
||||
area.inflate( - self.conf.hRoutingGauge.getPitch()*2
|
||||
, - self.conf.vRoutingGauge.getPitch()*2 )
|
||||
xmodulo = area.getWidth () % self.conf.sliceStep
|
||||
ymodulo = area.getHeight() % self.conf.sliceHeight
|
||||
area.inflate( 0, 0, -xmodulo, -ymodulo )
|
||||
self.harness.setAbutmentBox( area )
|
||||
return self.harness
|
Loading…
Reference in New Issue