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
${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/niolib.py
)
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.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 |
+---------+-----------------------------------------------------------+
"""
POWER = 0x0001
GROUND = 0x0002
CLOCK = 0x0004
TRISTATE = 0x0008
BIDIR = 0x0010
CORE_POWER = 0x0001
CORE_GROUND = 0x0002
IO_POWER = 0x0004
IO_GROUND = 0x0008
ALL_POWER = 0x0010
ALL_GROUND = 0x0020
CLOCK = 0x0040
TRISTATE = 0x0080
BIDIR = 0x0100
def __init__ ( self, datas ):
if not isinstance(datas,tuple):
@ -438,6 +442,7 @@ class IoPadConf ( object ):
self.flags = 0
self.index = None
self._datas = list( datas )
if len(self._datas) == 4: self._datas += [ None, None, None ]
if len(self._datas) == 5: self._datas += [ None, None ]
elif len(self._datas) == 6: self._datas.insert( 5, None )
self._datas.append( [] )
@ -445,9 +450,13 @@ class IoPadConf ( object ):
m = reSpecialPads.match( self.instanceName )
if m:
self.index = m.group('index')
if m.group('type') == 'power' : self.flags |= IoPadConf.POWER
if m.group('type') == 'ground': self.flags |= IoPadConf.GROUND
if m.group('type') == 'clock' : self.flags |= IoPadConf.CLOCK
if m.group('type') == 'allpower': self.flags |= IoPadConf.ALL_POWER
if m.group('type') == 'iopower': self.flags |= IoPadConf.IO_POWER
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:
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
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]
@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
def padClockNetName ( self ): return self._datas[4]
@ -491,12 +502,16 @@ class IoPadConf ( object ):
@property
def pads ( self ): return self._datas[7]
def isPower ( self ): return self.flags & IoPadConf.POWER
def isGround ( self ): return self.flags & IoPadConf.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 isCorePower ( self ): return self.flags & IoPadConf.CORE_POWER
def isIoPower ( self ): return self.flags & IoPadConf.IO_POWER
def isAllPower ( self ): return self.flags & IoPadConf.ALL_POWER
def isCoreGround ( self ): return self.flags & IoPadConf.CORE_GROUND
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 ):
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 helpers.io import WarningMessage
North = 0x0001
South = 0x0002
East = 0x0004
West = 0x0008
SouthWest = South|West
SouthEast = South|East
NorthWest = North|West
NorthEast = North|East
North = 0x0001
South = 0x0002
East = 0x0004
West = 0x0008
SouthWest = South|West
SouthEast = South|East
NorthWest = North|West
NorthEast = North|East
HORIZONTAL = North|South
VERTICAL = East |West
Superior = 0x0010
Inferior = 0x0020

View File

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

View File

@ -16,36 +16,25 @@ from __future__ import print_function
import sys
import os.path
import Cfg
from Hurricane import Breakpoint
from Hurricane import DbU
from Hurricane import Box
from Hurricane import Transformation
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
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
Path, Layer, Occurrence, Net, RoutingPad, \
Horizontal, Vertical, Contact, Pin, Plug, \
Instance
import CRL
from CRL import RoutingLayerGauge
from helpers import trace
from helpers.utils import classdecorator
from helpers.overlay import UpdateSession
from helpers.io import ErrorMessage
from helpers.io import WarningMessage
from helpers.io import catch
from plugins import getParameter
from helpers.io import ErrorMessage, WarningMessage, \
vprint, catch
import plugins.chip
from plugins.alpha.block.configuration import BlockConf
__all__ = [ 'ChipConf' ]
plugins.alpha.chip.importConstants( globals() )
af = CRL.AllianceFramework.get()
# -------------------------------------------------------------------
@ -116,7 +105,7 @@ class ChipConf ( BlockConf ):
# Global Nets.
self.coronaVdd = None
self.coronaVss = None
self.coronaCk = None
self.coronaCks = []
self.blockageNet = None
self.padsHavePosition = False
trace( 550, '-' )
@ -146,9 +135,13 @@ class ChipConf ( BlockConf ):
return self.cfg.chip.block.rails.vSpacing
def computeCoronaBorder ( self ):
global af
if self.useClockTree:
trace( 550, '\tcomputeCoronaBorder() useClockTree: {}\n'.format(self.useClockTree) )
self.railsCount = self.cfg.chip.block.rails.count + 1
clockNets = []
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) )
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
@ -259,7 +252,7 @@ class ChipConf ( BlockConf ):
return axis, width
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)) )
coronaAb = self.getInstanceAb( self.icorona )
lg = None
@ -378,9 +371,24 @@ class ChipConf ( BlockConf ):
trace( 550, '-' )
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 ):
trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
viaPitch = layer.getMinimalSize() + layer.getMinimalSpacing()
viaPitch = self.getViaPitch( layer )
coronaAb = self.getInstanceAb( self.icorona )
coronaNet = self.getCoronaNet( chipNet )
if not coronaNet: return None
@ -481,7 +489,7 @@ class ChipConf ( BlockConf ):
.format(i,padList[i][1],side) ))
return
af = CRL.AllianceFramework.get()
global af
cellPads = []
for instance in self.chip.getInstances():
if contains(self.southPads,'south',instance): continue
@ -559,13 +567,9 @@ class ChipConf ( BlockConf ):
self.coronaVdd = net
if netType == Net.Type.CLOCK:
if self.coronaCk and self.coronaCk != net:
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple clock nets "{}" and "{}" at corona level.' \
.format(self.coronaCk.getName(), net.getName()) )
self._validated = False
continue
else:
self.coronaCk = net
if not net in self.coronaCks:
self.coronaCks.append( net )
vprint( 2, ' - Using clock "{}".'.format(net.getName()) )
for net in self.corona.getNets():
if net.getType() == Net.Type.BLOCKAGE:
self.blockageNet = net

View File

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

View File

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

View File

@ -15,28 +15,19 @@
import sys
from Hurricane import DbU
from Hurricane import Point
from Hurricane import Transformation
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
from Hurricane import DbU, Point, Transformation, Box, Interval, \
Path, Occurrence, UpdateSession, Net, \
Contact, Horizontal, Vertical, Query
import CRL
import helpers
from helpers import trace
from helpers.io import ErrorMessage
from helpers.io import WarningMessage
from helpers.io import ErrorMessage, WarningMessage
from helpers.overlay import UpdateSession
import plugins
import plugins.chip
__all__ = [ 'Builder' ]
plugins.chip.importConstants( globals() )
@ -203,28 +194,23 @@ class Builder ( object ):
query.doQuery()
self.activePlane = None
def connectClock ( self ):
if not self.conf.useClockTree:
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
def _connectClock ( self, ck ):
trace( 550, '\tpower.Builder._connectClock() {}\n'.format(ck) )
blockCk = None
for plug in self.conf.icore.getPlugs():
if plug.getNet() == self.conf.coronaCk:
if plug.getNet() == ck:
blockCk = plug.getMasterNet()
if not blockCk:
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
htPlugs = []
for plug in self.conf.coronaCk.getPlugs():
for plug in ck.getPlugs():
if plug.getInstance().isTerminalNetlist():
htPlugs.append( plug )
if len(htPlugs) != 1:
message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
.format( self.conf.coronaCk.getName()
.format( ck.getName()
, self.conf.icore.getName()
, len(htPlugs)) ]
for plug in htPlugs:
@ -232,13 +218,11 @@ class Builder ( object ):
raise ErrorMessage( 1, message )
return
with UpdateSession():
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path())
, self.conf.coronaCk
, 0 )
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), ck, 0 )
blockAb = self.block.getAbutmentBox()
self.path.getTransformation().applyOn( blockAb )
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)
, bufferRp.getX()
, blockAb.getYMax()
@ -249,7 +233,18 @@ class Builder ( object ):
self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
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 ):
with UpdateSession():

View File

@ -47,11 +47,11 @@ class CoreToChip ( BaseCoreToChip ):
, 'vddi' : None
, 'ck' : None # Go through the pads from pck_px.
}
self.ioPadInfos = { IoPad.IN : BaseCoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] )
, IoPad.OUT : BaseCoreToChip.IoPadInfo( 'po_px' , 'pad', ['i',] )
, IoPad.TRI_OUT : BaseCoreToChip.IoPadInfo( 'pot_px' , 'pad', ['i', 'b' ] )
, IoPad.BIDIR : BaseCoreToChip.IoPadInfo( 'piot_px', 'pad', ['i', 't', 'b' ] )
}
self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.IN , 'pi_px' , 'pad', ['t',] )
, BaseCoreToChip.IoPadInfo( IoPad.OUT , 'po_px' , 'pad', ['i',] )
, BaseCoreToChip.IoPadInfo( IoPad.TRI_OUT, 'pot_px' , 'pad', ['i', 'b'] )
, BaseCoreToChip.IoPadInfo( IoPad.BIDIR , 'piot_px', 'pad', ['i', 't', 'b'] )
]
self._getPadLib()
return
@ -79,7 +79,7 @@ class CoreToChip ( BaseCoreToChip ):
% (self.padLib.getName(),masterCellName) )
return cell
def _buildGroundPads ( self, ioPadConf ):
def _buildAllGroundPads ( self, ioPadConf ):
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
@ -112,7 +112,7 @@ class CoreToChip ( BaseCoreToChip ):
self.groundPadCount += 1
self.chipPads += ioPadConf.pads
def _buildPowerPads ( self, ioPadConf ):
def _buildAllPowerPads ( self, ioPadConf ):
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
coronaNet = self.corona.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 exceptions import NotImplementedError
import re
from Hurricane import UpdateSession
from Hurricane import Net
from Hurricane import Instance
from CRL import Catalog
from CRL import AllianceFramework
from helpers import trace
from helpers import netDirectionToStr
from Hurricane import UpdateSession, Net, Instance
from CRL import Catalog, AllianceFramework
from helpers import trace, netDirectionToStr
from helpers.overlay import UpdateSession
from helpers.io import ErrorMessage
from helpers.io import ErrorMessage, WarningMessage
import plugins.chip
from plugins.alpha.block.block import Block
from plugins.alpha.block.configuration import BlockConf
from plugins.alpha.block.configuration import IoPadConf
from plugins.alpha.block.configuration import BlockConf, IoPadConf
# -------------------------------------------------------------------
@ -116,10 +112,12 @@ class IoNet ( object ):
, self.chipExtNet
, self.chipIntNet )
def isElem ( self ): return self._flags & IoNet.IsElem
def isEnable ( self ): return self._flags & IoNet.IsEnable
def isGlobal ( self ): return self.isGlobal( self._name )
def isSpecial ( self ): return self._type != Net.Type.LOGICAL
def isElem ( self ): return self._flags & IoNet.IsElem
def isEnable ( self ): return self._flags & IoNet.IsEnable
def isGlobal ( self ): return self.isGlobal( self._name )
def isSpecial ( self ): return self._type != Net.Type.LOGICAL
def setFlags ( self, flags ): self._flags |= flags
def resetFlags ( self, flags ): self._flags &= ~flags
@property
def name ( self ):
@ -169,7 +167,7 @@ class IoNet ( object ):
if state == True: 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
together.
@ -194,9 +192,9 @@ class IoNet ( object ):
self.chipIntNet.setType( netType )
self.coreToChip.icorona.getPlug( self.coronaNet ).setNet( self.chipIntNet )
# 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
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 )
if not self.chipExtNet:
self.chipExtNet = Net.create( self.coreToChip.chip, self.chipExtNetName )
@ -274,13 +272,18 @@ class IoPad ( object ):
, netDirectionToStr(self.nets[0].coreNet.getDirection())
, self.nets[0].coreNet.getName()
, 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:
self.direction = IoPad.TRI_OUT
if self.direction != IoPad.BIDIR:
self.direction = IoPad.TRI_OUT
elif len(self.nets) == 3:
self.direction = IoPad.BIDIR
else:
message = [ 'IoPad.addNet(): More than three core nets on I/O pad "{}".' \
.format(self.padInstanceName) ]
message = [ 'IoPad.addNet(): More than three core nets ({}) on I/O pad "{}".' \
.format(len(self.nets),self.padInstanceName) ]
for ioNet in self.nets:
message += [ "{}".format(ioNet.coreNet) ]
raise ErrorMessage( 1, message )
@ -293,40 +296,48 @@ class IoPad ( object ):
enable signal (if any) do not need an external chip signal
(it is *not* connected to the outside world).
"""
fromCoreNet = None
toCoreNet = 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):
padInfo = self.coreToChip.getPadInfo( self.direction )
if padInfo is None:
raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction {} ({}) for pad "{}".' \
.format( self.direction
, IoPad.directionToStr(self.direction)
, 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.padInstanceName
, self.coreToChip.getCell(padInfo.name) ) )
CoreToChip._connect( self.pads[0], fromCoreNet.chipExtNet, padInfo.padNet )
CoreToChip._connect( self.pads[0], fromCoreNet.chipIntNet, padInfo.coreNets[0] )
if toCoreNet: CoreToChip._connect( self.pads[0], toCoreNet.chipIntNet, padInfo.coreNets[-2] )
if enableNet: CoreToChip._connect( self.pads[0], enableNet.chipIntNet, padInfo.coreNets[-1] )
for connexion in connexions:
CoreToChip._connect( self.pads[0], connexion[0], connexion[1] )
self.coreToChip.chipPads += self.pads
@ -356,12 +367,35 @@ class CoreToChip ( object ):
class IoPadInfo ( object ):
def __init__ ( self, padName, padNet, coreNets ):
def __init__ ( self, flags, padName, padNet, coreNets ):
self.flags = flags
self.name = padName
self.padNet = padNet
self.coreNets = coreNets
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 ):
raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' )
@ -409,7 +443,7 @@ class CoreToChip ( object ):
state = block.state
self.state = state
self.ringNetNames = []
self.ioPadInfos = {}
self.ioPadInfos = []
self.chipPads = []
self.padLib = None
self.corona = None
@ -417,6 +451,7 @@ class CoreToChip ( object ):
self.powerPadCount = 0
self.groundPadCount = 0
self.clockPadCount = 0
self.dummyNetCount = 0
return
@property
@ -431,6 +466,12 @@ class CoreToChip ( object ):
@property
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 ):
"""
Look for an IoNet associated to *core* net ``netName``.
@ -438,6 +479,11 @@ class CoreToChip ( object ):
if self._ioNets.has_key(netName): return True
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 ):
"""
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
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".' \
% (ioNet.coreNet.getDirection()
,netDirectionToStr(ioNet.coreNet.getDirection())
,ioNet.coreNet.getName()) )
padInfo = self.ioPadInfos[ ioNet.coreNet.getDirection() ]
ioNet.pads.append( Instance.create( self.chip
, ioNet.padInstanceName
, self.getCell(padInfo.name) ) )
@ -482,21 +528,37 @@ class CoreToChip ( object ):
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, padInfo.coreNets[0] )
self.chipPads += ioNet.pads
def _buildGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to ground signals."""
raise NoImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildCoreGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to core ground signals."""
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
def _buildPowerPads ( self, ioPadConf ):
"""Build I/O pad relateds to power signals."""
raise NoImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
def _buildIoGroundPads ( self, ioPadConf ):
"""Build I/O pad relateds to pad internal ground signals."""
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 ):
"""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 ):
"""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 ):
"""
@ -504,6 +566,7 @@ class CoreToChip ( object ):
from the core cell.
"""
af = AllianceFramework.get()
self.state.cfg.apply()
with UpdateSession():
print( ' o Build Chip from Core.' )
print( ' - Core: "{}".'.format(self.state.cell.getName()) )
@ -516,11 +579,23 @@ class CoreToChip ( object ):
ioPads = []
clockIoNets = []
for ioPadConf in self.state.chipConf.padInstances:
if ioPadConf.isPower():
self._buildPowerPads( ioPadConf )
if ioPadConf.isAllPower():
self._buildAllPowerPads( ioPadConf )
continue
if ioPadConf.isGround():
self._buildGroundPads( ioPadConf )
if ioPadConf.isCorePower():
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
if ioPadConf.isClock():
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