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
|
set ( pyPluginAlphaC2C ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/__init__.py
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/core2chip.py
|
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/core2chip.py
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/cmos.py
|
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/cmos.py
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/niolib.py
|
||||||
)
|
)
|
||||||
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py
|
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py
|
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py
|
||||||
|
|
|
@ -422,11 +422,15 @@ class IoPadConf ( object ):
|
||||||
| | meta-generated power/ground/clock pads |
|
| | meta-generated power/ground/clock pads |
|
||||||
+---------+-----------------------------------------------------------+
|
+---------+-----------------------------------------------------------+
|
||||||
"""
|
"""
|
||||||
POWER = 0x0001
|
CORE_POWER = 0x0001
|
||||||
GROUND = 0x0002
|
CORE_GROUND = 0x0002
|
||||||
CLOCK = 0x0004
|
IO_POWER = 0x0004
|
||||||
TRISTATE = 0x0008
|
IO_GROUND = 0x0008
|
||||||
BIDIR = 0x0010
|
ALL_POWER = 0x0010
|
||||||
|
ALL_GROUND = 0x0020
|
||||||
|
CLOCK = 0x0040
|
||||||
|
TRISTATE = 0x0080
|
||||||
|
BIDIR = 0x0100
|
||||||
|
|
||||||
def __init__ ( self, datas ):
|
def __init__ ( self, datas ):
|
||||||
if not isinstance(datas,tuple):
|
if not isinstance(datas,tuple):
|
||||||
|
@ -438,6 +442,7 @@ class IoPadConf ( object ):
|
||||||
self.flags = 0
|
self.flags = 0
|
||||||
self.index = None
|
self.index = None
|
||||||
self._datas = list( datas )
|
self._datas = list( datas )
|
||||||
|
if len(self._datas) == 4: self._datas += [ None, None, None ]
|
||||||
if len(self._datas) == 5: self._datas += [ None, None ]
|
if len(self._datas) == 5: self._datas += [ None, None ]
|
||||||
elif len(self._datas) == 6: self._datas.insert( 5, None )
|
elif len(self._datas) == 6: self._datas.insert( 5, None )
|
||||||
self._datas.append( [] )
|
self._datas.append( [] )
|
||||||
|
@ -445,9 +450,13 @@ class IoPadConf ( object ):
|
||||||
m = reSpecialPads.match( self.instanceName )
|
m = reSpecialPads.match( self.instanceName )
|
||||||
if m:
|
if m:
|
||||||
self.index = m.group('index')
|
self.index = m.group('index')
|
||||||
if m.group('type') == 'power' : self.flags |= IoPadConf.POWER
|
if m.group('type') == 'allpower': self.flags |= IoPadConf.ALL_POWER
|
||||||
if m.group('type') == 'ground': self.flags |= IoPadConf.GROUND
|
if m.group('type') == 'iopower': self.flags |= IoPadConf.IO_POWER
|
||||||
if m.group('type') == 'clock' : self.flags |= IoPadConf.CLOCK
|
if m.group('type') == 'power': self.flags |= IoPadConf.CORE_POWER
|
||||||
|
if m.group('type') == 'allground': self.flags |= IoPadConf.ALL_GROUND
|
||||||
|
if m.group('type') == 'ioground': self.flags |= IoPadConf.IO_GROUND
|
||||||
|
if m.group('type') == 'ground': self.flags |= IoPadConf.CORE_GROUND
|
||||||
|
if m.group('type') == 'clock' : self.flags |= IoPadConf.CLOCK
|
||||||
else:
|
else:
|
||||||
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
|
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
|
||||||
elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE
|
elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE
|
||||||
|
@ -478,7 +487,9 @@ class IoPadConf ( object ):
|
||||||
def padSupplyNetName ( self ): return self._datas[3]
|
def padSupplyNetName ( self ): return self._datas[3]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def coreSupplyNetName ( self ): return self._datas[4]
|
def coreSupplyNetName ( self ):
|
||||||
|
if self._datas[4] is not None: return self._datas[4]
|
||||||
|
return self._datas[3]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def padClockNetName ( self ): return self._datas[4]
|
def padClockNetName ( self ): return self._datas[4]
|
||||||
|
@ -492,11 +503,15 @@ class IoPadConf ( object ):
|
||||||
@property
|
@property
|
||||||
def pads ( self ): return self._datas[7]
|
def pads ( self ): return self._datas[7]
|
||||||
|
|
||||||
def isPower ( self ): return self.flags & IoPadConf.POWER
|
def isCorePower ( self ): return self.flags & IoPadConf.CORE_POWER
|
||||||
def isGround ( self ): return self.flags & IoPadConf.GROUND
|
def isIoPower ( self ): return self.flags & IoPadConf.IO_POWER
|
||||||
def isClock ( self ): return self.flags & IoPadConf.CLOCK
|
def isAllPower ( self ): return self.flags & IoPadConf.ALL_POWER
|
||||||
def isTristate ( self ): return self.flags & IoPadConf.TRISTATE
|
def isCoreGround ( self ): return self.flags & IoPadConf.CORE_GROUND
|
||||||
def isBidir ( self ): return self.flags & IoPadConf.BIDIR
|
def isIoGround ( self ): return self.flags & IoPadConf.IO_GROUND
|
||||||
|
def isAllGround ( self ): return self.flags & IoPadConf.ALL_GROUND
|
||||||
|
def isClock ( self ): return self.flags & IoPadConf.CLOCK
|
||||||
|
def isTristate ( self ): return self.flags & IoPadConf.TRISTATE
|
||||||
|
def isBidir ( self ): return self.flags & IoPadConf.BIDIR
|
||||||
|
|
||||||
def __repr__ ( self ):
|
def __repr__ ( self ):
|
||||||
s = '<IoPadConf {} pad:{} from:{}'.format(self.instanceName,self.padNetName,self.fromCoreNetName)
|
s = '<IoPadConf {} pad:{} from:{}'.format(self.instanceName,self.padNetName,self.fromCoreNetName)
|
||||||
|
|
|
@ -26,14 +26,16 @@ dictionnary of other modules.
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from helpers.io import WarningMessage
|
from helpers.io import WarningMessage
|
||||||
|
|
||||||
North = 0x0001
|
North = 0x0001
|
||||||
South = 0x0002
|
South = 0x0002
|
||||||
East = 0x0004
|
East = 0x0004
|
||||||
West = 0x0008
|
West = 0x0008
|
||||||
SouthWest = South|West
|
SouthWest = South|West
|
||||||
SouthEast = South|East
|
SouthEast = South|East
|
||||||
NorthWest = North|West
|
NorthWest = North|West
|
||||||
NorthEast = North|East
|
NorthEast = North|East
|
||||||
|
HORIZONTAL = North|South
|
||||||
|
VERTICAL = East |West
|
||||||
|
|
||||||
Superior = 0x0010
|
Superior = 0x0010
|
||||||
Inferior = 0x0020
|
Inferior = 0x0020
|
||||||
|
|
|
@ -113,7 +113,7 @@ class Chip ( Block ):
|
||||||
def doConnectCore ( self ):
|
def doConnectCore ( self ):
|
||||||
power = plugins.alpha.chip.power.Builder( self.conf )
|
power = plugins.alpha.chip.power.Builder( self.conf )
|
||||||
power.connectPower()
|
power.connectPower()
|
||||||
power.connectClock()
|
power.connectClocks()
|
||||||
power.doLayout()
|
power.doLayout()
|
||||||
self.conf.refresh()
|
self.conf.refresh()
|
||||||
corona = plugins.alpha.chip.corona.Builder( power )
|
corona = plugins.alpha.chip.corona.Builder( power )
|
||||||
|
|
|
@ -16,36 +16,25 @@ from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
import Cfg
|
import Cfg
|
||||||
from Hurricane import Breakpoint
|
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
|
||||||
from Hurricane import DbU
|
Path, Layer, Occurrence, Net, RoutingPad, \
|
||||||
from Hurricane import Box
|
Horizontal, Vertical, Contact, Pin, Plug, \
|
||||||
from Hurricane import Transformation
|
Instance
|
||||||
from Hurricane import Box
|
|
||||||
from Hurricane import Path
|
|
||||||
from Hurricane import Layer
|
|
||||||
from Hurricane import Occurrence
|
|
||||||
from Hurricane import Net
|
|
||||||
from Hurricane import RoutingPad
|
|
||||||
from Hurricane import Horizontal
|
|
||||||
from Hurricane import Vertical
|
|
||||||
from Hurricane import Contact
|
|
||||||
from Hurricane import Pin
|
|
||||||
from Hurricane import Plug
|
|
||||||
from Hurricane import Instance
|
|
||||||
import CRL
|
import CRL
|
||||||
from CRL import RoutingLayerGauge
|
from CRL import RoutingLayerGauge
|
||||||
from helpers import trace
|
from helpers import trace
|
||||||
from helpers.utils import classdecorator
|
from helpers.utils import classdecorator
|
||||||
from helpers.overlay import UpdateSession
|
from helpers.overlay import UpdateSession
|
||||||
from helpers.io import ErrorMessage
|
from helpers.io import ErrorMessage, WarningMessage, \
|
||||||
from helpers.io import WarningMessage
|
vprint, catch
|
||||||
from helpers.io import catch
|
|
||||||
from plugins import getParameter
|
|
||||||
import plugins.chip
|
import plugins.chip
|
||||||
from plugins.alpha.block.configuration import BlockConf
|
from plugins.alpha.block.configuration import BlockConf
|
||||||
|
|
||||||
|
__all__ = [ 'ChipConf' ]
|
||||||
|
|
||||||
|
|
||||||
plugins.alpha.chip.importConstants( globals() )
|
plugins.alpha.chip.importConstants( globals() )
|
||||||
|
af = CRL.AllianceFramework.get()
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -116,7 +105,7 @@ class ChipConf ( BlockConf ):
|
||||||
# Global Nets.
|
# Global Nets.
|
||||||
self.coronaVdd = None
|
self.coronaVdd = None
|
||||||
self.coronaVss = None
|
self.coronaVss = None
|
||||||
self.coronaCk = None
|
self.coronaCks = []
|
||||||
self.blockageNet = None
|
self.blockageNet = None
|
||||||
self.padsHavePosition = False
|
self.padsHavePosition = False
|
||||||
trace( 550, '-' )
|
trace( 550, '-' )
|
||||||
|
@ -146,9 +135,13 @@ class ChipConf ( BlockConf ):
|
||||||
return self.cfg.chip.block.rails.vSpacing
|
return self.cfg.chip.block.rails.vSpacing
|
||||||
|
|
||||||
def computeCoronaBorder ( self ):
|
def computeCoronaBorder ( self ):
|
||||||
|
global af
|
||||||
if self.useClockTree:
|
if self.useClockTree:
|
||||||
trace( 550, '\tcomputeCoronaBorder() useClockTree: {}\n'.format(self.useClockTree) )
|
clockNets = []
|
||||||
self.railsCount = self.cfg.chip.block.rails.count + 1
|
for net in self.cellPnR.getNets():
|
||||||
|
if net.isClock():
|
||||||
|
clockNets.append( net )
|
||||||
|
self.railsCount = self.cfg.chip.block.rails.count + len(clockNets)
|
||||||
trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) )
|
trace( 550, '\tself.railsCount: {}\n'.format(self.railsCount) )
|
||||||
self.minHCorona = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + self.sliceHeight
|
self.minHCorona = self.railsCount*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + self.sliceHeight
|
||||||
self.minVCorona = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + 10*self.sliceStep
|
self.minVCorona = self.railsCount*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + 10*self.sliceStep
|
||||||
|
@ -259,7 +252,7 @@ class ChipConf ( BlockConf ):
|
||||||
return axis, width
|
return axis, width
|
||||||
|
|
||||||
def toCoronaPitchInChip ( self, uCore, layer ):
|
def toCoronaPitchInChip ( self, uCore, layer ):
|
||||||
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {}l %s\n' \
|
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {}l {}\n' \
|
||||||
.format(DbU.toLambda(uCore), DbU.getValueString(uCore)) )
|
.format(DbU.toLambda(uCore), DbU.getValueString(uCore)) )
|
||||||
coronaAb = self.getInstanceAb( self.icorona )
|
coronaAb = self.getInstanceAb( self.icorona )
|
||||||
lg = None
|
lg = None
|
||||||
|
@ -378,9 +371,24 @@ class ChipConf ( BlockConf ):
|
||||||
trace( 550, '-' )
|
trace( 550, '-' )
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
def getViaPitch ( self, viaLayer ):
|
||||||
|
topLayer = viaLayer.getTop()
|
||||||
|
topPitch = 2*viaLayer.getEnclosure \
|
||||||
|
( topLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
|
||||||
|
+ viaLayer.getMinimalSize() \
|
||||||
|
+ topLayer.getMinimalSpacing()
|
||||||
|
botLayer = viaLayer.getBottom()
|
||||||
|
botPitch = 2*viaLayer.getEnclosure \
|
||||||
|
( botLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
|
||||||
|
+ viaLayer.getMinimalSize() \
|
||||||
|
+ botLayer.getMinimalSpacing()
|
||||||
|
viaPitch = max( topPitch, botPitch )
|
||||||
|
trace( 550, '\tgetViaPitch of {}: {}l\n'.format(viaLayer.getName(),DbU.getValueString(viaPitch)) )
|
||||||
|
return viaPitch
|
||||||
|
|
||||||
def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
|
def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
|
||||||
trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
|
trace( 550, ',+', '\tChipConf.coronaContactArray\n' )
|
||||||
viaPitch = layer.getMinimalSize() + layer.getMinimalSpacing()
|
viaPitch = self.getViaPitch( layer )
|
||||||
coronaAb = self.getInstanceAb( self.icorona )
|
coronaAb = self.getInstanceAb( self.icorona )
|
||||||
coronaNet = self.getCoronaNet( chipNet )
|
coronaNet = self.getCoronaNet( chipNet )
|
||||||
if not coronaNet: return None
|
if not coronaNet: return None
|
||||||
|
@ -481,7 +489,7 @@ class ChipConf ( BlockConf ):
|
||||||
.format(i,padList[i][1],side) ))
|
.format(i,padList[i][1],side) ))
|
||||||
return
|
return
|
||||||
|
|
||||||
af = CRL.AllianceFramework.get()
|
global af
|
||||||
cellPads = []
|
cellPads = []
|
||||||
for instance in self.chip.getInstances():
|
for instance in self.chip.getInstances():
|
||||||
if contains(self.southPads,'south',instance): continue
|
if contains(self.southPads,'south',instance): continue
|
||||||
|
@ -559,13 +567,9 @@ class ChipConf ( BlockConf ):
|
||||||
self.coronaVdd = net
|
self.coronaVdd = net
|
||||||
|
|
||||||
if netType == Net.Type.CLOCK:
|
if netType == Net.Type.CLOCK:
|
||||||
if self.coronaCk and self.coronaCk != net:
|
if not net in self.coronaCks:
|
||||||
raise ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple clock nets "{}" and "{}" at corona level.' \
|
self.coronaCks.append( net )
|
||||||
.format(self.coronaCk.getName(), net.getName()) )
|
vprint( 2, ' - Using clock "{}".'.format(net.getName()) )
|
||||||
self._validated = False
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
self.coronaCk = net
|
|
||||||
for net in self.corona.getNets():
|
for net in self.corona.getNets():
|
||||||
if net.getType() == Net.Type.BLOCKAGE:
|
if net.getType() == Net.Type.BLOCKAGE:
|
||||||
self.blockageNet = net
|
self.blockageNet = net
|
||||||
|
|
|
@ -105,29 +105,37 @@ class HorizontalRail ( Rail ):
|
||||||
trace( 550, '\t{}\n'.format(self) )
|
trace( 550, '\t{}\n'.format(self) )
|
||||||
|
|
||||||
def __str__ ( self ):
|
def __str__ ( self ):
|
||||||
return '<HorizontalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order)
|
return '<HorizontalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order).getName()
|
||||||
, self.order
|
, self.order
|
||||||
, DbU.getValueString(self.axis) )
|
, DbU.getValueString(self.axis) )
|
||||||
|
|
||||||
def connect ( self, contact ):
|
def connect ( self, contact ):
|
||||||
|
trace( 550, ',+', '\tTry to connect to: {}\n'.format(self) )
|
||||||
contactBb = contact.getBoundingBox()
|
contactBb = contact.getBoundingBox()
|
||||||
if contactBb.getXMin() < self.side.innerBb.getXMin() \
|
if contactBb.getXMin() < self.side.innerBb.getXMin() \
|
||||||
or contactBb.getXMax() > self.side.innerBb.getXMax():
|
or contactBb.getXMax() > self.side.innerBb.getXMax():
|
||||||
|
trace( 550, '-' )
|
||||||
raise ErrorMessage( 1, [ '{} is outside rail/corona X range,'.format(contact)
|
raise ErrorMessage( 1, [ '{} is outside rail/corona X range,'.format(contact)
|
||||||
, 'power pad is likely to be to far off west or east.'
|
, 'power pad is likely to be to far off west or east.'
|
||||||
, '(core:{})'.format(self.side.innerBb) ] )
|
, '(core:{})'.format(self.side.innerBb) ] )
|
||||||
if self.vias.has_key(contact.getX()): return False
|
if self.vias.has_key(contact.getX()): return False
|
||||||
|
trace( 550, '\tvias:{}\n'.format(self.vias) )
|
||||||
keys = self.vias.keys()
|
keys = self.vias.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
insertIndex = bisect.bisect_left( keys, contact.getX() )
|
insertIndex = bisect.bisect_left( keys, contact.getX() )
|
||||||
|
|
||||||
if len(keys) > 0:
|
if len(keys) > 0:
|
||||||
|
trace( 550, '\tinsertIndex:{}\n'.format(insertIndex) )
|
||||||
if insertIndex < len(keys):
|
if insertIndex < len(keys):
|
||||||
insertPosition = keys[ insertIndex ]
|
insertPosition = keys[ insertIndex ]
|
||||||
|
trace( 550, '\tinsertPosition:{}\n'.format(insertPosition) )
|
||||||
if contactBb.getXMax() >= self.vias[insertPosition][2].getBoundingBox().getXMin():
|
if contactBb.getXMax() >= self.vias[insertPosition][2].getBoundingBox().getXMin():
|
||||||
|
trace( 550, ',-', '\tFailed: overlap with existing contact @{}.\n' \
|
||||||
|
.format(self.vias[insertPosition][2]) )
|
||||||
return False
|
return False
|
||||||
if insertIndex > 0:
|
if insertIndex > 0:
|
||||||
if self.vias[keys[insertIndex-1]][2].getBoundingBox().getXMax() >= contactBb.getXMin():
|
if self.vias[keys[insertIndex-1]][2].getBoundingBox().getXMax() >= contactBb.getXMin():
|
||||||
|
trace( 550, ',-', '\tFailed: overlap with existing contact @{}.\n' \
|
||||||
|
.format(self.vias[keys[insertIndex-1]][2]) )
|
||||||
return False
|
return False
|
||||||
self.vias[ contact.getX() ] = [ contact.getX()
|
self.vias[ contact.getX() ] = [ contact.getX()
|
||||||
, StackedVia( self.net
|
, StackedVia( self.net
|
||||||
|
@ -144,6 +152,7 @@ class HorizontalRail ( Rail ):
|
||||||
, DbU.getValueString(contact.getX())
|
, DbU.getValueString(contact.getX())
|
||||||
, DbU.getValueString(self.axis)) )
|
, DbU.getValueString(self.axis)) )
|
||||||
self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) )
|
self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) )
|
||||||
|
trace( 550, '-' )
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def doLayout ( self ):
|
def doLayout ( self ):
|
||||||
|
@ -183,7 +192,7 @@ class VerticalRail ( Rail ):
|
||||||
trace( 550, '\t{}\n'.format(self) )
|
trace( 550, '\t{}\n'.format(self) )
|
||||||
|
|
||||||
def __str__ ( self ):
|
def __str__ ( self ):
|
||||||
return '<VerticalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order)
|
return '<VerticalRail "{}" ({}) @{}>'.format( self.side.getRailNet(self.order).getName()
|
||||||
, self.order
|
, self.order
|
||||||
, DbU.getValueString(self.axis) )
|
, DbU.getValueString(self.axis) )
|
||||||
|
|
||||||
|
@ -217,14 +226,14 @@ class VerticalRail ( Rail ):
|
||||||
, 'power pad is likely to be to far off north or south.'
|
, 'power pad is likely to be to far off north or south.'
|
||||||
, '(core:{})'.format(self.side.innerBb) ] )
|
, '(core:{})'.format(self.side.innerBb) ] )
|
||||||
if self.vias.has_key(contact.getY()): return False
|
if self.vias.has_key(contact.getY()): return False
|
||||||
trace( 550, ',+', '\tVerticalRail.connect() [{}] @{}\n'.format(self.order,DbU.toLambda(self.axis)) )
|
trace( 550, ',+', '\tVerticalRail.connect() [{}] @{}\n'.format(self.order,DbU.getValueString(self.axis)) )
|
||||||
trace( 550, '\t{}\n'.format(contact) )
|
trace( 550, '\t{}\n'.format(contact) )
|
||||||
keys = self.vias.keys()
|
keys = self.vias.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
insertIndex = bisect.bisect_left( keys, contact.getY() )
|
insertIndex = bisect.bisect_left( keys, contact.getY() )
|
||||||
trace( 550, ',+', '\tkeys:' )
|
trace( 550, ',+', '\tkeys:' )
|
||||||
for key in keys:
|
for key in keys:
|
||||||
trace( 550, ' {}'.format(DbU.toLambda(key)) )
|
trace( 550, ' {}'.format(DbU.getValueString(key)) )
|
||||||
trace( 550, '\n' )
|
trace( 550, '\n' )
|
||||||
|
|
||||||
if len(keys) > 0:
|
if len(keys) > 0:
|
||||||
|
@ -266,9 +275,18 @@ class Side ( object ):
|
||||||
def __init__ ( self, corona ):
|
def __init__ ( self, corona ):
|
||||||
self.corona = corona
|
self.corona = corona
|
||||||
|
|
||||||
|
@property
|
||||||
|
def side ( self ):
|
||||||
|
raise NotImplementedError('Side.side is not implemented in base class.')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def railsCount ( self ): return self.corona.railsCount
|
def railsCount ( self ): return self.corona.railsCount
|
||||||
|
|
||||||
|
@property
|
||||||
|
def coronaCks ( self ):
|
||||||
|
if self.corona.conf.useClockTree: return self.corona.conf.coronaCks
|
||||||
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def innerBb ( self ): return self.corona.innerBb
|
def innerBb ( self ): return self.corona.innerBb
|
||||||
|
|
||||||
|
@ -296,6 +314,7 @@ class Side ( object ):
|
||||||
@property
|
@property
|
||||||
def blockageNet ( self ): return self.corona.blockageNet
|
def blockageNet ( self ): return self.corona.blockageNet
|
||||||
|
|
||||||
|
def isHorizontal ( self ): return (self.side & HORIZONTAL) == HORIZONTAL
|
||||||
def getLayerDepth ( self, metal ): return self.corona.getLayerDepth(metal)
|
def getLayerDepth ( self, metal ): return self.corona.getLayerDepth(metal)
|
||||||
def getRail ( self, i ): return self.rails[i]
|
def getRail ( self, i ): return self.rails[i]
|
||||||
def getRailNet ( self, i ): return self.corona.getRailNet(i)
|
def getRailNet ( self, i ): return self.corona.getRailNet(i)
|
||||||
|
@ -318,27 +337,41 @@ class Side ( object ):
|
||||||
return self.rails[-(i+1)]
|
return self.rails[-(i+1)]
|
||||||
|
|
||||||
def connect ( self, blockSide ):
|
def connect ( self, blockSide ):
|
||||||
|
trace( 550, '\tSide.connect()\n' )
|
||||||
for terminal in blockSide.terminals:
|
for terminal in blockSide.terminals:
|
||||||
trace( 550, '\tterminal:{}\n'.format(terminal) )
|
trace( 550, '\tterminal:{}\n'.format(terminal) )
|
||||||
for rail in self.rails:
|
for rail in self.rails:
|
||||||
rail.connect( terminal[1] )
|
rail.connect( terminal[1] )
|
||||||
|
|
||||||
|
def getRailRange ( self, net ):
|
||||||
|
if net.isClock(): return range(len(self.rails))
|
||||||
|
if not net.isSupply(): return []
|
||||||
|
if self.side & HORIZONTAL:
|
||||||
|
trace( 550, '\tHORIZONTAL rail.\n' )
|
||||||
|
return range( len(self.coronaCks), len(self.rails) )
|
||||||
|
else:
|
||||||
|
trace( 550, '\t{} > {}\n'.format(self.horizontalDepth,self.verticalDepth) )
|
||||||
|
if self.horizontalDepth > self.verticalDepth:
|
||||||
|
return range( len(self.coronaCks), len(self.rails) )
|
||||||
|
trace( 550, '\tUsing half rails only.\n' )
|
||||||
|
return range( len(self.coronaCks) + len(self.rails)/2 - 2, len(self.rails) )
|
||||||
|
|
||||||
def connectPads ( self, padSide ):
|
def connectPads ( self, padSide ):
|
||||||
for contact in padSide.pins:
|
#for contact in padSide.pins:
|
||||||
if contact.getNet().isClock():
|
# if contact.getNet().isClock():
|
||||||
for i in range(len(self.rails)):
|
# for i in range(len(self.rails)):
|
||||||
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.toLambda(self.getOuterRail(i).axis)) )
|
# trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.getValueString(self.getOuterRail(i).axis)) )
|
||||||
self.getOuterRail(i).connect( contact )
|
# self.getOuterRail(i).connect( contact )
|
||||||
elif contact.getNet().isSupply():
|
# elif contact.getNet().isSupply():
|
||||||
self.getOuterRail( 0 ).connect( contact )
|
# self.getOuterRail( 0 ).connect( contact )
|
||||||
halfRails = (len(self.rails)-1)/2
|
|
||||||
trace( 550, '\thalfRails:{}\n'.format(halfRails) )
|
|
||||||
for contact in padSide.pins:
|
for contact in padSide.pins:
|
||||||
if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue
|
if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue
|
||||||
trace( 550, ',+', '\tConnect pad contact {}\n'.format(contact) )
|
trace( 550, ',+', '\tConnect pad contact {}\n'.format(contact) )
|
||||||
for i in range(halfRails):
|
railRange = self.getRailRange( contact.getNet() )
|
||||||
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.toLambda(self.getOuterRail(i).axis)) )
|
trace( 550, '\trailRange:{}\n'.format(railRange) )
|
||||||
self.getOuterRail(i).connect( contact )
|
for i in railRange:
|
||||||
|
trace( 550, '\tConnect to [-{}] @{}\n'.format(i, DbU.getValueString(self.getInnerRail(i).axis)) )
|
||||||
|
self.getInnerRail(i).connect( contact )
|
||||||
trace( 550, '-' )
|
trace( 550, '-' )
|
||||||
|
|
||||||
def doLayout ( self ):
|
def doLayout ( self ):
|
||||||
|
@ -367,6 +400,9 @@ class SouthSide ( HorizontalSide ):
|
||||||
HorizontalSide.__init__( self, corona )
|
HorizontalSide.__init__( self, corona )
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def side ( self ): return South
|
||||||
|
|
||||||
def getRailAxis ( self, i ):
|
def getRailAxis ( self, i ):
|
||||||
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
|
return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \
|
||||||
- i*(self.hRailWidth + self.hRailSpace)
|
- i*(self.hRailWidth + self.hRailSpace)
|
||||||
|
@ -384,6 +420,9 @@ class NorthSide ( HorizontalSide ):
|
||||||
HorizontalSide.__init__( self, corona )
|
HorizontalSide.__init__( self, corona )
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def side ( self ): return North
|
||||||
|
|
||||||
def getRailAxis ( self, i ):
|
def getRailAxis ( self, i ):
|
||||||
return self.innerBb.getYMax() + self.hRailWidth/2 + self.hRailSpace \
|
return self.innerBb.getYMax() + self.hRailWidth/2 + self.hRailSpace \
|
||||||
+ i*(self.hRailWidth + self.hRailSpace)
|
+ i*(self.hRailWidth + self.hRailSpace)
|
||||||
|
@ -446,12 +485,15 @@ class WestSide ( VerticalSide ):
|
||||||
def __init__ ( self, corona ):
|
def __init__ ( self, corona ):
|
||||||
VerticalSide.__init__( self, corona )
|
VerticalSide.__init__( self, corona )
|
||||||
|
|
||||||
|
@property
|
||||||
|
def side ( self ): return West
|
||||||
|
|
||||||
def getRailAxis ( self, i ):
|
def getRailAxis ( self, i ):
|
||||||
return self.innerBb.getXMin() - self.vRailWidth/2 - self.vRailSpace \
|
return self.innerBb.getXMin() - self.vRailWidth/2 - self.vRailSpace \
|
||||||
- i*(self.vRailWidth + self.vRailSpace)
|
- i*(self.vRailWidth + self.vRailSpace)
|
||||||
|
|
||||||
def corner0 ( self, i ): return self.corners[SouthWest][i]
|
def corner0 ( self, i ): return self.corners[SouthWest][i]
|
||||||
def corner1 ( self, i ): return self.corners[NorthWest ][i]
|
def corner1 ( self, i ): return self.corners[NorthWest][i]
|
||||||
|
|
||||||
def addBlockages ( self ):
|
def addBlockages ( self ):
|
||||||
sideXMin = self.getOuterRail(0).axis - self.vRailWidth
|
sideXMin = self.getOuterRail(0).axis - self.vRailWidth
|
||||||
|
@ -467,12 +509,15 @@ class EastSide ( VerticalSide ):
|
||||||
def __init__ ( self, corona ):
|
def __init__ ( self, corona ):
|
||||||
VerticalSide.__init__( self, corona )
|
VerticalSide.__init__( self, corona )
|
||||||
|
|
||||||
|
@property
|
||||||
|
def side ( self ): return East
|
||||||
|
|
||||||
def getRailAxis ( self, i ):
|
def getRailAxis ( self, i ):
|
||||||
return self.innerBb.getXMax() + self.vRailWidth/2 + self.vRailSpace \
|
return self.innerBb.getXMax() + self.vRailWidth/2 + self.vRailSpace \
|
||||||
+ i*(self.vRailWidth + self.vRailSpace)
|
+ i*(self.vRailWidth + self.vRailSpace)
|
||||||
|
|
||||||
def corner0 ( self, i ): return self.corners[SouthEast][i]
|
def corner0 ( self, i ): return self.corners[SouthEast][i]
|
||||||
def corner1 ( self, i ): return self.corners[NorthEast ][i]
|
def corner1 ( self, i ): return self.corners[NorthEast][i]
|
||||||
|
|
||||||
def addBlockages ( self ):
|
def addBlockages ( self ):
|
||||||
sideXMin = self.getInnerRail(0).axis - self.vRailWidth
|
sideXMin = self.getInnerRail(0).axis - self.vRailWidth
|
||||||
|
@ -532,7 +577,8 @@ class Builder ( object ):
|
||||||
return self.conf.routingGauge.getLayerDepth( metal )
|
return self.conf.routingGauge.getLayerDepth( metal )
|
||||||
|
|
||||||
def getRailNet ( self, i ):
|
def getRailNet ( self, i ):
|
||||||
if self.conf.useClockTree and i == 0: return self.conf.coronaCk
|
if self.conf.useClockTree and i < len(self.conf.coronaCks):
|
||||||
|
return self.conf.coronaCks[i]
|
||||||
if i % 2: return self.conf.coronaVss
|
if i % 2: return self.conf.coronaVss
|
||||||
return self.conf.coronaVdd
|
return self.conf.coronaVdd
|
||||||
|
|
||||||
|
|
|
@ -278,78 +278,64 @@ class Side ( object ):
|
||||||
self.u += gapWidth
|
self.u += gapWidth
|
||||||
|
|
||||||
def _placePad ( self, padInstance ):
|
def _placePad ( self, padInstance ):
|
||||||
if self.type == North:
|
if self.type == North:
|
||||||
x = self.conf.chipAb.getXMin() + self.u
|
x = self.conf.chipAb.getXMin() + self.u
|
||||||
y = self.conf.chipAb.getYMax()
|
y = self.conf.chipAb.getYMax()
|
||||||
|
if self.corona.padOrient == Transformation.Orientation.ID:
|
||||||
if self.corona.padOrient == Transformation.Orientation.ID:
|
orientation = Transformation.Orientation.MY
|
||||||
orientation = Transformation.Orientation.MY
|
else:
|
||||||
else:
|
orientation = Transformation.Orientation.ID
|
||||||
orientation = Transformation.Orientation.ID
|
y -= self.conf.ioPadHeight
|
||||||
y -= self.conf.ioPadHeight
|
elif self.type == South:
|
||||||
|
x = self.conf.chipAb.getXMin() + self.u
|
||||||
elif self.type == South:
|
y = self.conf.chipAb.getYMin()
|
||||||
x = self.conf.chipAb.getXMin() + self.u
|
if self.corona.padOrient == Transformation.Orientation.ID:
|
||||||
y = self.conf.chipAb.getYMin()
|
orientation = Transformation.Orientation.ID
|
||||||
|
else:
|
||||||
if self.corona.padOrient == Transformation.Orientation.ID:
|
orientation = Transformation.Orientation.MY
|
||||||
orientation = Transformation.Orientation.ID
|
y += self.conf.ioPadHeight
|
||||||
else:
|
elif self.type == West:
|
||||||
orientation = Transformation.Orientation.MY
|
x = self.conf.chipAb.getXMin()
|
||||||
y += self.conf.ioPadHeight
|
y = self.conf.chipAb.getYMin() + self.u
|
||||||
|
if self.corona.padOrient == Transformation.Orientation.ID:
|
||||||
elif self.type == West:
|
orientation = Transformation.Orientation.R3
|
||||||
x = self.conf.chipAb.getXMin()
|
y += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
||||||
y = self.conf.chipAb.getYMin() + self.u
|
else:
|
||||||
|
orientation = Transformation.Orientation.R1
|
||||||
if self.corona.padOrient == Transformation.Orientation.ID:
|
x += padInstance.getMasterCell().getAbutmentBox().getHeight()
|
||||||
orientation = Transformation.Orientation.R3
|
elif self.type == East:
|
||||||
y += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
x = self.conf.chipAb.getXMax()
|
||||||
else:
|
y = self.conf.chipAb.getYMin() + self.u
|
||||||
orientation = Transformation.Orientation.R1
|
if self.corona.padOrient == Transformation.Orientation.ID:
|
||||||
x += padInstance.getMasterCell().getAbutmentBox().getHeight()
|
orientation = Transformation.Orientation.R1
|
||||||
|
else:
|
||||||
elif self.type == East:
|
orientation = Transformation.Orientation.R3
|
||||||
x = self.conf.chipAb.getXMax()
|
x -= padInstance.getMasterCell().getAbutmentBox().getHeight()
|
||||||
y = self.conf.chipAb.getYMin() + self.u
|
y += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
||||||
|
padInstance.setTransformation ( Transformation( self.toGrid(x), self.toGrid(y), orientation ) )
|
||||||
if self.corona.padOrient == Transformation.Orientation.ID:
|
padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||||
orientation = Transformation.Orientation.R1
|
self.u += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
||||||
else:
|
p = None
|
||||||
orientation = Transformation.Orientation.R3
|
if self.conf.ioPadGauge.getName() == 'pxlib':
|
||||||
x -= padInstance.getMasterCell().getAbutmentBox().getHeight()
|
p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' )
|
||||||
y += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
if self.conf.ioPadGauge.getName().startswith('phlib'):
|
||||||
|
p = re.compile( r'p(?P<power>v[sd]{2})ck2_sp' )
|
||||||
padInstance.setTransformation ( Transformation( self.toGrid(x), self.toGrid(y), orientation ) )
|
if self.conf.ioPadGauge.getName() == 'niolib':
|
||||||
padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
p = re.compile( r'(?P<power>(io)?v[sd]{2})' )
|
||||||
|
if p:
|
||||||
self.u += padInstance.getMasterCell().getAbutmentBox().getWidth()
|
m = p.match( padInstance.getMasterCell().getName() )
|
||||||
|
padName = 'pad'
|
||||||
p = None
|
if m: padName = m.group( 'power' )
|
||||||
if self.conf.ioPadGauge.getName() == 'pxlib':
|
padNet = padInstance.getMasterCell().getNet( padName )
|
||||||
p = re.compile( r'p(?P<power>v[sd]{2}[ei])ck_px' )
|
trace( 550, '\tpadName:{} padNet:{}\n'.format(padName,padNet) )
|
||||||
|
if padNet:
|
||||||
if self.conf.ioPadGauge.getName().startswith('phlib'):
|
plug = padInstance.getPlug( padNet )
|
||||||
p = re.compile( r'p(?P<power>v[sd]{2})ck2_sp' )
|
chipNet = plug.getNet()
|
||||||
|
if not chipNet and padNet.isGlobal():
|
||||||
if p:
|
chipNet = padInstance.getCell().getNet( padNet.getName() )
|
||||||
m = p.match( padInstance.getMasterCell().getName() )
|
if chipNet:
|
||||||
|
rp = RoutingPad.create( chipNet, Occurrence(plug), RoutingPad.BiggestArea )
|
||||||
padName = 'pad'
|
return
|
||||||
if m: padName = m.group( 'power' )
|
|
||||||
|
|
||||||
padNet = padInstance.getMasterCell().getNet( padName )
|
|
||||||
#print 'padName:', padName, 'padNet:', padNet
|
|
||||||
if padNet:
|
|
||||||
plug = padInstance.getPlug( padNet )
|
|
||||||
chipNet = plug.getNet()
|
|
||||||
|
|
||||||
if not chipNet and padNet.isGlobal():
|
|
||||||
chipNet = padInstance.getCell().getNet( padNet.getName() )
|
|
||||||
|
|
||||||
if chipNet:
|
|
||||||
rp = RoutingPad.create( chipNet, Occurrence(plug), RoutingPad.BiggestArea )
|
|
||||||
return
|
|
||||||
|
|
||||||
def _placePads ( self ):
|
def _placePads ( self ):
|
||||||
padLength = 0
|
padLength = 0
|
||||||
|
@ -483,7 +469,6 @@ class Side ( object ):
|
||||||
class CoreWire ( object ):
|
class CoreWire ( object ):
|
||||||
|
|
||||||
# Should be read from the symbolic technology rules.
|
# Should be read from the symbolic technology rules.
|
||||||
viaPitch = DbU.fromLambda( 4.0 )
|
|
||||||
|
|
||||||
NoOffset = 0x0000
|
NoOffset = 0x0000
|
||||||
AtBegin = 0x0001
|
AtBegin = 0x0001
|
||||||
|
@ -501,6 +486,9 @@ class CoreWire ( object ):
|
||||||
self.inCoronaRange = True
|
self.inCoronaRange = True
|
||||||
self.arraySize = None
|
self.arraySize = None
|
||||||
self.count = count
|
self.count = count
|
||||||
|
self.viaPitch = DbU.fromLambda( 4.0 )
|
||||||
|
self.gapWidth = 0
|
||||||
|
self._computeCoreLayers()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def conf ( self ): return self.corona.conf
|
def conf ( self ): return self.corona.conf
|
||||||
|
@ -548,22 +536,22 @@ class CoreWire ( object ):
|
||||||
self.symContactSize = ( self.bbSegment.getHeight(), self.bbSegment.getHeight() )
|
self.symContactSize = ( self.bbSegment.getHeight(), self.bbSegment.getHeight() )
|
||||||
else:
|
else:
|
||||||
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() )
|
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() )
|
||||||
|
self.viaPitch = self.conf.getViaPitch( self.symContactLayer )
|
||||||
contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer()
|
contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer()
|
||||||
, Layer.EnclosureH|Layer.EnclosureV ) \
|
, Layer.EnclosureH|Layer.EnclosureV ) \
|
||||||
+ self.symContactLayer.getMinimalSize()
|
+ self.symContactLayer.getMinimalSize()
|
||||||
arrayWidth = self.symContactSize[0]
|
arrayWidth = self.symContactSize[0]
|
||||||
arrayCount = (arrayWidth - contactMinSize) / CoreWire.viaPitch
|
arrayCount = (arrayWidth - contactMinSize) / self.viaPitch
|
||||||
trace( 550, '\tCoreWire.viaPitch: {}l\n'.format(DbU.toLambda(CoreWire.viaPitch)) )
|
|
||||||
trace( 550, '\tcontactMinSize: {}l, arrayWidth: {}l, arrayCount: {}\n' \
|
trace( 550, '\tcontactMinSize: {}l, arrayWidth: {}l, arrayCount: {}\n' \
|
||||||
.format(DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) )
|
.format(DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) )
|
||||||
if arrayCount < 0: arrayCount = 0
|
if arrayCount < 0: arrayCount = 0
|
||||||
if arrayCount < 3:
|
#if arrayCount < 3:
|
||||||
if self.side & (North|South):
|
if self.side & (North|South):
|
||||||
self.arraySize = ( arrayCount+1, 2 )
|
self.arraySize = ( arrayCount+1, 2 )
|
||||||
else:
|
else:
|
||||||
self.arraySize = ( 2, arrayCount+1 )
|
self.arraySize = ( 2, arrayCount+1 )
|
||||||
trace( 550, '\tarraySize = ({},{})\n'.format(self.arraySize[0], self.arraySize[1]) )
|
trace( 550, '\tarraySize = ({},{})\n'.format(self.arraySize[0], self.arraySize[1]) )
|
||||||
|
self.gapWidth = 4*self.viaPitch
|
||||||
trace( 550, ',-' )
|
trace( 550, ',-' )
|
||||||
return
|
return
|
||||||
raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \
|
raise ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \
|
||||||
|
@ -594,7 +582,8 @@ class CoreWire ( object ):
|
||||||
xPadMax = xContact
|
xPadMax = xContact
|
||||||
xCore = coronaAb.getXMin()
|
xCore = coronaAb.getXMin()
|
||||||
if not self.preferredDir:
|
if not self.preferredDir:
|
||||||
xPadMax += self.bbSegment.getHeight()/2
|
#xPadMax += self.bbSegment.getHeight()/2
|
||||||
|
xPadMin += 3*vPitch
|
||||||
else:
|
else:
|
||||||
accessDirection = Pin.Direction.EAST
|
accessDirection = Pin.Direction.EAST
|
||||||
xPadMax = self.bbSegment.getXMax()
|
xPadMax = self.bbSegment.getXMax()
|
||||||
|
@ -602,7 +591,8 @@ class CoreWire ( object ):
|
||||||
xPadMin = xContact
|
xPadMin = xContact
|
||||||
xCore = coronaAb.getXMax()
|
xCore = coronaAb.getXMax()
|
||||||
if not self.preferredDir:
|
if not self.preferredDir:
|
||||||
xPadMin -= self.bbSegment.getHeight()/2
|
#xPadMin -= self.bbSegment.getHeight()/2
|
||||||
|
xPadMin -= 3*vPitch
|
||||||
hReal = Horizontal.create( self.chipNet
|
hReal = Horizontal.create( self.chipNet
|
||||||
, self.padSegment.getLayer()
|
, self.padSegment.getLayer()
|
||||||
, self.bbSegment.getCenter().getY()
|
, self.bbSegment.getCenter().getY()
|
||||||
|
@ -683,16 +673,18 @@ class CoreWire ( object ):
|
||||||
yPadMax = self.corona.coreSymBb.getYMin() - self.offset * 2*hPitch
|
yPadMax = self.corona.coreSymBb.getYMin() - self.offset * 2*hPitch
|
||||||
yContact = yPadMax
|
yContact = yPadMax
|
||||||
yCore = coronaAb.getYMin()
|
yCore = coronaAb.getYMin()
|
||||||
if not self.preferredDir:
|
#if not self.preferredDir:
|
||||||
yPadMax += self.bbSegment.getWidth()/2
|
# yPadMax += self.bbSegment.getWidth()/2
|
||||||
|
# yPadMin += 3*hPitch
|
||||||
else:
|
else:
|
||||||
accessDirection = Pin.Direction.NORTH
|
accessDirection = Pin.Direction.NORTH
|
||||||
yPadMax = self.bbSegment.getYMax()
|
yPadMax = self.bbSegment.getYMax()
|
||||||
yPadMin = self.corona.coreSymBb.getYMax() + self.offset * 2*hPitch
|
yPadMin = self.corona.coreSymBb.getYMax() + self.offset * 2*hPitch
|
||||||
yContact = yPadMin
|
yContact = yPadMin
|
||||||
yCore = coronaAb.getYMax()
|
yCore = coronaAb.getYMax()
|
||||||
if not self.preferredDir:
|
#if not self.preferredDir:
|
||||||
yPadMin -= self.bbSegment.getWidth()/2
|
# yPadMin -= self.bbSegment.getWidth()/2
|
||||||
|
# yPadMin -= 3*hPitch
|
||||||
vReal = Vertical.create( self.chipNet
|
vReal = Vertical.create( self.chipNet
|
||||||
, self.padSegment.getLayer()
|
, self.padSegment.getLayer()
|
||||||
, self.bbSegment.getCenter().getX()
|
, self.bbSegment.getCenter().getX()
|
||||||
|
@ -805,9 +797,10 @@ class Corona ( object ):
|
||||||
self.padSpacers = []
|
self.padSpacers = []
|
||||||
self.padCorner = []
|
self.padCorner = []
|
||||||
self.padRails = [] # [ , [net, layer, axis, width] ]
|
self.padRails = [] # [ , [net, layer, axis, width] ]
|
||||||
if Cfg.hasParameter('chip.padCoreSide'):
|
self.conf.cfg.chip.padCoreSide = None
|
||||||
if Cfg.getParamString('chip.padCoreSide').asString().lower() == 'south':
|
if self.conf.cfg.chip.padCoreSide.lower() == 'south':
|
||||||
self.padOrient = Transformation.Orientation.MY
|
self.padOrient = Transformation.Orientation.MY
|
||||||
|
trace( 550, '\tchip.padCoreSide: {}\n'.format(self.conf.cfg.chip.padCoreSide) )
|
||||||
self._allPadsAnalysis()
|
self._allPadsAnalysis()
|
||||||
if Cfg.hasParameter('chip.padSpacers'):
|
if Cfg.hasParameter('chip.padSpacers'):
|
||||||
for spacerName in Cfg.getParamString('chip.padSpacers').asString().split(','):
|
for spacerName in Cfg.getParamString('chip.padSpacers').asString().split(','):
|
||||||
|
@ -889,10 +882,10 @@ class Corona ( object ):
|
||||||
if plug.getMasterNet().isGlobal():
|
if plug.getMasterNet().isGlobal():
|
||||||
net = self.conf.cell.getNet( plug.getMasterNet().getName() )
|
net = self.conf.cell.getNet( plug.getMasterNet().getName() )
|
||||||
if not net:
|
if not net:
|
||||||
raise ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is not connected and there is no global net (in pad \"%s").' \
|
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "%s" is not connected and there is no global net (in pad \"%s").' \
|
||||||
% plug.getMasterNet().getName(), padCell.getName() )
|
% plug.getMasterNet().getName(), padCell.getName() )
|
||||||
else:
|
else:
|
||||||
raise ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \
|
raise ErrorMessage( 1, 'Corona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \
|
||||||
% plug.getMasterNet().getName(), padCell.getName() )
|
% plug.getMasterNet().getName(), padCell.getName() )
|
||||||
if net:
|
if net:
|
||||||
self.padRails.append( ( net
|
self.padRails.append( ( net
|
||||||
|
@ -901,12 +894,18 @@ class Corona ( object ):
|
||||||
, component.getWidth() ) )
|
, component.getWidth() ) )
|
||||||
|
|
||||||
def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ):
|
def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ):
|
||||||
|
trace( 550, ',+', '\tCorona._createCoreWire()\n' )
|
||||||
|
trace( 550, '\tchipIntNet:{}\n'.format(chipIntNet) )
|
||||||
|
trace( 550, '\tpadNet:{}\n'.format(padNet) )
|
||||||
|
trace( 550, '\tpadInstance:{}\n'.format(padInstance) )
|
||||||
side = None
|
side = None
|
||||||
if self.hasSouthPad(padInstance): side = self.southSide
|
if self.hasSouthPad(padInstance): side = self.southSide
|
||||||
elif self.hasNorthPad(padInstance): side = self.northSide
|
elif self.hasNorthPad(padInstance): side = self.northSide
|
||||||
elif self.hasEastPad (padInstance): side = self.eastSide
|
elif self.hasEastPad (padInstance): side = self.eastSide
|
||||||
elif self.hasWestPad (padInstance): side = self.westSide
|
elif self.hasWestPad (padInstance): side = self.westSide
|
||||||
if not side: return count
|
if not side:
|
||||||
|
trace( 550, '-' )
|
||||||
|
return count
|
||||||
innerBb = self.conf.chip.getAbutmentBox().inflate( -self.conf.ioPadHeight )
|
innerBb = self.conf.chip.getAbutmentBox().inflate( -self.conf.ioPadHeight )
|
||||||
rg = self.conf.routingGauge
|
rg = self.conf.routingGauge
|
||||||
hsegments = {}
|
hsegments = {}
|
||||||
|
@ -946,25 +945,28 @@ class Corona ( object ):
|
||||||
coreWires = []
|
coreWires = []
|
||||||
if segments:
|
if segments:
|
||||||
for segment, bb in segments:
|
for segment, bb in segments:
|
||||||
if not inPreferredDir:
|
|
||||||
if side.type == North or side.type == South:
|
|
||||||
trace( 550, '\tNorth/South "{}" but RDir H, gapWidth: {}\n' \
|
|
||||||
.format(chipIntNet.getName(),DbU.getValueString(bb.getWidth()) ) )
|
|
||||||
side.updateGap( bb.getWidth() )
|
|
||||||
else:
|
|
||||||
trace( 550, '\tEast/West "{}" but RDir V, gapWidth: {}\n' \
|
|
||||||
.format(chipIntNet.getName(),DbU.getValueString(bb.getHeight())) )
|
|
||||||
side.updateGap( bb.getHeight() )
|
|
||||||
side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) )
|
side.addCoreWire( CoreWire( self, chipIntNet, segment, bb, side.type, inPreferredDir, count ) )
|
||||||
|
side.updateGap( side.coreWires[-1].gapWidth )
|
||||||
|
#if not inPreferredDir:
|
||||||
|
# if side.type == North or side.type == South:
|
||||||
|
# trace( 550, '\tNorth/South "{}" but RDir H, gapWidth: {}\n' \
|
||||||
|
# .format(chipIntNet.getName(),DbU.getValueString(bb.getWidth()) ) )
|
||||||
|
# side.updateGap( bb.getWidth() )
|
||||||
|
# else:
|
||||||
|
# trace( 550, '\tEast/West "{}" but RDir V, gapWidth: {}\n' \
|
||||||
|
# .format(chipIntNet.getName(),DbU.getValueString(bb.getHeight())) )
|
||||||
|
# side.updateGap( bb.getHeight() )
|
||||||
count += 1
|
count += 1
|
||||||
else:
|
else:
|
||||||
if not (chipIntNet.isGlobal() or chipIntNet.isSupply() or chipIntNet.isClock()):
|
if not (chipIntNet.isGlobal() or chipIntNet.isSupply() or chipIntNet.isClock()):
|
||||||
raise ErrorMessage( 1, [ 'PadsCorona._createCoreWire(): In I/O pad "{}" ({},{}),' \
|
trace( 550, '-' )
|
||||||
|
raise ErrorMessage( 1, [ 'Corona._createCoreWire(): In I/O pad "{}" ({},{}),' \
|
||||||
.format( padInstance.getMasterCell().getName()
|
.format( padInstance.getMasterCell().getName()
|
||||||
, padInstance.getName(), padInstance.getTransformation() )
|
, padInstance.getName(), padInstance.getTransformation() )
|
||||||
, 'connector "{}" has no suitable segment for net "{}".' \
|
, 'connector "{}" has no suitable segment for net "{}".' \
|
||||||
.format( padNet, chipIntNet.getName() )
|
.format( padNet, chipIntNet.getName() )
|
||||||
] )
|
] )
|
||||||
|
trace( 550, '-' )
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def _placeInnerCorona ( self ):
|
def _placeInnerCorona ( self ):
|
||||||
|
|
|
@ -15,28 +15,19 @@
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from Hurricane import DbU
|
from Hurricane import DbU, Point, Transformation, Box, Interval, \
|
||||||
from Hurricane import Point
|
Path, Occurrence, UpdateSession, Net, \
|
||||||
from Hurricane import Transformation
|
Contact, Horizontal, Vertical, Query
|
||||||
from Hurricane import Box
|
|
||||||
from Hurricane import Interval
|
|
||||||
from Hurricane import Path
|
|
||||||
from Hurricane import Occurrence
|
|
||||||
from Hurricane import UpdateSession
|
|
||||||
from Hurricane import Net
|
|
||||||
from Hurricane import Contact
|
|
||||||
from Hurricane import Horizontal
|
|
||||||
from Hurricane import Vertical
|
|
||||||
from Hurricane import Query
|
|
||||||
import CRL
|
import CRL
|
||||||
import helpers
|
import helpers
|
||||||
from helpers import trace
|
from helpers import trace
|
||||||
from helpers.io import ErrorMessage
|
from helpers.io import ErrorMessage, WarningMessage
|
||||||
from helpers.io import WarningMessage
|
|
||||||
from helpers.overlay import UpdateSession
|
from helpers.overlay import UpdateSession
|
||||||
import plugins
|
import plugins
|
||||||
import plugins.chip
|
import plugins.chip
|
||||||
|
|
||||||
|
__all__ = [ 'Builder' ]
|
||||||
|
|
||||||
plugins.chip.importConstants( globals() )
|
plugins.chip.importConstants( globals() )
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,28 +194,23 @@ class Builder ( object ):
|
||||||
query.doQuery()
|
query.doQuery()
|
||||||
self.activePlane = None
|
self.activePlane = None
|
||||||
|
|
||||||
def connectClock ( self ):
|
def _connectClock ( self, ck ):
|
||||||
if not self.conf.useClockTree:
|
trace( 550, '\tpower.Builder._connectClock() {}\n'.format(ck) )
|
||||||
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
|
|
||||||
return
|
|
||||||
if not self.conf.coronaCk:
|
|
||||||
raise ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' )
|
|
||||||
return
|
|
||||||
blockCk = None
|
blockCk = None
|
||||||
for plug in self.conf.icore.getPlugs():
|
for plug in self.conf.icore.getPlugs():
|
||||||
if plug.getNet() == self.conf.coronaCk:
|
if plug.getNet() == ck:
|
||||||
blockCk = plug.getMasterNet()
|
blockCk = plug.getMasterNet()
|
||||||
if not blockCk:
|
if not blockCk:
|
||||||
raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \
|
raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \
|
||||||
.format(self.conf.icore.getName(),self.conf.coronaCk.getName()) )
|
.format(self.conf.icore.getName(),ck.getName()) )
|
||||||
return
|
return
|
||||||
htPlugs = []
|
htPlugs = []
|
||||||
for plug in self.conf.coronaCk.getPlugs():
|
for plug in ck.getPlugs():
|
||||||
if plug.getInstance().isTerminalNetlist():
|
if plug.getInstance().isTerminalNetlist():
|
||||||
htPlugs.append( plug )
|
htPlugs.append( plug )
|
||||||
if len(htPlugs) != 1:
|
if len(htPlugs) != 1:
|
||||||
message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
|
message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
|
||||||
.format( self.conf.coronaCk.getName()
|
.format( ck.getName()
|
||||||
, self.conf.icore.getName()
|
, self.conf.icore.getName()
|
||||||
, len(htPlugs)) ]
|
, len(htPlugs)) ]
|
||||||
for plug in htPlugs:
|
for plug in htPlugs:
|
||||||
|
@ -232,13 +218,11 @@ class Builder ( object ):
|
||||||
raise ErrorMessage( 1, message )
|
raise ErrorMessage( 1, message )
|
||||||
return
|
return
|
||||||
with UpdateSession():
|
with UpdateSession():
|
||||||
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path())
|
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), ck, 0 )
|
||||||
, self.conf.coronaCk
|
|
||||||
, 0 )
|
|
||||||
blockAb = self.block.getAbutmentBox()
|
blockAb = self.block.getAbutmentBox()
|
||||||
self.path.getTransformation().applyOn( blockAb )
|
self.path.getTransformation().applyOn( blockAb )
|
||||||
layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth)
|
layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth)
|
||||||
contact = Contact.create( self.conf.coronaCk
|
contact = Contact.create( ck
|
||||||
, self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth)
|
, self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth)
|
||||||
, bufferRp.getX()
|
, bufferRp.getX()
|
||||||
, blockAb.getYMax()
|
, blockAb.getYMax()
|
||||||
|
@ -249,7 +233,18 @@ class Builder ( object ):
|
||||||
self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
|
self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
|
||||||
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
|
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
|
||||||
self.path.getTransformation().getInvert().applyOn( bb )
|
self.path.getTransformation().getInvert().applyOn( bb )
|
||||||
self.activePlane.addTerminal( self.conf.coronaCk, Plane.Vertical, bb )
|
self.activePlane.addTerminal( ck, Plane.Vertical, bb )
|
||||||
|
trace( 550, '\tAdded terminal of {} to vertical plane @{}\n'.format(ck,bb) )
|
||||||
|
|
||||||
|
def connectClocks ( self ):
|
||||||
|
if not self.conf.useClockTree:
|
||||||
|
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
|
||||||
|
return
|
||||||
|
if len(self.conf.coronaCks) == 0:
|
||||||
|
raise ErrorMessage( 1, 'Cannot build clock terminal as no clock is not known.' )
|
||||||
|
return
|
||||||
|
for ck in self.conf.coronaCks:
|
||||||
|
self._connectClock( ck )
|
||||||
|
|
||||||
def doLayout ( self ):
|
def doLayout ( self ):
|
||||||
with UpdateSession():
|
with UpdateSession():
|
||||||
|
|
|
@ -47,11 +47,11 @@ class CoreToChip ( BaseCoreToChip ):
|
||||||
, 'vddi' : None
|
, 'vddi' : None
|
||||||
, 'ck' : None # Go through the pads from pck_px.
|
, 'ck' : None # Go through the pads from pck_px.
|
||||||
}
|
}
|
||||||
self.ioPadInfos = { IoPad.IN : BaseCoreToChip.IoPadInfo( 'pi_px' , 'pad', ['t',] )
|
self.ioPadInfos = [ BaseCoreToChip.IoPadInfo( IoPad.IN , 'pi_px' , 'pad', ['t',] )
|
||||||
, IoPad.OUT : BaseCoreToChip.IoPadInfo( 'po_px' , 'pad', ['i',] )
|
, BaseCoreToChip.IoPadInfo( IoPad.OUT , 'po_px' , 'pad', ['i',] )
|
||||||
, IoPad.TRI_OUT : BaseCoreToChip.IoPadInfo( 'pot_px' , 'pad', ['i', 'b' ] )
|
, BaseCoreToChip.IoPadInfo( IoPad.TRI_OUT, 'pot_px' , 'pad', ['i', 'b'] )
|
||||||
, IoPad.BIDIR : BaseCoreToChip.IoPadInfo( 'piot_px', 'pad', ['i', 't', 'b' ] )
|
, BaseCoreToChip.IoPadInfo( IoPad.BIDIR , 'piot_px', 'pad', ['i', 't', 'b'] )
|
||||||
}
|
]
|
||||||
self._getPadLib()
|
self._getPadLib()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class CoreToChip ( BaseCoreToChip ):
|
||||||
% (self.padLib.getName(),masterCellName) )
|
% (self.padLib.getName(),masterCellName) )
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
def _buildGroundPads ( self, ioPadConf ):
|
def _buildAllGroundPads ( self, ioPadConf ):
|
||||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||||
|
@ -112,7 +112,7 @@ class CoreToChip ( BaseCoreToChip ):
|
||||||
self.groundPadCount += 1
|
self.groundPadCount += 1
|
||||||
self.chipPads += ioPadConf.pads
|
self.chipPads += ioPadConf.pads
|
||||||
|
|
||||||
def _buildPowerPads ( self, ioPadConf ):
|
def _buildAllPowerPads ( self, ioPadConf ):
|
||||||
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
coreNet = self.core .getNet( ioPadConf.coreSupplyNetName )
|
||||||
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
coronaNet = self.corona.getNet( ioPadConf.coreSupplyNetName )
|
||||||
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
chipNet = self.chip .getNet( ioPadConf.coreSupplyNetName )
|
||||||
|
|
|
@ -44,20 +44,16 @@ The double level chip+corona serves two purpose:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
from exceptions import NotImplementedError
|
||||||
import re
|
import re
|
||||||
from Hurricane import UpdateSession
|
from Hurricane import UpdateSession, Net, Instance
|
||||||
from Hurricane import Net
|
from CRL import Catalog, AllianceFramework
|
||||||
from Hurricane import Instance
|
from helpers import trace, netDirectionToStr
|
||||||
from CRL import Catalog
|
|
||||||
from CRL import AllianceFramework
|
|
||||||
from helpers import trace
|
|
||||||
from helpers import netDirectionToStr
|
|
||||||
from helpers.overlay import UpdateSession
|
from helpers.overlay import UpdateSession
|
||||||
from helpers.io import ErrorMessage
|
from helpers.io import ErrorMessage, WarningMessage
|
||||||
import plugins.chip
|
import plugins.chip
|
||||||
from plugins.alpha.block.block import Block
|
from plugins.alpha.block.block import Block
|
||||||
from plugins.alpha.block.configuration import BlockConf
|
from plugins.alpha.block.configuration import BlockConf, IoPadConf
|
||||||
from plugins.alpha.block.configuration import IoPadConf
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
@ -116,10 +112,12 @@ class IoNet ( object ):
|
||||||
, self.chipExtNet
|
, self.chipExtNet
|
||||||
, self.chipIntNet )
|
, self.chipIntNet )
|
||||||
|
|
||||||
def isElem ( self ): return self._flags & IoNet.IsElem
|
def isElem ( self ): return self._flags & IoNet.IsElem
|
||||||
def isEnable ( self ): return self._flags & IoNet.IsEnable
|
def isEnable ( self ): return self._flags & IoNet.IsEnable
|
||||||
def isGlobal ( self ): return self.isGlobal( self._name )
|
def isGlobal ( self ): return self.isGlobal( self._name )
|
||||||
def isSpecial ( self ): return self._type != Net.Type.LOGICAL
|
def isSpecial ( self ): return self._type != Net.Type.LOGICAL
|
||||||
|
def setFlags ( self, flags ): self._flags |= flags
|
||||||
|
def resetFlags ( self, flags ): self._flags &= ~flags
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name ( self ):
|
def name ( self ):
|
||||||
|
@ -169,7 +167,7 @@ class IoNet ( object ):
|
||||||
if state == True: self._flags |= IoNet.IsEnable
|
if state == True: self._flags |= IoNet.IsEnable
|
||||||
else: self._flags &= ~IoNet.IsEnable
|
else: self._flags &= ~IoNet.IsEnable
|
||||||
|
|
||||||
def buildNets ( self, context=DoExtNet ):
|
def buildNets ( self ):
|
||||||
"""
|
"""
|
||||||
Creates the signals in corona and chip Cells, then connect them
|
Creates the signals in corona and chip Cells, then connect them
|
||||||
together.
|
together.
|
||||||
|
@ -194,9 +192,9 @@ class IoNet ( object ):
|
||||||
self.chipIntNet.setType( netType )
|
self.chipIntNet.setType( netType )
|
||||||
self.coreToChip.icorona.getPlug( self.coronaNet ).setNet( self.chipIntNet )
|
self.coreToChip.icorona.getPlug( self.coronaNet ).setNet( self.chipIntNet )
|
||||||
# Chip "external" net, connected to the pad I/O to the outside world.
|
# Chip "external" net, connected to the pad I/O to the outside world.
|
||||||
if context & IoNet.PadPassthrough:
|
if self._flags & IoNet.PadPassthrough:
|
||||||
self.chipExtNet = self.chipIntNet
|
self.chipExtNet = self.chipIntNet
|
||||||
elif not self.chipExtNet and (context & IoNet.DoExtNet):
|
elif not self.chipExtNet and (self._flags & IoNet.DoExtNet):
|
||||||
self.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName )
|
self.chipExtNet = self.coreToChip.chip.getNet( self.chipExtNetName )
|
||||||
if not self.chipExtNet:
|
if not self.chipExtNet:
|
||||||
self.chipExtNet = Net.create( self.coreToChip.chip, self.chipExtNetName )
|
self.chipExtNet = Net.create( self.coreToChip.chip, self.chipExtNetName )
|
||||||
|
@ -274,13 +272,18 @@ class IoPad ( object ):
|
||||||
, netDirectionToStr(self.nets[0].coreNet.getDirection())
|
, netDirectionToStr(self.nets[0].coreNet.getDirection())
|
||||||
, self.nets[0].coreNet.getName()
|
, self.nets[0].coreNet.getName()
|
||||||
, self.padInstanceName ))
|
, self.padInstanceName ))
|
||||||
|
if self.coreToChip.getPadInfo(self.direction) is None:
|
||||||
|
print( WarningMessage( 'IoPad.addNet(): No simple pad in direction {} for "{}", fallback to bi-directional.' \
|
||||||
|
.format(netDirectionToStr(self.direction),ioNet.padInstanceName)) )
|
||||||
|
self.direction = IoPad.BIDIR
|
||||||
elif len(self.nets) == 2:
|
elif len(self.nets) == 2:
|
||||||
self.direction = IoPad.TRI_OUT
|
if self.direction != IoPad.BIDIR:
|
||||||
|
self.direction = IoPad.TRI_OUT
|
||||||
elif len(self.nets) == 3:
|
elif len(self.nets) == 3:
|
||||||
self.direction = IoPad.BIDIR
|
self.direction = IoPad.BIDIR
|
||||||
else:
|
else:
|
||||||
message = [ 'IoPad.addNet(): More than three core nets on I/O pad "{}".' \
|
message = [ 'IoPad.addNet(): More than three core nets ({}) on I/O pad "{}".' \
|
||||||
.format(self.padInstanceName) ]
|
.format(len(self.nets),self.padInstanceName) ]
|
||||||
for ioNet in self.nets:
|
for ioNet in self.nets:
|
||||||
message += [ "{}".format(ioNet.coreNet) ]
|
message += [ "{}".format(ioNet.coreNet) ]
|
||||||
raise ErrorMessage( 1, message )
|
raise ErrorMessage( 1, message )
|
||||||
|
@ -293,40 +296,48 @@ class IoPad ( object ):
|
||||||
enable signal (if any) do not need an external chip signal
|
enable signal (if any) do not need an external chip signal
|
||||||
(it is *not* connected to the outside world).
|
(it is *not* connected to the outside world).
|
||||||
"""
|
"""
|
||||||
fromCoreNet = None
|
padInfo = self.coreToChip.getPadInfo( self.direction )
|
||||||
toCoreNet = None
|
if padInfo is None:
|
||||||
enableNet = None
|
|
||||||
for ioNet in self.nets:
|
|
||||||
context = 0
|
|
||||||
if self.direction == IoPad.TRI_OUT:
|
|
||||||
if ioNet.isEnable(): enableNet = ioNet
|
|
||||||
else:
|
|
||||||
fromCoreNet = ioNet
|
|
||||||
context |= IoNet.DoExtNet
|
|
||||||
elif self.direction == IoPad.BIDIR:
|
|
||||||
if ioNet.coreNet.getDirection() == Net.Direction.IN: toCoreNet = ioNet
|
|
||||||
if ioNet.coreNet.getDirection() == Net.Direction.OUT:
|
|
||||||
if ioNet.isEnable(): enableNet = ioNet
|
|
||||||
else:
|
|
||||||
fromCoreNet = ioNet
|
|
||||||
context |= IoNet.DoExtNet
|
|
||||||
else:
|
|
||||||
context |= IoNet.DoExtNet
|
|
||||||
fromCoreNet = ioNet
|
|
||||||
ioNet.buildNets( context )
|
|
||||||
if not self.coreToChip.ioPadInfos.has_key(self.direction):
|
|
||||||
raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction {} ({}) for pad "{}".' \
|
raise ErrorMessage( 1, 'IoPad.createPad(): Unsupported direction {} ({}) for pad "{}".' \
|
||||||
.format( self.direction
|
.format( self.direction
|
||||||
, IoPad.directionToStr(self.direction)
|
, IoPad.directionToStr(self.direction)
|
||||||
, self.padInstanceName ))
|
, self.padInstanceName ))
|
||||||
padInfo = self.coreToChip.ioPadInfos[ self.direction ]
|
connexions = []
|
||||||
|
# Case of BIDIR as fallback for simple IN/OUT.
|
||||||
|
if (self.direction == IoPad.BIDIR) and (len(self.nets) < 3):
|
||||||
|
self.nets[0].setFlags( IoNet.DoExtNet )
|
||||||
|
self.nets[0].buildNets()
|
||||||
|
self.nets[1].buildNets()
|
||||||
|
connexions.append( ( self.nets[0].chipExtNet, padInfo.padNet ) )
|
||||||
|
if self.nets[0].coreNet.getDirection() == Net.Direction.IN:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet , padInfo.inputNet ) )
|
||||||
|
connexions.append( ( self.coreToChip.newDummyNet(), padInfo.outputNet ) )
|
||||||
|
else:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet , padInfo.outputNet ) )
|
||||||
|
connexions.append( ( self.coreToChip.newDummyNet(), padInfo.inputNet ) )
|
||||||
|
connexions.append( ( self.nets[1].chipIntNet, padInfo.enableNet ) )
|
||||||
|
else:
|
||||||
|
for ioNet in self.nets:
|
||||||
|
if not ioNet.isEnable():
|
||||||
|
ioNet.setFlags( IoNet.DoExtNet )
|
||||||
|
ioNet.buildNets()
|
||||||
|
connexions.append( ( self.nets[0].chipExtNet, padInfo.padNet ) )
|
||||||
|
if self.direction == IoPad.IN:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
|
||||||
|
elif self.direction == IoPad.OUT:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet, padInfo.outputNet ) )
|
||||||
|
elif self.direction == IoPad.TRI_OUT:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
|
||||||
|
connexions.append( ( self.nets[1].chipIntNet, padInfo.enableNet ) )
|
||||||
|
elif self.direction == IoPad.BUDIR:
|
||||||
|
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
|
||||||
|
connexions.append( ( self.nets[1].chipIntNet, padInfo.outputNet ) )
|
||||||
|
connexions.append( ( self.nets[2].chipIntNet, padInfo.enableNet ) )
|
||||||
self.pads.append( Instance.create( self.coreToChip.chip
|
self.pads.append( Instance.create( self.coreToChip.chip
|
||||||
, self.padInstanceName
|
, self.padInstanceName
|
||||||
, self.coreToChip.getCell(padInfo.name) ) )
|
, self.coreToChip.getCell(padInfo.name) ) )
|
||||||
CoreToChip._connect( self.pads[0], fromCoreNet.chipExtNet, padInfo.padNet )
|
for connexion in connexions:
|
||||||
CoreToChip._connect( self.pads[0], fromCoreNet.chipIntNet, padInfo.coreNets[0] )
|
CoreToChip._connect( self.pads[0], connexion[0], connexion[1] )
|
||||||
if toCoreNet: CoreToChip._connect( self.pads[0], toCoreNet.chipIntNet, padInfo.coreNets[-2] )
|
|
||||||
if enableNet: CoreToChip._connect( self.pads[0], enableNet.chipIntNet, padInfo.coreNets[-1] )
|
|
||||||
self.coreToChip.chipPads += self.pads
|
self.coreToChip.chipPads += self.pads
|
||||||
|
|
||||||
|
|
||||||
|
@ -356,12 +367,35 @@ class CoreToChip ( object ):
|
||||||
|
|
||||||
class IoPadInfo ( object ):
|
class IoPadInfo ( object ):
|
||||||
|
|
||||||
def __init__ ( self, padName, padNet, coreNets ):
|
def __init__ ( self, flags, padName, padNet, coreNets ):
|
||||||
|
self.flags = flags
|
||||||
self.name = padName
|
self.name = padName
|
||||||
self.padNet = padNet
|
self.padNet = padNet
|
||||||
self.coreNets = coreNets
|
self.coreNets = coreNets
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@property
|
||||||
|
def inputNet ( self ):
|
||||||
|
if self.flags & (IoPad.IN|IoPad.BIDIR|IoPad.TRI_OUT):
|
||||||
|
return self.coreNets[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def outputNet ( self ):
|
||||||
|
if self.flags & (IoPad.IN|IoPad.BIDIR|IoPad.TRI_OUT):
|
||||||
|
return self.coreNets[1]
|
||||||
|
elif self.flags & IoPad.OUT:
|
||||||
|
return self.coreNets[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enableNet ( self ):
|
||||||
|
if self.flags & IoPad.BIDIR:
|
||||||
|
return self.coreNets[2]
|
||||||
|
elif self.flags & IoPad.TRI_OUT:
|
||||||
|
return self.coreNets[1]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def getNetType ( self, netName ):
|
def getNetType ( self, netName ):
|
||||||
raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' )
|
raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' )
|
||||||
|
@ -409,7 +443,7 @@ class CoreToChip ( object ):
|
||||||
state = block.state
|
state = block.state
|
||||||
self.state = state
|
self.state = state
|
||||||
self.ringNetNames = []
|
self.ringNetNames = []
|
||||||
self.ioPadInfos = {}
|
self.ioPadInfos = []
|
||||||
self.chipPads = []
|
self.chipPads = []
|
||||||
self.padLib = None
|
self.padLib = None
|
||||||
self.corona = None
|
self.corona = None
|
||||||
|
@ -417,6 +451,7 @@ class CoreToChip ( object ):
|
||||||
self.powerPadCount = 0
|
self.powerPadCount = 0
|
||||||
self.groundPadCount = 0
|
self.groundPadCount = 0
|
||||||
self.clockPadCount = 0
|
self.clockPadCount = 0
|
||||||
|
self.dummyNetCount = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -431,6 +466,12 @@ class CoreToChip ( object ):
|
||||||
@property
|
@property
|
||||||
def chip ( self ): return self.state.chip
|
def chip ( self ): return self.state.chip
|
||||||
|
|
||||||
|
def getPadInfo ( self, padType ):
|
||||||
|
for ioPadInfo in self.ioPadInfos:
|
||||||
|
if ioPadInfo.flags & padType:
|
||||||
|
return ioPadInfo
|
||||||
|
return None
|
||||||
|
|
||||||
def hasIoNet ( self, netName ):
|
def hasIoNet ( self, netName ):
|
||||||
"""
|
"""
|
||||||
Look for an IoNet associated to *core* net ``netName``.
|
Look for an IoNet associated to *core* net ``netName``.
|
||||||
|
@ -438,6 +479,11 @@ class CoreToChip ( object ):
|
||||||
if self._ioNets.has_key(netName): return True
|
if self._ioNets.has_key(netName): return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def newDummyNet ( self ):
|
||||||
|
dummy = Net.create( self.chip, '{}_dummy_{}'.format(self.chip.getName(),self.dummyNetCount) )
|
||||||
|
self.dummyNetCount += 1
|
||||||
|
return dummy
|
||||||
|
|
||||||
def getIoNet ( self, coreNet ):
|
def getIoNet ( self, coreNet ):
|
||||||
"""
|
"""
|
||||||
Lookup, and create if it doesn't exist, for an IoNet associated to *core*
|
Lookup, and create if it doesn't exist, for an IoNet associated to *core*
|
||||||
|
@ -469,12 +515,12 @@ class CoreToChip ( object ):
|
||||||
Build all the I/O pads for normal signals (that are not related to
|
Build all the I/O pads for normal signals (that are not related to
|
||||||
power or clock).
|
power or clock).
|
||||||
"""
|
"""
|
||||||
if not self.ioPadInfos.has_key(ioNet.coreNet.getDirection()):
|
padInfo = self.getPadInfo( ioNet.coreNet.getDirection() )
|
||||||
|
if not padInfo:
|
||||||
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \
|
raise ErrorMessage( 1, 'CoreToChip._buildStandardPad(): Unsupported direction %d (%s) for core net "%s".' \
|
||||||
% (ioNet.coreNet.getDirection()
|
% (ioNet.coreNet.getDirection()
|
||||||
,netDirectionToStr(ioNet.coreNet.getDirection())
|
,netDirectionToStr(ioNet.coreNet.getDirection())
|
||||||
,ioNet.coreNet.getName()) )
|
,ioNet.coreNet.getName()) )
|
||||||
padInfo = self.ioPadInfos[ ioNet.coreNet.getDirection() ]
|
|
||||||
ioNet.pads.append( Instance.create( self.chip
|
ioNet.pads.append( Instance.create( self.chip
|
||||||
, ioNet.padInstanceName
|
, ioNet.padInstanceName
|
||||||
, self.getCell(padInfo.name) ) )
|
, self.getCell(padInfo.name) ) )
|
||||||
|
@ -482,21 +528,37 @@ class CoreToChip ( object ):
|
||||||
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, padInfo.coreNets[0] )
|
CoreToChip._connect( ioNet.pads[0], ioNet.chipIntNet, padInfo.coreNets[0] )
|
||||||
self.chipPads += ioNet.pads
|
self.chipPads += ioNet.pads
|
||||||
|
|
||||||
def _buildGroundPads ( self, ioPadConf ):
|
def _buildCoreGroundPads ( self, ioPadConf ):
|
||||||
"""Build I/O pad relateds to ground signals."""
|
"""Build I/O pad relateds to core ground signals."""
|
||||||
raise NoImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
def _buildPowerPads ( self, ioPadConf ):
|
def _buildIoGroundPads ( self, ioPadConf ):
|
||||||
"""Build I/O pad relateds to power signals."""
|
"""Build I/O pad relateds to pad internal ground signals."""
|
||||||
raise NoImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
|
def _buildAllGroundPads ( self, ioPadConf ):
|
||||||
|
"""Build I/O pad relateds to ground signals for core and pads."""
|
||||||
|
raise NotImplementedError( 'coreToChip._buildGroundPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
|
def _buildCorePowerPads ( self, ioPadConf ):
|
||||||
|
"""Build I/O pad relateds to core power signals."""
|
||||||
|
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
|
def _buildIoPowerPads ( self, ioPadConf ):
|
||||||
|
"""Build I/O pad relateds to pad internal power signals."""
|
||||||
|
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
|
def _buildAllPowerPads ( self, ioPadConf ):
|
||||||
|
"""Build I/O pad relateds to power signals for core and pads."""
|
||||||
|
raise NotImplementedError( 'coreToChip._buildPowerPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
def _buildClockPads ( self, ioPadConf ):
|
def _buildClockPads ( self, ioPadConf ):
|
||||||
"""Build I/O pad relateds to clock signals."""
|
"""Build I/O pad relateds to clock signals."""
|
||||||
raise NoImplementedError( 'coreToChip._buildClockPads(): This method must be overloaded.' )
|
raise NotImplementedError( 'coreToChip._buildClockPads(): This method must be overloaded.' )
|
||||||
|
|
||||||
def _connectClocks ( self ):
|
def _connectClocks ( self ):
|
||||||
"""Connect inner clocks signal to the corona (towards the core) ."""
|
"""Connect inner clocks signal to the corona (towards the core) ."""
|
||||||
raise NoImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' )
|
raise NotImplementedError( 'coreToChip._connectClocks(): This method must be overloaded.' )
|
||||||
|
|
||||||
def buildChip ( self ):
|
def buildChip ( self ):
|
||||||
"""
|
"""
|
||||||
|
@ -504,6 +566,7 @@ class CoreToChip ( object ):
|
||||||
from the core cell.
|
from the core cell.
|
||||||
"""
|
"""
|
||||||
af = AllianceFramework.get()
|
af = AllianceFramework.get()
|
||||||
|
self.state.cfg.apply()
|
||||||
with UpdateSession():
|
with UpdateSession():
|
||||||
print( ' o Build Chip from Core.' )
|
print( ' o Build Chip from Core.' )
|
||||||
print( ' - Core: "{}".'.format(self.state.cell.getName()) )
|
print( ' - Core: "{}".'.format(self.state.cell.getName()) )
|
||||||
|
@ -516,11 +579,23 @@ class CoreToChip ( object ):
|
||||||
ioPads = []
|
ioPads = []
|
||||||
clockIoNets = []
|
clockIoNets = []
|
||||||
for ioPadConf in self.state.chipConf.padInstances:
|
for ioPadConf in self.state.chipConf.padInstances:
|
||||||
if ioPadConf.isPower():
|
if ioPadConf.isAllPower():
|
||||||
self._buildPowerPads( ioPadConf )
|
self._buildAllPowerPads( ioPadConf )
|
||||||
continue
|
continue
|
||||||
if ioPadConf.isGround():
|
if ioPadConf.isCorePower():
|
||||||
self._buildGroundPads( ioPadConf )
|
self._buildCorePowerPads( ioPadConf )
|
||||||
|
continue
|
||||||
|
if ioPadConf.isIoPower():
|
||||||
|
self._buildIoPowerPads( ioPadConf )
|
||||||
|
continue
|
||||||
|
if ioPadConf.isAllGround():
|
||||||
|
self._buildAllGroundPads( ioPadConf )
|
||||||
|
continue
|
||||||
|
if ioPadConf.isCoreGround():
|
||||||
|
self._buildCoreGroundPads( ioPadConf )
|
||||||
|
continue
|
||||||
|
if ioPadConf.isIoGround():
|
||||||
|
self._buildIoGroundPads( ioPadConf )
|
||||||
continue
|
continue
|
||||||
if ioPadConf.isClock():
|
if ioPadConf.isClock():
|
||||||
self._buildClockPads( ioPadConf )
|
self._buildClockPads( ioPadConf )
|
||||||
|
|
|
@ -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