# PCells, Views and Properties¶

This session introduces PCells, Views and Properties, which are the basics of the IPKISS framework. It may seem a little abstract at first, but understanding the underlying structure of IPKISS is very important to be able to design complex circuits in the future.

IPKISS organizes these different aspects of the design flow using PCells and Views. In IPKISS each component or circuit is a PCell. This PCell contains all the information about the component or the circuit. This information can cover aspects that are relevant at different stages of the design flow and is categorized into one or several views that are tightly linked to a particular stage in the design flow. For instance, a PCell can have a LayoutView that describes how to build a GDSII description of the component/circuit. At the same time, this PCell could also have a CircuitModelView which would contain a circuit model for the same component. Both PCells and Views are parametric through the use of properties.

A more detailed introduction to PCells, Views and Properties can be found in the Luceda documentation (Properties and Parametric Cells). You can also open the documentation from the “Luceda Control Center” by clicking on the “Documentation” button.

## Importing IPKISS and the technology¶

Before we start doing anything with IPKISS, we have to import the IPKISS module and a technology file into Python. The technology file contains a series of constants that describe the process you will use to fabricate your chip. Here we use the SiFab technology that is included in this training material.

from si_fab import all as pdk
from ipkiss3 import all as i3


## A first PCell with properties¶

Now we are ready to start building our first PCell class, an MMI. Our MMI will be described by the following parameters:

• the length of the MMI (length)
• the width of the MMI (width)
• the width of the taper (taper_width)
• the spacing between the waveguides (waveguide_spacing)
class MMI(i3.PCell):
# Properties that describe the MMI
width = i3.PositiveNumberProperty(doc="Width of the MMI section.")
length = i3.PositiveNumberProperty(doc="Length of the MMI section.")
taper_width = i3.PositiveNumberProperty(doc="Width of the taper.")
waveguide_spacing = i3.PositiveNumberProperty(doc="Spacing between the waveguides.")


Let’s have a closer look at what we have in this piece of code:

• MMI : class name of the MMI.
• i3.PCell : class of a PCell. Using this syntax MMI inherits all the code that describes a PCell.
• width : property describing the width of the MMI. This is a positive number.
• length : property describing the length of the MMI. This is a positive number.
• waveguide_spacing : property describing the spacing between the center of the two output waveguides.

We have just created an MMI class with four properties. We now create an MMI object using the description provided by the class. When creating this object, we have to assign values to the properties.

mmi1 = MMI(width=5.0, length=20.0, taper_width=2.0, waveguide_spacing=2.0)
print('\nMMI 1')
print(mmi1.width)
print(mmi1.length)
print(mmi1.taper_width)
print(mmi1.waveguide_spacing)


Through the statement mmi_object = MMI(width=50.0, length=20.0, taper_width=0.5, waveguide_spacing=2.0) we instantiated an MMI object. We assigned the value 5.0 to width, the value 20.0 to length, the value 2.0 to taper_width and the value 2.0 to waveguide_spacing.

## Properties with default values¶

In many cases it is useful to assign default values to properties. That way, when you instantiate an object from a PCell and you do not specify a property value, the default value of that property will be used. This can be achieved in 2 ways:

1. Directly from the property definition line, using the argument default=<something>.
2. Through a default method, called _default_<name_of_the_property>. The function returns the default value.

Let’s now implement both of these methods to assing default values to the properties of the MMI class.

class MMIWithDefaults(i3.PCell):
# Properties with default values
width = i3.PositiveNumberProperty(default=5.0, doc="Width of the MMI section.")
length = i3.PositiveNumberProperty(default=10.0, doc="Length of the MMI section.")
taper_width = i3.PositiveNumberProperty(doc="Width of the taper.")
waveguide_spacing = i3.PositiveNumberProperty(doc="Spacing between the waveguides.")

def _default_taper_width(self):
return self.width / 4.0

def _default_waveguide_spacing(self):
return self.width / 2.0


The PCell MMIWithDefaults is the same as MMI but

• when width is not specified, the default value of 5.0 will be used;
• when length is not specified, the default value of 10.0 will be used;
• when taper_width is not specified, the default value of width / 4.0 will be used;
• when waveguide_spacing is not specified, the default value of width / 2.0 will be used.

When the default value of a property is a simple value, such as a number, it can be assigned in the property definition line. Sometimes the default value can be more complex. That’s when the default method comes in handy. This is the case, for example, when values of other properties are used for the calculation, such as for taper_width.

We can now instantiate an MMI cell without specifying any property value:

mmi2 = MMIWithDefaults()
print('\nMMI 2')
print(mmi2.width)
print(mmi2.length)
print(mmi2.taper_width)
print(mmi2.waveguide_spacing)


When we specify some of the values, then the default values are overwritten:

mmi3 = MMIWithDefaults(width=7.0, length=20.0)