Example of defining a customized technology


In this example, we define a customized technology by extending a predefined technology in ipkiss. We add a layer which is used to open the back-end oxide (top oxide) on top of the waveguides. This can be used to open a window for a sensing application, for instance to let a gas or fluid reach a ring resonator on top of which a window is opened.

Ring resonator with opening layer

Fig. 55 Ring resonator covered by a back-end opening layer


  1. how to create a customized technology file by importing a predefined file
  2. how to add a new process layer
  3. how to define import and export settings and visualization
  4. how to define a virtual fabrication process
  5. how to alter values in the predefined technology files

Files (see: samples/ipkiss3/samples/wrapped_disk)

There are two files contained in this step.

  • mytech/__init__.py : this is the file which defines the customized technology
  • execute.py : this is the file that is executed by python. It defines the covered ring resonator

How to run this example

To run the example, run ‘execute.py’.

Getting started

We start by creating an empty folder for the new technology (in this example ‘mytech’), and create a file __init__.py.

The __init__.py file starts by importing a predefined technology in ipkiss, and assigning a meaningful name to the technology:

from technologies import silicon_photonics


Adding a process layer

In order to add a new layer, we need to do two things:

  • Add the ProcessLayer - this tells ipkiss about the existance of the layer related to a specific process module
  • Add one or more ProcessPurposeLayers - this tells ipkiss which combinations of the new ProcessLayer and PatterPurposes exist. In this sample we’ll add only one.
TECH.PROCESS.OXIDE_OPEN = ProcessLayer(name="OX_OPEN", extension="OXO")

The TECH.PURPOSE.DF.TRENCH pattern purpose means that the geometries drawn will be etched trenches on a dark (unetched) field.

Defining rules

The technology tree can contain some design rules, defaults or drawing guidelines. In this case, we’ll add a few keys for the minimum width and spacing of patterns on our new OXIDE_OPEN layer:

TECH.OXIDE_OPEN = TechnologyTree()
TECH.OXIDE_OPEN.MIN_WIDTH = 10.0  # minimum width of 10.0um
TECH.OXIDE_OPEN.MIN_SPACING = 5.0 # minimum spacing of 5.0um

Visualization and import/export settings

In order to make the new layer export to GDSII (and import from GDSII), we need to tell ipkiss which layer number to use for the process layer. In the technology example shipped with Ipkiss, every process layer corresponds to a GDSII Layer number, and every pattern purpose corresponds to a GDSII datatype. This can be controlled in a more fine-grained way, but that is outside the scope of this sample.

In order to have Ipkiss visualize the layer using the .visualize() method on a Layout view, we need to set the display style for the ProcessPurposeLayer. In this case, we set it to a yellow color with a 50% transparance.


DISPLAY_OXIDE_OPEN = DisplayStyle(color = color.COLOR_YELLOW, alpha = 0.5, edgewidth = 1.0)

Overwriting technology keys

Overwriting technology settings which were already defined, is possible as well. We can for instance increase the default bend radius on the WG layer to 10 micrometer:


Example: ring resonator with back-end opening cover layer

In order to use our newly defined technology, we make sure to import it before anything else in the main script. Make sure it is imported before ipkiss3 and before any picazzo library components ! Make sure that your new technology folder (in this case ‘mytech’) is in your PYTHONPATH.

from mytech import TECH
import ipkiss3.all as i3
from picazzo3.filters.ring import RingRect180DropFilter

We continue by defining a simple PCell which consists of a ring resonator and a cover layer:

class RingWithWindow(i3.PCell):
    ring_resonator = i3.ChildCellProperty()

    def _default_ring_resonator(self):
        return RingRect180DropFilter()

    class Layout(i3.LayoutView):
        def _generate_instances(self, insts):
            insts += i3.SRef(reference=self.ring_resonator,
            return insts

        def _generate_elements(self, elems):
            si = self.ring_resonator.size_info()
            size = (min(si.width, TECH.OXIDE_OPEN.MIN_WIDTH), min(si.height, TECH.OXIDE_OPEN.MIN_WIDTH)) # use rule in tech
            elems += i3.Rectangle(layer=TECH.PPLAYER.OXIDE_OPEN,
            return elems

We can now instantiate the component, visualize its layout and export to GDSII:

R = RingWithWindow(name="ring_with_window")
Rlayout = R.Layout()
Rlayout.visualize()    # show layout elements
Rlayout.visualize_2d() # virtually fabricated
Ring resonator with opening layer

Fig. 56 Ring resonator covered by a back-end opening layer: visualization

Ring resonator with opening layer

Fig. 57 Ring resonator covered by a back-end opening layer: GDSII

Ring resonator with opening layer

Fig. 58 Ring resonator covered by a back-end opening layer: virtually fabricated geometry