Hierarchical PCells

As your designs become more complex it is important to divide your design in several blocks that are manageable by themselves. These blocks are then reused at several points in the design. Introducing hierarchy in your design allows you to do create manageable blocks without duplicating code. This is important as this makes components more robust, less prone to errors, easier to document and easier to modify. We strongly recommend that you use hierarchy in your designs. It may look like overhead in the beginning, but it pays off later when you increase the complexity of your designs.

ChildCells

Within IPKISS PCells, it is possible to reuse cells hierarchically through ChildCells. Each ChildCell has views that have to be instantiated as instances (once or several times) in the views of the parent PCell. To use a ChildCell in a Parent Cell you need to go through the following steps:

  1. Define a class that is going to be used as a ChildCell. This is a regular PCell with regular views.
  2. Declare the existence of a ChildCell in your parent PCell. This is done via a special property named ChildCellProperty.
  3. In each view of your parent cell one or several instances of the corresponding view has to be placed. In each view this happens through a special method: _generate_instances() and some other functions that are specific to each view.

In the figure below, these steps are illustrated in pseudo-code for a Parent Cell that uses 2 ChildCells. The first ChildCell (child_1) is instantiated twice in every view, whereas the second ChildCell(child_2) is instantiated once.

Circuit simulation overview.

Fig. 78 Illustration of ChildCells.

We will now dig a bit deeper in the last two steps: The definition of the ChildCellProperty and the instantiations of the views of the child cells in the views of the parent cell.

ChildCellProperty

For a parent PCell to use child PCells in a hierarchical way, the child cells have to be declared with ChildCellProperty. ChildCellProperties are different from other properties as they make the views of the child cells available in the corresponding views of the parent cell.

This is best exemplified by the following piece of code:

class ParentPCell(i3.PCell):

    # 1.
    child = i3.ChildCellProperty()

    def _some_method_using_child(self):
       self.child #Refers to the child pcell.

    class Layout(i3.LayoutView):

       # 2.
       def _some_method_using_child(self):
          self.child # refers to the layout (that inherits from i3.LayoutView) of the child.

    class CapheModelView(i3.CapheSModelView)
      # 3.
       def _some_method_using_child(self):
          self.child # refers to the CapheSModelView view (that inherits from i3.CapheModelView) of the child
  1. Here we define child as child cell of ParentPCell
  2. In the Layout view the self.child will refer to the Layout view of child. The views are matched by the viewtype from which they inherit. This means that Child will have to have a view that inherits from i3.Layoutview
  3. In the CapheModelView view the self.child will refer to the CapheModelView view of child. The views are matched by the viewtype from which they inherit. This means that Child will have to have a view that inherits from i3.CapheSModelView

Corresponding views are from the same view type, which means that they inherit from one of the base view types as represented in the table below.

View class Base view type Functions to create an instance in _generate_instances(self,insts)
Layout i3.LayoutView SRef(), ARef(), MRef()
Netlist i3.NetlistView Instance()
Caphemodel i3.CapheSModelView CapheModelInstance() or use of i3.CapheModelFromNetlist

Note

When a cell has two views that are from the same base view type, ChildCellProperty will pick the one that is set as the default_view of that type. You can read more on default view types in pcell.

Adding the child views

As mentioned before, the next step is adding one or several instances of each child view to the views of the parent. In each view, this is done in the method _generate_instances. Inside _generate_instances functions specific to the base view type add each of the instances.

In the Layout view for example, this can be done through SRef, where a name and a transformation have to be defined.

class ParentPCell(i3.PCell):

    child = i3.ChildCellProperty()

    class Layout(i3.LayoutView):

       def _generate_instances(self,insts):
         insts += i3.SRef(self.child, name="Name of the instance", transformation =...)

For other views this is very similar: in the table above, a listing of the Base View Type and the corresponding functions to use inside _generate_instances is given.

Overriding views originating from ChildCellProperty

It may be that the default_view that is automatically set by ChildCellProperty in each view of the Parent cell is not be the one you want. In that case you can always override it using _default_ methods that can override the default value of any property. Lets illustrate this with a code excerpt.

class Child(i3.PCell):
   #...
   class Layout(i3.LayoutView):
      #...
   class CapheModel(i3.CapheSModelView):
      #...
   class CapheModel2(i3.CapheSModelView):
      #....

class ParentPCell(i3.PCell):

    child = i3.ChildCellProperty()

    def _some_method_using_child(self):
         self.child # refers to the PCell of child.

    class Layout(i3.LayoutView):
       def _some_method_using_child(self):
          self.child # refers to the layout (that inherits from i3.LayoutView) of the child.  This is the default value as set by the ChildCellProperty

    class CapheModel(i3.CapheSModelView):

       # Override the CapheModelView of child to be used with "caphemodel2", which is also defined in Child
       def _default_child(self):
          return self.cell.child.views['caphemodel2']

       def _some_method_using_child(self):
          self.child # Now refers to the view caphemodel2

In the code excerpt we have overridden the fact that self.child in the CapheModel of ParentPCell would refer to the CapheModel of Child, which would have been the default behavior. self.child in the CapheModel of ParentPCell now refers to CapheModel2 of Child.

Caution setting properties of child cell

If the child cells are automatically calculated by a _default method in the parent cell, as with the ParentPCell.CapheModelView above, you should not modify properties on the child cell using the pattern below, since it may lead to undefined behaviour:

parent = ParentPCell(name="parent")
cm = parent.CapheModel()
lay.child.some_property = 10.0 # This is not OK - undefined behaviour

The reason is that in this case, the parent cell is responsible of calculating its child cells. Since you are not the owner of that child cell, it is difficult to predict what would happen since the parent cell might have defined interdependencies.

If on the other hand you created the child cell yourself, it is possible to modify parameters:

child = Child(name="achild")
child_cm = child.CapheModel(some_property=2.0)

parent = ParentPCell(name="parent", child=child_cm)
child_cm.some_property = 10.0 # this is OK