coriolis/oroshi/python/paramsmatrix.py

249 lines
8.8 KiB
Python
Raw Normal View History

# -*- 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
# 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 ):
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'
return
def setGlobalResistorParams ( self, boundingBox ):
self.matrix[0][0]['box' ] = boundingBox
self.matrix[0][0]['family' ] = 'Resistor'
return
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.' ))
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.' ))
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.' ))
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) ))
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) ))
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