coriolis/documentation/content/pages/users-guide/ScriptsPlugins.rst

330 lines
16 KiB
ReStructuredText
Raw Normal View History

.. -*- Mode: rst -*-
.. URLs that changes between the various backends.
.. _Stratus Documentation: file:///usr/share/doc/coriolis2/en/html/stratus/index.html
.. .. |ChipStructure-1| image:: ./images/chip-structure-1.png
.. :alt: Chip Top Structure
.. :align: middle
.. :width: 90%
.. _Python Interface to Coriolis:
|newpage|
Python Interface for |Hurricane| / |Coriolis|
=============================================
The (almost) complete interface of |Hurricane| is exported as a |Python| module
and some part of the other components of |Coriolis| (each one in a separate
module). The interface has been made to mirror as closely as possible the
C++ one, so the C++ doxygen documentation could be used to write code with
either languages.
`Summary of the C++ Documentation <file:../../../index.html>`_
A script could be run directly in text mode from the command line or through
the graphical interface (see `Python Scripts in Cgt`).
Aside for this requirement, the python script can contain anything valid
in |Python|, so don't hesitate to use any package or extention.
Small example of Python/Stratus script:
.. code-block:: python
from Hurricane import *
from Stratus import *
def doSomething ():
# ...
return
def scriptMain ( **kw ):
editor = None
if kw.has_key('editor') and kw['editor']:
editor = kw['editor']
stratus.setEditor( editor )
doSomething()
return
if __name__ == "__main__" :
kw = {}
success = scriptMain( **kw )
shellSuccess = 0
if not success: shellSuccess = 1
sys.exit( shellSuccess )
scriptMain ()
This typical script can be executed in two ways:
Migrating the initialisation system to be completely Python-like. * New: In bootstrap/coriolisEnv.py, add the "etc" directory to the PYTHONPATH as initialization are now Python modules. * New: In Hurricane/analogic, first groundwork for the integration of PIP/MIM/MOM multi-capacitors. Add C++ and Python interface for the allocation matrix and the list of capacities values. * Change: In Hurricane::RegularLayer, add a layer parameter to the constructor so the association between the RegularLayer and it's BasicLayer can readily be done. * Change: In Hurricane::Layer, add a new getCut() accessor to get the cut layer in ViaLayer. * Change: In Hurricane::DataBase::get(), the Python wrapper should no longer consider an error if the data-base has not been created yet. Just return None. * Bug: In Isobar::PyLayer::getEnclosure() wrapper, if the overall enclosure is requested, pass the right parameter to the C++ function. * Change: In AllianceFramework, make public _bindLibraries() and export it to the Python interface. * Change: In AllianceFramework::create(), do not longer call bindLibraries(). This now must be done explicitely and afterwards. * Change: In AllianceFramework::createLibrary() and Environement::addSYSTEM_LIBRARY(), minor bug corrections that I don't recall. * Change: In SearchPath::prepend(), set the selected index to zero and return it. * Change: In CRL::System CTOR, add "etc" to the PYTHONPATH as the configuration files are now organized as Python modules. * New: In PyCRL, export the CRL::System singleton, it's creation is no longer triggered by the one of AllianceFramework. * New: In CRL/etc/, convert most of the configuration files into the Python module format. For now, keep the old ".conf", but that are no longer used. For the real technologies, we cannot keep the directory name as "180" or "45" as it not allowed by Python syntax, so we create "node180" or "node45" instead. Most of the helpers and coriolisInit.py are no longer used now. To be removed in future commits after being sure that everything works... * Bug: In AutoSegment::makeDogleg(AutoContact*), the layer of the contacts where badly computed when one end of the original segment was attached to a non-preferred direction segment (mostly on terminal contacts). Now use the new AutoContact::updateLayer() method. * Bug: In Dijkstra::load(), limit symetric search area only if the net is a symmetric one ! * Change: In Katana/python/katanaInit.py, comply with the new initialisation scheme. * Change: In Unicorn/cgt.py, comply to the new inititalization scheme. * Change: In cumulus various Python scripts remove the call to helpers.staticInitialization() as they are not needed now (we run in only *one* interpreter, so we correctly share all init). In plugins/__init__.py, read the new NDA directory variable. * Bug: In cumulus/plugins/Chip.doCoronafloorplan(), self.railsNb was not correctly managed when there was no clock. * Change: In cumulus/plugins/Configuration.coronaContactArray(), compute the viaPitch from the technology instead of the hard-coded 4.0 lambdas. In Configuration.loadConfiguration(), read the "ioring.py" from the new user's settings module. * Bug: In stratus.dpgen_ADSB2F, gives coordinates translated into DbU to the XY functions. In st_model.Save(), use the VstUseConcat flag to get correct VST files. In st_net.hur_net(), when a net is POWER/GROUND or CLOCK also make it global. * Change: In Oroshi/python/WIP_Transistor.py, encapsulate the generator inside a try/except block to get prettier error (and stop at the first).
2019-10-28 12:09:14 -05:00
#. Run directly as a |Python| script, thanks to the
Migrating the initialisation system to be completely Python-like. * New: In bootstrap/coriolisEnv.py, add the "etc" directory to the PYTHONPATH as initialization are now Python modules. * New: In Hurricane/analogic, first groundwork for the integration of PIP/MIM/MOM multi-capacitors. Add C++ and Python interface for the allocation matrix and the list of capacities values. * Change: In Hurricane::RegularLayer, add a layer parameter to the constructor so the association between the RegularLayer and it's BasicLayer can readily be done. * Change: In Hurricane::Layer, add a new getCut() accessor to get the cut layer in ViaLayer. * Change: In Hurricane::DataBase::get(), the Python wrapper should no longer consider an error if the data-base has not been created yet. Just return None. * Bug: In Isobar::PyLayer::getEnclosure() wrapper, if the overall enclosure is requested, pass the right parameter to the C++ function. * Change: In AllianceFramework, make public _bindLibraries() and export it to the Python interface. * Change: In AllianceFramework::create(), do not longer call bindLibraries(). This now must be done explicitely and afterwards. * Change: In AllianceFramework::createLibrary() and Environement::addSYSTEM_LIBRARY(), minor bug corrections that I don't recall. * Change: In SearchPath::prepend(), set the selected index to zero and return it. * Change: In CRL::System CTOR, add "etc" to the PYTHONPATH as the configuration files are now organized as Python modules. * New: In PyCRL, export the CRL::System singleton, it's creation is no longer triggered by the one of AllianceFramework. * New: In CRL/etc/, convert most of the configuration files into the Python module format. For now, keep the old ".conf", but that are no longer used. For the real technologies, we cannot keep the directory name as "180" or "45" as it not allowed by Python syntax, so we create "node180" or "node45" instead. Most of the helpers and coriolisInit.py are no longer used now. To be removed in future commits after being sure that everything works... * Bug: In AutoSegment::makeDogleg(AutoContact*), the layer of the contacts where badly computed when one end of the original segment was attached to a non-preferred direction segment (mostly on terminal contacts). Now use the new AutoContact::updateLayer() method. * Bug: In Dijkstra::load(), limit symetric search area only if the net is a symmetric one ! * Change: In Katana/python/katanaInit.py, comply with the new initialisation scheme. * Change: In Unicorn/cgt.py, comply to the new inititalization scheme. * Change: In cumulus various Python scripts remove the call to helpers.staticInitialization() as they are not needed now (we run in only *one* interpreter, so we correctly share all init). In plugins/__init__.py, read the new NDA directory variable. * Bug: In cumulus/plugins/Chip.doCoronafloorplan(), self.railsNb was not correctly managed when there was no clock. * Change: In cumulus/plugins/Configuration.coronaContactArray(), compute the viaPitch from the technology instead of the hard-coded 4.0 lambdas. In Configuration.loadConfiguration(), read the "ioring.py" from the new user's settings module. * Bug: In stratus.dpgen_ADSB2F, gives coordinates translated into DbU to the XY functions. In st_model.Save(), use the VstUseConcat flag to get correct VST files. In st_net.hur_net(), when a net is POWER/GROUND or CLOCK also make it global. * Change: In Oroshi/python/WIP_Transistor.py, encapsulate the generator inside a try/except block to get prettier error (and stop at the first).
2019-10-28 12:09:14 -05:00
.. code-block:: python
if __name__ == "__main__" :
part (this is standart |Python|). It is a simple adapter that will
calls :cb:`scriptMain()`.
#. Through |cgt|, either in text or graphical mode. In that case, the
:cb:`scriptMain()` is directly called trough a sub-interpreter.
The arguments of the script are passed through the ``**kw`` dictionnary.
+----------------------+-----------------------------------------------+
| \*\*kw Dictionnary |
+----------------------+-----------------------------------------------+
| Parameter Key/Name | Contents type |
+======================+===============================================+
| ``'cell'`` | A Hurricane cell on which to work. Depending |
| | on the context, it may be ``None``. |
| | For example, when run from |cgt|, it the cell |
| | currently loaded in the viewer, if any. |
+----------------------+-----------------------------------------------+
| ``'editor'`` | The viewer from which the script is run, when |
| | lauched through |cgt|. |
+----------------------+-----------------------------------------------+
Plugins
~~~~~~~
Plugins are |Python| scripts specially crafted to integrate with |cgt|.
Their entry point is a :cb:`scriptMain()` method as described in
`Python Interface to Coriolis`_. They can be called by user scripts
through this method.
Chip Placement
--------------
Automatically perform the placement of a complete chip. This plugin, as well
as the other P&R tools expect a specific top-level hierarchy for the design.
The top-level hierarchy must contains the instances of all the I/O pads and
**exactly one** instance named ``corona`` of an eponym cell ``corona``.
The ``corona`` cell in turn containing the instance of the chip's core model.
The intermediate ``corona`` hierarchical level has been introduced to handle
the possible discoupling between real I/O pads supplied by a foundry and a
symbolic core. So the *chip* level contains only real layout and the corona
and below only symbolic layer.
.. note:: This do not prevent having a design either fully symbolic (pads and core)
or fully real.
.. note:: The ``corona`` also avoid the router to actually have to manage directly
the pads which simplificate it's configuration and accessorily avoid
to have the pads stuffed with blockages.
|bcenter| |ChipStructure-1| |ecenter|
The designer must provide a configuration file that defines the rules for the
placement of the top-level hierarchy (that is, the pads and the core).
This file must be named after the chip's name, by appending ``_ioring.py``
(obviously, it is a |Python| file). For instance if the chip netlist file
is called ``amd2901.vst``, then the configuration file must be named
``amd2901_ioring.vst``.
Example of chip placement configuration file (for ``AM2901``):
.. code-block:: python
from helpers import l, u, n
chip = \
{ 'pads.ioPadGauge' : 'pxlib'
, 'pads.south' : [ 'p_a3' , 'p_a2' , 'p_a1' , 'p_r0'
, 'p_vddick0', 'p_vssick0', 'p_a0' , 'p_i6'
, 'p_i8' , 'p_i7' , 'p_r3' ]
, 'pads.east' : [ 'p_zero' , 'p_i0' , 'p_i1' , 'p_i2'
, 'p_vddeck0', 'p_vsseck0', 'p_q3' , 'p_b0'
, 'p_b1' , 'p_b2' , 'p_b3' ]
, 'pads.north' : [ 'p_noe' , 'p_y3' , 'p_y2' , 'p_y1'
, 'p_y0' , 'p_vddeck1', 'p_vsseck1', 'p_np'
, 'p_ovr' , 'p_cout' , 'p_ng' ]
, 'pads.west' : [ 'p_cin' , 'p_i4' , 'p_i5' , 'p_i3'
, 'p_ck' , 'p_d0' , 'p_d1' , 'p_d2'
, 'p_d3' , 'p_q0' , 'p_f3' ]
, 'core.size' : ( l(1500), l(1500) )
, 'chip.size' : ( l(3000), l(3000) )
, 'chip.clockTree' : True
}
The file must contain *one dictionnary* named ``chip``.
+----------------------+-------------------------------------------------------+
| Chip Dictionnary |
+----------------------+-------------------------------------------------------+
| Parameter Key/Name | Value/Contents type |
+======================+=======================================================+
| ``'pad.ioPadGauge'`` | The routing gauge to use for the pad. Must be given |
| | as it differs from the one used to route standard |
| | inside the core |
+----------------------+-------------------------------------------------------+
| ``'pad.south'`` | Ordered list (left to right) of pad instances names |
| | to put on the south side of the chip |
+----------------------+-------------------------------------------------------+
| ``'pad.east'`` | Ordered list (down to up) of pad instances names |
| | to put on the east side of the chip |
+----------------------+-------------------------------------------------------+
| ``'pad.north'`` | Ordered list (left to right) of pad instances names |
| | to put on the north side of the chip |
+----------------------+-------------------------------------------------------+
| ``'pad.west'`` | Ordered list (down to up) of pad instances names |
| | to put on the west side of the chip |
+----------------------+-------------------------------------------------------+
| ``'core.size'`` | The size of the core (to be used by the placer) |
+----------------------+-------------------------------------------------------+
| ``'chip.size'`` | The size of the whole chip. The sides must be great |
| | enough to accomodate all the pads |
+----------------------+-------------------------------------------------------+
| ``'chip.clockTree'`` | Whether to generate a clock tree or not. This calls |
| | the ClockTree plugin |
+----------------------+-------------------------------------------------------+
Configuration parameters, defaults are defined in ``etc/coriolis2/<STECHNO>/plugins.conf``.
+-----------------------------------+------------------+----------------------------+
| Parameter Identifier | Type | Default |
+===================================+==================+============================+
| **Chip Plugin Parameters** |
+-----------------------------------+------------------+----------------------------+
|``chip.block.rails.count`` | TypeInt | :cb:`5` |
| +------------------+----------------------------+
| | The minimum number of rails around the core |
| | block. Must be odd and suppérior to 5. |
| | One rail for the clock and at least two pairs |
| | of power/grounds |
+-----------------------------------+------------------+----------------------------+
|``chip.block.rails.hWidth`` | TypeInt | :cb:`12` |lambda| |
| +------------------+----------------------------+
| | The horizontal with of the rails |
+-----------------------------------+------------------+----------------------------+
|``chip.block.rails.vWidth`` | TypeInt | :cb:`12` |lambda| |
| +------------------+----------------------------+
| | The vertical with of the rails |
+-----------------------------------+------------------+----------------------------+
|``chip.block.rails.hSpacing`` | TypeInt | :cb:`6` |lambda| |
| +------------------+----------------------------+
| | The spacing, *edge to edge* of two adjacent |
| | horizontal rails |
+-----------------------------------+------------------+----------------------------+
|``chip.block.rails.vSpacing`` | TypeInt | :cb:`6` |lambda| |
| +------------------+----------------------------+
| | The spacing, *edge to edge* of two adjacent |
| | vertical rails |
+-----------------------------------+------------------+----------------------------+
.. note::
If no clock tree is generated, then the clock rail is *not* created.
So even if the requested number of rails ``chip.block.rails.count`` is, say 5,
only four rails (2* ``power``, 2* ``ground``) will be generateds.
Clock Tree
----------
Inserts a clock tree into a block. The clock tree uses the H strategy.
The clock net is splitted into sub-nets, one for each branch of the
tree.
* On **chip** design, the sub-nets are created in the model of the
core block (then trans-hierarchically flattened to be shown at
chip level).
* On **blocks**, the sub nets are created directly in the top block.
* The sub-nets are named according to a simple geometrical scheme.
A common prefix ``ck_htree``, then one postfix by level telling
on which quarter of plane the sub-clock is located:
#. ``_bl``: bottom left plane quarter.
#. ``_br``: bottom right plane quarter.
#. ``_tl``: top left plane quarter.
#. ``_tr``: top right plane quarter.
We can have ``ck_htree_bl``, ``ck_htree_bl_bl``, ``ch_htree_bl_tl`` and so on.
The clock tree plugin works in four steps:
#. Builds the clock tree: creates the top-block abutment box, compute the
required levels of H tree and places the clock buffers.
#. Once the clock buffers are placed, calls the placer (|etesian|) to place
the ordinary standard cells, whithout disturbing clock H-tree buffers.
#. At this point we know the exact positions of all the DFFs, so we can
connect them to the nearest H-tree leaf clock signal.
#. Leaf clock signals that are not connected to any DFFs are removed.
Netlist reorganisation:
* Obviously the top block or chip core model netlist is modified to
contain all the clock sub-nets. The interface is *not* changed.
* If the top block contains instances of other models *and* those models
contain DFFs that get re-connected to the clock sub-nets (from the
top level). Changes both the model netlist and interface to propagate
the relevant clock sub-nets to the instanciated model. The new model
with the added clock signal is renamed with a ``_cts`` suffix.
For example, the sub-block model ``ram.vst`` will become ``ram_cts.vst``.
.. note::
If you are to re-run the clock tree plugin on a netlist, be careful
to erase any previously generated ``_cts`` file (both netlist and
layout: ``rm *_cts.{ap,vst}``). And restart |cgt| to clear its
memory cache.
Configuration parameters, defaults are defined in ``etc/coriolis2/<STECHNO>/plugins.conf``.
+-----------------------------------+------------------+----------------------------+
| Parameter Identifier | Type | Default |
+===================================+==================+============================+
| **ClockTree Plugin Parameters** |
+-----------------------------------+------------------+----------------------------+
|``clockTree.minimumSide`` | TypeInt | :cb:`300` |lambda| |
| +------------------+----------------------------+
| | The minimum size below which the clock tree |
| | will stop to perform quadri-partitions |
+-----------------------------------+------------------+----------------------------+
|``clockTree.buffer`` | TypeString | :cb:`buf_x2` |
| +------------------+----------------------------+
| | The buffer model to use to drive sub-nets |
+-----------------------------------+------------------+----------------------------+
Recursive-Save (RSave)
----------------------
Performs a recursive top down save of all the models from the top cell
loaded in |cgt|. Forces a write of any non-terminal model. This plugin is used
by the clock tree plugin after the netlist clock sub-nets creation.
A Simple Example: AM2901
~~~~~~~~~~~~~~~~~~~~~~~~
To illustrate the capabilities of |Coriolis| tools and |Python| scripting, a small
example, derived from the |Alliance| :cb:`AM2901` is supplied.
This example contains only the synthetized netlists and the :cb:`doChip.py` script
which perform the whole P&R of the design.
You can generate the chip using one of the following method:
#. **Command line mode:** directly run the script:
.. code-block:: sh
dummy@lepka:AM2901> ./doChip -V --cell=amd2901
#. **Graphic mode:** launch |cgt|, load chip netlist ``amd2901`` (the top cell)
then run the |Python| script :cb:`doChip.py`.
.. note::
Between two consecutive run, be sure to erase the netlist/layout generateds:
.. code-block:: sh
dummy@lepka:AM2901> rm *_cts*.vst *.ap