Added support for real LibreSOCIO pads.
* New: In cumulus/plugins.block.configuration, added class ConstantsConf to store information and create instances of "zero" and "one" cells. Added attribute in BlockConf class. * Change: In cumulus/plugins.block.configuration, moved the cell cloning and saving from block.spares.Spares to configuration.BlockConf as it is a service that can be used by other modules than just spares. Other modules may modificate the netlists also, like in XXXX. * Change: In cumulus/plugins.chip.configuration, in various methods, manage both cases when the layer is symbolic or real (difference in accessing the underlying BasicLayers). * Change: In cumulus/plugins.chip.configuration, less clutered display of lambda length in trace mode (and use of 'L' as 'l' was too close to '1'). * Bug: In cumulus/plugins.chip.corona.VerticalSide.addBlockages(), as the clock are now on the *inner* rail(s), blockage must be on the *outer* rails (power lines). * New: In cumulus/plugins.chip.pads.Corner, add support for 45 degree corners (cfg setting "chip.use45corners"). * New: In cumulus/plugins.chip.pads.Side.check(), correct computation of the side's length. Was using the ioPadStep instead of the pad cell width! * Change: In cumulus/plugins.chip.pads.Corona._padAnalysis(), LibreSOCIO pads uses Verticals for their ring wires (common sense would want them *Horizontal*). So they must be included in the physical pin detection, but in turn this cause havoc in pxlib... So create a filtering according to the library name. This is *not* robust but will do for now. * New: In cumulus/plugins.chip.pad.core2chip.CoreToChip, rename self.state into self.conf for clarity. New method newEnableForNet(), to create "enable" nets on the fly for emulated In/Out pads. As it can edit the netlist (new "enable" nets) call the BlockConf.rsave() method instead of direct saving through AllianceFramework. Raise NotImplementederror instead of ErrorMessage. * New: In cumulus/plugins.chip.pad.core2chip.IoPad.createPad(), on emulated In/Out I/O pad like for LibreSOC, generate on the fly the right enable signal. If an enable signal is given, it will be used (backward compatible with the previous behavior). * New: In cumulus/plugins.chip.pad.core2chip, support for real LibreSOCIO pads in libresocio.py module.
This commit is contained in:
parent
1b6d5bd09d
commit
acc9405ba3
|
@ -61,6 +61,7 @@
|
|||
${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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/core2chip/libresocio.py
|
||||
)
|
||||
set ( pyPluginAlphaChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/__init__.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/chip/configuration.py
|
||||
|
|
|
@ -517,14 +517,14 @@ class Block ( object ):
|
|||
#katana.printConfiguration ()
|
||||
katana.digitalInit ()
|
||||
#katana.runNegociatePreRouted()
|
||||
#Breakpoint.stop( 0, 'Block.route() Before global routing.' )
|
||||
Breakpoint.stop( 100, 'Block.route() Before global routing.' )
|
||||
katana.runGlobalRouter ( Katana.Flags.NoFlags )
|
||||
katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet )
|
||||
#Breakpoint.stop( 0, 'Block.route() After global routing.' )
|
||||
Breakpoint.stop( 100, 'Block.route() After global routing.' )
|
||||
katana.layerAssign ( Anabatic.EngineNoNetLayerAssign )
|
||||
katana.runNegociate ( Katana.Flags.NoFlags )
|
||||
success = katana.isDetailedRoutingSuccess()
|
||||
#Breakpoint.stop( 0, 'Block.route() done, success:{}.'.format(success) )
|
||||
Breakpoint.stop( 100, 'Block.route() done, success:{}.'.format(success) )
|
||||
katana.finalizeLayout()
|
||||
katana.destroy()
|
||||
return success
|
||||
|
@ -639,7 +639,7 @@ class Block ( object ):
|
|||
def save ( self ):
|
||||
if not self.conf.validated:
|
||||
raise ErrorMessage( 1, 'block.save(): Chip is not valid, aborting.' )
|
||||
self.spares.save()
|
||||
self.conf.save()
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,18 @@ from plugins import getParameter
|
|||
from plugins.alpha.utils import getPlugByName
|
||||
|
||||
|
||||
def findCellOutput ( cell, callerName, parameterId ):
|
||||
"""Find the *external* output net of a cell and return it's name."""
|
||||
for net in cell.getNets():
|
||||
if not net.isExternal(): continue
|
||||
if net.isGlobal(): continue
|
||||
elif net.getDirection() & Net.Direction.OUT:
|
||||
return net.getName()
|
||||
raise ErrorMessage( 3, [ '{}: Cannot guess the input terminal of "{}",' \
|
||||
.format(callerName,Cfg.getParamString(parameterId).asString())
|
||||
, ' please check that the Nets directions are set.' ] )
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Class : "configuration.GaugeConf".
|
||||
|
||||
|
@ -580,7 +592,7 @@ class BufferConf ( object ):
|
|||
trace( 550, '-' )
|
||||
raise ErrorMessage( 3, [ 'BufferConf.__init__(): Buffer cell "{}" not found in library,' \
|
||||
.format(Cfg.getParamString('spares.buffer').asString())
|
||||
, ' please check the "spares.buffer" configuration parameter in "plugins.conf".' ] )
|
||||
, ' please check the "spares.buffer" configuration parameter in "plugins.py".' ] )
|
||||
trace( 550, '\t| masterCell :{}\n'.format(self.masterCell) )
|
||||
trace( 550, '\t| maximum sinks:{}\n'.format(self.maxSinks) )
|
||||
self.count = 0
|
||||
|
@ -627,6 +639,90 @@ class BufferConf ( object ):
|
|||
self.count = 0
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Class : "configuration.ConstantsConf".
|
||||
|
||||
class ConstantsConf ( object ):
|
||||
"""
|
||||
Store informations on cells used to generate constant signals ("zero"
|
||||
and "one")
|
||||
"""
|
||||
|
||||
ZERO = 1
|
||||
ONE = 2
|
||||
|
||||
def __init__ ( self, framework, cfg ):
|
||||
trace( 550, ',+', '\tConstantsConf.__init__()\n' )
|
||||
cfg.etesian.cell.zero = None
|
||||
cfg.etesian.cell.one = None
|
||||
self.zeroCell = framework.getCell( cfg.etesian.cell.zero, CRL.Catalog.State.Views )
|
||||
self.oneCell = framework.getCell( cfg.etesian.cell.one , CRL.Catalog.State.Views )
|
||||
if not self.zeroCell:
|
||||
trace( 550, '-' )
|
||||
raise ErrorMessage( 3, [ 'ConstantsConf.__init__(): Zero cell "{}" not found in library,' \
|
||||
.format(cfg.etesian.cell.zero)
|
||||
, ' please check the "etesian.cell.zero" configuration parameter in "etesian.py".' ] )
|
||||
if not self.oneCell:
|
||||
trace( 550, '-' )
|
||||
raise ErrorMessage( 3, [ 'ConstantsConf.__init__(): One cell "{}" not found in library,' \
|
||||
.format(cfg.etesian.cell.zero)
|
||||
, ' please check the "etesian.cell.one" configuration parameter in "etesian.py".' ] )
|
||||
trace( 550, '\t| zeroCell:{}\n'.format(self.zeroCell) )
|
||||
trace( 550, '\t| oneCell :{}\n'.format(self.oneCell ) )
|
||||
self.zeroCount = 0
|
||||
self.oneCount = 0
|
||||
self.zeroOutput = findCellOutput( self.zeroCell, 'ConstantsConf.__init__()', 'etesian.cell.zero' )
|
||||
self.oneOutput = findCellOutput( self.oneCell , 'ConstantsConf.__init__()', 'etesian.cell.one' )
|
||||
trace( 550, '\t| zeroOutput:"{}"\n'.format(self.zeroOutput) )
|
||||
trace( 550, '\t| oneOutput :"{}"\n'.format(self.oneOutput ) )
|
||||
trace( 550, '-' )
|
||||
return
|
||||
|
||||
def name ( self, cellType ):
|
||||
"""Returns the master cell *name* of the selected type."""
|
||||
if cellType == ConstantsConf.ZERO: return self.zeroCell.getName()
|
||||
elif cellType == ConstantsConf.ONE : return self.oneCell .getName()
|
||||
return None
|
||||
|
||||
def output ( self, cellType ):
|
||||
"""Returns the master cell *output* of the selected type."""
|
||||
if cellType == ConstantsConf.ZERO: return self.zeroOutput
|
||||
elif cellType == ConstantsConf.ONE : return self.oneOutput
|
||||
return None
|
||||
|
||||
def width ( self, cellType ):
|
||||
"""Returns the master cell abutment box width of the selected type."""
|
||||
if cellType == ConstantsConf.ZERO: return self.zeroCell.getAbutmentBox().getWidth()
|
||||
elif cellType == ConstantsConf.ONE : return self.oneCell .getAbutmentBox().getWidth()
|
||||
return None
|
||||
|
||||
def height ( self, cellType ):
|
||||
"""Returns the master cell abutment box height of the selected type."""
|
||||
if cellType == ConstantsConf.ZERO: return self.zeroCell.getAbutmentBox().getHeight()
|
||||
elif cellType == ConstantsConf.ONE : return self.oneCell .getAbutmentBox().getHeight()
|
||||
return None
|
||||
|
||||
def createInstance ( self, cell, cellType ):
|
||||
"""
|
||||
Create a new zero/one *instance* in Cell. The instance is named "constant_<type>_<Nb>",
|
||||
where ``<type>`` is the kind of constante (zero or one) and ``<Nb>`` is an ever
|
||||
incrementing counter (self.<type>count).
|
||||
"""
|
||||
instance = None
|
||||
if cellType == ConstantsConf.ZERO:
|
||||
instance = Instance.create( cell, 'constant_zero_{}'.format(self.zeroCount), self.zeroCell )
|
||||
self.zeroCount += 1
|
||||
elif cellType == ConstantsConf.ONE:
|
||||
instance = Instance.create( cell, 'constant_one_{}'.format(self.oneCount), self.oneCell )
|
||||
self.oneCount += 1
|
||||
return instance
|
||||
|
||||
def resetCounts ( self ):
|
||||
"""Reset the zero/one instance counters (to use only in case of design reset)."""
|
||||
self.zeroCount = 0
|
||||
self.oneCount = 0
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Class : "configuration.FeedsConf".
|
||||
|
||||
|
@ -857,10 +953,12 @@ class BlockConf ( GaugeConf ):
|
|||
self.framework = CRL.AllianceFramework.get()
|
||||
self.cfg = CfgCache('',Cfg.Parameter.Priority.Interactive)
|
||||
self.bufferConf = BufferConf( self.framework )
|
||||
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
||||
self.feedsConf = FeedsConf( self.framework )
|
||||
self.chipConf = ChipConf( self )
|
||||
self.bColumns = 2
|
||||
self.bRows = 2
|
||||
self.cloneds = []
|
||||
self.cell = cell
|
||||
self.icore = None
|
||||
self.icorona = None
|
||||
|
@ -957,3 +1055,39 @@ class BlockConf ( GaugeConf ):
|
|||
|
||||
def resetBufferCount ( self ):
|
||||
self.bufferConf.resetBufferCount()
|
||||
|
||||
def addClonedCell ( self, masterCell ):
|
||||
if not masterCell in self.cloneds:
|
||||
trace( 550, '\tNew cloned cell: "{}"\n'.format(masterCell) )
|
||||
self.cloneds.append( masterCell )
|
||||
return
|
||||
|
||||
def rsave ( self, cell ):
|
||||
"""
|
||||
Save the complete cell hierarchy. Saves only the physical view, except
|
||||
for the ones that has been cloned (their names should end up by "_cts"),
|
||||
for which logical and physical views are to be saved. They are completely
|
||||
new cells.
|
||||
"""
|
||||
flags = CRL.Catalog.State.Physical
|
||||
if cell.getName().endswith('_cts'):
|
||||
flags = flags | CRL.Catalog.State.Logical
|
||||
self.framework.saveCell( cell, flags )
|
||||
for instance in cell.getInstances():
|
||||
masterCell = instance.getMasterCell()
|
||||
if not masterCell.isTerminal():
|
||||
self.rsave( masterCell )
|
||||
|
||||
def save ( self ):
|
||||
"""
|
||||
Frontend to BlockConf.rsave(). Append the "_cts" suffix to the cloned
|
||||
cells, then call rsave().
|
||||
"""
|
||||
trace( 550,'\tBlockConf.save() on "{}"\n'.format(self.cell.getName()) )
|
||||
for cell in self.cloneds:
|
||||
trace( 550, '\tRenaming cloned cell: "{}"\n'.format(cell) )
|
||||
cell.setName( cell.getName()+'_cts' )
|
||||
if self.chip is None:
|
||||
self.cell.setName( self.cell.getName()+'_r' )
|
||||
self.rsave( self.cell )
|
||||
return
|
||||
|
|
|
@ -732,7 +732,6 @@ class Spares ( object ):
|
|||
def __init__ ( self, block ):
|
||||
self.conf = block.conf
|
||||
self.quadTree = None
|
||||
self.cloneds = []
|
||||
self.strayBuffers = []
|
||||
|
||||
def reset ( self ):
|
||||
|
@ -838,12 +837,6 @@ class Spares ( object ):
|
|||
raise ErrorMessage( 2, 'Spares.getFreeBufferUnder(): No more free buffers under {}.'.format(area) )
|
||||
return leaf.selectFree()
|
||||
|
||||
def addClonedCell ( self, masterCell ):
|
||||
if not masterCell in self.cloneds:
|
||||
trace( 550, '\tNew cloned cell: "{}"\n'.format(masterCell) )
|
||||
self.cloneds.append( masterCell )
|
||||
return
|
||||
|
||||
def raddTransNet ( self, topNet, path ):
|
||||
"""
|
||||
Add a net through a whole hierarchy of Instance/Cells. The master cells
|
||||
|
@ -881,7 +874,7 @@ class Spares ( object ):
|
|||
|
||||
trace( 540, '\tSpares.raddTransNet() top:{} path:{}\n'.format(topNet,path) )
|
||||
if path.isEmpty():
|
||||
self.addClonedCell( topNet.getCell() )
|
||||
self.conf.addClonedCell( topNet.getCell() )
|
||||
return None
|
||||
tailPath = path.getTailPath()
|
||||
headInstance = path.getHeadInstance()
|
||||
|
@ -898,8 +891,8 @@ class Spares ( object ):
|
|||
raise ErrorMessage( 3, 'Plug not created for %s on instance %s of %s' \
|
||||
% (topNet.getName(),headInstance.getName(),masterCell.getName()) )
|
||||
headPlug.setNet( topNet )
|
||||
self.addClonedCell( masterCell )
|
||||
self.addClonedCell( headInstance.getCell() )
|
||||
self.conf.addClonedCell( masterCell )
|
||||
self.conf.addClonedCell( headInstance.getCell() )
|
||||
else:
|
||||
masterNet = headPlug.getMasterNet()
|
||||
trace( 540, '\ttailPath {}\n'.format(tailPath) )
|
||||
|
@ -909,35 +902,3 @@ class Spares ( object ):
|
|||
def removeUnusedBuffers ( self ):
|
||||
with UpdateSession():
|
||||
self.quadTree.removeUnusedBuffers()
|
||||
|
||||
def rsave ( self, cell ):
|
||||
"""
|
||||
Save the complete cell hierarchy. Saves only the physical view, except
|
||||
for the ones that has been cloned (their names should end up by "_cts"),
|
||||
for which logical and physical views are to be saved. They are completely
|
||||
new cells.
|
||||
"""
|
||||
|
||||
flags = CRL.Catalog.State.Physical
|
||||
if cell.getName().endswith('_cts'):
|
||||
flags = flags | CRL.Catalog.State.Logical
|
||||
framework.saveCell( cell, flags )
|
||||
|
||||
for instance in cell.getInstances():
|
||||
masterCell = instance.getMasterCell()
|
||||
if not masterCell.isTerminal():
|
||||
self.rsave( masterCell )
|
||||
|
||||
def save ( self ):
|
||||
"""
|
||||
Frontend to Spares.rsave(). Append the "_cts" suffix to the cloned
|
||||
cells, then call rsave().
|
||||
"""
|
||||
trace( 550,'\tSpares.save() on "{}"\n'.format(self.conf.cell.getName()) )
|
||||
for cell in self.cloneds:
|
||||
trace( 550, '\tRenaming cloned cell: "{}"\n'.format(cell) )
|
||||
cell.setName( cell.getName()+'_cts' )
|
||||
if self.conf.chip is None:
|
||||
self.conf.cell.setName( self.conf.cell.getName()+'_r' )
|
||||
self.rsave( self.conf.cell )
|
||||
return
|
||||
|
|
|
@ -238,13 +238,17 @@ class ChipConf ( BlockConf ):
|
|||
axis = (uTrackMax + uTrackMin) / 2
|
||||
width = (iTrackMax - iTrackMin) * lg.getPitch() + lg.getWireWidth()
|
||||
if self.routingGauge.isSymbolic():
|
||||
trace( 550, '\tRoutingGauge is symbolic, adjust on lambda.\n' )
|
||||
oneLambda = DbU.fromLambda( 1.0 )
|
||||
if axis % oneLambda:
|
||||
axis -= oneLambda / 2
|
||||
width -= oneLambda
|
||||
trace( 550, '\t[{} {}]\n'.format(iTrackMin, iTrackMax) )
|
||||
trace( 550, '\taxis: {}l {}\n'.format(DbU.toLambda(axis ), DbU.getValueString(axis )) )
|
||||
trace( 550, '\twidth: {}l {}\n'.format(DbU.toLambda(width), DbU.getValueString(width)) )
|
||||
trace( 550, '\t[{} {}] -> [{} {}]\n'.format( iTrackMin
|
||||
, iTrackMax
|
||||
, DbU.getValueString(uTrackMin)
|
||||
, DbU.getValueString(uTrackMax) ) )
|
||||
trace( 550, '\taxis: {:.1f}L {}\n'.format(DbU.toLambda(axis ), DbU.getValueString(axis )) )
|
||||
trace( 550, '\twidth: {:.1f}L {}\n'.format(DbU.toLambda(width), DbU.getValueString(width)) )
|
||||
else:
|
||||
axis = (uMax + uMin) / 2
|
||||
width = (uMax - uMin)
|
||||
|
@ -252,7 +256,7 @@ class ChipConf ( BlockConf ):
|
|||
return axis, width
|
||||
|
||||
def toCoronaPitchInChip ( self, uCore, layer ):
|
||||
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {}l {}\n' \
|
||||
trace( 550, ',+', '\tChipConf.toCoronaPitchInChip(): uCore: {:.1f}L {}\n' \
|
||||
.format(DbU.toLambda(uCore), DbU.getValueString(uCore)) )
|
||||
coronaAb = self.getInstanceAb( self.icorona )
|
||||
lg = None
|
||||
|
@ -271,15 +275,15 @@ class ChipConf ( BlockConf ):
|
|||
else:
|
||||
uCorona = uCore - coronaAb.getXMin()
|
||||
uCorona, width = self.toRoutingGauge( uCorona, uCorona, layer )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {}l {}\n' \
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {:.1f}L {}\n' \
|
||||
.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
if lg:
|
||||
if lg.getDirection() == RoutingLayerGauge.Horizontal:
|
||||
uCore = uCorona + coronaAb.getYMin()
|
||||
else:
|
||||
uCore = uCorona + coronaAb.getXMin()
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {}l %s\n'.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCore: {}l %s\n'.format(DbU.toLambda(uCore ), DbU.getValueString(uCore )) )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCorona: {:.1f}L {}\n'.format(DbU.toLambda(uCorona), DbU.getValueString(uCorona)) )
|
||||
trace( 550, '\ttoCoronaPitchInChip(): uCore: {:.1f}L {}\n'.format(DbU.toLambda(uCore ), DbU.getValueString(uCore )) )
|
||||
trace( 550, '-' )
|
||||
return uCore
|
||||
|
||||
|
@ -295,16 +299,16 @@ class ChipConf ( BlockConf ):
|
|||
trace( 550, '\t| Real\n' )
|
||||
trace( 550, '\t| axis: {}\n'.format(DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| width:{}\n'.format(DbU.getValueString(width)) )
|
||||
trace( 550, '\t| dxMin:{} ({}l)\n' \
|
||||
trace( 550, '\t| dxMin:{} ({:.1f}L)\n' \
|
||||
.format( DbU.getValueString(chipXMin - coronaAb.getXMin())
|
||||
, DbU.toLambda(chipXMin - coronaAb.getXMin()) ) )
|
||||
trace( 550, '\t| dxMax:{}\n'.format(DbU.getValueString(chipXMax - coronaAb.getXMin())) )
|
||||
coronaY, width = self.toRoutingGauge( coronaY - width/2, coronaY + width/2, layer )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| axis: {}l or {}\n'.format(DbU.toLambda(coronaY), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| width:{}l or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
trace( 550, '\t| dxMin:{}l\n'.format(DbU.toLambda(dxMin)) )
|
||||
trace( 550, '\t| dxMax:{}l\n'.format(DbU.toLambda(dxMax)) )
|
||||
trace( 550, '\t| axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaY), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| width:{:.1f}L or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
trace( 550, '\t| dxMin:{:.1f}L\n'.format(DbU.toLambda(dxMin)) )
|
||||
trace( 550, '\t| dxMax:{:.1f}L\n'.format(DbU.toLambda(dxMax)) )
|
||||
h = Horizontal.create( coronaNet, layer, coronaY, width, dxMin, dxMax )
|
||||
trace( 550, '\t| {}\n'.format(h) )
|
||||
trace( 550, '-' )
|
||||
|
@ -324,8 +328,8 @@ class ChipConf ( BlockConf ):
|
|||
trace( 550, '\t| width:{}\n'.format(DbU.getValueString(width)) )
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width/2, coronaX + width/2, layer )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| axis: {} or {}\n'.format(DbU.toLambda(coronaX), DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| width:{} or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
trace( 550, '\t| axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaX), DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| width:{:.1f}L or {}\n'.format(DbU.toLambda(width) , DbU.getValueString(width)) )
|
||||
v = Vertical.create( coronaNet, layer, coronaX, width, dyMin, dyMax )
|
||||
trace( 550, '\t| {}\n'.format(v) )
|
||||
trace( 550, '-' )
|
||||
|
@ -343,12 +347,13 @@ class ChipConf ( BlockConf ):
|
|||
trace( 550, '\t| center: {:>12} {:>12}\n'.format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {:>12} {:>12}\n'.format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
topLayer = layer.getTop()
|
||||
botLayer = layer.getBottom()
|
||||
if self.isHorizontal(topLayer):
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, layer.getBottom() )
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, botLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, topLayer )
|
||||
else:
|
||||
coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, topLayer )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, layer.getBottom() )
|
||||
coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, botLayer )
|
||||
if not (flags & OnHorizontalPitch):
|
||||
trace( 550, '\tNot on horizontal routing pitch, Y on lambda only.\n' )
|
||||
coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), Superior )
|
||||
|
@ -356,8 +361,8 @@ class ChipConf ( BlockConf ):
|
|||
trace( 550, '\tNot on vertical routing pitch, X on lambda only.\n' )
|
||||
coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), Superior )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| X axis: {:>12} or {:>12}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| Y axis: {:>12} or {:>12}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| X axis: {:>12.1f}L or {:>12}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| Y axis: {:>12.1f}L or {:>12}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| center: {:>12} {:>12}\n' .format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {:>12} {:>12}\n' .format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
c = Contact.create( coronaNet
|
||||
|
@ -373,17 +378,20 @@ class ChipConf ( BlockConf ):
|
|||
|
||||
def getViaPitch ( self, viaLayer ):
|
||||
topLayer = viaLayer.getTop()
|
||||
topPitch = 2*viaLayer.getEnclosure \
|
||||
( topLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
|
||||
+ viaLayer.getMinimalSize() \
|
||||
+ topLayer.getMinimalSpacing()
|
||||
if topLayer.isSymbolic():
|
||||
topLayer = topLayer.getBasicLayer()
|
||||
topEnclosure = viaLayer.getEnclosure( topLayer, Layer.EnclosureH|Layer.EnclosureV )
|
||||
topPitch = 2*topEnclosure + viaLayer.getMinimalSize() + topLayer.getMinimalSpacing()
|
||||
botLayer = viaLayer.getBottom()
|
||||
botPitch = 2*viaLayer.getEnclosure \
|
||||
( botLayer.getBasicLayer(), Layer.EnclosureH|Layer.EnclosureV ) \
|
||||
+ viaLayer.getMinimalSize() \
|
||||
+ botLayer.getMinimalSpacing()
|
||||
if botLayer.isSymbolic():
|
||||
botLayer = botLayer.getBasicLayer()
|
||||
botEnclosure = viaLayer.getEnclosure( botLayer, Layer.EnclosureH|Layer.EnclosureV )
|
||||
botPitch = 2*botEnclosure + viaLayer.getMinimalSize() + botLayer.getMinimalSpacing()
|
||||
viaPitch = max( topPitch, botPitch )
|
||||
trace( 550, '\tgetViaPitch of {}: {}l\n'.format(viaLayer.getName(),DbU.getValueString(viaPitch)) )
|
||||
trace( 550, '\tgetViaPitch of {}: {}\n'.format(viaLayer.getName(),DbU.getValueString(viaPitch)) )
|
||||
trace( 550, '\t| minimal size of {}: {}\n'.format(viaLayer.getName(),DbU.getValueString(viaLayer.getMinimalSize())) )
|
||||
trace( 550, '\t| enclosure of {}: {}\n'.format(topLayer.getName(),DbU.getValueString(topEnclosure)) )
|
||||
trace( 550, '\t| enclosure of {}: {}\n'.format(botLayer.getName(),DbU.getValueString(botEnclosure)) )
|
||||
return viaPitch
|
||||
|
||||
def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ):
|
||||
|
@ -412,7 +420,7 @@ class ChipConf ( BlockConf ):
|
|||
xContact = coronaX - viaPitch * (array[0]-1)/2
|
||||
yContact = coronaY - viaPitch * (array[1]-1)/2
|
||||
contactSize = layer.getMinimalSize()
|
||||
trace( 550, '\txContact:{}l yContact:{}l\n'.format(DbU.toLambda(xContact),DbU.toLambda(yContact)) )
|
||||
trace( 550, '\txContact:{} yContact:{}\n'.format(DbU.getValueString(xContact),DbU.getValueString(yContact)) )
|
||||
for i in range(array[0]):
|
||||
for j in range(array[1]):
|
||||
c = Contact.create( coronaNet
|
||||
|
@ -452,8 +460,8 @@ class ChipConf ( BlockConf ):
|
|||
trace( 550, '\tNorth/South not on vertical routing pitch, X on lambda only.\n' )
|
||||
coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), Superior )
|
||||
trace( 550, '\t| On Grid\n' )
|
||||
trace( 550, '\t| X axis: {} or {}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| Y axis: {} or {}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| X axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| Y axis: {:.1f}L or {}\n'.format(DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) )
|
||||
trace( 550, '\t| center: {} {}\n' .format(DbU.getValueString(coronaX), DbU.getValueString(coronaY)) )
|
||||
trace( 550, '\t| WxH: {} {}\n' .format(DbU.getValueString(width ), DbU.getValueString(height )) )
|
||||
c = Pin.create( coronaNet
|
||||
|
|
|
@ -451,8 +451,10 @@ class VerticalSide ( Side ):
|
|||
if via[1].getNet() != via[2].getNet(): continue
|
||||
spans.merge( via[1]._y - via[1]._height/2, via[1]._y + via[1]._height/2 )
|
||||
routingGauge = self.corona.routingGauge
|
||||
for depth in range(self.getInnerRail(0).vias.values()[0][1].bottomDepth
|
||||
,self.getInnerRail(0).vias.values()[0][1].topDepth ):
|
||||
print( self.getOuterRail(0) )
|
||||
print( self.getOuterRail(0).vias.values() )
|
||||
for depth in range(self.getOuterRail(0).vias.values()[0][1].bottomDepth
|
||||
,self.getOuterRail(0).vias.values()[0][1].topDepth ):
|
||||
blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer()
|
||||
pitch = routingGauge.getLayerPitch(depth)
|
||||
for chunk in spans.chunks:
|
||||
|
|
|
@ -18,30 +18,16 @@ import sys
|
|||
import re
|
||||
from operator import itemgetter
|
||||
import Cfg
|
||||
from Hurricane import DbU
|
||||
from Hurricane import Point
|
||||
from Hurricane import Transformation
|
||||
from Hurricane import Interval
|
||||
from Hurricane import Box
|
||||
from Hurricane import Path
|
||||
from Hurricane import Occurrence
|
||||
from Hurricane import UpdateSession
|
||||
from Hurricane import Layer
|
||||
from Hurricane import BasicLayer
|
||||
from Hurricane import Net
|
||||
from Hurricane import Pin
|
||||
from Hurricane import Contact
|
||||
from Hurricane import Segment
|
||||
from Hurricane import Horizontal
|
||||
from Hurricane import Vertical
|
||||
from Hurricane import RoutingPad
|
||||
from Hurricane import Instance
|
||||
from Hurricane import DbU, Point, Transformation, Interval, Box, \
|
||||
Path, Occurrence, UpdateSession, Layer, \
|
||||
BasicLayer, Net, Pin, Contact, Segment, \
|
||||
Horizontal, Vertical, Diagonal, RoutingPad, \
|
||||
Instance
|
||||
import CRL
|
||||
from CRL import RoutingLayerGauge
|
||||
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.alpha.chip
|
||||
|
||||
|
@ -62,35 +48,55 @@ class Corner ( object ):
|
|||
def conf ( self ): return self.corona.conf
|
||||
|
||||
def _getPoints ( self, axis ):
|
||||
"""
|
||||
Compute the various coordinates to draw the corner for a wire
|
||||
positioned at ``axis`` distance from the *border* of the chip.
|
||||
xExtend and yExtend are used only in case of 45 degree corners,
|
||||
the 0.5 ratio is an approximate of ``sqrt(2) - 1``.
|
||||
"""
|
||||
if self.type == SouthWest:
|
||||
xCorner = self.conf.chipAb.getXMin() + axis
|
||||
yCorner = self.conf.chipAb.getYMin() + axis
|
||||
xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight
|
||||
yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight
|
||||
xExtend = - long( 0.5 * float(self.conf.ioPadHeight - axis) )
|
||||
yExtend = xExtend
|
||||
elif self.type == SouthEast:
|
||||
xCorner = self.conf.chipAb.getXMax() - axis
|
||||
yCorner = self.conf.chipAb.getYMin() + axis
|
||||
xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight
|
||||
yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight
|
||||
xExtend = long( 0.5 * float(self.conf.ioPadHeight - axis) )
|
||||
yExtend = - xExtend
|
||||
elif self.type == NorthEast:
|
||||
xCorner = self.conf.chipAb.getXMax() - axis
|
||||
yCorner = self.conf.chipAb.getYMax() - axis
|
||||
xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight
|
||||
yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight
|
||||
xExtend = long( 0.5 * float(self.conf.ioPadHeight - axis) )
|
||||
yExtend = xExtend
|
||||
elif self.type == NorthWest:
|
||||
xCorner = self.conf.chipAb.getXMin() + axis
|
||||
yCorner = self.conf.chipAb.getYMax() - axis
|
||||
xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight
|
||||
yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight
|
||||
return xCorner, yCorner, xBb, yBb
|
||||
xExtend = - long( 0.5 * float(self.conf.ioPadHeight - axis) )
|
||||
yExtend = - xExtend
|
||||
return xCorner, yCorner, xBb, yBb, xExtend, yExtend
|
||||
|
||||
def _createCorner ( self ):
|
||||
self.corona.conf.cfg.chip.use45corners = None
|
||||
for rail in self.corona.padRails:
|
||||
net = rail[0]
|
||||
layer = rail[1]
|
||||
axis = rail[2]
|
||||
width = rail[3]
|
||||
xCorner, yCorner, xBb, yBb = self._getPoints( axis )
|
||||
xCorner, yCorner, xBb, yBb, xExtend, yExtend = self._getPoints( axis )
|
||||
if self.corona.conf.cfg.chip.use45corners:
|
||||
Diagonal.create( net, layer, Point(xBb+xExtend,yCorner), Point(xCorner,yBb+yExtend), width )
|
||||
Horizontal.create( net, layer, yCorner, width, xBb+xExtend, xBb )
|
||||
Vertical .create( net, layer, xCorner, width, yBb+yExtend, yBb )
|
||||
else:
|
||||
Contact .create( net, layer, xCorner, yCorner, width, width )
|
||||
Horizontal.create( net, layer, yCorner, width, xCorner, xBb )
|
||||
Vertical .create( net, layer, xCorner, width, yCorner, yBb )
|
||||
|
@ -243,9 +249,10 @@ class Side ( object ):
|
|||
checkName = 'east pads'
|
||||
elif self.type == South: checkName = 'south pads'
|
||||
elif self.type == West: checkName = 'west pads'
|
||||
self.conf.validated = self._check( len(self.pads) * self.conf.ioPadStep
|
||||
+ 2*self.conf.ioPadHeight
|
||||
, checkName ) and self.conf.validated
|
||||
padLength = 2*self.conf.ioPadHeight
|
||||
for pad in self.pads:
|
||||
padLength += pad[1].getMasterCell().getAbutmentBox().getWidth()
|
||||
self.conf.validated = self._check( padLength, checkName ) and self.conf.validated
|
||||
return self.conf.validated
|
||||
|
||||
def _fillPadSpacing ( self, gapWidth ):
|
||||
|
@ -537,13 +544,16 @@ class CoreWire ( object ):
|
|||
else:
|
||||
self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() )
|
||||
self.viaPitch = self.conf.getViaPitch( self.symContactLayer )
|
||||
contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer()
|
||||
basicLayer = self.symSegmentLayer
|
||||
if basicLayer.isSymbolic():
|
||||
basicLayer = basicLayer.getBasicLayer()
|
||||
contactMinSize = 2*self.symContactLayer.getEnclosure( basicLayer
|
||||
, Layer.EnclosureH|Layer.EnclosureV ) \
|
||||
+ self.symContactLayer.getMinimalSize()
|
||||
arrayWidth = self.symContactSize[0]
|
||||
arrayCount = (arrayWidth - contactMinSize) / self.viaPitch
|
||||
trace( 550, '\tcontactMinSize: {}l, arrayWidth: {}l, arrayCount: {}\n' \
|
||||
.format(DbU.toLambda(contactMinSize),DbU.toLambda(arrayWidth),arrayCount) )
|
||||
trace( 550, '\tcontactMinSize: {}, arrayWidth: {}, arrayCount: {}\n' \
|
||||
.format(DbU.getValueString(contactMinSize),DbU.getValueString(arrayWidth),arrayCount) )
|
||||
if arrayCount < 0: arrayCount = 0
|
||||
#if arrayCount < 3:
|
||||
if self.side & (North|South):
|
||||
|
@ -731,7 +741,7 @@ class CoreWire ( object ):
|
|||
if self.arraySize:
|
||||
if self.side == South: yContact = min( yContact, hStrapBb.getYMin() )
|
||||
else: yContact = max( yContact, hStrapBb.getYMax() )
|
||||
trace( 550, '\txCore: %sl %s\n' % (DbU.toLambda(xCore), DbU.getValueString(xCore)) )
|
||||
trace( 550, '\txCore: {:.1f}L {}\n'.format(DbU.toLambda(xCore), DbU.getValueString(xCore)) )
|
||||
self.conf.coronaVertical( self.chipNet
|
||||
, self.symSegmentLayer
|
||||
, xCore
|
||||
|
@ -855,11 +865,20 @@ class Corona ( object ):
|
|||
if not self.padLib: self.padLib = padCell.getLibrary()
|
||||
for plug in padInstance.getPlugs():
|
||||
for component in plug.getMasterNet().getComponents():
|
||||
if component is None: continue
|
||||
bb = component.getBoundingBox()
|
||||
hspan = Interval( bb.getXMin(), bb.getXMax() )
|
||||
axis = bb.getCenter().getY()
|
||||
if isinstance(component,Horizontal):
|
||||
hspan = Interval( component.getBoundingBox().getXMin()
|
||||
, component.getBoundingBox().getXMax() )
|
||||
width = component.getWidth()
|
||||
elif isinstance(component,Vertical):
|
||||
width = bb.getHeight()
|
||||
else:
|
||||
continue
|
||||
# Specific hack for Alliance pxlib pad library.
|
||||
if self.conf.ioPadGauge.getName() == 'pxlib':
|
||||
if isinstance(component,Vertical):
|
||||
continue
|
||||
if plug.getMasterNet().isClock():
|
||||
hspan.inflate( DbU.fromLambda(5.0) )
|
||||
else:
|
||||
|
@ -867,9 +886,9 @@ class Corona ( object ):
|
|||
if hspan.contains( ab.getXMin() ) or hspan.contains( ab.getXMax() ):
|
||||
duplicate = False
|
||||
if self.padOrient == Transformation.Orientation.ID:
|
||||
axis = component.getY()
|
||||
pass
|
||||
else:
|
||||
axis = self.conf.ioPadHeight - component.getY()
|
||||
axis = self.conf.ioPadHeight - axis
|
||||
for rail in self.padRails:
|
||||
if rail[0] == plug.getNet() \
|
||||
and rail[1] == component.getLayer() \
|
||||
|
@ -891,7 +910,7 @@ class Corona ( object ):
|
|||
self.padRails.append( ( net
|
||||
, component.getLayer()
|
||||
, axis
|
||||
, component.getWidth() ) )
|
||||
, width ) )
|
||||
|
||||
def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ):
|
||||
trace( 550, ',+', '\tCorona._createCoreWire()\n' )
|
||||
|
@ -906,6 +925,12 @@ class Corona ( object ):
|
|||
if not side:
|
||||
trace( 550, '-' )
|
||||
return count
|
||||
if chipIntNet.isPower() and not padInstance.getName().startswith('p_vdd'):
|
||||
trace( 550, '-' )
|
||||
return count
|
||||
if chipIntNet.isGround() and not padInstance.getName().startswith('p_vss'):
|
||||
trace( 550, '-' )
|
||||
return count
|
||||
innerBb = self.conf.chip.getAbutmentBox().inflate( -self.conf.ioPadHeight )
|
||||
rg = self.conf.routingGauge
|
||||
hsegments = {}
|
||||
|
|
|
@ -155,7 +155,10 @@ class GoCb ( object ):
|
|||
if go.getNet().getType() == long(Net.Type.GROUND): rootNet = self.block.conf.coronaVss
|
||||
if not rootNet: return
|
||||
if self.block.activePlane:
|
||||
bb = go.getBoundingBox( self.block.activePlane.metal.getBasicLayer() )
|
||||
layer = self.block.activePlane.metal
|
||||
if layer.isSymbolic():
|
||||
layer = layer.getBasicLayer()
|
||||
bb = go.getBoundingBox( layer )
|
||||
query.getPath().getTransformation().applyOn( bb )
|
||||
self.block.activePlane.addTerminal( rootNet, direction, bb )
|
||||
else:
|
||||
|
@ -190,7 +193,10 @@ class Builder ( object ):
|
|||
query.setFilter( Query.DoComponents|Query.DoTerminalCells )
|
||||
for layerGauge in self.conf.routingGauge.getLayerGauges():
|
||||
self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
|
||||
query.setBasicLayer( layerGauge.getLayer().getBasicLayer() )
|
||||
layer = layerGauge.getLayer()
|
||||
if layer.isSymbolic():
|
||||
layer = layer.getBasicLayer()
|
||||
query.setBasicLayer( layer )
|
||||
query.doQuery()
|
||||
self.activePlane = None
|
||||
|
||||
|
@ -231,7 +237,10 @@ class Builder ( object ):
|
|||
)
|
||||
segment = self.conf.createVertical( bufferRp, contact, bufferRp.getX(), 0 )
|
||||
self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
|
||||
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
|
||||
layer = self.activePlane.metal
|
||||
if layer.isSymbolic():
|
||||
layer = layer.getBasicLayer()
|
||||
bb = segment.getBoundingBox( layer )
|
||||
self.path.getTransformation().getInvert().applyOn( bb )
|
||||
self.activePlane.addTerminal( ck, Plane.Vertical, bb )
|
||||
trace( 550, '\tAdded terminal of {} to vertical plane @{}\n'.format(ck,bb) )
|
||||
|
|
|
@ -52,8 +52,9 @@ from helpers import trace, netDirectionToStr
|
|||
from helpers.overlay import UpdateSession
|
||||
from helpers.io import ErrorMessage, WarningMessage
|
||||
import plugins.chip
|
||||
from plugins.alpha.utils import getPlugByName
|
||||
from plugins.alpha.block.block import Block
|
||||
from plugins.alpha.block.configuration import BlockConf, IoPadConf
|
||||
from plugins.alpha.block.configuration import BlockConf, IoPadConf, ConstantsConf
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
@ -307,6 +308,9 @@ class IoPad ( object ):
|
|||
if (self.direction == IoPad.BIDIR) and (len(self.nets) < 3):
|
||||
self.nets[0].setFlags( IoNet.DoExtNet )
|
||||
self.nets[0].buildNets()
|
||||
if len(self.nets) < 2:
|
||||
enableNet = self.coreToChip.newEnableForNet( self.nets[0] )
|
||||
self.nets.append( self.coreToChip.getIoNet( enableNet ) )
|
||||
self.nets[1].buildNets()
|
||||
connexions.append( ( self.nets[0].chipExtNet, padInfo.padNet ) )
|
||||
if self.nets[0].coreNet.getDirection() == Net.Direction.IN:
|
||||
|
@ -329,7 +333,7 @@ class IoPad ( object ):
|
|||
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:
|
||||
elif self.direction == IoPad.BIDIR:
|
||||
connexions.append( ( self.nets[0].chipIntNet, padInfo.inputNet ) )
|
||||
connexions.append( ( self.nets[1].chipIntNet, padInfo.outputNet ) )
|
||||
connexions.append( ( self.nets[2].chipIntNet, padInfo.enableNet ) )
|
||||
|
@ -398,13 +402,13 @@ class CoreToChip ( object ):
|
|||
|
||||
|
||||
def getNetType ( self, netName ):
|
||||
raise ErrorMessage( 1, 'coreToChip.getNetType(): This method must be overloaded.' )
|
||||
raise NotImplementedError( 'coreToChip.getNetType(): This method must be overloaded.' )
|
||||
|
||||
def isGlobal ( self, netName ):
|
||||
raise ErrorMessage( 1, 'coreToChip.isGlobal(): This method must be overloaded.' )
|
||||
raise NotImplementedError( 'coreToChip.isGlobal(): This method must be overloaded.' )
|
||||
|
||||
def getCell ( self, masterCellName ):
|
||||
raise ErrorMessage( 1, 'coreToChip.getCell(): This method must be overloaded.' )
|
||||
raise NotImplementedError( 'coreToChip.getCell(): This method must be overloaded.' )
|
||||
|
||||
@staticmethod
|
||||
def _connect ( instance, netO, masterNetO=None ):
|
||||
|
@ -431,17 +435,17 @@ class CoreToChip ( object ):
|
|||
|
||||
def __init__ ( self, core ):
|
||||
if isinstance(core,Block):
|
||||
state = core.state
|
||||
conf = core.state
|
||||
elif isinstance(core,BlockConf):
|
||||
state = core
|
||||
conf = core
|
||||
else:
|
||||
block = Block.lookup( core )
|
||||
if not block:
|
||||
raise ErrorMessage( 1, [ 'Core2Chip.__init__(): Core cell "{}" has no Block defined.' \
|
||||
.format( core.getName() )
|
||||
] )
|
||||
state = block.state
|
||||
self.state = state
|
||||
conf = block.state
|
||||
self.conf = conf
|
||||
self.ringNetNames = []
|
||||
self.ioPadInfos = []
|
||||
self.chipPads = []
|
||||
|
@ -455,16 +459,16 @@ class CoreToChip ( object ):
|
|||
return
|
||||
|
||||
@property
|
||||
def core ( self ): return self.state.cell
|
||||
def core ( self ): return self.conf.cell
|
||||
|
||||
@property
|
||||
def icore ( self ): return self.state.icore
|
||||
def icore ( self ): return self.conf.icore
|
||||
|
||||
@property
|
||||
def icorona ( self ): return self.state.icorona
|
||||
def icorona ( self ): return self.conf.icorona
|
||||
|
||||
@property
|
||||
def chip ( self ): return self.state.chip
|
||||
def chip ( self ): return self.conf.chip
|
||||
|
||||
def getPadInfo ( self, padType ):
|
||||
for ioPadInfo in self.ioPadInfos:
|
||||
|
@ -480,10 +484,30 @@ class CoreToChip ( object ):
|
|||
return False
|
||||
|
||||
def newDummyNet ( self ):
|
||||
"""Create a dummy net in *chip* cell (for unconnected terminals)."""
|
||||
dummy = Net.create( self.chip, '{}_dummy_{}'.format(self.chip.getName(),self.dummyNetCount) )
|
||||
self.dummyNetCount += 1
|
||||
return dummy
|
||||
|
||||
def newEnableForNet ( self, ioNet ):
|
||||
"""
|
||||
Create a new enable signal, in *core* cell, to control the associated I/O pad.
|
||||
This is to be used in the case of bi-directional I/O pads used as simples inputs
|
||||
or outputs.
|
||||
"""
|
||||
if ioNet.coreNet.getDirection() & Net.Direction.IN: constantType = ConstantsConf.ZERO
|
||||
elif ioNet.coreNet.getDirection() & Net.Direction.OUT: constantType = ConstantsConf.ONE
|
||||
else:
|
||||
raise ErrorMessage( 2, 'CoreToChip.newEnableForNet(): Net "{}" is neither IN nor OUT.' \
|
||||
.format(ioNet.coreNet.getName()) )
|
||||
instance = self.conf.constantsConf.createInstance( self.core, constantType )
|
||||
enable = Net.create( self.core, '{}_enable'.format(ioNet.padInstanceName) )
|
||||
enable.setExternal ( True )
|
||||
enable.setDirection( Net.Direction.OUT )
|
||||
getPlugByName( instance, self.conf.constantsConf.output(constantType) ).setNet( enable )
|
||||
self.conf.addClonedCell( self.conf.core )
|
||||
return enable
|
||||
|
||||
def getIoNet ( self, coreNet ):
|
||||
"""
|
||||
Lookup, and create if it doesn't exist, for an IoNet associated to *core*
|
||||
|
@ -566,19 +590,19 @@ class CoreToChip ( object ):
|
|||
from the core cell.
|
||||
"""
|
||||
af = AllianceFramework.get()
|
||||
self.state.cfg.apply()
|
||||
self.conf.cfg.apply()
|
||||
with UpdateSession():
|
||||
print( ' o Build Chip from Core.' )
|
||||
print( ' - Core: "{}".'.format(self.state.cell.getName()) )
|
||||
print( ' - Core: "{}".'.format(self.conf.cell.getName()) )
|
||||
print( ' - Corona: "{}".'.format('corona') )
|
||||
print( ' - Chip: "{}".'.format(self.state.chipConf.name) )
|
||||
self.state.chip = af.createCell( self.state.chipConf.name )
|
||||
print( ' - Chip: "{}".'.format(self.conf.chipConf.name) )
|
||||
self.conf.chip = af.createCell( self.conf.chipConf.name )
|
||||
self.corona = af.createCell( 'corona' )
|
||||
self.state.icore = Instance.create( self.corona , 'core' , self.state.cell )
|
||||
self.state.icorona = Instance.create( self.state.chip, 'corona', self.corona )
|
||||
self.conf.icore = Instance.create( self.corona , 'core' , self.conf.cell )
|
||||
self.conf.icorona = Instance.create( self.conf.chip, 'corona', self.corona )
|
||||
ioPads = []
|
||||
clockIoNets = []
|
||||
for ioPadConf in self.state.chipConf.padInstances:
|
||||
for ioPadConf in self.conf.chipConf.padInstances:
|
||||
if ioPadConf.isAllPower():
|
||||
self._buildAllPowerPads( ioPadConf )
|
||||
continue
|
||||
|
@ -638,5 +662,4 @@ class CoreToChip ( object ):
|
|||
ioPad.udata.createPad()
|
||||
self._connectRing()
|
||||
self._connectClocks()
|
||||
af.saveCell( self.chip , Catalog.State.Logical )
|
||||
af.saveCell( self.corona, Catalog.State.Logical )
|
||||
self.conf.rsave( self.chip )
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of the Coriolis Software.
|
||||
# Copyright (c) SU 2020-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/libresocio.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
"""
|
||||
Core2Chip configuration for the FlexLib I/O pad library.
|
||||
|
||||
It provides the same features as the symbolic "niolib", but is
|
||||
using the real cells provided by LibreSOC.py. For now, apart from
|
||||
cell library change, the only difference is that the cell names are
|
||||
in upppercase. We can use them because, in real mode, we are less
|
||||
dependent from the Alliance design flow.
|
||||
"""
|
||||
|
||||
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 ):
|
||||
"""
|
||||
Provide pad-specific part for LibreSOCIO I/O pads (works in real mode).
|
||||
"""
|
||||
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', ['s', 'd', 'de'] )
|
||||
]
|
||||
self._getPadLib()
|
||||
return
|
||||
|
||||
def _getPadLib ( self ):
|
||||
self.padLib = AllianceFramework.get().getLibrary( "LibreSOCIO" )
|
||||
if not self.padLib:
|
||||
message = [ 'CoreToChip.libresocio._getPadLib(): Unable to find Alliance "LibreSOCIO" 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, 'libresocio.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 "LibreSOCIO" there is no specialized clock I/O pad. So do nothing."""
|
||||
pass
|
||||
|
||||
def _connectClocks ( self ):
|
||||
"""For "LibreSOCIO" there is no pad internal clock ring. So do nothing."""
|
||||
pass
|
Loading…
Reference in New Issue