Validating channel routing mode (two metals) on SNX.
* New: In Hurricane::Entity, add an id counter limit and a memory size
limit. The two limits are checked only when a new Entity object is
created. This should help avoiding massive memory links.
* New: In CRL Core, add a "crlcore.groundName" and a "crlcore.powerName"
parameter to specify the name of the ground/power signals to be
created if they are missing in a Cell. For Alliance libraries it
would be "vss" & "vdd" (default values), but for real technologies,
it is often "gnd!" & "vdd!".
The Blif parser is modificated to make use of it.
* Bug: In AnabaticEngine::unify(), set the resulting unified segment in
the center of the GCells common side. Gcells under a segment are
found by using the edge that cover the segment axis. When we have
a "bend" GCell stack and the axis is wrong, they could be ommited.
This was causing deleted segments to be not removed from some
Edges, then core dump.
* Change: In Anabatic::AutoSegment::create(), smarter choosing of the
reference contact, select the fixed or terminal one instead of
always the source one.
* New: In Anabatic::Edge::isEnding(), new function to check if a
segment going through an Edge is starting/ending in either source
or target GCell of the edge (active only when running in channel
mode).
* New: In Anabatic::Edge::add(), a segment takes part in the occupancy
only if it is not ending in either source or target (channel mode
only). The occupancy due to terminal is pre-computed in Katana.
* New: In Anabatic::Edge::ripup(), in channel mode, never ripup a
segment which is ending in either source or target (we *have* to
access this edge to connect to the terminal).
* Bug: In Anabatic::GCell::hcut() and vcut(), force the update of
the Edge which is on the side that will get splitted by the cut.
It's capacity will be reduced to it must be updated.
* Change: In Anabatic::GCell::updateGContacts() add a flag to conditionnally
update horizontals or verticals only. We may require only a partial
update when resizing the GCell in only one direction.
This, again, related to the fact that we compute the GCells under
a segment thanks to it's axis position, so we need to be very careful
when modificating axis.
* Change: In Katana::Block::resizeChannels(), only update GContact vertical
position. Do not disturb X positions of segments.
* Bug: In Katana::GlobalRoute::DigitalDistance, in channel mode, some
Edges can have a zero capacity, but still be reachable if the net has
a terminal in either source or target. Look for this case and return
a distance of zero instead of "unreachable". This was causing the
global routing not to complete in channel mode.
For computing the edge distance, makes the vertical edges much more
long (10 times) than the horizontal ones as the vertical capacity is
very limited. Hard coded for now, should make it a parameter in the
future.
* Change: In KatanaEngine::annotateGlobalGraph(), decrease the capacity
of edges with reserveCapacity for each terminal inside a GCell.
Both north and south edges are decreased as we a terminal will
block both north and south edges.
As a counterpart, the Edge capacity is not decreased when the
global router connect to a terminal.
* Change: In Katana::RoutingEvent::revalidate(), when in repair stage,
do not expand the slack for horizontal segments in channel mode.
So they may not overlap the standard cell row.
* Bug: In Stratus documentation, do not use the french option in babel,
the documentation is in english!
* New: In Documentation, added Hurricane/Python tutorial, part for drawing
layout.
2018-03-16 10:20:04 -05:00
|
|
|
.. -*- Mode: rst -*-
|
|
|
|
.. include:: ../etc/definitions.rst
|
|
|
|
.. include:: ./definitions.rst
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-18 17:28:49 -05:00
|
|
|
3. Making a Standard Cell -- Layout
|
|
|
|
===================================
|
|
|
|
|
|
|
|
In this part, we well show how to create and save a terminal Cell_,
|
|
|
|
that is, a cell without instances (the end point of a hierarchical
|
|
|
|
design). To illustrate the case we will draw the layout of a
|
|
|
|
standard cell.
|
|
|
|
|
|
|
|
We will introduce the following classes : Cell_, Net_, Component_
|
|
|
|
and it's derived classes.
|
Validating channel routing mode (two metals) on SNX.
* New: In Hurricane::Entity, add an id counter limit and a memory size
limit. The two limits are checked only when a new Entity object is
created. This should help avoiding massive memory links.
* New: In CRL Core, add a "crlcore.groundName" and a "crlcore.powerName"
parameter to specify the name of the ground/power signals to be
created if they are missing in a Cell. For Alliance libraries it
would be "vss" & "vdd" (default values), but for real technologies,
it is often "gnd!" & "vdd!".
The Blif parser is modificated to make use of it.
* Bug: In AnabaticEngine::unify(), set the resulting unified segment in
the center of the GCells common side. Gcells under a segment are
found by using the edge that cover the segment axis. When we have
a "bend" GCell stack and the axis is wrong, they could be ommited.
This was causing deleted segments to be not removed from some
Edges, then core dump.
* Change: In Anabatic::AutoSegment::create(), smarter choosing of the
reference contact, select the fixed or terminal one instead of
always the source one.
* New: In Anabatic::Edge::isEnding(), new function to check if a
segment going through an Edge is starting/ending in either source
or target GCell of the edge (active only when running in channel
mode).
* New: In Anabatic::Edge::add(), a segment takes part in the occupancy
only if it is not ending in either source or target (channel mode
only). The occupancy due to terminal is pre-computed in Katana.
* New: In Anabatic::Edge::ripup(), in channel mode, never ripup a
segment which is ending in either source or target (we *have* to
access this edge to connect to the terminal).
* Bug: In Anabatic::GCell::hcut() and vcut(), force the update of
the Edge which is on the side that will get splitted by the cut.
It's capacity will be reduced to it must be updated.
* Change: In Anabatic::GCell::updateGContacts() add a flag to conditionnally
update horizontals or verticals only. We may require only a partial
update when resizing the GCell in only one direction.
This, again, related to the fact that we compute the GCells under
a segment thanks to it's axis position, so we need to be very careful
when modificating axis.
* Change: In Katana::Block::resizeChannels(), only update GContact vertical
position. Do not disturb X positions of segments.
* Bug: In Katana::GlobalRoute::DigitalDistance, in channel mode, some
Edges can have a zero capacity, but still be reachable if the net has
a terminal in either source or target. Look for this case and return
a distance of zero instead of "unreachable". This was causing the
global routing not to complete in channel mode.
For computing the edge distance, makes the vertical edges much more
long (10 times) than the horizontal ones as the vertical capacity is
very limited. Hard coded for now, should make it a parameter in the
future.
* Change: In KatanaEngine::annotateGlobalGraph(), decrease the capacity
of edges with reserveCapacity for each terminal inside a GCell.
Both north and south edges are decreased as we a terminal will
block both north and south edges.
As a counterpart, the Edge capacity is not decreased when the
global router connect to a terminal.
* Change: In Katana::RoutingEvent::revalidate(), when in repair stage,
do not expand the slack for horizontal segments in channel mode.
So they may not overlap the standard cell row.
* Bug: In Stratus documentation, do not use the french option in babel,
the documentation is in english!
* New: In Documentation, added Hurricane/Python tutorial, part for drawing
layout.
2018-03-16 10:20:04 -05:00
|
|
|
|
|
|
|
|
|
|
|
3.1 The AllianceFramework (CRL Core)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
The |Hurricane| database only manage objects in memory. To load or save
|
|
|
|
something from the outside, we need to use a *framework*. As of today, only
|
|
|
|
one is available : the Alliance framework. It allows |Coriolis| to handle
|
|
|
|
|Alliance| libraries and cells in the exact same way.
|
|
|
|
|
|
|
|
.. note:: To see how the AllianceFramework_ is configured for your
|
|
|
|
installation, please have a look to ``alliance.conf`` in the
|
|
|
|
``etc/coriolis2`` directory. It must contains the same settings
|
|
|
|
as the various ``MBK_`` variables used for |Alliance|.
|
|
|
|
|
|
|
|
|
|
|
|
3.2 Session Mechanism (Hurricane)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
In the |Hurricane| database, all modifications must take place inside
|
|
|
|
an UpdateSession_. At the closing of a session, created or modificateds
|
|
|
|
objects are fully inserted in the database. This is especially true for
|
|
|
|
the visualisation, a created component will be visible *only* only after
|
|
|
|
the session close.
|
|
|
|
|
|
|
|
.. note:: See ``QuadTree`` and ``Query``.
|
|
|
|
|
|
|
|
|
|
|
|
3.3 Creating a new Cell (CRL Core)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
The creation of a new Cell_ occurs through the AllianceFramework_,
|
|
|
|
and, as stated above, inside a UpdateSession_. The AllianceFramework_
|
|
|
|
environment is provided by the |CRL| module.
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
from Hurricane import *
|
|
|
|
from CRL import *
|
|
|
|
|
|
|
|
af = AllianceFramework.get()
|
|
|
|
UpdateSession.open()
|
|
|
|
|
|
|
|
cell = af.createCell( 'my_inv' )
|
|
|
|
|
|
|
|
# Build then save the Cell.
|
|
|
|
|
|
|
|
UpdateSession.close()
|
|
|
|
|
|
|
|
|
|
|
|
This is the simplest call to ``createCell()``, and it that case, the newly
|
|
|
|
created Cell_ will be saved in the *working library* (usually, the current
|
|
|
|
directory). You may supply a second argument telling into which library
|
|
|
|
you want the Cell_ to be created.
|
|
|
|
|
|
|
|
In the |Hurricane| Cell_ object, there is no concept of *view*, it contains
|
|
|
|
completly fused logical (netlist) and physical (layout) views.
|
|
|
|
|
|
|
|
|
|
|
|
3.4 The DbU Measurement Unit
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
All coordinates in the |Hurricane| database are expressed in DbU_
|
|
|
|
(for *Database Unit*) which are integer numbers of foundry grid.
|
|
|
|
To be more precise, they are fixed points numbers expressed in
|
|
|
|
hundredth of foundry grid (to allow transient non-integer
|
|
|
|
computation).
|
|
|
|
|
|
|
|
To work with symbolic layout, that is, using lambda based lengths,
|
|
|
|
two conversion functions are provideds:
|
|
|
|
|
|
|
|
* ``unit = DbU.fromLambda( lbd )`` convert a lambda :cb:`lbd` into a ``DbU``.
|
|
|
|
* ``lbd = DbU.toLambda( unit )`` convert a ``DbU`` into a lambda :cb:`lbd`.
|
|
|
|
|
|
|
|
In the weakly typed |Python| world, :cb:`lbd` is *float* while :cb:`unit`
|
|
|
|
is *integer*.
|
|
|
|
|
|
|
|
|
|
|
|
3.5 Setting up the Abutment Box
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
To setup the abutment box, we use a Box_ which define a box from
|
|
|
|
the coordinates of the lower left corner ``(x1,y1)`` and upper left
|
|
|
|
corner ``(x2,y2)``.
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
b = Box( DbU.fromLambda( 0.0) # x1
|
|
|
|
, DbU.fromLambda( 0.0) # y1
|
|
|
|
, DbU.fromLambda(15.0) # x2
|
|
|
|
, DbU.fromLambda(50.0) ) # y2
|
|
|
|
cell.setAbutmentBox( b )
|
|
|
|
|
|
|
|
Or more simply:
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
cell.setAbutmentBox( Box( DbU.fromLambda( 0.0)
|
|
|
|
, DbU.fromLambda( 0.0)
|
|
|
|
, DbU.fromLambda(15.0)
|
|
|
|
, DbU.fromLambda(50.0) ) )
|
|
|
|
|
|
|
|
|
|
|
|
3.6 Adding Nets and Components
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
In the |Hurricane| terminology, a **component** is any kind of physical object
|
|
|
|
among:
|
|
|
|
|
|
|
|
* Contact_
|
|
|
|
* Pad_
|
|
|
|
* RoutingPad_
|
|
|
|
* Horizontal_
|
|
|
|
* Vertical_
|
|
|
|
* Plug_ is the only exception and will be detailed later (see ??).
|
|
|
|
|
|
|
|
Components_ cannot be created *alone*. They must be part of a Net_.
|
|
|
|
|
|
|
|
|
|
|
|
3.6.1 Getting a Layer
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
As physical elements, Components_ are created using a Layer_. So prior to
|
|
|
|
their creation, we must get one from the database. Layers_ are stored in the
|
|
|
|
Technology_, which in turn, is stored in the DataBase_. So, to get a
|
|
|
|
Layer_:
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
layer = DataBase.getDB().getTechnology().getLayer( 'METAL1' )
|
|
|
|
|
|
|
|
|
|
|
|
.. note:: **Convention for layer names.** As the database can manage both real layers
|
|
|
|
and symbolic ones we adopt the following convention:
|
|
|
|
|
|
|
|
* **Real layers** are named in lowercase (``metal1``, ``nwell``).
|
|
|
|
* **Symbolic layers** are named in uppercase (``METAL1``, ``NWELL``).
|
|
|
|
|
|
|
|
|
|
|
|
3.6.2 Creating a Net
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
As said above, prior to creating any Component_, we must create the Net_ it
|
|
|
|
will belongs to. In that example we also make it an *external* net, that is,
|
|
|
|
a part of the interface. Do not mistake the name of the net given as a string
|
|
|
|
argument :cb:`'i'` and the name of the *variable* :cb:`i` holding the Net_ object.
|
|
|
|
For the sake of clarity we try to give the variable a close name, but this is
|
|
|
|
not mandatory.
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
i = Net.create( cell, 'i' )
|
|
|
|
i.setExternal( True )
|
|
|
|
|
2018-03-18 17:28:49 -05:00
|
|
|
.. note:: Unlike some other database models, in |Hurricane|,
|
|
|
|
**there is no explicit terminal object**, you only need to make the
|
|
|
|
net external. For more information about how to connect to an
|
|
|
|
external net, see `6.2 Creating Nets and connecting to Instances`_.
|
|
|
|
|
|
|
|
|
Validating channel routing mode (two metals) on SNX.
* New: In Hurricane::Entity, add an id counter limit and a memory size
limit. The two limits are checked only when a new Entity object is
created. This should help avoiding massive memory links.
* New: In CRL Core, add a "crlcore.groundName" and a "crlcore.powerName"
parameter to specify the name of the ground/power signals to be
created if they are missing in a Cell. For Alliance libraries it
would be "vss" & "vdd" (default values), but for real technologies,
it is often "gnd!" & "vdd!".
The Blif parser is modificated to make use of it.
* Bug: In AnabaticEngine::unify(), set the resulting unified segment in
the center of the GCells common side. Gcells under a segment are
found by using the edge that cover the segment axis. When we have
a "bend" GCell stack and the axis is wrong, they could be ommited.
This was causing deleted segments to be not removed from some
Edges, then core dump.
* Change: In Anabatic::AutoSegment::create(), smarter choosing of the
reference contact, select the fixed or terminal one instead of
always the source one.
* New: In Anabatic::Edge::isEnding(), new function to check if a
segment going through an Edge is starting/ending in either source
or target GCell of the edge (active only when running in channel
mode).
* New: In Anabatic::Edge::add(), a segment takes part in the occupancy
only if it is not ending in either source or target (channel mode
only). The occupancy due to terminal is pre-computed in Katana.
* New: In Anabatic::Edge::ripup(), in channel mode, never ripup a
segment which is ending in either source or target (we *have* to
access this edge to connect to the terminal).
* Bug: In Anabatic::GCell::hcut() and vcut(), force the update of
the Edge which is on the side that will get splitted by the cut.
It's capacity will be reduced to it must be updated.
* Change: In Anabatic::GCell::updateGContacts() add a flag to conditionnally
update horizontals or verticals only. We may require only a partial
update when resizing the GCell in only one direction.
This, again, related to the fact that we compute the GCells under
a segment thanks to it's axis position, so we need to be very careful
when modificating axis.
* Change: In Katana::Block::resizeChannels(), only update GContact vertical
position. Do not disturb X positions of segments.
* Bug: In Katana::GlobalRoute::DigitalDistance, in channel mode, some
Edges can have a zero capacity, but still be reachable if the net has
a terminal in either source or target. Look for this case and return
a distance of zero instead of "unreachable". This was causing the
global routing not to complete in channel mode.
For computing the edge distance, makes the vertical edges much more
long (10 times) than the horizontal ones as the vertical capacity is
very limited. Hard coded for now, should make it a parameter in the
future.
* Change: In KatanaEngine::annotateGlobalGraph(), decrease the capacity
of edges with reserveCapacity for each terminal inside a GCell.
Both north and south edges are decreased as we a terminal will
block both north and south edges.
As a counterpart, the Edge capacity is not decreased when the
global router connect to a terminal.
* Change: In Katana::RoutingEvent::revalidate(), when in repair stage,
do not expand the slack for horizontal segments in channel mode.
So they may not overlap the standard cell row.
* Bug: In Stratus documentation, do not use the french option in babel,
the documentation is in english!
* New: In Documentation, added Hurricane/Python tutorial, part for drawing
layout.
2018-03-16 10:20:04 -05:00
|
|
|
3.6.3 Creating a Component
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
Finally, we get ready to create a Component_, we will make a Vertical_ segment
|
|
|
|
of ``METAL1``.
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
segment = Vertical.create( i # The owner Net.
|
|
|
|
, layer # The layer.
|
|
|
|
, DbU.fromLambda( 5.0 ) # The X coordinate.
|
|
|
|
, DbU.fromLambda( 2.0 ) # The width.
|
|
|
|
, DbU.fromLambda( 10.0 ) # The Y source coordinate.
|
|
|
|
, DbU.fromLambda( 40.0 ) ) # The Y target coordinate.
|
|
|
|
|
|
|
|
With this overload of the ``Vertical.create()`` function the segment is created at an
|
|
|
|
absolute position. There is a second overload for creating a relatively placed
|
|
|
|
segment, see *articulated layout*.
|
|
|
|
|
|
|
|
If the net is external, that is, part of the interface of the cell, you may have
|
|
|
|
to declare some of it's components as physical connectors usable by the router.
|
|
|
|
This is done by calling the NetExternalComponents_ class:
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
NetExternalComponents.setExternal( segment )
|
|
|
|
|
|
|
|
|
|
|
|
3.7 Saving to Disk (CRL Core)
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Once you are finished building your cell, you have to save it on disk.
|
|
|
|
Using the AllianceFramework_ you can save it as a pair of file:
|
|
|
|
|
|
|
|
========================= =================================== =======================
|
|
|
|
View Flag File extension
|
|
|
|
========================= =================================== =======================
|
|
|
|
Logical / Netlist ``Catalog.State.Logical`` ``.vst``
|
|
|
|
Physical / Layout ``Catalog.State.Physical`` ``.ap``
|
|
|
|
========================= =================================== =======================
|
|
|
|
|
|
|
|
To save both views, use the ``Catalog.State.Views`` flag. The files
|
|
|
|
will be written in the |Alliance| ``WORK_DIR``.
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
af.saveCell( cell, Catalog.State.Views )
|
2018-03-18 17:28:49 -05:00
|
|
|
|
|
|
|
|
|
|
|
3.8 The Complete Example File
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
The example files can be found in the ``share/doc/coriolis2/examples/scripts/``
|
|
|
|
directory (under the the root of the |Coriolis| installation).
|
|
|
|
|
|
|
|
The code needed to run it through the |cgt| viewer as been added. For the
|
|
|
|
explanation of that part of the code, refer to `5. Make a script runnable through cgt`_.
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: Python
|
|
|
|
|
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
import sys
|
|
|
|
from Hurricane import *
|
|
|
|
from CRL import *
|
|
|
|
|
|
|
|
|
|
|
|
def toDbU ( l ): return DbU.fromLambda(l)
|
|
|
|
|
|
|
|
|
|
|
|
def doBreak ( level, message ):
|
|
|
|
UpdateSession.close()
|
|
|
|
Breakpoint.stop( level, message )
|
|
|
|
UpdateSession.open()
|
|
|
|
|
|
|
|
|
|
|
|
def buildInvertor ( editor ):
|
|
|
|
UpdateSession.open()
|
|
|
|
|
|
|
|
cell = AllianceFramework.get().createCell( 'invertor' )
|
|
|
|
cell.setTerminal( True )
|
|
|
|
|
|
|
|
cell.setAbutmentBox( Box( toDbU(0.0), toDbU(0.0), toDbU(15.0), toDbU(50.0) ) )
|
|
|
|
|
|
|
|
if editor:
|
|
|
|
UpdateSession.close()
|
|
|
|
editor.setCell( cell )
|
|
|
|
editor.fit()
|
|
|
|
UpdateSession.open()
|
|
|
|
|
|
|
|
technology = DataBase.getDB().getTechnology()
|
|
|
|
metal1 = technology.getLayer( "METAL1" )
|
|
|
|
poly = technology.getLayer( "POLY" )
|
|
|
|
ptrans = technology.getLayer( "PTRANS" )
|
|
|
|
ntrans = technology.getLayer( "NTRANS" )
|
|
|
|
pdif = technology.getLayer( "PDIF" )
|
|
|
|
ndif = technology.getLayer( "NDIF" )
|
|
|
|
contdifn = technology.getLayer( "CONT_DIF_N" )
|
|
|
|
contdifp = technology.getLayer( "CONT_DIF_P" )
|
|
|
|
nwell = technology.getLayer( "NWELL" )
|
|
|
|
contpoly = technology.getLayer( "CONT_POLY" )
|
|
|
|
ntie = technology.getLayer( "NTIE" )
|
|
|
|
|
|
|
|
net = Net.create( cell, "nwell" )
|
|
|
|
Vertical.create( net, nwell, toDbU(7.5), toDbU(15.0), toDbU(27.0), toDbU(51.0) )
|
|
|
|
|
|
|
|
vdd = Net.create( cell, "vdd" )
|
|
|
|
vdd.setExternal( True )
|
|
|
|
vdd.setGlobal ( True )
|
|
|
|
h = Horizontal.create(vdd, metal1, toDbU(47.0), toDbU(6.0), toDbU(0.0), toDbU(15.0) )
|
|
|
|
NetExternalComponents.setExternal( h )
|
|
|
|
Contact.create ( vdd, contdifn, toDbU(10.0), toDbU(47.0), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
Contact.create ( vdd, contdifp, toDbU( 4.0), toDbU(45.0), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
Vertical.create( vdd, pdif , toDbU( 3.5), toDbU( 4.0), toDbU(28.0), toDbU(46.0) )
|
|
|
|
Vertical.create( vdd, ntie , toDbU(10.0), toDbU( 3.0), toDbU(43.0), toDbU(48.0) )
|
|
|
|
doBreak( 1, 'Done building vdd.' )
|
|
|
|
|
|
|
|
vss = Net.create( cell, "vss" )
|
|
|
|
vss.setExternal( True )
|
|
|
|
vss.setGlobal ( True )
|
|
|
|
h = Horizontal.create(vss, metal1, toDbU(3.0), toDbU(6.0), toDbU(0.0), toDbU(15.0))
|
|
|
|
NetExternalComponents.setExternal( h )
|
|
|
|
Vertical.create( vss, ndif , toDbU(3.5), toDbU(4.0), toDbU(4.0), toDbU(12.0) )
|
|
|
|
Contact.create ( vss, contdifn, toDbU(4.0), toDbU(5.0), toDbU(1.0), toDbU( 1.0) )
|
|
|
|
doBreak( 1, 'Done building vss.' )
|
|
|
|
|
|
|
|
i = Net.create( cell, "i" )
|
|
|
|
i.setExternal( True )
|
|
|
|
v = Vertical.create ( i, metal1, toDbU(5.0), toDbU(2.0), toDbU(10.0), toDbU(40.0) )
|
|
|
|
NetExternalComponents.setExternal( v )
|
|
|
|
Vertical.create ( i, ptrans , toDbU( 7.0), toDbU( 1.0), toDbU(26.0), toDbU(39.0) )
|
|
|
|
Vertical.create ( i, ntrans , toDbU( 7.0), toDbU( 1.0), toDbU( 6.0), toDbU(14.0) )
|
|
|
|
Vertical.create ( i, poly , toDbU( 7.0), toDbU( 1.0), toDbU(14.0), toDbU(26.0) )
|
|
|
|
Horizontal.create( i, poly , toDbU(20.0), toDbU( 3.0), toDbU( 4.0), toDbU( 7.0) )
|
|
|
|
Contact.create ( i, contpoly, toDbU( 5.0), toDbU(20.0), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
doBreak( 1, 'Done building i.' )
|
|
|
|
|
|
|
|
nq = Net.create ( cell, "nq" )
|
|
|
|
nq.setExternal( True )
|
|
|
|
v = Vertical.create( nq, metal1, toDbU(10.0), toDbU(2.0), toDbU(10.0), toDbU(40.0) )
|
|
|
|
NetExternalComponents.setExternal( v )
|
|
|
|
Vertical.create( nq, pdif , toDbU(10.0), toDbU( 3.0), toDbU(28.0), toDbU(37.0) )
|
|
|
|
Vertical.create( nq, ndif , toDbU(10.0), toDbU( 3.0), toDbU( 8.0), toDbU(12.0) )
|
|
|
|
Contact.create ( nq, contdifp, toDbU(10.0), toDbU(35.0), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
Contact.create ( nq, contdifp, toDbU(10.0), toDbU(30.5), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
Contact.create ( nq, contdifn, toDbU(10.0), toDbU(10.0), toDbU( 1.0), toDbU( 1.0) )
|
|
|
|
doBreak( 1, 'Done building q.' )
|
|
|
|
|
|
|
|
UpdateSession.close()
|
|
|
|
AllianceFramework.get().saveCell( cell, Catalog.State.Views )
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
def ScriptMain ( **kw ):
|
|
|
|
editor = None
|
|
|
|
if kw.has_key('editor') and kw['editor']:
|
|
|
|
editor = kw['editor']
|
|
|
|
|
|
|
|
buildInvertor( editor )
|
|
|
|
return True
|