333 lines
11 KiB
ReStructuredText
333 lines
11 KiB
ReStructuredText
.. -*- Mode: rst -*-
|
|
|
|
|
|
1. Introduction
|
|
===============
|
|
|
|
This tutorial is aimed at two goals :
|
|
|
|
* Presenting how to use Python scripts to control |Coriolis|.
|
|
|
|
* Make a basic introduction about the |Hurricane| database and its
|
|
concepts.
|
|
|
|
While this tutorial is aimed at presenting the |Hurricane| database,
|
|
do not feel limited by it. You can use |Hurricane| objects as attributes
|
|
of |Python| objects or use |Python| containers to store them.
|
|
The only limitation is that you may not use |Hurricane| classes as base
|
|
classes in |Python|.
|
|
|
|
All the example scripts given in this tutorial con be found under: ::
|
|
|
|
<CORIOLIS_INSTALL>/share/doc/coriolis2/examples/scripts/
|
|
|
|
Provided scripts:
|
|
|
|
======================= ==============================================================
|
|
**Script** **Feature**
|
|
======================= ==============================================================
|
|
:cb:`coriolisLogo.py` Draw a layout of the |Coriolis| logo
|
|
:cb:`diagonals.py` Test the :cb:`Hurricane::Diagonal` class
|
|
:cb:`polygons.py` Test the :cb:`Hurricane::Polygon` class
|
|
:cb:`rectilinear.py` Test the :cb:`Hurricane::rectilinear` class
|
|
:cb:`invertor.py` Procedural build of the layout of an invertor standard cell
|
|
:cb:`fulladder.py` Procedural build of a small netlist along with it's manual
|
|
placement and the routing of one net (:cb:`"a"`)
|
|
:cb:`toolengines.py` Build the netlist (only) of the full adder then call the
|
|
place and route engines
|
|
======================= ==============================================================
|
|
|
|
|
|
1.1 Terminology
|
|
~~~~~~~~~~~~~~~
|
|
|
|
In the |Hurricane| database, the *logical* (netlist) and *physical* (layout)
|
|
views are fused. As the main goal of the database is to support place & route
|
|
tools, we usually starts with a *pure* netlist which is progessively enriched
|
|
to become a layout. Cell, in particular, is able to be in any intermediate
|
|
state. Many of our objects have self-explanatory names, but some
|
|
don't. Thus we summarize below the more important ones:
|
|
|
|
=============== =====================================================
|
|
**Class** **Meaning**
|
|
=============== =====================================================
|
|
Cell_ The model. A Cell does not have terminals, only nets
|
|
flagged as *external*
|
|
Instance_ An instance of a model
|
|
Net_ A grouping of electrically connected components
|
|
Plug_ A terminal of an instance
|
|
RoutingPad_ A physical connexion (*pin*) to an instance
|
|
=============== =====================================================
|
|
|
|
|
|
1.2 Generalities
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
The C++ API has been exported in Python as closely as possible. Meaning
|
|
that, save for a slight change in syntax, any code written in |Python|
|
|
could be easily transformed into C++ code. There is no specific documentation
|
|
written for the |Python| interface, you may directly use the C++ one.
|
|
|
|
Mostly:
|
|
|
|
* C++ namespaces are exported as |Python| modules.
|
|
* The *scope resolution operator* :fboxtt:`::` converts into :fboxtt:`.`.
|
|
* C++ blocks (between braces :fboxtt:`{}`) are replaced by indentations.
|
|
* In C++, names are managed through a dedicated ``Name`` class.
|
|
It has not been exported to the |Python| interface, you only have
|
|
to use ``string``.
|
|
* Coordinates are expressed in ``DbU`` which are ``long`` with a special
|
|
semantic (see ??).
|
|
* All |Hurricane| objects implements the |Python| ``__str__()`` function,
|
|
they print the result of the C++ method ``::getString()``.
|
|
|
|
In ``hurricane/Net.h`` header we have:
|
|
|
|
.. code-block:: c++
|
|
|
|
namespace Hurricane {
|
|
|
|
class Net : public Entity {
|
|
public:
|
|
class Direction {
|
|
public: enum Code { DirIn = 0x0001
|
|
, DirOut = 0x0002
|
|
, DirUndefined = 0x0000
|
|
, ConnTristate = 0x0100
|
|
, ConnWiredOr = 0x0200
|
|
, UNDEFINED = DirUndefined
|
|
, IN = DirIn
|
|
, OUT = DirOut
|
|
, INOUT = DirIn | DirOut
|
|
, TRISTATE = DirOut | ConnTristate
|
|
, TRANSCV = DirIn | DirOut | ConnTristate
|
|
, WOR_OUT = DirOut | ConnWiredOr
|
|
, WOR_INOUT = DirIn | DirOut | ConnWiredOr
|
|
, DirMask = DirIn | DirOut | DirUndefined
|
|
};
|
|
// [The rest of Class Direction]
|
|
};
|
|
public:
|
|
static Net* create ( Cell* , const Name& );
|
|
bool isGlobal ();
|
|
bool isExternal ();
|
|
const Direction& getDirection ();
|
|
void setName ( Name );
|
|
void setGlobal ( bool );
|
|
void setExternal ( bool );
|
|
void setDirection ( const Direction& );
|
|
// [The rest of Class Net]
|
|
};
|
|
|
|
}
|
|
|
|
|
|
So we can use it the following way in C++:
|
|
|
|
.. code-block:: c++
|
|
|
|
#include "hurricane/Net.h"
|
|
|
|
using namespace Hurricane;
|
|
|
|
void addNetToCell ( Cell* cell )
|
|
{
|
|
Net* net = Net::create( cell, "new_net" );
|
|
net->setGlobal ( false );
|
|
net->setExternal ( true );
|
|
net->setDirection( Net.Direction.IN );
|
|
cout << "Created " << net << endl;
|
|
return net;
|
|
}
|
|
|
|
|
|
The equivalent |Python| code will be:
|
|
|
|
.. code-block:: Python
|
|
|
|
from Hurricane import Net
|
|
|
|
def addNetToCell ( cell ):
|
|
net = Net.create( cell, "new_net" )
|
|
net.setGlobal ( False )
|
|
net.setExternal( True )
|
|
net.setDirection( Net.Direction.IN )
|
|
print( "Created", net )
|
|
return net
|
|
|
|
|
|
1.3 Various Kinds of Constructors
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Regarding the memory allocation, the |Hurricane| database contains two kind of objects.
|
|
|
|
#. Objects that are linked to others in the database and whose creation or deletion
|
|
implies coherency operations. This is the case for Net_ or Horizontal_.
|
|
They must be created using the static :cb:`create()` method of their class
|
|
and destroyed with their :cb:`destroy()` method.
|
|
|
|
And, of course, they cannot be copied (the copy constructor has been disabled).
|
|
|
|
.. code-block:: Python
|
|
|
|
net = Net.create( cell, 'tmp' ) # Call the static Net.create() function.
|
|
# Work with this net.
|
|
# ...
|
|
net.destroy() # Call the dynamic destroy() method.
|
|
|
|
#. Objects that are *standalone*, like Point_ or Box_, uses the usual construction
|
|
methods. They also use the |Python| garbage collector mechanism and do not need
|
|
to be explicitly deleted.
|
|
|
|
.. code-block:: Python
|
|
|
|
from Hurricane import DbU, Box
|
|
|
|
def myfunc():
|
|
bb = Box( DbU.fromLambda( 0.0)
|
|
, DbU.fromLambda( 0.0)
|
|
, DbU.fromLambda(15.0)
|
|
, DbU.fromLambda(50.0) )
|
|
return # bb will be freed at that point.
|
|
|
|
|
|
1.4 Collections and Iterators
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Hurricane Collection_ behave like containers under |Python| and provide
|
|
support for the :cb:`iterator` protocol.
|
|
|
|
.. code-block:: Python
|
|
|
|
from Hurricane import Net, Horizontal
|
|
|
|
def delAllHorizontals ( net ):
|
|
horizontals = []
|
|
for component in net.getComponents():
|
|
if isinstance(component,Horizontal):
|
|
horizontals.append( component )
|
|
# Now we can remove the Horizontals.
|
|
for horizontal in horizontals:
|
|
horizontal.destroy()
|
|
|
|
.. note:: **Never remove an element from a Collection_ while iterating over it**.
|
|
You must save the to be removed elements in an auxiliary container
|
|
then remove them, like shown in the example above
|
|
|
|
|
|
1.5 Dynamically decorating data-base objects
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
When writing algorithms directly in Python, it may come in handy to be
|
|
able to add attributes over the Hurricane data-base objects. As C++
|
|
objects exposed to the Python realm cannot natively do so (it would
|
|
means to be able to modify a C++ aobject attributes *at runtime*),
|
|
we add a special Property tasked with handling the extra Python
|
|
attributes. The syntax has been made as simple as possible.
|
|
|
|
.. code-block:: python
|
|
|
|
from Hurricane import PythonAttributes
|
|
|
|
class MyAttribute ( object ):
|
|
count = 0
|
|
|
|
def __init__ ( self ):
|
|
self.value = MyAttribute.count
|
|
print( '{} has been created'.format(self) )
|
|
MyAttribute.count += 1
|
|
|
|
def __del__ ( self ):
|
|
print( '{} has been deleted'.format(self) )
|
|
|
|
def __str__ ( self ):
|
|
return '<MyAttribute {}>'.format(self.value)
|
|
|
|
|
|
def demoAttributes ( cell ):
|
|
PythonAttributes.enable( cell )
|
|
cell.myAttribute0 = MyAttribute()
|
|
cell.myAttribute1 = MyAttribute()
|
|
print( 'cell.myAttribute0 =', cell.myAttribute0 )
|
|
del cell.myAttribute0
|
|
PythonAttributes.disable( cell )
|
|
|
|
|
|
Detailing the life cycle of Python attributes on a DBo_:
|
|
|
|
1. Enabling the addition of Python attribute on a DBo_:
|
|
|
|
.. code-block:: python
|
|
|
|
PythonAttributes.enable( cell )
|
|
|
|
2. Adding/removing properties on the DBo_:
|
|
|
|
.. code-block:: python
|
|
|
|
cell.myAttribute0 = MyAttribute()
|
|
cell.myAttribute1 = MyAttribute()
|
|
print( 'cell.myAttribute0 =', cell.myAttribute0 )
|
|
del cell.myAttribute0
|
|
|
|
3. And finally disabling the use of Python attributes on the DBo.
|
|
Any still attached Python attributes will be released.
|
|
|
|
.. code-block:: python
|
|
|
|
PythonAttributes.disable( cell )
|
|
|
|
.. note::
|
|
|
|
When the attributes of a DBo_ are released it does not automatically
|
|
imply that they are removed. Their reference count is decreased, and
|
|
if they are only referenced here, they will be deleted. But if other
|
|
variables still holds reference onto them, they will stay allocateds.
|
|
|
|
4. There is no need to keep track of all the DBo_ that have Python
|
|
attributes to disable them. One can directly call:
|
|
|
|
.. code-block:: python
|
|
|
|
PythonAttributes.disableAll()
|
|
|
|
|
|
1.6 Adapting C++ : Overlay
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Sometimes, the use of a wrapped C++ feature would be counter intuitive regarding
|
|
the |Python| feature. For those cases the :cb:`overlay` module provide an
|
|
adaptation of the C++ API for a more *Python-like* code. A typical example is
|
|
with the UpdateSession_ mechanism.
|
|
|
|
Using directly the C++ wrapper, we would write a code like this:
|
|
|
|
.. code-block:: python
|
|
|
|
from Hurricane import UpdateSession, Net, Vertical
|
|
from helpers import l
|
|
|
|
def editCell ( cell ):
|
|
UpdateSession.open()
|
|
net = Net.create( cell, "nwell" )
|
|
Vertical.create( net, nwell, l(7.5), l(15.0), l(27.0), l(51.0) )
|
|
# Continued cell's layout building.
|
|
# ...
|
|
UpdateSession.close()
|
|
|
|
|
|
But, using the :cb:`overlay` we got the more *pythonic* code:
|
|
|
|
.. code-block:: python
|
|
|
|
from Hurricane import Net, Vertical
|
|
from helpers import l
|
|
from helpers.overlay import UpdateSession
|
|
|
|
def editCell ( cell ):
|
|
with UpdateSession():
|
|
net = Net.create( cell, "nwell" )
|
|
Vertical.create( net, nwell, l(7.5), l(15.0), l(27.0), l(51.0) )
|
|
# Continued cell's layout building.
|
|
# ...
|