2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
# -*- mode:Python -*-
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os.path
|
|
|
|
import string
|
|
|
|
import traceback
|
|
|
|
import Hurricane
|
|
|
|
from Hurricane import DbU
|
Make the Python interface closely mirroring the C++ one.
* Change: In Isobar, the Python interface was not exactly mirroring the
C++ one, now it is the case. The Python code should look likes almost
exactly like the C++ one, the only differences remaining being due
to the languages respective syntaxes. Note that in the case of
constructor functions, it leads to a slightly longer notation in
Python that it could have been (mimic the ".create()" static
member). Main modifications:
1. Mirror the static constructor syntax with create():
Cell( ... ) ==> Cell.create( ... )
2. Correct hierarchy for constants in Instance, Net, Pin
& Transformation. For example:
Hurricane.PlacementStatusFIXED
==> Hurricane.Instance.PlacementStatus.FIXED
Hurricane.OrientationID
==> Hurricane.Transformation.Orientation.ID
Hurricane.TypeLOGICAL ==> Hurricane.Net.Type.LOGICAL
Hurricane.DirectionIN ==> Hurricane.Net.Direction.IN
* Change: In CRL Core, correction to match the improved Python API
in the configutation helpers.
* Change: In Cumulus, correction to match the improved Python API.
* Change: In Stratus, correction to match the improved Python API.
* Change: In Documenation, update for the new Python interface
(both user's guide & examples).
* Note: We must port those changes into Chams for it to continue
to run.
* Change: In Documenation, update the Python script support part.
2014-06-28 10:37:59 -05:00
|
|
|
from Hurricane import DataBase
|
2012-11-16 06:49:47 -06:00
|
|
|
from Hurricane import Layer
|
|
|
|
from Hurricane import BasicLayer
|
|
|
|
from Hurricane import DiffusionLayer
|
|
|
|
from Hurricane import TransistorLayer
|
|
|
|
from Hurricane import RegularLayer
|
|
|
|
from Hurricane import ContactLayer
|
|
|
|
from Hurricane import ViaLayer
|
Added support for multiple symbolic+real technology in configuration.
In CRL Core, the layout of the files under "/coriolis2/etc" changes.
Instead of having them directly under "etc", they are now replicated,
in subdirectories. Each subdirectory having the name of the associated
symbolic or real technology (they are kept separated). We have, for
now:
* etc/cmos/ : symbolic, the Alliance original one.
* etc/vsc200/ : symbolic, for G. Petley vsclib.
* etc/hcmos9/ : real, generic fake (130nm).
To tell which pair (symbolic,real) technologies must be used we create
a *second* (sigh) configuration file "coriolis2_techno.conf", and it's
hidden counterpart in the user's account, to set it up. It needs to be
separate because it is read as early as possible and select which set
of configuration files would be read.
Also add support up to METAL8 and POLY2 in CRL core and it's Alliance
parser/drivers.
2014-05-21 07:50:22 -05:00
|
|
|
from CRL import AllianceFramework
|
2012-11-16 06:49:47 -06:00
|
|
|
from helpers import ErrorMessage
|
|
|
|
|
|
|
|
|
Added support for multiple symbolic+real technology in configuration.
In CRL Core, the layout of the files under "/coriolis2/etc" changes.
Instead of having them directly under "etc", they are now replicated,
in subdirectories. Each subdirectory having the name of the associated
symbolic or real technology (they are kept separated). We have, for
now:
* etc/cmos/ : symbolic, the Alliance original one.
* etc/vsc200/ : symbolic, for G. Petley vsclib.
* etc/hcmos9/ : real, generic fake (130nm).
To tell which pair (symbolic,real) technologies must be used we create
a *second* (sigh) configuration file "coriolis2_techno.conf", and it's
hidden counterpart in the user's account, to set it up. It needs to be
separate because it is read as early as possible and select which set
of configuration files would be read.
Also add support up to METAL8 and POLY2 in CRL core and it's Alliance
parser/drivers.
2014-05-21 07:50:22 -05:00
|
|
|
symbolicFile = '<No symbolic file specified>'
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
|
|
|
|
class SymbolicLayerType ( object ):
|
|
|
|
|
|
|
|
Regular = 1
|
|
|
|
Diffusion = 2
|
|
|
|
Transistor = 3
|
|
|
|
Contact = 4
|
|
|
|
Via = 5
|
|
|
|
|
|
|
|
def __init__ ( self, code ):
|
|
|
|
self._code = code
|
|
|
|
return
|
|
|
|
|
|
|
|
def __int__ ( self ):
|
|
|
|
return self._code
|
|
|
|
|
|
|
|
def __str__ ( self ):
|
|
|
|
if self._code == SymbolicLayerType.Regular: return 'TypeRegular'
|
|
|
|
if self._code == SymbolicLayerType.Diffusion: return 'TypeDiffusion'
|
|
|
|
if self._code == SymbolicLayerType.Transistor: return 'TypeTransistor'
|
|
|
|
if self._code == SymbolicLayerType.Contact: return 'TypeContact'
|
|
|
|
if self._code == SymbolicLayerType.Via: return 'TypeVia'
|
|
|
|
return 'TypeUnknown (%d)', self._code
|
|
|
|
|
|
|
|
def __repr__ ( self ):
|
|
|
|
return str(self)
|
|
|
|
|
|
|
|
def realLayerLength ( self ):
|
|
|
|
if self._code == SymbolicLayerType.Regular: return 1
|
|
|
|
if self._code == SymbolicLayerType.Diffusion: return 3
|
|
|
|
if self._code == SymbolicLayerType.Transistor: return 4
|
|
|
|
if self._code == SymbolicLayerType.Contact: return 5
|
|
|
|
if self._code == SymbolicLayerType.Via: return 3
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
TypeRegular = SymbolicLayerType(SymbolicLayerType.Regular)
|
|
|
|
TypeDiffusion = SymbolicLayerType(SymbolicLayerType.Diffusion)
|
|
|
|
TypeTransistor = SymbolicLayerType(SymbolicLayerType.Transistor)
|
|
|
|
TypeContact = SymbolicLayerType(SymbolicLayerType.Contact)
|
|
|
|
TypeVia = SymbolicLayerType(SymbolicLayerType.Via)
|
|
|
|
|
|
|
|
|
|
|
|
class LayersLUT ( object ):
|
|
|
|
|
|
|
|
Real = 0x1
|
|
|
|
Symbolic = 0x2
|
|
|
|
MissingError = 0x8
|
|
|
|
|
|
|
|
def __init__ ( self ):
|
|
|
|
self._realLayers = {}
|
|
|
|
self._symbolicLayers = {}
|
|
|
|
return
|
|
|
|
|
|
|
|
def add ( self, layer ):
|
|
|
|
if isinstance(layer,BasicLayer): self._realLayers [ layer.getName() ] = layer
|
|
|
|
else: self._symbolicLayers[ layer.getName() ] = layer
|
|
|
|
return
|
|
|
|
|
|
|
|
def lookup ( self, name, flags=Real|Symbolic ):
|
|
|
|
layer = None
|
|
|
|
if flags & LayersLUT.Real and self._realLayers.has_key(name):
|
|
|
|
layer = self._realLayers[name]
|
|
|
|
if flags & LayersLUT.Symbolic and self._symbolicLayers.has_key(name):
|
|
|
|
layer = self._symbolicLayers[name]
|
|
|
|
|
|
|
|
if not layer and flags&LayersLUT.MissingError:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Layer <%s> is not defined (yet?).'%name])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
return layer
|
|
|
|
|
|
|
|
|
|
|
|
layersLUT = LayersLUT()
|
|
|
|
|
|
|
|
|
New coriolis launcher. Configuration files cleanup.
* Change: In CRL Core, simplify the loading sequence. The technology,
both symbolic and real is now loaded directly from coriolisInit.py
and not through the Alliance loader. This was a leftover from the
time configuration was in XML. Remove others traces of XML loading.
Remove SYMB_TECHNO_NAME, REAL_TECHNO_NAME & DISPLAY from the Alliance
environement, as they was no longer used.
Note that technology *still* need to be loader *after* Alliance
framework has been initialized.
Gauge information is moved from <alliance.conf> to <kite.conf>.
* Bug: In Coloquinte, in optimization_subproblems.cxx static variables
must not be inlined. Generate a problem when linking in debug mode
(seems the symbol gets optimised out).
* Bug: In Katabatic, in Grid::getGCell(), when the coordinate is *outside*
the area, do not try to find a GCell, directly return NULL.
* New: In Unicorn, create a generic command launcher named "coriolis" which
automatically take cares of all environement setup, then run a command
by default, it's <cgt>, but it can be anything. For example: <zsh>.
2015-04-13 11:54:09 -05:00
|
|
|
def loadRealLayers ( realLayersTable, confFile ):
|
|
|
|
global symbolicFile
|
|
|
|
symbolicFile = confFile
|
|
|
|
technology = DataBase.getDB().getTechnology()
|
|
|
|
|
2012-11-16 06:49:47 -06:00
|
|
|
entryNo = 0
|
|
|
|
for entry in realLayersTable:
|
|
|
|
entryNo += 1
|
|
|
|
|
|
|
|
try:
|
|
|
|
if len(entry) < 2:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Malformed entry in <realLayersTable>.'
|
|
|
|
,'Less than two fields: missing name and/or material.'
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
if len(entry) > 2:
|
|
|
|
if entry[1] != BasicLayer.Material.blockage:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <realLayersTable>.'
|
|
|
|
,'Only blockage material can have a third field.'
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
routingLayer = technology.getBasicLayer(entry[2])
|
|
|
|
if not routingLayer:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Incoherency in <realLayersTable> entry at.'
|
|
|
|
,'The metal <%s> associated to the blockage doesn\'t exist (yet?).' % entry[2]
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
basicLayer = BasicLayer.create( technology
|
|
|
|
, entry[0]
|
|
|
|
, BasicLayer.Material(entry[1]) )
|
|
|
|
layersLUT.add ( basicLayer )
|
|
|
|
if len(entry) > 2:
|
|
|
|
routingLayer.setBlockageLayer(basicLayer)
|
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
ErrorMessage.wrapPrint(e,'In %s:<symbolicLayersTable> at index %d.' % (symbolicFile,entryNo))
|
|
|
|
return
|
|
|
|
|
|
|
|
|
New coriolis launcher. Configuration files cleanup.
* Change: In CRL Core, simplify the loading sequence. The technology,
both symbolic and real is now loaded directly from coriolisInit.py
and not through the Alliance loader. This was a leftover from the
time configuration was in XML. Remove others traces of XML loading.
Remove SYMB_TECHNO_NAME, REAL_TECHNO_NAME & DISPLAY from the Alliance
environement, as they was no longer used.
Note that technology *still* need to be loader *after* Alliance
framework has been initialized.
Gauge information is moved from <alliance.conf> to <kite.conf>.
* Bug: In Coloquinte, in optimization_subproblems.cxx static variables
must not be inlined. Generate a problem when linking in debug mode
(seems the symbol gets optimised out).
* Bug: In Katabatic, in Grid::getGCell(), when the coordinate is *outside*
the area, do not try to find a GCell, directly return NULL.
* New: In Unicorn, create a generic command launcher named "coriolis" which
automatically take cares of all environement setup, then run a command
by default, it's <cgt>, but it can be anything. For example: <zsh>.
2015-04-13 11:54:09 -05:00
|
|
|
def loadSymbolicLayers ( symbolicLayersData, confFile ):
|
|
|
|
global symbolicFile
|
|
|
|
symbolicFile = confFile
|
|
|
|
technology = DataBase.getDB().getTechnology()
|
|
|
|
|
2012-11-16 06:49:47 -06:00
|
|
|
entryNo = 0
|
|
|
|
for entry in symbolicLayersData:
|
|
|
|
entryNo += 1
|
|
|
|
|
|
|
|
try:
|
|
|
|
if len(entry) != 3:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Malformed entry in <symbolicLayersTable>.'
|
|
|
|
,'Must contains exactly three fields: ( name, type, (real_layers,) ).'
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
name, layerType, realLayers = entry
|
|
|
|
|
|
|
|
if not isinstance(layerType,SymbolicLayerType):
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <symbolicLayersTable>.'
|
|
|
|
,'The layer type code is not valid, should be any of:'
|
|
|
|
,' * TypeRegular'
|
|
|
|
,' * TypeDiffusion'
|
|
|
|
,' * TypeTransistor'
|
|
|
|
,' * TypeContact'
|
|
|
|
,' * TypeVia'
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
if layerType.realLayerLength() != len(realLayers):
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <symbolicLayersTable>.'
|
|
|
|
,'Layer of type <%s> contains %d real layers instead of %d.' \
|
|
|
|
% (layerType,len(realLayers),layerType.realLayerLength())
|
|
|
|
,str(entry)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
realLayersArgs = []
|
|
|
|
for layerName in realLayers:
|
|
|
|
if layerName:
|
|
|
|
realLayersArgs += [ layersLUT.lookup(layerName
|
|
|
|
,LayersLUT.Real
|
|
|
|
|LayersLUT.Symbolic
|
|
|
|
|LayersLUT.MissingError) ]
|
|
|
|
else:
|
|
|
|
realLayersArgs += [ None ]
|
|
|
|
|
|
|
|
symbolicLayer = None
|
|
|
|
|
|
|
|
if layerType == TypeRegular:
|
|
|
|
symbolicLayer = RegularLayer.create(technology,entry[0])
|
|
|
|
symbolicLayer.setBasicLayer( *realLayersArgs )
|
|
|
|
elif layerType == TypeDiffusion:
|
|
|
|
symbolicLayer = DiffusionLayer.create(technology ,entry[0], *realLayersArgs)
|
|
|
|
elif layerType == TypeTransistor:
|
|
|
|
symbolicLayer = TransistorLayer.create(technology ,entry[0], *realLayersArgs)
|
|
|
|
elif layerType == TypeContact:
|
|
|
|
symbolicLayer = ContactLayer.create(technology ,entry[0], *realLayersArgs)
|
|
|
|
elif layerType == TypeVia:
|
|
|
|
symbolicLayer = ViaLayer.create(technology ,entry[0], *realLayersArgs)
|
|
|
|
|
|
|
|
layersLUT.add( symbolicLayer )
|
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
ErrorMessage.wrapPrint(e,'In %s:<symbolicLayersTable> at index %d.' % (symbolicFile,entryNo))
|
|
|
|
return
|
|
|
|
|
|
|
|
|
New coriolis launcher. Configuration files cleanup.
* Change: In CRL Core, simplify the loading sequence. The technology,
both symbolic and real is now loaded directly from coriolisInit.py
and not through the Alliance loader. This was a leftover from the
time configuration was in XML. Remove others traces of XML loading.
Remove SYMB_TECHNO_NAME, REAL_TECHNO_NAME & DISPLAY from the Alliance
environement, as they was no longer used.
Note that technology *still* need to be loader *after* Alliance
framework has been initialized.
Gauge information is moved from <alliance.conf> to <kite.conf>.
* Bug: In Coloquinte, in optimization_subproblems.cxx static variables
must not be inlined. Generate a problem when linking in debug mode
(seems the symbol gets optimised out).
* Bug: In Katabatic, in Grid::getGCell(), when the coordinate is *outside*
the area, do not try to find a GCell, directly return NULL.
* New: In Unicorn, create a generic command launcher named "coriolis" which
automatically take cares of all environement setup, then run a command
by default, it's <cgt>, but it can be anything. For example: <zsh>.
2015-04-13 11:54:09 -05:00
|
|
|
def loadSymbolicRules ( symbolicRulesTable, confFile ):
|
|
|
|
global symbolicFile
|
|
|
|
symbolicFile = confFile
|
|
|
|
technology = DataBase.getDB().getTechnology()
|
|
|
|
|
2012-11-16 06:49:47 -06:00
|
|
|
entryNo = 0
|
|
|
|
for rule in symbolicRulesTable:
|
|
|
|
entryNo += 1
|
|
|
|
|
|
|
|
try:
|
|
|
|
if len(rule) != 2:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Malformed entry in <symbolicRulesTable>.'
|
|
|
|
,'Must contains exactly two fields: ( rule_path, value ).'
|
|
|
|
,str(rule)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
if not isinstance(rule[1],int) and not isinstance(rule[1],float):
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.'
|
|
|
|
,'Rule value must be of integer or float type.'
|
|
|
|
,str(rule)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
value = DbU.fromLambda(rule[1])
|
|
|
|
elements = rule[0].split('.')
|
|
|
|
if len(elements) < 3:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.'
|
|
|
|
,'Rule name must contains at least three components: \"LAYER.category.dimension\".'
|
|
|
|
,str(rule)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Symbolic|LayersLUT.MissingError )
|
|
|
|
subLayer = layersLUT.lookup( elements[1], LayersLUT.Real )
|
|
|
|
|
|
|
|
if subLayer: ruleTag = string.join(elements[2:],'.')
|
|
|
|
else: ruleTag = string.join(elements[1:],'.')
|
|
|
|
|
|
|
|
if ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value )
|
|
|
|
elif ruleTag == 'extention.width': ruleLayer.setExtentionWidth( subLayer, value )
|
|
|
|
elif ruleTag == 'enclosure': ruleLayer.setEnclosure ( subLayer, value )
|
|
|
|
elif ruleTag == 'minimum.width': ruleLayer.setMinimalSize ( value )
|
|
|
|
elif ruleTag == 'minimum.side': ruleLayer.setMinimalSize ( value )
|
|
|
|
else:
|
2012-12-03 02:27:41 -06:00
|
|
|
raise ErrorMessage(1,['Invalid entry in <symbolicRulesTable>.'
|
|
|
|
,'Unknown rule kind: \".%s\", should be any of:' % ruleTag
|
|
|
|
,' * "RULE_HEAD.extention.cap"'
|
|
|
|
,' * "RULE_HEAD.extention.width"'
|
|
|
|
,' * "RULE_HEAD.enclosure"'
|
|
|
|
,' * "RULE_HEAD.minimum.width"'
|
|
|
|
,' * "RULE_HEAD.minimum.side"'
|
|
|
|
,str(rule)
|
|
|
|
])
|
2012-11-16 06:49:47 -06:00
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
ErrorMessage.wrapPrint(e,'In %s:<symbolicRulesTable> at index %d.' % (symbolicFile,entryNo))
|
|
|
|
return
|
|
|
|
|
|
|
|
|
New coriolis launcher. Configuration files cleanup.
* Change: In CRL Core, simplify the loading sequence. The technology,
both symbolic and real is now loaded directly from coriolisInit.py
and not through the Alliance loader. This was a leftover from the
time configuration was in XML. Remove others traces of XML loading.
Remove SYMB_TECHNO_NAME, REAL_TECHNO_NAME & DISPLAY from the Alliance
environement, as they was no longer used.
Note that technology *still* need to be loader *after* Alliance
framework has been initialized.
Gauge information is moved from <alliance.conf> to <kite.conf>.
* Bug: In Coloquinte, in optimization_subproblems.cxx static variables
must not be inlined. Generate a problem when linking in debug mode
(seems the symbol gets optimised out).
* Bug: In Katabatic, in Grid::getGCell(), when the coordinate is *outside*
the area, do not try to find a GCell, directly return NULL.
* New: In Unicorn, create a generic command launcher named "coriolis" which
automatically take cares of all environement setup, then run a command
by default, it's <cgt>, but it can be anything. For example: <zsh>.
2015-04-13 11:54:09 -05:00
|
|
|
def loadWorkingLayers ( workingLayersTable, confFile ):
|
|
|
|
global symbolicFile
|
|
|
|
symbolicFile = confFile
|
|
|
|
technology = DataBase.getDB().getTechnology()
|
|
|
|
|
2012-11-16 06:49:47 -06:00
|
|
|
entryNo = 0
|
|
|
|
for layerName in workingLayersTable:
|
|
|
|
entryNo += 1
|
|
|
|
try:
|
|
|
|
# This call is just to generate an error if the layer is non-existent.
|
|
|
|
layersLUT.lookup(layerName,LayersLUT.Real|LayersLUT.Symbolic|LayersLUT.MissingError)
|
|
|
|
technology.setWorkingLayer(layerName)
|
|
|
|
except Exception, e:
|
|
|
|
ErrorMessage.wrapPrint(e,'In %s:<symbolicRulesTable> at index %d.' % (symbolicFile,entryNo))
|
|
|
|
return
|
|
|
|
|
|
|
|
|
New coriolis launcher. Configuration files cleanup.
* Change: In CRL Core, simplify the loading sequence. The technology,
both symbolic and real is now loaded directly from coriolisInit.py
and not through the Alliance loader. This was a leftover from the
time configuration was in XML. Remove others traces of XML loading.
Remove SYMB_TECHNO_NAME, REAL_TECHNO_NAME & DISPLAY from the Alliance
environement, as they was no longer used.
Note that technology *still* need to be loader *after* Alliance
framework has been initialized.
Gauge information is moved from <alliance.conf> to <kite.conf>.
* Bug: In Coloquinte, in optimization_subproblems.cxx static variables
must not be inlined. Generate a problem when linking in debug mode
(seems the symbol gets optimised out).
* Bug: In Katabatic, in Grid::getGCell(), when the coordinate is *outside*
the area, do not try to find a GCell, directly return NULL.
* New: In Unicorn, create a generic command launcher named "coriolis" which
automatically take cares of all environement setup, then run a command
by default, it's <cgt>, but it can be anything. For example: <zsh>.
2015-04-13 11:54:09 -05:00
|
|
|
def loadViewerConfig ( viewerConfig, confFile ):
|
|
|
|
global symbolicFile
|
|
|
|
symbolicFile = confFile
|
2012-11-16 06:49:47 -06:00
|
|
|
try:
|
|
|
|
if viewerConfig.has_key('precision'): DbU.setPrecision(viewerConfig['precision'])
|
|
|
|
except Exception, e:
|
|
|
|
ErrorMessage.wrapPrint(e,'In %s:<viewerConfig>.')
|
|
|
|
return
|