2018-10-01 09:52:17 -05:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
Comprehensive reorganisation of the Python part of Coriolis.
* Move all Python stuff under a common Python namespace "coriolis".
* Instead of having a series subtrees for each tool, integrate
everything in one common tree. So now, all components can be
located either with an absolute path from "coriolis" or, inside
cross-reference themselves through relatives imports.
* As a consequence, we only need to add ".../site-packages/coriolis/"
to the PYTHONPATH, and not a whole bunch of subdirectories.
And nothing, if installed in-system.
* The tree of free technologies configuration files is also moved
below "coriolis/technos" instead of "/etc".
* Supressed "cumulus" level for the plugins.
* All python modules are rewritten using relative imports except
for the configuration files that uses absolute import as they
can be cloned outside of the tree to serve as templates.
* Change: In boostrap/FindPythonSitePackages, include "/coriolis" in
Python_CORIOLISARCH and Python_CORIOLISLIB.
Provide a Python_SITELIB *without* "/coriolis" appended.
* Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules
read in the plugins directory by "coriolis.plugins.". No longer need
to add their path to sys.path.
* Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of
the layouts generators must be prefixed by "coriolis.oroshi.".
* Change: In CRL::System CTOR, no longer add the pathes of the various
plugins to sys.path. Only "site-packages/coriolis/".
* New: In Utilities::Path::toPyModePath(), new method to convert a
filesystem path into a python module path.
Examples:
"coriolis/plugins/block" --> "coriolis.plugins.block".
"coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave".
* Change: In katanaEngine::_runKatanaEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In BoraEngine::_runBoraEngine(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In UnicornGui::_runUnicornInit(), rename the hook script
initHook.py. No longer need to modify sys.path.
* Change: In cumulus.plugins.chip.constants, put the constants
outside __init__.py to avoid a loop at initialization.
2023-02-27 15:14:32 -06:00
|
|
|
from ..Hurricane import DataBase, DbU, Box, Net
|
|
|
|
from ..helpers.io import ErrorMessage as Error
|
|
|
|
from ..helpers import trace
|
2018-10-01 09:52:17 -05:00
|
|
|
|
|
|
|
|
|
|
|
# Rows are stacks.
|
|
|
|
# Columns are metaTransistors.
|
|
|
|
#
|
|
|
|
# There must be the exact same number of metaTransistors in each stack.
|
|
|
|
# Storage is matrix[row][col] ie matrix[stack][metaTransistor]
|
|
|
|
|
|
|
|
NoFlags = 0x0000
|
|
|
|
Top = 0x0001
|
|
|
|
Left = 0x0002
|
|
|
|
|
|
|
|
class ParamsMatrix ( object ):
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def gateToId ( gateName ):
|
|
|
|
if len(gateName) == 1: return None
|
|
|
|
return int( gateName[1:] )
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def idToGate ( index ):
|
|
|
|
if index is None: return 'G'
|
|
|
|
return 'G'+str(index)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def idToTran ( index ):
|
|
|
|
if index is None: return 'T'
|
|
|
|
return 'T'+str(index)
|
|
|
|
|
|
|
|
|
|
|
|
def __init__ ( self ):
|
|
|
|
self.matrix = [ [ {} ] ]
|
|
|
|
self.rows = 1
|
|
|
|
self.columns = 1
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def getMatrix ( self ): return self.matrix
|
|
|
|
|
|
|
|
|
First stage in analog capacitor integration
* Bug: In Technology::getPhysicalRule(), if the named layerdo not exists,
throw an exception instead of silently putting a NULL pointer inside
a rule.
* New: In Hurricane/Analog, new parameters classes for capacitor devices:
- Analog::Matrix, a matrix of null or positives integers to encode
capacitor matrix matching.
- Analog::Capacities, a list of float values for all component of a
multi-capacitor.
* New: In Hurricane::Script, add a "getFileName()" method to get the full
path name of the Python module.
* Change: In Analog::LayoutGenerator, completly remove the logger utility
as it is no longer used. Simply print error messages instead.
* Change: In Analog::MetaCapacitor, rename top & bottom plate 'T' & 'B'.
Accessors renamed in "getTopPlate()" & "getBottomPlate()".
* New: In Analog::MultiCapacitor, complete rewrite. Makes use of the
new parameters "capacities" and "matrix". Dynamically generates it's
terminals as we do not know beforehand how many capacitors could be
put in it.
* Bug: In isobar/PyHurricane.h, in Type object definition, do not prepend
a "Py" to class name (so the keep the C++ name).
* Change: In CRL/etc/scn6m_deep_09/devices.py, add entry for the new
capacitor generator.
* New: In oroshi/python/ParamsMatrix, add a "family" entry in the [0,0]
element to distinguish between transistor, capacitor and resistor.
(this is the matrix of values returned to the LayoutGenerator after
device generation).
Now have one "setGlobalParams()" function per family.
* New: In oroshi/python/Rules.py, added DTR rules needed by capacitors.
Catch exceptions if something wrong append when we extract the rules
from the technology.
* New: In Bora, the devices are no longer *only* transistors, so the
possibles configurations are no longer defined only by a number of
fingers. We must be able to support any kind of range of configuration.
So the explicit range of number of fingers is replaced by a base
class ParameterRange, and it's derived classes:
- Bora::StepParameterRange, to encode the possible number of fingers
of a transistor (the former only possibility).
- Bora::MatrixParameterRange, to encode all the possible matching
scheme for a capacitor. As there is no way to compress it, this
is a vector of Matrix (from Analog).
* Change: In Bora::DSlicingNode::_place(), the ParameterRange has to be set
on the right configuration (through the index) before being called.
The generation parameters are taken from the active item in the
ParameterRange.
* Change: In Bora::NodeSets::create(), iterate over the ParameterRange
to build all the configuration. Adjustement to the routing gauge
pitchs are moved into the DBoxSet CTOR to save a lot of code.
Semantic change: the index in the NodeSets is now the index in
the associated ParameterRange and no longer the number of fingers
of a transistor.
Check that the ParameterRange dynamic class is consitent with the
device family.
* Change: In Bora::DBoxSet, same semantic change as for NodeSets, the
number of finger become an index in ParameterRange.
In DBoxSet::create(), now also perform the abutment box adjustement
to the RoutingGauge, if possible.
* New: In Karakaze/python/AnalogDesign.py, add support for Capacitor
devices.
2019-11-07 10:05:49 -06:00
|
|
|
def setGlobalTransistorParams ( self, w, L, M, boundingBox ):
|
2018-10-01 09:52:17 -05:00
|
|
|
self.matrix[0][0]['L' ] = L
|
|
|
|
self.matrix[0][0]['W' ] = w
|
|
|
|
self.matrix[0][0]['M' ] = M
|
|
|
|
self.matrix[0][0]['box' ] = boundingBox
|
|
|
|
self.matrix[0][0]['globalActiveBox' ] = Box()
|
First stage in analog capacitor integration
* Bug: In Technology::getPhysicalRule(), if the named layerdo not exists,
throw an exception instead of silently putting a NULL pointer inside
a rule.
* New: In Hurricane/Analog, new parameters classes for capacitor devices:
- Analog::Matrix, a matrix of null or positives integers to encode
capacitor matrix matching.
- Analog::Capacities, a list of float values for all component of a
multi-capacitor.
* New: In Hurricane::Script, add a "getFileName()" method to get the full
path name of the Python module.
* Change: In Analog::LayoutGenerator, completly remove the logger utility
as it is no longer used. Simply print error messages instead.
* Change: In Analog::MetaCapacitor, rename top & bottom plate 'T' & 'B'.
Accessors renamed in "getTopPlate()" & "getBottomPlate()".
* New: In Analog::MultiCapacitor, complete rewrite. Makes use of the
new parameters "capacities" and "matrix". Dynamically generates it's
terminals as we do not know beforehand how many capacitors could be
put in it.
* Bug: In isobar/PyHurricane.h, in Type object definition, do not prepend
a "Py" to class name (so the keep the C++ name).
* Change: In CRL/etc/scn6m_deep_09/devices.py, add entry for the new
capacitor generator.
* New: In oroshi/python/ParamsMatrix, add a "family" entry in the [0,0]
element to distinguish between transistor, capacitor and resistor.
(this is the matrix of values returned to the LayoutGenerator after
device generation).
Now have one "setGlobalParams()" function per family.
* New: In oroshi/python/Rules.py, added DTR rules needed by capacitors.
Catch exceptions if something wrong append when we extract the rules
from the technology.
* New: In Bora, the devices are no longer *only* transistors, so the
possibles configurations are no longer defined only by a number of
fingers. We must be able to support any kind of range of configuration.
So the explicit range of number of fingers is replaced by a base
class ParameterRange, and it's derived classes:
- Bora::StepParameterRange, to encode the possible number of fingers
of a transistor (the former only possibility).
- Bora::MatrixParameterRange, to encode all the possible matching
scheme for a capacitor. As there is no way to compress it, this
is a vector of Matrix (from Analog).
* Change: In Bora::DSlicingNode::_place(), the ParameterRange has to be set
on the right configuration (through the index) before being called.
The generation parameters are taken from the active item in the
ParameterRange.
* Change: In Bora::NodeSets::create(), iterate over the ParameterRange
to build all the configuration. Adjustement to the routing gauge
pitchs are moved into the DBoxSet CTOR to save a lot of code.
Semantic change: the index in the NodeSets is now the index in
the associated ParameterRange and no longer the number of fingers
of a transistor.
Check that the ParameterRange dynamic class is consitent with the
device family.
* Change: In Bora::DBoxSet, same semantic change as for NodeSets, the
number of finger become an index in ParameterRange.
In DBoxSet::create(), now also perform the abutment box adjustement
to the RoutingGauge, if possible.
* New: In Karakaze/python/AnalogDesign.py, add support for Capacitor
devices.
2019-11-07 10:05:49 -06:00
|
|
|
self.matrix[0][0]['family' ] = 'Transistor'
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def setGlobalCapacitorParams ( self, boundingBox ):
|
|
|
|
self.matrix[0][0]['box' ] = boundingBox
|
|
|
|
self.matrix[0][0]['family' ] = 'Capacitor'
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
|
Added Resistor support. Completed Capacitor & Resistor support in Bora.
* New: In Analog, added Analog::ResitorFamily & Analog::Resistor classes.
* New: In Analog, added inspector support for all Parameter classes.
* New: In Analog, new FloatParameter class (for resistor value).
* New: In CRL/etc/scn6m_deep_09/devices.py, added resistor device.
* New: In Oroshi, support for Resistors, stub for ResistorSnake generator.
* New: In Bora::DNodeSets, added support for Resistor devices.
* Change: In Bora::DSlicingNode, rename setNFing()/getNFing() into
setBoxSetIndex()/getBoxSetIndex() for semantic coherency.
* New: In Karakaze/python/AnalogDesign.py, added support for Resistor.
Change in addDevice(), the span which was only meaningful for
transistor devices is replaced by a parameter argument.
The parameter argument has to be consistent with the device type.
2019-11-11 19:21:03 -06:00
|
|
|
def setGlobalResistorParams ( self, boundingBox ):
|
|
|
|
self.matrix[0][0]['box' ] = boundingBox
|
|
|
|
self.matrix[0][0]['family' ] = 'Resistor'
|
|
|
|
return
|
|
|
|
|
|
|
|
|
2018-10-01 09:52:17 -05:00
|
|
|
def setStacks ( self, stacks ):
|
|
|
|
if not isinstance(stacks,list):
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
print( Error( 3, 'ParamsMatrix::setGlobalParams(): <stack> argument must be of <list> type.' ))
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
if not len(stacks):
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
print( Error( 3, 'ParamsMatrix::setGlobalParams(): There must be at least one Stack.' ))
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
mtIds = []
|
|
|
|
if len(stacks[0].metaTransistors) == 0:
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
print( Error( 3, 'ParamsMatrix::setGlobalParams(): Stack without any meta-transistor.' ))
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
else:
|
|
|
|
for gateName in stacks[0].metaTransistors.keys():
|
|
|
|
mtIds.append( ParamsMatrix.gateToId(gateName) )
|
|
|
|
mtIds.sort()
|
|
|
|
|
|
|
|
for i in range(1,len(stacks)):
|
|
|
|
if len(stacks[0].metaTransistors) != len(stacks[i].metaTransistors):
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
print( Error( 3, 'ParamsMatrix::setGlobalParams(): Stacks {} and {}' \
|
|
|
|
' have different numbers of meta-transistor.'.format(0,i) ))
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
for id in mtIds:
|
|
|
|
gateName = ParamsMatrix.idToGate( id )
|
Migration towards Python3, first stage: still based on C-Macros.
* New: Python/C++ API level:
* Write a new C++/template wrapper to get rid of boost::python
* The int & long Python type are now merged. So a C/C++ level,
it became "PyLong_X" (remove "PyInt_X") and at Python code
level, it became "int" (remove "long").
* Change: VLSISAPD finally defunct.
* Configuration is now integrated as a Hurricane component,
makes use of the new C++/template wrapper.
* vlsisapd is now defunct. Keep it in the source for now as
some remaining non essential code may have to be ported in
the future.
* Note: Python code (copy of the migration howto):
* New print function syntax print().
* Changed "dict.has_key(k)" for "k" in dict.
* Changed "except Exception, e" for "except Exception as e".
* The division "/" is now the floating point division, even if
both operand are integers. So 3/2 now gives 1.5 and no longer 1.
The integer division is now "//" : 1 = 3//2. So have to carefully
review the code to update. Most of the time we want to use "//".
We must never change to float for long that, in fact, represents
DbU (exposed as Python int type).
* execfile() must be replaced by exec(open("file").read()).
* iter().__next__() becomes iter(x).__next__().
* __getslice__() has been removed, integrated to __getitem__().
* The formating used for str(type(o)) has changed, so In Stratus,
have to update them ("<class 'MyClass'>" instead of "MyClass").
* the "types" module no longer supply values for default types
like str (types.StringType) or list (types.StringType).
Must use "isinstance()" where they were occuring.
* Remove the 'L' to indicate "long integer" (like "12L"), now
all Python integer are long.
* Change in bootstrap:
* Ported Coriolis builder (ccb) to Python3.
* Ported Coriolis socInstaller.py to Python3.
* Note: In PyQt4+Python3, QVariant no longer exists. Use None or
directly convert using the python syntax: bool(x), int(x), ...
By default, it is a string (str).
* Note: PyQt4 bindings & Python3 under SL7.
* In order to compile user's must upgrade to my own rebuild of
PyQt 4 & 5 bindings 4.19.21-1.el7.soc.
* Bug: In cumulus/plugins.block.htree.HTree.splitNet(), set the root
buffer of the H-Tree to the original signal (mainly: top clock).
Strangely, it was only done when working in full chip mode.
2021-09-19 12:41:24 -05:00
|
|
|
if not gateName in stacks[i].metaTransistors:
|
|
|
|
print( Error( 3, 'ParamsMatrix::setGlobalParams(): Stack {} ' \
|
|
|
|
' is missing meta-transistor "{}".'.format(i,gateName) ))
|
2018-10-01 09:52:17 -05:00
|
|
|
return
|
|
|
|
|
|
|
|
# Thoses parameters must be the same in all the stacks.
|
|
|
|
self.matrix[0][0]['DMCG'] = stacks[0].DMCG
|
|
|
|
self.matrix[0][0]['DMCI'] = stacks[0].DMCI
|
|
|
|
self.matrix[0][0]['DGG' ] = stacks[0].DGG
|
|
|
|
self.matrix[0][0]['DGI' ] = stacks[0].DGI
|
|
|
|
|
|
|
|
for iStack in range(len(stacks)):
|
|
|
|
activeBox = stacks[iStack].activeBox
|
|
|
|
stackMTs = [ { 'activeBox':activeBox } ]
|
|
|
|
self.matrix[0][0]['globalActiveBox'].merge( activeBox )
|
|
|
|
|
|
|
|
for iMT in range(len(mtIds)):
|
|
|
|
gateName = ParamsMatrix.idToGate( mtIds[iMT] )
|
|
|
|
tranName = ParamsMatrix.idToTran( mtIds[iMT] )
|
|
|
|
mt = stacks[iStack].metaTransistors[ gateName ]
|
|
|
|
|
|
|
|
stackMTs.append( { 'name':tranName } )
|
|
|
|
for key, value in mt.items():
|
|
|
|
stackMTs[-1][ key.split('.')[-1] ] = value
|
|
|
|
|
|
|
|
if iStack == 0:
|
|
|
|
self.matrix[0].append( { 'name':tranName } )
|
|
|
|
for key in stackMTs[-1].keys():
|
|
|
|
if key == 'name' or key == 'style.geomod': continue
|
|
|
|
if key.startswith('stress.'):
|
|
|
|
self.matrix[0][-1][key] = stackMTs[-1][key] / len(stacks)
|
|
|
|
else:
|
|
|
|
self.matrix[0][-1][key] = stackMTs[-1][key]
|
|
|
|
else:
|
|
|
|
for key in stackMTs[-1].keys():
|
|
|
|
if key == 'name' or key == 'style.geomod': continue
|
|
|
|
if key.startswith('stress.'):
|
|
|
|
self.matrix[0][-1][key] += stackMTs[-1][key] / len(stacks)
|
|
|
|
else:
|
|
|
|
self.matrix[0][-1][key] += stackMTs[-1][key]
|
|
|
|
|
|
|
|
self.matrix.append( stackMTs )
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def stackHeader ( self, lines, iStack ):
|
|
|
|
for i in range(28):
|
|
|
|
if i in [1, 2, 3, 4]:
|
|
|
|
if i == 1:
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
self.toBoxDatasheet( lines, self.matrix[iStack][0]['activeBox'], 'Active Box', Left )
|
|
|
|
continue
|
|
|
|
|
|
|
|
if i == 0: lines.append( '|{0:^23s}'.format( 'Stack %d'%iStack ) )
|
|
|
|
elif i == 27: lines.append( '+-----------------------' )
|
|
|
|
else: lines.append( '| ' )
|
|
|
|
|
|
|
|
if i in [1, 14, 21, 27]: lines[-1] += '+'
|
|
|
|
else: lines[-1] += '|'
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def toMtDatasheet ( self, lines, mt, comment, flags ):
|
|
|
|
if flags & Top: lines[-29] += '-----------------------+'
|
|
|
|
|
|
|
|
lines[-28] += '{0:^23s}|'.format( mt['name']+comment )
|
|
|
|
lines[-27] += '-----------------------+'
|
|
|
|
lines[-26] += ' BSIM4 |'
|
|
|
|
lines[-25] += ' NSint %7s |' % mt['NSint']
|
|
|
|
lines[-24] += ' NDint %7s |' % mt['NDint']
|
|
|
|
lines[-23] += ' NSend %7s |' % mt['NSend']
|
|
|
|
lines[-22] += ' NDend %7s |' % mt['NDend']
|
|
|
|
lines[-21] += ' SAeff %7.2g m |' % mt['SAeff_Bsim4']
|
|
|
|
lines[-20] += ' SBeff %7.2g m |' % mt['SBeff_Bsim4']
|
|
|
|
lines[-19] += ' SAinv %7.2g 1/m |' % mt['SBinv_Bsim4']
|
|
|
|
lines[-18] += ' SBinv %7.2g 1/m |' % mt['SBinv_Bsim4']
|
|
|
|
lines[-17] += ' alpha %7.2g m |' % mt['alpha' ]
|
|
|
|
lines[-16] += ' alphaInv %7.2g 1/m |' % mt['alphaInv' ]
|
|
|
|
lines[-15] += ' LODeffect %7.2g 1/m |' % mt['alphaInv' ]
|
|
|
|
lines[-14] += '-----------------------+'
|
|
|
|
lines[-13] += ' Crolles |'
|
|
|
|
lines[-12] += ' SAeff %7.2g m |' % mt['SAeff_Crolles']
|
|
|
|
lines[-11] += ' SBeff %7.2g m |' % mt['SBeff_Crolles']
|
|
|
|
lines[-10] += ' SAinv %7.2g 1/m |' % mt['SBinv_Crolles']
|
|
|
|
lines[- 9] += ' SBinv %7.2g 1/m |' % mt['SBinv_Crolles']
|
|
|
|
lines[- 8] += ' po2actEff %7.2g m |' % mt['po2actEff_Crolles']
|
|
|
|
lines[- 7] += '-----------------------+'
|
|
|
|
lines[- 6] += ' Layout Parasitics |'
|
|
|
|
lines[- 5] += ' ASeff %11.2g m2 |' % mt['ASeff']
|
|
|
|
lines[- 4] += ' PSeff %11.2g m |' % mt['PSeff']
|
|
|
|
lines[- 3] += ' ADeff %11.2g m2 |' % mt['ADeff']
|
|
|
|
lines[- 2] += ' PDeff %11.2g m |' % mt['PDeff']
|
|
|
|
lines[- 1] += '-----------------------+'
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def toBoxDatasheet ( self, lines, box, comment, flags ):
|
|
|
|
if flags & Left:
|
|
|
|
for i in range(3): lines.append( '|' )
|
|
|
|
|
|
|
|
lines[-3] += '{0:^23s}|'.format( comment )
|
|
|
|
lines[-2] += ' bl %8s %8s |' % (DbU.getValueString(box.getXMin()), DbU.getValueString(box.getYMin()))
|
|
|
|
lines[-1] += ' tr %8s %8s |' % (DbU.getValueString(box.getXMax()), DbU.getValueString(box.getYMax()))
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def toDatasheet ( self ):
|
|
|
|
lines = []
|
|
|
|
# Matrix element [0,0]
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
lines.append( '| Device Datas |' )
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
lines.append( '| L %14.2g m |' % self.matrix[0][0]['L'] )
|
|
|
|
lines.append( '| wF %14.2g m |' % self.matrix[0][0]['W'] )
|
|
|
|
lines.append( '| M %14.2g |' % self.matrix[0][0]['M'] )
|
|
|
|
lines.append( '| DMCG %14.2g m |' % self.matrix[0][0]['DMCG'] )
|
|
|
|
lines.append( '| DMCI %14.2g m |' % self.matrix[0][0]['DMCI'] )
|
|
|
|
lines.append( '| DGG %14.2g m |' % self.matrix[0][0]['DGG'] )
|
|
|
|
lines.append( '| DGI %14.2g m |' % self.matrix[0][0]['DGI'] )
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
self.toBoxDatasheet( lines, self.matrix[0][0]['box'], 'Bounding Box', Left )
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
self.toBoxDatasheet( lines, self.matrix[0][0]['globalActiveBox'], 'Active Box', Left )
|
|
|
|
lines[-3] = lines[-3][0:-1] + '+'
|
|
|
|
for i in range(len(lines),28):
|
|
|
|
lines.append( '| ' )
|
|
|
|
if i in [0, 2, 15, 22, 28]: lines[-1] += '+'
|
|
|
|
else: lines[-1] += '|'
|
|
|
|
lines.append( '+-----------------------+' )
|
|
|
|
|
|
|
|
# Row 0: Meta-Transistors aggregated parameters.
|
|
|
|
mts = self.matrix[0]
|
|
|
|
for iMT in range(1,len(mts)):
|
|
|
|
self.toMtDatasheet( lines, mts[iMT], ' (meta)', Top )
|
|
|
|
|
|
|
|
# Rows 1+: One stack and its's meta-transistors.
|
|
|
|
for iStack in range(1,len(self.matrix)):
|
|
|
|
self.stackHeader( lines, iStack )
|
|
|
|
for iMT in range(1,len(self.matrix[iStack])):
|
|
|
|
self.toMtDatasheet( lines, self.matrix[iStack][iMT], '', NoFlags )
|
|
|
|
|
|
|
|
return lines
|
|
|
|
|
|
|
|
|
|
|
|
def __str__ ( self ):
|
|
|
|
s = ''
|
|
|
|
for line in self.toDatasheet(): s += line + '\n'
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
def trace( self ):
|
|
|
|
for line in self.toDatasheet():
|
|
|
|
trace( 100, '\t%s\n' % line )
|
|
|
|
return
|