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:
parent
f8a9dd9f71
commit
541b23216c
|
@ -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
|
||||
|
|
|
@ -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,8 +450,12 @@ 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') == '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
|
||||
|
@ -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]
|
||||
|
@ -492,8 +503,12 @@ 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 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
|
||||
|
|
|
@ -34,6 +34,8 @@ SouthWest = South|West
|
|||
SouthEast = South|East
|
||||
NorthWest = North|West
|
||||
NorthEast = North|East
|
||||
HORIZONTAL = North|South
|
||||
VERTICAL = East |West
|
||||
|
||||
Superior = 0x0010
|
||||
Inferior = 0x0020
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,6 +485,9 @@ 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)
|
||||
|
@ -467,6 +509,9 @@ 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)
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -281,72 +281,58 @@ class Side ( object ):
|
|||
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 )
|
||||
#print 'padName:', padName, 'padNet:', padNet
|
||||
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
|
||||
|
@ -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 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.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 ):
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
@ -120,6 +116,8 @@ class IoNet ( object ):
|
|||
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:
|
||||
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 )
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue