2020-10-25 05:42:25 -05:00
|
|
|
# -*- mode:Python -*-
|
|
|
|
#
|
|
|
|
# This file is part of the Coriolis Software.
|
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
|
|
|
# Copyright (c) Sorbonne Université 2020-2021, All Rights Reserved
|
2020-10-25 05:42:25 -05:00
|
|
|
#
|
|
|
|
# +-----------------------------------------------------------------+
|
|
|
|
# | C O R I O L I S |
|
|
|
|
# | Alliance / Hurricane Interface |
|
|
|
|
# | |
|
|
|
|
# | Author : Jean-Paul Chaput |
|
|
|
|
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
|
|
# | =============================================================== |
|
|
|
|
# | Python : "./crlcore/helpers/technology.py" |
|
|
|
|
# +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
"""
|
|
|
|
Some helpers to create or load a technology and it's libraries.
|
|
|
|
"""
|
|
|
|
|
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, Library, BasicLayer, Layer, ViaLayer
|
2020-10-25 05:42:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
__all__ = [ 'safeGetLibrary', 'createBL', 'setEnclosures' ]
|
|
|
|
|
|
|
|
|
|
|
|
def safeGetLibrary ( frameworkName, libName ):
|
|
|
|
"""
|
|
|
|
Return the library named ``libName`` if it already exists,
|
|
|
|
or create it if needed. To avoid potential collision, design
|
|
|
|
kits libraries should not be created directly under the DataBase
|
|
|
|
root library but be grouped under a common technology library,
|
|
|
|
in this case ``CM018``.
|
|
|
|
"""
|
|
|
|
db = DataBase.getDB()
|
|
|
|
tech = db.getTechnology()
|
|
|
|
frameLib = db.getRootLibrary().getLibrary( frameworkName )
|
|
|
|
if frameLib is None:
|
|
|
|
frameLib = Library.create( db.getRootLibrary(), frameworkName )
|
|
|
|
lib = frameLib.getLibrary( libName )
|
|
|
|
if lib is None:
|
|
|
|
lib = Library.create( frameLib, libName )
|
|
|
|
return lib
|
|
|
|
|
|
|
|
|
2020-11-26 10:17:36 -06:00
|
|
|
def createBL ( tech, layerName, material, size=None, spacing=None, gds2Layer=None, gds2DataType=0, area=None ):
|
2020-10-25 05:42:25 -05:00
|
|
|
"""
|
|
|
|
Create a new BasicLayer. Parameters ``tech``, ``layerName`` and ``material``
|
|
|
|
are mandatory.
|
|
|
|
|
|
|
|
:param tech: The technology the basic layer will be part of.
|
|
|
|
:param layerName: The name of the layer.
|
|
|
|
:param material: The kind of layer, see BasicLayer.Material.
|
|
|
|
:param size: The minimal size (i.e. width).
|
|
|
|
:param spacing: The minimal distance, edge to edge between two wires.
|
|
|
|
:param gds2layer: The GDSII layer number (for the GDSII driver).
|
|
|
|
:param gds2DataType: The GDSII DataType (i.e purpose).
|
2020-11-26 10:17:36 -06:00
|
|
|
:param area: The minimum area (in um2)
|
2020-10-25 05:42:25 -05:00
|
|
|
"""
|
|
|
|
layer = BasicLayer.create( tech, layerName, BasicLayer.Material(material) )
|
|
|
|
if size is not None:
|
|
|
|
layer.setMinimalSize( size )
|
|
|
|
if spacing is not None:
|
|
|
|
layer.setMinimalSpacing( spacing )
|
|
|
|
if gds2Layer is not None:
|
|
|
|
layer.setGds2Layer ( gds2Layer )
|
|
|
|
layer.setGds2Datatype( gds2DataType )
|
2020-11-26 10:17:36 -06:00
|
|
|
if area is not None:
|
|
|
|
layer.setMinimalArea( area )
|
2020-10-25 05:42:25 -05:00
|
|
|
return layer
|
|
|
|
|
|
|
|
|
2020-11-25 14:52:05 -06:00
|
|
|
def createVia ( tech, viaName, botName, cutName, topName, size=None ):
|
|
|
|
"""
|
|
|
|
Create a new ViaLayer. Parameters ``tech``, ``viaName``, ``botName``,
|
|
|
|
``cutName`` and ``topName`` are mandatory.
|
|
|
|
|
|
|
|
:param tech: The technology the basic layer will be part of.
|
|
|
|
:param viaName: The name of the newly defined VIA layer.
|
|
|
|
:param botName: The name of the *bottom* metal layer.
|
|
|
|
:param cutName: The name of the *cut* (aka, via hole) layer.
|
|
|
|
:param topName: The name of the *top* metal layer.
|
|
|
|
:param size: The minimal side size of the square *cut* layer.
|
|
|
|
"""
|
|
|
|
layer = ViaLayer.create( tech
|
|
|
|
, viaName
|
|
|
|
, tech.getLayer(botName)
|
|
|
|
, tech.getLayer(cutName)
|
|
|
|
, tech.getLayer(topName) )
|
|
|
|
if size is not None:
|
|
|
|
layer.setMinimalSize( size )
|
|
|
|
return layer
|
|
|
|
|
|
|
|
|
2020-10-25 05:42:25 -05:00
|
|
|
def setEnclosures ( layer, subLayer, enclosures ):
|
|
|
|
"""
|
|
|
|
Set horizontal & vertical enclosure for a given ``subLayer`` in a
|
|
|
|
composite ``layer`` (typically a ViaLayer). If ``enclosures`` is a
|
|
|
|
number, both H/V will be set to that same value. If it is a tuple
|
|
|
|
(a pair), then the first value is horizontal and the seconf is
|
|
|
|
vertical.
|
|
|
|
"""
|
|
|
|
if isinstance(enclosures,tuple):
|
|
|
|
henclosure = enclosures[0]
|
|
|
|
venclosure = enclosures[1]
|
|
|
|
else:
|
|
|
|
henclosure = enclosures
|
|
|
|
venclosure = enclosures
|
|
|
|
layer.setEnclosure( subLayer, henclosure, Layer.EnclosureH )
|
|
|
|
layer.setEnclosure( subLayer, venclosure, Layer.EnclosureV )
|
|
|
|
return
|