Support of FlexLib I/O in Core2Chip & chip plugins (alpha).

* New: In cumulus/plugins/core2chip/, support for the FlexLib I/O cells
    symbolic abstracts ("niolib"). More flexible way of specifying the
    number and positions of the various power pads, both I/O power and
    core power.
      For niolib (FlexLib I/O abstract), support for multiple clocks,
    that is, clock become ordinary pad (with signals typed as CLOCK).
* New: In cumulus/plugins/chip/, added support for niolib and final
    integration of multiple clocks (only for niolib).
This commit is contained in:
Jean-Paul Chaput 2020-11-02 17:42:32 +01:00
parent f8a9dd9f71
commit 541b23216c
11 changed files with 573 additions and 282 deletions

View File

@ -60,6 +60,7 @@
set ( pyPluginAlphaC2C ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/__init__.py set ( pyPluginAlphaC2C ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/core2chip.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/core2chip.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/cmos.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/cmos.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/niolib.py
) )
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py

View File

@ -422,11 +422,15 @@ class IoPadConf ( object ):
| | meta-generated power/ground/clock pads | | | meta-generated power/ground/clock pads |
+---------+-----------------------------------------------------------+ +---------+-----------------------------------------------------------+
""" """
POWER = 0x0001 CORE_POWER = 0x0001
GROUND = 0x0002 CORE_GROUND = 0x0002
CLOCK = 0x0004 IO_POWER = 0x0004
TRISTATE = 0x0008 IO_GROUND = 0x0008
BIDIR = 0x0010 ALL_POWER = 0x0010
ALL_GROUND = 0x0020
CLOCK = 0x0040
TRISTATE = 0x0080
BIDIR = 0x0100
def __init__ ( self, datas ): def __init__ ( self, datas ):
if not isinstance(datas,tuple): if not isinstance(datas,tuple):
@ -438,6 +442,7 @@ class IoPadConf ( object ):
self.flags = 0 self.flags = 0
self.index = None self.index = None
self._datas = list( datas ) self._datas = list( datas )
if len(self._datas) == 4: self._datas += [ None, None, None ]
if len(self._datas) == 5: self._datas += [ None, None ] if len(self._datas) == 5: self._datas += [ None, None ]
elif len(self._datas) == 6: self._datas.insert( 5, None ) elif len(self._datas) == 6: self._datas.insert( 5, None )
self._datas.append( [] ) self._datas.append( [] )
@ -445,9 +450,13 @@ class IoPadConf ( object ):
m = reSpecialPads.match( self.instanceName ) m = reSpecialPads.match( self.instanceName )
if m: if m:
self.index = m.group('index') self.index = m.group('index')
if m.group('type') == 'power' : self.flags |= IoPadConf.POWER if m.group('type') == 'allpower': self.flags |= IoPadConf.ALL_POWER
if m.group('type') == 'ground': self.flags |= IoPadConf.GROUND if m.group('type') == 'iopower': self.flags |= IoPadConf.IO_POWER
if m.group('type') == 'clock' : self.flags |= IoPadConf.CLOCK if m.group('type') == 'power': self.flags |= IoPadConf.CORE_POWER
if m.group('type') == 'allground': self.flags |= IoPadConf.ALL_GROUND
if m.group('type') == 'ioground': self.flags |= IoPadConf.IO_GROUND
if m.group('type') == 'ground': self.flags |= IoPadConf.CORE_GROUND
if m.group('type') == 'clock' : self.flags |= IoPadConf.CLOCK
else: else:
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE
@ -478,7 +487,9 @@ class IoPadConf ( object ):
def padSupplyNetName ( self ): return self._datas[3] def padSupplyNetName ( self ): return self._datas[3]
@property @property
def coreSupplyNetName ( self ): return self._datas[4] def coreSupplyNetName ( self ):
if self._datas[4] is not None: return self._datas[4]
return self._datas[3]
@property @property
def padClockNetName ( self ): return self._datas[4] def padClockNetName ( self ): return self._datas[4]
@ -492,11 +503,15 @@ class IoPadConf ( object ):
@property @property
def pads ( self ): return self._datas[7] def pads ( self ): return self._datas[7]
def isPower ( self ): return self.flags & IoPadConf.POWER def isCorePower ( self ): return self.flags & IoPadConf.CORE_POWER
def isGround ( self ): return self.flags & IoPadConf.GROUND def isIoPower ( self ): return self.flags & IoPadConf.IO_POWER
def isClock ( self ): return self.flags & IoPadConf.CLOCK def isAllPower ( self ): return self.flags & IoPadConf.ALL_POWER
def isTristate ( self ): return self.flags & IoPadConf.TRISTATE def isCoreGround ( self ): return self.flags & IoPadConf.CORE_GROUND
def isBidir ( self ): return self.flags & IoPadConf.BIDIR def isIoGround ( self ): return self.flags & IoPadConf.IO_GROUND
def isAllGround ( self ): return self.flags & IoPadConf.ALL_GROUND
def isClock ( self ): return self.flags & IoPadConf.CLOCK
def isTristate ( self ): return self.flags & IoPadConf.TRISTATE
def isBidir ( self ): return self.flags & IoPadConf.BIDIR
def __repr__ ( self ): def __repr__ ( self ):
s = '<IoPadConf {} pad:{} from:{}'.format(self.instanceName,self.padNetName,self.fromCoreNetName) s = '<IoPadConf {} pad:{} from:{}'.format(self.instanceName,self.padNetName,self.fromCoreNetName)

View File

@ -26,14 +26,16 @@ dictionnary of other modules.
from __future__ import print_function from __future__ import print_function
from helpers.io import WarningMessage from helpers.io import WarningMessage
North = 0x0001 North = 0x0001
South = 0x0002 South = 0x0002
East = 0x0004 East = 0x0004
West = 0x0008 West = 0x0008
SouthWest = South|West SouthWest = South|West
SouthEast = South|East SouthEast = South|East
NorthWest = North|West NorthWest = North|West
NorthEast = North|East NorthEast = North|East
HORIZONTAL = North|South
VERTICAL = East |West
Superior = 0x0010 Superior = 0x0010
Inferior = 0x0020 Inferior = 0x0020

View File

@ -113,7 +113,7 @@ class Chip ( Block ):
def doConnectCore ( self ): def doConnectCore ( self ):
power = plugins.alpha.chip.power.Builder( self.conf ) power = plugins.alpha.chip.power.Builder( self.conf )
power.connectPower() power.connectPower()
power.connectClock() power.connectClocks()
power.doLayout() power.doLayout()
self.conf.refresh() self.conf.refresh()
corona = plugins.alpha.chip.corona.Builder( power ) corona = plugins.alpha.chip.corona.Builder( power )

View File

@ -16,36 +16,25 @@ from __future__ import print_function
import sys import sys
import os.path import os.path
import Cfg import Cfg
from Hurricane import Breakpoint from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
from Hurricane import DbU Path, Layer, Occurrence, Net, RoutingPad, \
from Hurricane import Box Horizontal, Vertical, Contact, Pin, Plug, \
from Hurricane import Transformation Instance
from Hurricane import Box
from Hurricane import Path
from Hurricane import Layer
from Hurricane import Occurrence
from Hurricane import Net
from Hurricane import RoutingPad
from Hurricane import Horizontal
from Hurricane import Vertical
from Hurricane import Contact
from Hurricane import Pin
from Hurricane import Plug
from Hurricane import Instance
import CRL import CRL
from CRL import RoutingLayerGauge from CRL import RoutingLayerGauge
from helpers import trace from helpers import trace
from helpers.utils import classdecorator from helpers.utils import classdecorator
from helpers.overlay import UpdateSession from helpers.overlay import UpdateSession
from helpers.io import ErrorMessage from helpers.io import ErrorMessage, WarningMessage, \
from helpers.io import WarningMessage vprint, catch
from helpers.io import catch
from plugins import getParameter
import plugins.chip import plugins.chip
from plugins.alpha.block.configuration import BlockConf from plugins.alpha.block.configuration import BlockConf
__all__ = [ 'ChipConf' ]
plugins.alpha.chip.importConstants( globals() ) plugins.alpha.chip.importConstants( globals() )
af = CRL.AllianceFramework.get()
# ------------------------------------------------------------------- # -------------------------------------------------------------------
@ -116,7 +105,7 @@ class ChipConf ( BlockConf ):
# Global Nets. # Global Nets.
self.coronaVdd = None self.coronaVdd = None
self.coronaVss = None self.coronaVss = None
self.coronaCk = None self.coronaCks = []
self.blockageNet = None self.blockageNet = None
self.padsHavePosition = False self.padsHavePosition = False
trace( 550, '-' ) trace( 550, '-' )
@ -146,9 +135,13 @@ class ChipConf ( BlockConf ):
return self.cfg.chip.block.rails.vSpacing return self.cfg.chip.block.rails.vSpacing
def computeCoronaBorder ( self ): def computeCoronaBorder ( self ):
global af
if self.useClockTree: if self.useClockTree:
trace( 550, '\tcomputeCoronaBorder() useClockTree: {}\n'.format(self.useClockTree) ) clockNets = []
self.railsCount = self.cfg.chip.block.rails.count + 1 for net in self.cellPnR.getNets():
if net.isClock():
clockNets.append( net )
self.railsCount = self.cfg.chip.block.rails.count + len(clockNets)
trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) ) trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) )
self.minHCorona = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + self.sliceHeight self.minHCorona = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + self.sliceHeight
self.minVCorona = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + 10*self.sliceStep self.minVCorona = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + 10*self.sliceStep
@ -259,7 +252,7 @@ class ChipConf ( BlockConf ):
return axis, width return axis, width
def toCoronaPitchInChip ( self, uCore, layer ): def toCoronaPitchInChip ( self, uCore, layer ):
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {}l %s\n' \ trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {}l {}\n' \
.format(DbU.toLambda(uCore), DbU.getValueString(uCore)) ) .format(DbU.toLambda(uCore), DbU.getValueString(uCore)) )
coronaAb = self.getInstanceAb( self.icorona ) coronaAb = self.getInstanceAb( self.icorona )
lg = None lg = None
@ -378,9 +371,24 @@ class ChipConf ( BlockConf ):
trace( 550, '-' ) trace( 550, '-' )
return c return c
def getViaPitch ( self, viaLayer ):
topLayer = viaLayer.getTop()
topPitch = 2*viaLayer.getEnclosure \
( topLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
+ viaLayer.getMinimalSize() \
+ topLayer.getMinimalSpacing()
botLayer = viaLayer.getBottom()
botPitch = 2*viaLayer.getEnclosure \
( botLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
+ viaLayer.getMinimalSize() \
+ botLayer.getMinimalSpacing()
viaPitch = max( topPitch, botPitch )
trace( 550, '\tgetViaPitch of {}: {}l\n'.format(viaLayer.getName(),DbU.getValueString(viaPitch)) )
return viaPitch
def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ): def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
trace( 550, ',+', '\tChipConf.coronaContactArray\n' ) trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
viaPitch = layer.getMinimalSize() + layer.getMinimalSpacing() viaPitch = self.getViaPitch( layer )
coronaAb = self.getInstanceAb( self.icorona ) coronaAb = self.getInstanceAb( self.icorona )
coronaNet = self.getCoronaNet( chipNet ) coronaNet = self.getCoronaNet( chipNet )
if not coronaNet: return None if not coronaNet: return None
@ -481,7 +489,7 @@ class ChipConf ( BlockConf ):
.format(i,padList[i][1],side) )) .format(i,padList[i][1],side) ))
return return
af = CRL.AllianceFramework.get() global af
cellPads = [] cellPads = []
for instance in self.chip.getInstances(): for instance in self.chip.getInstances():
if contains(self.southPads,'south',instance): continue if contains(self.southPads,'south',instance): continue
@ -559,13 +567,9 @@ class ChipConf ( BlockConf ):
self.coronaVdd = net self.coronaVdd = net
if netType == Net.Type.CLOCK: if netType == Net.Type.CLOCK:
if self.coronaCk and self.coronaCk != net: if not net in self.coronaCks:
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple clock nets "{}" and "{}" at corona level.' \ self.coronaCks.append( net )
.format(self.coronaCk.getName(), net.getName()) ) vprint( 2, ' - Using clock "{}".'.format(net.getName()) )
self._validated = False
continue
else:
self.coronaCk = net
for net in self.corona.getNets(): for net in self.corona.getNets():
if net.getType() == Net.Type.BLOCKAGE: if net.getType() == Net.Type.BLOCKAGE:
self.blockageNet = net self.blockageNet = net

View File

@ -105,29 +105,37 @@ class HorizontalRail ( Rail ):
trace( 550, '\t{}\n'.format(self) ) trace( 550, '\t{}\n'.format(self) )
def __str__ ( self ): def __str__ ( self ):
return '<HorizontalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order) return '<HorizontalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order).getName()
, self.order , self.order
, DbU.getValueString(self.axis) ) , DbU.getValueString(self.axis) )
def connect ( self, contact ): def connect ( self, contact ):
trace( 550, ',+', '\tTry to connect to: {}\n'.format(self) )
contactBb = contact.getBoundingBox() contactBb = contact.getBoundingBox()
if contactBb.getXMin() < self.side.innerBb.getXMin() \ if contactBb.getXMin() < self.side.innerBb.getXMin() \
or contactBb.getXMax() > self.side.innerBb.getXMax(): or contactBb.getXMax() > self.side.innerBb.getXMax():
trace( 550, '-' )
raise ErrorMessage( 1, [ '{} is outside rail/corona X range,'.format(contact) raise ErrorMessage( 1, [ '{} is outside rail/corona X range,'.format(contact)
, 'power pad is likely to be to far off west or east.' , 'power pad is likely to be to far off west or east.'
, '(core:{})'.format(self.side.innerBb) ] ) , '(core:{})'.format(self.side.innerBb) ] )
if self.vias.has_key(contact.getX()): return False if self.vias.has_key(contact.getX()): return False
trace( 550, '\tvias:{}\n'.format(self.vias) )
keys = self.vias.keys() keys = self.vias.keys()
keys.sort() keys.sort()
insertIndex = bisect.bisect_left( keys, contact.getX() ) insertIndex = bisect.bisect_left( keys, contact.getX() )
if len(keys) > 0: if len(keys) > 0:
trace( 550, '\tinsertIndex:{}\n'.format(insertIndex) )
if insertIndex < len(keys): if insertIndex < len(keys):
insertPosition = keys[ insertIndex ] insertPosition = keys[ insertIndex ]
trace( 550, '\tinsertPosition:{}\n'.format(insertPosition) )
if contactBb.getXMax() >= self.vias[insertPosition][2].getBoundingBox().getXMin(): if contactBb.getXMax() >= self.vias[insertPosition][2].getBoundingBox().getXMin():
trace( 550, ',-', '\tFailed: overlap with existing contact @{}.\n' \
.format(self.vias[insertPosition][2]) )
return False return False
if insertIndex > 0: if insertIndex > 0:
if self.vias[keys[insertIndex-1]][2].getBoundingBox().getXMax() >= contactBb.getXMin(): if self.vias[keys[insertIndex-1]][2].getBoundingBox().getXMax() >= contactBb.getXMin():
trace( 550, ',-', '\tFailed: overlap with existing contact @{}.\n' \
.format(self.vias[keys[insertIndex-1]][2]) )
return False return False
self.vias[ contact.getX() ] = [ contact.getX() self.vias[ contact.getX() ] = [ contact.getX()
, StackedVia( self.net , StackedVia( self.net
@ -144,6 +152,7 @@ class HorizontalRail ( Rail ):
, DbU.getValueString(contact.getX()) , DbU.getValueString(contact.getX())
, DbU.getValueString(self.axis)) ) , DbU.getValueString(self.axis)) )
self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) )
trace( 550, '-' )
return True return True
def doLayout ( self ): def doLayout ( self ):
@ -183,7 +192,7 @@ class VerticalRail ( Rail ):
trace( 550, '\t{}\n'.format(self) ) trace( 550, '\t{}\n'.format(self) )
def __str__ ( self ): def __str__ ( self ):
return '<VerticalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order) return '<VerticalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order).getName()
, self.order , self.order
, DbU.getValueString(self.axis) ) , DbU.getValueString(self.axis) )
@ -217,14 +226,14 @@ class VerticalRail ( Rail ):
, 'power pad is likely to be to far off north or south.' , 'power pad is likely to be to far off north or south.'
, '(core:{})'.format(self.side.innerBb) ] ) , '(core:{})'.format(self.side.innerBb) ] )
if self.vias.has_key(contact.getY()): return False if self.vias.has_key(contact.getY()): return False
trace( 550, ',+', '\tVerticalRail.connect() [{}] @{}\n'.format(self.order,DbU.toLambda(self.axis)) ) trace( 550, ',+', '\tVerticalRail.connect() [{}] @{}\n'.format(self.order,DbU.getValueString(self.axis)) )
trace( 550, '\t{}\n'.format(contact) ) trace( 550, '\t{}\n'.format(contact) )
keys = self.vias.keys() keys = self.vias.keys()
keys.sort() keys.sort()
insertIndex = bisect.bisect_left( keys, contact.getY() ) insertIndex = bisect.bisect_left( keys, contact.getY() )
trace( 550, ',+', '\tkeys:' ) trace( 550, ',+', '\tkeys:' )
for key in keys: for key in keys:
trace( 550, ' {}'.format(DbU.toLambda(key)) ) trace( 550, ' {}'.format(DbU.getValueString(key)) )
trace( 550, '\n' ) trace( 550, '\n' )
if len(keys) > 0: if len(keys) > 0:
@ -266,9 +275,18 @@ class Side ( object ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
self.corona = corona self.corona = corona
@property
def side ( self ):
raise NotImplementedError('Side.side is not implemented in base class.')
@property @property
def railsCount ( self ): return self.corona.railsCount def railsCount ( self ): return self.corona.railsCount
@property
def coronaCks ( self ):
if self.corona.conf.useClockTree: return self.corona.conf.coronaCks
return []
@property @property
def innerBb ( self ): return self.corona.innerBb def innerBb ( self ): return self.corona.innerBb
@ -296,6 +314,7 @@ class Side ( object ):
@property @property
def blockageNet ( self ): return self.corona.blockageNet def blockageNet ( self ): return self.corona.blockageNet
def isHorizontal ( self ): return (self.side & HORIZONTAL) == HORIZONTAL
def getLayerDepth ( self, metal ): return self.corona.getLayerDepth(metal) def getLayerDepth ( self, metal ): return self.corona.getLayerDepth(metal)
def getRail ( self, i ): return self.rails[i] def getRail ( self, i ): return self.rails[i]
def getRailNet ( self, i ): return self.corona.getRailNet(i) def getRailNet ( self, i ): return self.corona.getRailNet(i)
@ -318,27 +337,41 @@ class Side ( object ):
return self.rails[-(i+1)] return self.rails[-(i+1)]
def connect ( self, blockSide ): def connect ( self, blockSide ):
trace( 550, '\tSide.connect()\n' )
for terminal in blockSide.terminals: for terminal in blockSide.terminals:
trace( 550, '\tterminal:{}\n'.format(terminal) ) trace( 550, '\tterminal:{}\n'.format(terminal) )
for rail in self.rails: for rail in self.rails:
rail.connect( terminal[1] ) rail.connect( terminal[1] )
def getRailRange ( self, net ):
if net.isClock(): return range(len(self.rails))
if not net.isSupply(): return []
if self.side & HORIZONTAL:
trace( 550, '\tHORIZONTAL rail.\n' )
return range( len(self.coronaCks), len(self.rails) )
else:
trace( 550, '\t{} > {}\n'.format(self.horizontalDepth,self.verticalDepth) )
if self.horizontalDepth > self.verticalDepth:
return range( len(self.coronaCks), len(self.rails) )
trace( 550, '\tUsing half rails only.\n' )
return range( len(self.coronaCks) + len(self.rails)/2 - 2, len(self.rails) )
def connectPads ( self, padSide ): def connectPads ( self, padSide ):
for contact in padSide.pins: #for contact in padSide.pins:
if contact.getNet().isClock(): # if contact.getNet().isClock():
for i in range(len(self.rails)): # for i in range(len(self.rails)):
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.toLambda(self.getOuterRail(i).axis)) ) # trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.getValueString(self.getOuterRail(i).axis)) )
self.getOuterRail(i).connect( contact ) # self.getOuterRail(i).connect( contact )
elif contact.getNet().isSupply(): # elif contact.getNet().isSupply():
self.getOuterRail( 0 ).connect( contact ) # self.getOuterRail( 0 ).connect( contact )
halfRails = (len(self.rails)-1)/2
trace( 550, '\thalfRails:{}\n'.format(halfRails) )
for contact in padSide.pins: for contact in padSide.pins:
if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue
trace( 550, ',+', '\tConnect pad contact {}\n'.format(contact) ) trace( 550, ',+', '\tConnect pad contact {}\n'.format(contact) )
for i in range(halfRails): railRange = self.getRailRange( contact.getNet() )
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.toLambda(self.getOuterRail(i).axis)) ) trace( 550, '\trailRange:{}\n'.format(railRange) )
self.getOuterRail(i).connect( contact ) for i in railRange:
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.getValueString(self.getInnerRail(i).axis)) )
self.getInnerRail(i).connect( contact )
trace( 550, '-' ) trace( 550, '-' )
def doLayout ( self ): def doLayout ( self ):
@ -367,6 +400,9 @@ class SouthSide ( HorizontalSide ):
HorizontalSide.__init__( self, corona ) HorizontalSide.__init__( self, corona )
return return
@property
def side ( self ): return South
def getRailAxis ( self, i ): def getRailAxis ( self, i ):
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \ return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
- i*(self.hRailWidth + self.hRailSpace) - i*(self.hRailWidth + self.hRailSpace)
@ -384,6 +420,9 @@ class NorthSide ( HorizontalSide ):
HorizontalSide.__init__( self, corona ) HorizontalSide.__init__( self, corona )
return return
@property
def side ( self ): return North
def getRailAxis ( self, i ): def getRailAxis ( self, i ):
return self.innerBb.getYMax() + self.hRailWidth/2 + self.hRailSpace \ return self.innerBb.getYMax() + self.hRailWidth/2 + self.hRailSpace \
+ i*(self.hRailWidth + self.hRailSpace) + i*(self.hRailWidth + self.hRailSpace)
@ -446,12 +485,15 @@ class WestSide ( VerticalSide ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
VerticalSide.__init__( self, corona ) VerticalSide.__init__( self, corona )
@property
def side ( self ): return West
def getRailAxis ( self, i ): def getRailAxis ( self, i ):
return self.innerBb.getXMin() - self.vRailWidth/2 - self.vRailSpace \ return self.innerBb.getXMin() - self.vRailWidth/2 - self.vRailSpace \
- i*(self.vRailWidth + self.vRailSpace) - i*(self.vRailWidth + self.vRailSpace)
def corner0 ( self, i ): return self.corners[SouthWest][i] def corner0 ( self, i ): return self.corners[SouthWest][i]
def corner1 ( self, i ): return self.corners[NorthWest ][i] def corner1 ( self, i ): return self.corners[NorthWest][i]
def addBlockages ( self ): def addBlockages ( self ):
sideXMin = self.getOuterRail(0).axis - self.vRailWidth sideXMin = self.getOuterRail(0).axis - self.vRailWidth
@ -467,12 +509,15 @@ class EastSide ( VerticalSide ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
VerticalSide.__init__( self, corona ) VerticalSide.__init__( self, corona )
@property
def side ( self ): return East
def getRailAxis ( self, i ): def getRailAxis ( self, i ):
return self.innerBb.getXMax() + self.vRailWidth/2 + self.vRailSpace \ return self.innerBb.getXMax() + self.vRailWidth/2 + self.vRailSpace \
+ i*(self.vRailWidth + self.vRailSpace) + i*(self.vRailWidth + self.vRailSpace)
def corner0 ( self, i ): return self.corners[SouthEast][i] def corner0 ( self, i ): return self.corners[SouthEast][i]
def corner1 ( self, i ): return self.corners[NorthEast ][i] def corner1 ( self, i ): return self.corners[NorthEast][i]
def addBlockages ( self ): def addBlockages ( self ):
sideXMin = self.getInnerRail(0).axis - self.vRailWidth sideXMin = self.getInnerRail(0).axis - self.vRailWidth
@ -532,7 +577,8 @@ class Builder ( object ):
return self.conf.routingGauge.getLayerDepth( metal ) return self.conf.routingGauge.getLayerDepth( metal )
def getRailNet ( self, i ): def getRailNet ( self, i ):
if self.conf.useClockTree and i == 0: return self.conf.coronaCk if self.conf.useClockTree and i < len(self.conf.coronaCks):
return self.conf.coronaCks[i]
if i % 2: return self.conf.coronaVss if i % 2: return self.conf.coronaVss
return self.conf.coronaVdd return self.conf.coronaVdd

View File

@ -278,78 +278,64 @@ class Side ( object ):
self.u += gapWidth self.u += gapWidth
def _placePad ( self, padInstance ): def _placePad ( self, padInstance ):
if self.type == North: if self.type == North:
x = self.conf.chipAb.getXMin() + self.u x = self.conf.chipAb.getXMin() + self.u
y = self.conf.chipAb.getYMax() y = self.conf.chipAb.getYMax()
if self.corona.padOrient == Transformation.Orientation.ID:
if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.MY
orientation = Transformation.Orientation.MY else:
else: orientation = Transformation.Orientation.ID
orientation = Transformation.Orientation.ID y -= self.conf.ioPadHeight
y -= self.conf.ioPadHeight elif self.type == South:
x = self.conf.chipAb.getXMin() + self.u
elif self.type == South: y = self.conf.chipAb.getYMin()
x = self.conf.chipAb.getXMin() + self.u if self.corona.padOrient == Transformation.Orientation.ID:
y = self.conf.chipAb.getYMin() orientation = Transformation.Orientation.ID
else:
if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.MY
orientation = Transformation.Orientation.ID y += self.conf.ioPadHeight
else: elif self.type == West:
orientation = Transformation.Orientation.MY x = self.conf.chipAb.getXMin()
y += self.conf.ioPadHeight y = self.conf.chipAb.getYMin() + self.u
if self.corona.padOrient == Transformation.Orientation.ID:
elif self.type == West: orientation = Transformation.Orientation.R3
x = self.conf.chipAb.getXMin() y += padInstance.getMasterCell().getAbutmentBox().getWidth()
y = self.conf.chipAb.getYMin() + self.u else:
orientation = Transformation.Orientation.R1
if self.corona.padOrient == Transformation.Orientation.ID: x += padInstance.getMasterCell().getAbutmentBox().getHeight()
orientation = Transformation.Orientation.R3 elif self.type == East:
y += padInstance.getMasterCell().getAbutmentBox().getWidth() x = self.conf.chipAb.getXMax()
else: y = self.conf.chipAb.getYMin() + self.u
orientation = Transformation.Orientation.R1 if self.corona.padOrient == Transformation.Orientation.ID:
x += padInstance.getMasterCell().getAbutmentBox().getHeight() orientation = Transformation.Orientation.R1
else:
elif self.type == East: orientation = Transformation.Orientation.R3
x = self.conf.chipAb.getXMax() x -= padInstance.getMasterCell().getAbutmentBox().getHeight()
y = self.conf.chipAb.getYMin() + self.u y += padInstance.getMasterCell().getAbutmentBox().getWidth()
padInstance.setTransformation ( Transformation( self.toGrid(x), self.toGrid(y), orientation ) )
if self.corona.padOrient == Transformation.Orientation.ID: padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED )
orientation = Transformation.Orientation.R1 self.u += padInstance.getMasterCell().getAbutmentBox().getWidth()
else: p = None
orientation = Transformation.Orientation.R3 if self.conf.ioPadGauge.getName() == 'pxlib':
x -= padInstance.getMasterCell().getAbutmentBox().getHeight() p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' )
y += padInstance.getMasterCell().getAbutmentBox().getWidth() if self.conf.ioPadGauge.getName().startswith('phlib'):
p = re.compile( r'p(?P<power>v[sd]{2})ck2_sp' )
padInstance.setTransformation ( Transformation( self.toGrid(x), self.toGrid(y), orientation ) ) if self.conf.ioPadGauge.getName() == 'niolib':
padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED ) p = re.compile( r'(?P<power>(io)?v[sd]{2})' )
if p:
self.u += padInstance.getMasterCell().getAbutmentBox().getWidth() m = p.match( padInstance.getMasterCell().getName() )
padName = 'pad'
p = None if m: padName = m.group( 'power' )
if self.conf.ioPadGauge.getName() == 'pxlib': padNet = padInstance.getMasterCell().getNet( padName )
p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' ) trace( 550, '\tpadName:{} padNet:{}\n'.format(padName,padNet) )
if padNet:
if self.conf.ioPadGauge.getName().startswith('phlib'): plug = padInstance.getPlug( padNet )
p = re.compile( r'p(?P<power>v[sd]{2})ck2_sp' ) chipNet = plug.getNet()
if not chipNet and padNet.isGlobal():
if p: chipNet = padInstance.getCell().getNet( padNet.getName() )
m = p.match( padInstance.getMasterCell().getName() ) if chipNet:
rp = RoutingPad.create( chipNet, Occurrence(plug), RoutingPad.BiggestArea )
padName = 'pad' return
if m: padName = m.group( 'power' )
padNet = padInstance.getMasterCell().getNet( padName )
#print 'padName:', padName, 'padNet:', padNet
if padNet:
plug = padInstance.getPlug( padNet )
chipNet = plug.getNet()
if not chipNet and padNet.isGlobal():
chipNet = padInstance.getCell().getNet( padNet.getName() )
if chipNet:
rp = RoutingPad.create( chipNet, Occurrence(plug), RoutingPad.BiggestArea )
return
def _placePads ( self ): def _placePads ( self ):
padLength = 0 padLength = 0
@ -483,7 +469,6 @@ class Side ( object ):
class CoreWire ( object ): class CoreWire ( object ):
# Should be read from the symbolic technology rules. # Should be read from the symbolic technology rules.
viaPitch = DbU.fromLambda( 4.0 )
NoOffset = 0x0000 NoOffset = 0x0000
AtBegin = 0x0001 AtBegin = 0x0001
@ -501,6 +486,9 @@ class CoreWire ( object ):
self.inCoronaRange = True self.inCoronaRange = True
self.arraySize = None self.arraySize = None
self.count = count self.count = count
self.viaPitch = DbU.fromLambda( 4.0 )
self.gapWidth = 0
self._computeCoreLayers()
@property @property
def conf ( self ): return self.corona.conf def conf ( self ): return self.corona.conf
@ -548,22 +536,22 @@ class CoreWire ( object ):
self.symContactSize = ( self.bbSegment.getHeight(), self.bbSegment.getHeight() ) self.symContactSize = ( self.bbSegment.getHeight(), self.bbSegment.getHeight() )
else: else:
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() ) self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() )
self.viaPitch = self.conf.getViaPitch( self.symContactLayer )
contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer() contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer()
, Layer.EnclosureH|Layer.EnclosureV ) \ , Layer.EnclosureH|Layer.EnclosureV ) \
+ self.symContactLayer.getMinimalSize() + self.symContactLayer.getMinimalSize()
arrayWidth = self.symContactSize[0] arrayWidth = self.symContactSize[0]
arrayCount = (arrayWidth - contactMinSize) / CoreWire.viaPitch arrayCount = (arrayWidth - contactMinSize) / self.viaPitch
trace( 550, '\tCoreWire.viaPitch: {}l\n'.format(DbU.toLambda(CoreWire.viaPitch)) )
trace( 550, '\tcontactMinSize: {}l, arrayWidth: {}l, arrayCount: {}\n' \ trace( 550, '\tcontactMinSize: {}l, arrayWidth: {}l, arrayCount: {}\n' \
.format(DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) ) .format(DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) )
if arrayCount < 0: arrayCount = 0 if arrayCount < 0: arrayCount = 0
if arrayCount < 3: #if arrayCount < 3:
if self.side & (North|South): if self.side & (North|South):
self.arraySize = ( arrayCount+1, 2 ) self.arraySize = ( arrayCount+1, 2 )
else: else:
self.arraySize = ( 2, arrayCount+1 ) self.arraySize = ( 2, arrayCount+1 )
trace( 550, '\tarraySize = ({},{})\n'.format(self.arraySize[0], self.arraySize[1]) ) trace( 550, '\tarraySize = ({},{})\n'.format(self.arraySize[0], self.arraySize[1]) )
self.gapWidth = 4*self.viaPitch
trace( 550, ',-' ) trace( 550, ',-' )
return return
raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \ raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \
@ -594,7 +582,8 @@ class CoreWire ( object ):
xPadMax = xContact xPadMax = xContact
xCore = coronaAb.getXMin() xCore = coronaAb.getXMin()
if not self.preferredDir: if not self.preferredDir:
xPadMax += self.bbSegment.getHeight()/2 #xPadMax += self.bbSegment.getHeight()/2
xPadMin += 3*vPitch
else: else:
accessDirection = Pin.Direction.EAST accessDirection = Pin.Direction.EAST
xPadMax = self.bbSegment.getXMax() xPadMax = self.bbSegment.getXMax()
@ -602,7 +591,8 @@ class CoreWire ( object ):
xPadMin = xContact xPadMin = xContact
xCore = coronaAb.getXMax() xCore = coronaAb.getXMax()
if not self.preferredDir: if not self.preferredDir:
xPadMin -= self.bbSegment.getHeight()/2 #xPadMin -= self.bbSegment.getHeight()/2
xPadMin -= 3*vPitch
hReal = Horizontal.create( self.chipNet hReal = Horizontal.create( self.chipNet
, self.padSegment.getLayer() , self.padSegment.getLayer()
, self.bbSegment.getCenter().getY() , self.bbSegment.getCenter().getY()
@ -683,16 +673,18 @@ class CoreWire ( object ):
yPadMax = self.corona.coreSymBb.getYMin() - self.offset * 2*hPitch yPadMax = self.corona.coreSymBb.getYMin() - self.offset * 2*hPitch
yContact = yPadMax yContact = yPadMax
yCore = coronaAb.getYMin() yCore = coronaAb.getYMin()
if not self.preferredDir: #if not self.preferredDir:
yPadMax += self.bbSegment.getWidth()/2 # yPadMax += self.bbSegment.getWidth()/2
# yPadMin += 3*hPitch
else: else:
accessDirection = Pin.Direction.NORTH accessDirection = Pin.Direction.NORTH
yPadMax = self.bbSegment.getYMax() yPadMax = self.bbSegment.getYMax()
yPadMin = self.corona.coreSymBb.getYMax() + self.offset * 2*hPitch yPadMin = self.corona.coreSymBb.getYMax() + self.offset * 2*hPitch
yContact = yPadMin yContact = yPadMin
yCore = coronaAb.getYMax() yCore = coronaAb.getYMax()
if not self.preferredDir: #if not self.preferredDir:
yPadMin -= self.bbSegment.getWidth()/2 # yPadMin -= self.bbSegment.getWidth()/2
# yPadMin -= 3*hPitch
vReal = Vertical.create( self.chipNet vReal = Vertical.create( self.chipNet
, self.padSegment.getLayer() , self.padSegment.getLayer()
, self.bbSegment.getCenter().getX() , self.bbSegment.getCenter().getX()
@ -805,9 +797,10 @@ class Corona ( object ):
self.padSpacers = [] self.padSpacers = []
self.padCorner = [] self.padCorner = []
self.padRails = [] # [ , [net, layer, axis, width] ] self.padRails = [] # [ , [net, layer, axis, width] ]
if Cfg.hasParameter('chip.padCoreSide'): self.conf.cfg.chip.padCoreSide = None
if Cfg.getParamString('chip.padCoreSide').asString().lower() == 'south': if self.conf.cfg.chip.padCoreSide.lower() == 'south':
self.padOrient = Transformation.Orientation.MY self.padOrient = Transformation.Orientation.MY
trace( 550, '\tchip.padCoreSide: {}\n'.format(self.conf.cfg.chip.padCoreSide) )
self._allPadsAnalysis() self._allPadsAnalysis()
if Cfg.hasParameter('chip.padSpacers'): if Cfg.hasParameter('chip.padSpacers'):
for spacerName in Cfg.getParamString('chip.padSpacers').asString().split(','): for spacerName in Cfg.getParamString('chip.padSpacers').asString().split(','):
@ -889,10 +882,10 @@ class Corona ( object ):
if plug.getMasterNet().isGlobal(): if plug.getMasterNet().isGlobal():
net = self.conf.cell.getNet( plug.getMasterNet().getName() ) net = self.conf.cell.getNet( plug.getMasterNet().getName() )
if not net: if not net:
raise ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is not connected and there is no global net (in pad \"%s").' \ 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() ) % plug.getMasterNet().getName(), padCell.getName() )
else: else:
raise ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \ raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \
% plug.getMasterNet().getName(), padCell.getName() ) % plug.getMasterNet().getName(), padCell.getName() )
if net: if net:
self.padRails.append( ( net self.padRails.append( ( net
@ -901,12 +894,18 @@ class Corona ( object ):
, component.getWidth() ) ) , component.getWidth() ) )
def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ): def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ):
trace( 550, ',+', '\tCorona._createCoreWire()\n' )
trace( 550, '\tchipIntNet:{}\n'.format(chipIntNet) )
trace( 550, '\tpadNet:{}\n'.format(padNet) )
trace( 550, '\tpadInstance:{}\n'.format(padInstance) )
side = None side = None
if self.hasSouthPad(padInstance): side = self.southSide if self.hasSouthPad(padInstance): side = self.southSide
elif self.hasNorthPad(padInstance): side = self.northSide elif self.hasNorthPad(padInstance): side = self.northSide
elif self.hasEastPad (padInstance): side = self.eastSide elif self.hasEastPad (padInstance): side = self.eastSide
elif self.hasWestPad (padInstance): side = self.westSide elif self.hasWestPad (padInstance): side = self.westSide
if not side: return count if not side:
trace( 550, '-' )
return count
innerBb = self.conf.chip.getAbutmentBox().inflate( -self.conf.ioPadHeight ) innerBb = self.conf.chip.getAbutmentBox().inflate( -self.conf.ioPadHeight )
rg = self.conf.routingGauge rg = self.conf.routingGauge
hsegments = {} hsegments = {}
@ -946,25 +945,28 @@ class Corona ( object ):
coreWires = [] coreWires = []
if segments: if segments:
for segment, bb in segments: for segment, bb in segments:
if not inPreferredDir:
if side.type == North or side.type == South:
trace( 550, '\tNorth/South "{}" but RDir H, gapWidth: {}\n' \
.format(chipIntNet.getName(),DbU.getValueString(bb.getWidth()) ) )
side.updateGap( bb.getWidth() )
else:
trace( 550, '\tEast/West "{}" but RDir V, gapWidth: {}\n' \
.format(chipIntNet.getName(),DbU.getValueString(bb.getHeight())) )
side.updateGap( bb.getHeight() )
side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) ) side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) )
side.updateGap( side.coreWires[-1].gapWidth )
#if not inPreferredDir:
# if side.type == North or side.type == South:
# trace( 550, '\tNorth/South "{}" but RDir H, gapWidth: {}\n' \
# .format(chipIntNet.getName(),DbU.getValueString(bb.getWidth()) ) )
# side.updateGap( bb.getWidth() )
# else:
# trace( 550, '\tEast/West "{}" but RDir V, gapWidth: {}\n' \
# .format(chipIntNet.getName(),DbU.getValueString(bb.getHeight())) )
# side.updateGap( bb.getHeight() )
count += 1 count += 1
else: else:
if not (chipIntNet.isGlobal() or chipIntNet.isSupply() or chipIntNet.isClock()): if not (chipIntNet.isGlobal() or chipIntNet.isSupply() or chipIntNet.isClock()):
raise ErrorMessage( 1, [ 'PadsCorona._createCoreWire(): In I/O pad "{}" ({},{}),' \ trace( 550, '-' )
raise ErrorMessage( 1, [ 'Corona._createCoreWire(): In I/O pad "{}" ({},{}),' \
.format( padInstance.getMasterCell().getName() .format( padInstance.getMasterCell().getName()
, padInstance.getName(), padInstance.getTransformation() ) , padInstance.getName(), padInstance.getTransformation() )
, 'connector "{}" has no suitable segment for net "{}".' \ , 'connector "{}" has no suitable segment for net "{}".' \
.format( padNet, chipIntNet.getName() ) .format( padNet, chipIntNet.getName() )
] ) ] )
trace( 550, '-' )
return count return count
def _placeInnerCorona ( self ): def _placeInnerCorona ( self ):

View File

@ -15,28 +15,19 @@
import sys import sys
from Hurricane import DbU from Hurricane import DbU, Point, Transformation, Box, Interval, \
from Hurricane import Point Path, Occurrence, UpdateSession, Net, \
from Hurricane import Transformation Contact, Horizontal, Vertical, Query
from Hurricane import Box
from Hurricane import Interval
from Hurricane import Path
from Hurricane import Occurrence
from Hurricane import UpdateSession
from Hurricane import Net
from Hurricane import Contact
from Hurricane import Horizontal
from Hurricane import Vertical
from Hurricane import Query
import CRL import CRL
import helpers import helpers
from helpers import trace from helpers import trace
from helpers.io import ErrorMessage from helpers.io import ErrorMessage, WarningMessage
from helpers.io import WarningMessage
from helpers.overlay import UpdateSession from helpers.overlay import UpdateSession
import plugins import plugins
import plugins.chip import plugins.chip
__all__ = [ 'Builder' ]
plugins.chip.importConstants( globals() ) plugins.chip.importConstants( globals() )
@ -203,28 +194,23 @@ class Builder ( object ):
query.doQuery() query.doQuery()
self.activePlane = None self.activePlane = None
def connectClock ( self ): def _connectClock ( self, ck ):
if not self.conf.useClockTree: trace( 550, '\tpower.Builder._connectClock() {}\n'.format(ck) )
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
return
if not self.conf.coronaCk:
raise ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' )
return
blockCk = None blockCk = None
for plug in self.conf.icore.getPlugs(): for plug in self.conf.icore.getPlugs():
if plug.getNet() == self.conf.coronaCk: if plug.getNet() == ck:
blockCk = plug.getMasterNet() blockCk = plug.getMasterNet()
if not blockCk: if not blockCk:
raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \ raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \
.format(self.conf.icore.getName(),self.conf.coronaCk.getName()) ) .format(self.conf.icore.getName(),ck.getName()) )
return return
htPlugs = [] htPlugs = []
for plug in self.conf.coronaCk.getPlugs(): for plug in ck.getPlugs():
if plug.getInstance().isTerminalNetlist(): if plug.getInstance().isTerminalNetlist():
htPlugs.append( plug ) htPlugs.append( plug )
if len(htPlugs) != 1: if len(htPlugs) != 1:
message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \ message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
.format( self.conf.coronaCk.getName() .format( ck.getName()
, self.conf.icore.getName() , self.conf.icore.getName()
, len(htPlugs)) ] , len(htPlugs)) ]
for plug in htPlugs: for plug in htPlugs:
@ -232,13 +218,11 @@ class Builder ( object ):
raise ErrorMessage( 1, message ) raise ErrorMessage( 1, message )
return return
with UpdateSession(): with UpdateSession():
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()) bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), ck, 0 )
, self.conf.coronaCk
, 0 )
blockAb = self.block.getAbutmentBox() blockAb = self.block.getAbutmentBox()
self.path.getTransformation().applyOn( blockAb ) self.path.getTransformation().applyOn( blockAb )
layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth) layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth)
contact = Contact.create( self.conf.coronaCk contact = Contact.create( ck
, self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth) , self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth)
, bufferRp.getX() , bufferRp.getX()
, blockAb.getYMax() , blockAb.getYMax()
@ -249,7 +233,18 @@ class Builder ( object ):
self.activePlane = self.planes[ layerGauge.getLayer().getName() ] self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() ) bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
self.path.getTransformation().getInvert().applyOn( bb ) self.path.getTransformation().getInvert().applyOn( bb )
self.activePlane.addTerminal( self.conf.coronaCk, Plane.Vertical, bb ) self.activePlane.addTerminal( ck, Plane.Vertical, bb )
trace( 550, '\tAdded terminal of {} to vertical plane @{}\n'.format(ck,bb) )
def connectClocks ( self ):
if not self.conf.useClockTree:
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
return
if len(self.conf.coronaCks) == 0:
raise ErrorMessage( 1, 'Cannot build clock terminal as no clock is not known.' )
return
for ck in self.conf.coronaCks:
self._connectClock( ck )
def doLayout ( self ): def doLayout ( self ):
with UpdateSession(): with UpdateSession():

View File

@ -47,11 +47,11 @@ class CoreToChip ( BaseCoreToChip ):
, 'vddi' : None , 'vddi' : None
, 'ck' : None # Go through the pads from pck_px. , 'ck' : None # Go through the pads from pck_px.
} }
self.ioPadInfos = { IoPad.IN : BaseCoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] ) self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.IN , 'pi_px' , 'pad', ['t',] )
, IoPad.OUT : BaseCoreToChip.IoPadInfo( 'po_px' , 'pad', ['i',] ) , BaseCoreToChip.IoPadInfo( IoPad.OUT , 'po_px' , 'pad', ['i',] )
, IoPad.TRI_OUT : BaseCoreToChip.IoPadInfo( 'pot_px' , 'pad', ['i', 'b' ] ) , BaseCoreToChip.IoPadInfo( IoPad.TRI_OUT, 'pot_px' , 'pad', ['i', 'b'] )
, IoPad.BIDIR : BaseCoreToChip.IoPadInfo( 'piot_px', 'pad', ['i', 't', 'b' ] ) , BaseCoreToChip.IoPadInfo( IoPad.BIDIR , 'piot_px', 'pad', ['i', 't', 'b'] )
} ]
self._getPadLib() self._getPadLib()
return return
@ -79,7 +79,7 @@ class CoreToChip ( BaseCoreToChip ):
% (self.padLib.getName(),masterCellName) ) % (self.padLib.getName(),masterCellName) )
return cell return cell
def _buildGroundPads ( self, ioPadConf ): def _buildAllGroundPads ( self, ioPadConf ):
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.coreSupplyNetName )
@ -112,7 +112,7 @@ class CoreToChip ( BaseCoreToChip ):
self.groundPadCount += 1 self.groundPadCount += 1
self.chipPads += ioPadConf.pads self.chipPads += ioPadConf.pads
def _buildPowerPads ( self, ioPadConf ): def _buildAllPowerPads ( self, ioPadConf ):
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.coreSupplyNetName )

View File

@ -44,20 +44,16 @@ The double level chip+corona serves two purpose:
""" """
from __future__ import print_function from __future__ import print_function
from exceptions import NotImplementedError
import re import re
from Hurricane import UpdateSession from Hurricane import UpdateSession, Net, Instance
from Hurricane import Net from CRL import Catalog, AllianceFramework
from Hurricane import Instance from helpers import trace, netDirectionToStr
from CRL import Catalog
from CRL import AllianceFramework
from helpers import trace
from helpers import netDirectionToStr
from helpers.overlay import UpdateSession from helpers.overlay import UpdateSession
from helpers.io import ErrorMessage from helpers.io import ErrorMessage, WarningMessage
import plugins.chip import plugins.chip
from plugins.alpha.block.block import Block from plugins.alpha.block.block import Block
from plugins.alpha.block.configuration import BlockConf from plugins.alpha.block.configuration import BlockConf, IoPadConf
from plugins.alpha.block.configuration import IoPadConf
# ------------------------------------------------------------------- # -------------------------------------------------------------------
@ -116,10 +112,12 @@ class IoNet ( object ):
, self.chipExtNet , self.chipExtNet
, self.chipIntNet ) , self.chipIntNet )
def isElem ( self ): return self._flags & IoNet.IsElem def isElem ( self ): return self._flags & IoNet.IsElem
def isEnable ( self ): return self._flags & IoNet.IsEnable def isEnable ( self ): return self._flags & IoNet.IsEnable
def isGlobal ( self ): return self.isGlobal( self._name ) def isGlobal ( self ): return self.isGlobal( self._name )
def isSpecial ( self ): return self._type != Net.Type.LOGICAL def isSpecial ( self ): return self._type != Net.Type.LOGICAL
def setFlags ( self, flags ): self._flags |= flags
def resetFlags ( self, flags ): self._flags &= ~flags
@property @property
def name ( self ): def name ( self ):
@ -169,7 +167,7 @@ class IoNet ( object ):
if state == True: self._flags |= IoNet.IsEnable if state == True: self._flags |= IoNet.IsEnable
else: self._flags &= ~IoNet.IsEnable else: self._flags &= ~IoNet.IsEnable
def buildNets ( self, context=DoExtNet ): def buildNets ( self ):
""" """
Creates the signals in corona and chip Cells, then connect them Creates the signals in corona and chip Cells, then connect them
together. together.
@ -194,9 +192,9 @@ class IoNet ( object ):
self.chipIntNet.setType( netType ) self.chipIntNet.setType( netType )
self.coreToChip.icorona.getPlug( self.coronaNet ).setNet( self.chipIntNet ) self.coreToChip.icorona.getPlug( self.coronaNet ).setNet( self.chipIntNet )
# Chip "external" net, connected to the pad I/O to the outside world. # Chip "external" net, connected to the pad I/O to the outside world.
if context & IoNet.PadPassthrough: if self._flags & IoNet.PadPassthrough:
self.chipExtNet = self.chipIntNet self.chipExtNet = self.chipIntNet
elif not self.chipExtNet and (context & IoNet.DoExtNet): elif not self.chipExtNet and (self._flags & IoNet.DoExtNet):
self.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName ) self.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName )
if not self.chipExtNet: if not self.chipExtNet:
self.chipExtNet = Net.create( self.coreToChip.chip, self.chipExtNetName ) self.chipExtNet = Net.create( self.coreToChip.chip, self.chipExtNetName )
@ -274,13 +272,18 @@ class IoPad ( object ):
, netDirectionToStr(self.nets[0].coreNet.getDirection()) , netDirectionToStr(self.nets[0].coreNet.getDirection())
, self.nets[0].coreNet.getName() , self.nets[0].coreNet.getName()
, self.padInstanceName )) , self.padInstanceName ))
if self.coreToChip.getPadInfo(self.direction) is None:
print( WarningMessage( 'IoPad.addNet(): No simple pad in direction {} for "{}", fallback to bi-directional.' \
.format(netDirectionToStr(self.direction),ioNet.padInstanceName)) )
self.direction = IoPad.BIDIR
elif len(self.nets) == 2: elif len(self.nets) == 2:
self.direction = IoPad.TRI_OUT if self.direction != IoPad.BIDIR:
self.direction = IoPad.TRI_OUT
elif len(self.nets) == 3: elif len(self.nets) == 3:
self.direction = IoPad.BIDIR self.direction = IoPad.BIDIR
else: else:
message = [ 'IoPad.addNet(): More than three core nets on I/O pad "{}".' \ message = [ 'IoPad.addNet(): More than three core nets ({}) on I/O pad "{}".' \
.format(self.padInstanceName) ] .format(len(self.nets),self.padInstanceName) ]
for ioNet in self.nets: for ioNet in self.nets:
message += [ "{}".format(ioNet.coreNet) ] message += [ "{}".format(ioNet.coreNet) ]
raise ErrorMessage( 1, message ) raise ErrorMessage( 1, message )
@ -293,40 +296,48 @@ class IoPad ( object ):
enable signal (if any) do not need an external chip signal enable signal (if any) do not need an external chip signal
(it is *not* connected to the outside world). (it is *not* connected to the outside world).
""" """
fromCoreNet = None padInfo = self.coreToChip.getPadInfo( self.direction )
toCoreNet = None if padInfo is None:
enableNet = None
for ioNet in self.nets:
context = 0
if self.direction == IoPad.TRI_OUT:
if ioNet.isEnable(): enableNet = ioNet
else:
fromCoreNet = ioNet
context |= IoNet.DoExtNet
elif self.direction == IoPad.BIDIR:
if ioNet.coreNet.getDirection() == Net.Direction.IN: toCoreNet = ioNet
if ioNet.coreNet.getDirection() == Net.Direction.OUT:
if ioNet.isEnable(): enableNet = ioNet
else:
fromCoreNet = ioNet
context |= IoNet.DoExtNet
else:
context |= IoNet.DoExtNet
fromCoreNet = ioNet
ioNet.buildNets( context )
if not self.coreToChip.ioPadInfos.has_key(self.direction):
raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction {} ({}) for pad "{}".' \ raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction {} ({}) for pad "{}".' \
.format( self.direction .format( self.direction
, IoPad.directionToStr(self.direction) , IoPad.directionToStr(self.direction)
, self.padInstanceName )) , self.padInstanceName ))
padInfo = self.coreToChip.ioPadInfos[ self.direction ] connexions = []
# Case of BIDIR as fallback for simple IN/OUT.
if (self.direction == IoPad.BIDIR) and (len(self.nets) < 3):
self.nets[0].setFlags( IoNet.DoExtNet )
self.nets[0].buildNets()
self.nets[1].buildNets()
connexions.append( ( self.nets[0].chipExtNet, padInfo.padNet ) )
if self.nets[0].coreNet.getDirection() == Net.Direction.IN:
connexions.append( ( self.nets[0].chipIntNet , padInfo.inputNet ) )
connexions.append( ( self.coreToChip.newDummyNet(), padInfo.outputNet ) )
else:
connexions.append( ( self.nets[0].chipIntNet , padInfo.outputNet ) )
connexions.append( ( self.coreToChip.newDummyNet(), padInfo.inputNet ) )
connexions.append( ( self.nets[1].chipIntNet, padInfo.enableNet ) )
else:
for ioNet in self.nets:
if not ioNet.isEnable():
ioNet.setFlags( IoNet.DoExtNet )
ioNet.buildNets()
connexions.append( ( self.nets[0].chipExtNet, padInfo.padNet ) )
if self.direction == IoPad.IN:
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
elif self.direction == IoPad.OUT:
connexions.append( ( self.nets[0].chipIntNet, padInfo.outputNet ) )
elif self.direction == IoPad.TRI_OUT:
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
connexions.append( ( self.nets[1].chipIntNet, padInfo.enableNet ) )
elif self.direction == IoPad.BUDIR:
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
connexions.append( ( self.nets[1].chipIntNet, padInfo.outputNet ) )
connexions.append( ( self.nets[2].chipIntNet, padInfo.enableNet ) )
self.pads.append( Instance.create( self.coreToChip.chip self.pads.append( Instance.create( self.coreToChip.chip
, self.padInstanceName , self.padInstanceName
, self.coreToChip.getCell(padInfo.name) ) ) , self.coreToChip.getCell(padInfo.name) ) )
CoreToChip._connect( self.pads[0], fromCoreNet.chipExtNet, padInfo.padNet ) for connexion in connexions:
CoreToChip._connect( self.pads[0], fromCoreNet.chipIntNet, padInfo.coreNets[0] ) CoreToChip._connect( self.pads[0], connexion[0], connexion[1] )
if toCoreNet: CoreToChip._connect( self.pads[0], toCoreNet.chipIntNet, padInfo.coreNets[-2] )
if enableNet: CoreToChip._connect( self.pads[0], enableNet.chipIntNet, padInfo.coreNets[-1] )
self.coreToChip.chipPads += self.pads self.coreToChip.chipPads += self.pads
@ -356,12 +367,35 @@ class CoreToChip ( object ):
class IoPadInfo ( object ): class IoPadInfo ( object ):
def __init__ ( self, padName, padNet, coreNets ): def __init__ ( self, flags, padName, padNet, coreNets ):
self.flags = flags
self.name = padName self.name = padName
self.padNet = padNet self.padNet = padNet
self.coreNets = coreNets self.coreNets = coreNets
return return
@property
def inputNet ( self ):
if self.flags & (IoPad.IN|IoPad.BIDIR|IoPad.TRI_OUT):
return self.coreNets[0]
return None
@property
def outputNet ( self ):
if self.flags & (IoPad.IN|IoPad.BIDIR|IoPad.TRI_OUT):
return self.coreNets[1]
elif self.flags & IoPad.OUT:
return self.coreNets[0]
return None
@property
def enableNet ( self ):
if self.flags & IoPad.BIDIR:
return self.coreNets[2]
elif self.flags & IoPad.TRI_OUT:
return self.coreNets[1]
return None
def getNetType ( self, netName ): def getNetType ( self, netName ):
raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' ) raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' )
@ -409,7 +443,7 @@ class CoreToChip ( object ):
state = block.state state = block.state
self.state = state self.state = state
self.ringNetNames = [] self.ringNetNames = []
self.ioPadInfos = {} self.ioPadInfos = []
self.chipPads = [] self.chipPads = []
self.padLib = None self.padLib = None
self.corona = None self.corona = None
@ -417,6 +451,7 @@ class CoreToChip ( object ):
self.powerPadCount = 0 self.powerPadCount = 0
self.groundPadCount = 0 self.groundPadCount = 0
self.clockPadCount = 0 self.clockPadCount = 0
self.dummyNetCount = 0
return return
@property @property
@ -431,6 +466,12 @@ class CoreToChip ( object ):
@property @property
def chip ( self ): return self.state.chip def chip ( self ): return self.state.chip
def getPadInfo ( self, padType ):
for ioPadInfo in self.ioPadInfos:
if ioPadInfo.flags & padType:
return ioPadInfo
return None
def hasIoNet ( self, netName ): def hasIoNet ( self, netName ):
""" """
Look for an IoNet associated to *core* net ``netName``. Look for an IoNet associated to *core* net ``netName``.
@ -438,6 +479,11 @@ class CoreToChip ( object ):
if self._ioNets.has_key(netName): return True if self._ioNets.has_key(netName): return True
return False return False
def newDummyNet ( self ):
dummy = Net.create( self.chip, '{}_dummy_{}'.format(self.chip.getName(),self.dummyNetCount) )
self.dummyNetCount += 1
return dummy
def getIoNet ( self, coreNet ): def getIoNet ( self, coreNet ):
""" """
Lookup, and create if it doesn't exist, for an IoNet associated to *core* Lookup, and create if it doesn't exist, for an IoNet associated to *core*
@ -469,12 +515,12 @@ class CoreToChip ( object ):
Build all the I/O pads for normal signals (that are not related to Build all the I/O pads for normal signals (that are not related to
power or clock). power or clock).
""" """
if not self.ioPadInfos.has_key(ioNet.coreNet.getDirection()): padInfo = self.getPadInfo( ioNet.coreNet.getDirection() )
if not padInfo:
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \ raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \
% (ioNet.coreNet.getDirection() % (ioNet.coreNet.getDirection()
,netDirectionToStr(ioNet.coreNet.getDirection()) ,netDirectionToStr(ioNet.coreNet.getDirection())
,ioNet.coreNet.getName()) ) ,ioNet.coreNet.getName()) )
padInfo = self.ioPadInfos[ ioNet.coreNet.getDirection() ]
ioNet.pads.append( Instance.create( self.chip ioNet.pads.append( Instance.create( self.chip
, ioNet.padInstanceName , ioNet.padInstanceName
, self.getCell(padInfo.name) ) ) , self.getCell(padInfo.name) ) )
@ -482,21 +528,37 @@ class CoreToChip ( object ):
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, padInfo.coreNets[0] ) CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, padInfo.coreNets[0] )
self.chipPads += ioNet.pads self.chipPads += ioNet.pads
def _buildGroundPads ( self, ioPadConf ): def _buildCoreGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to ground signals.""" """Build I/O pad relateds to core ground signals."""
raise NoImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildPowerPads ( self, ioPadConf ): def _buildIoGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to power signals.""" """Build I/O pad relateds to pad internal ground signals."""
raise NoImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' ) 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."""
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildCorePowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to core power signals."""
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
def _buildIoPowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to pad internal power signals."""
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."""
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
def _buildClockPads ( self, ioPadConf ): def _buildClockPads ( self, ioPadConf ):
"""Build I/O pad relateds to clock signals.""" """Build I/O pad relateds to clock signals."""
raise NoImplementedError( 'coreToChip._buildClockPads(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._buildClockPads(): This method must be overloaded.' )
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) ."""
raise NoImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' ) raise NotImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' )
def buildChip ( self ): def buildChip ( self ):
""" """
@ -504,6 +566,7 @@ class CoreToChip ( object ):
from the core cell. from the core cell.
""" """
af = AllianceFramework.get() af = AllianceFramework.get()
self.state.cfg.apply()
with UpdateSession(): with UpdateSession():
print( ' o Build Chip from Core.' ) print( ' o Build Chip from Core.' )
print( ' - Core: "{}".'.format(self.state.cell.getName()) ) print( ' - Core: "{}".'.format(self.state.cell.getName()) )
@ -516,11 +579,23 @@ class CoreToChip ( object ):
ioPads = [] ioPads = []
clockIoNets = [] clockIoNets = []
for ioPadConf in self.state.chipConf.padInstances: for ioPadConf in self.state.chipConf.padInstances:
if ioPadConf.isPower(): if ioPadConf.isAllPower():
self._buildPowerPads( ioPadConf ) self._buildAllPowerPads( ioPadConf )
continue continue
if ioPadConf.isGround(): if ioPadConf.isCorePower():
self._buildGroundPads( ioPadConf ) self._buildCorePowerPads( ioPadConf )
continue
if ioPadConf.isIoPower():
self._buildIoPowerPads( ioPadConf )
continue
if ioPadConf.isAllGround():
self._buildAllGroundPads( ioPadConf )
continue
if ioPadConf.isCoreGround():
self._buildCoreGroundPads( ioPadConf )
continue
if ioPadConf.isIoGround():
self._buildIoGroundPads( ioPadConf )
continue continue
if ioPadConf.isClock(): if ioPadConf.isClock():
self._buildClockPads( ioPadConf ) self._buildClockPads( ioPadConf )

View File

@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
#
# This file is part of the Coriolis Software.
# Copyright (c) SU 2019-2020, 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/niolib.py" |
# +-----------------------------------------------------------------+
"""
Core2Chip configuration for the FlexLib I/O pad library ("niolib").
"""
from __future__ import print_function
import sys
import re
from Hurricane import DbU, DataBase, UpdateSession, Breakpoint, \
Transformation , Instance , Net
import Viewer
from CRL import Catalog
from CRL import AllianceFramework
from helpers.io import ErrorMessage, WarningMessage
from plugins.alpha.core2chip.core2chip import CoreToChip as BaseCoreToChip, \
IoNet, IoPad
class CoreToChip ( BaseCoreToChip ):
rePadType = re.compile(r'(?P<type>.+)_(?P<index>[\d]+)$')
def __init__ ( self, core ):
BaseCoreToChip.__init__ ( self, core )
self.ringNetNames = { 'iovdd' : None
, 'iovss' : None
, 'vdd' : None
, 'vss' : None
}
self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.BIDIR, 'gpio', 'pad', ['i', 'o', 'oe'] )
]
self._getPadLib()
return
def _getPadLib ( self ):
self.padLib = AllianceFramework.get().getLibrary( "niolib" )
if not self.padLib:
message = [ 'CoreToChip.niolib._getPadLib(): Unable to find Alliance "niolib" library' ]
raise ErrorMessage( 1, message )
def getNetType ( self, netName ):
if netName.startswith('vss') or netName.startswith('iovss'): return Net.Type.GROUND
if netName.startswith('vdd') or netName.startswith('iovdd'): 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, 'cmos.getCell(): I/O pad library "%s" does not contain cell named "%s"' \
% (self.padLib.getName(),masterCellName) )
return cell
def _buildCoreGroundPads ( self, ioPadConf ):
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
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 )
self.icorona.getPlug( coronaNet ).setNet( chipNet )
self.ringNetNames['vss'] = chipNet
ioPadConf.pads.append( Instance.create( self.chip
, 'p_vss_{}'.format(ioPadConf.index)
, self.getCell('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('iovss') ) )
self._connect( ioPadConf.pads[0], padNet , 'iovss' )
self.groundPadCount += 1
self.chipPads += ioPadConf.pads
def _buildCorePowerPads ( self, ioPadConf ):
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
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 )
self.ringNetNames['vdd'] = chipNet
ioPadConf.pads.append( Instance.create( self.chip
, 'p_vdd_{}'.format(ioPadConf.index)
, self.getCell('vdd') ) )
self._connect( ioPadConf.pads[0], chipNet, 'vdd' )
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('iovdd') ) )
self._connect( ioPadConf.pads[0], padNet , 'iovdd' )
self.powerPadCount += 1
self.chipPads += ioPadConf.pads
def _buildClockPads ( self, ioPadConf ):
"""For "niolib" there is no specialized clock I/O pad. So do nothing."""
pass
def _connectClocks ( self ):
"""For "niolib" there is no pad internal clock ring. So do nothing."""
pass