Modifying the GDSII table of an existing technology

This sample illustrates how to modify the GDSII export layer of an existing technology to another one. This allows you to start from our existing si_fab and remap the layers avoiding the work of having to create a new technology from scratch.

Importing the technology We first import the technology from where we start.

from si_fab import technology  # noqa
from ipkiss3 import all as i3

CUSTOM_PROCESS = i3.ProcessLayer("custom", "CUST")
CUSTOM_LAYER = i3.PPLayer(process=CUSTOM_PROCESS, purpose=i3.TECH.PURPOSE.DRAWING)

We first create a simple dummy PCell to use in our example

class MyPCell(i3.PCell):
    class Layout(i3.LayoutView):
        def _generate_elements(self, elems):
            rect1 = i3.Rectangle(
                layer=CUSTOM_LAYER,
                box_size=(4.0, 1.0),
            )
            rect2 = i3.Rectangle(
                layer=i3.TECH.PPLAYER.SI,
                box_size=(4.0, 1.0),
                center=(0.0, 2.0),
            )
            elems += rect1
            elems += rect2
            return elems


layout = MyPCell().Layout()

In order to be able to export this layout to a GDS-file we need to provide a layer-map, so that IPKISS can map our layers to process and purpose numbers

try:
    # this will result in an Error:
    layout.write_gdsii("my_cell.gds")
except Exception:
    print("Catched error: write_gdsii doesn't know how to export CUSTOM_LAYER")

layer_table = {
    (i3.TECH.PROCESS.SI, i3.TECH.PURPOSE.DRAWING): (2014, 6),
    (CUSTOM_PROCESS, i3.TECH.PURPOSE.DRAWING): (2014, 9),
}

from ipkiss.process.layer_map import GenericGdsiiPPLayerOutputMap  # noqa

output_layer_map = GenericGdsiiPPLayerOutputMap(pplayer_map=layer_table)

# we tell the write_gdsii method to use our new layer_map.
layout.write_gdsii("my_cell.gds", layer_map=output_layer_map)

# Sometimes you'll just want to start from an already defined layer_table (e.g. the one in the technology)
# and remap the numbers used. This you can accomplish with the following snippet:
# here we declare that we want to map (1, 0) to (42, 1)

gds_remap = {
    # FYI the layertable in the si_fab technology contains the following entry:
    # (ProcessLayer, PatternPurpose) : (GDSIILayer, GDSIIDatatype)
    # (TECH.PROCESS.SI,  TECH.PURPOSE.DRAWING): (1, 0),
    (1, 0): (42, 1)
}

original_layer_table = i3.TECH.GDSII.LAYERTABLE
remapped_layer_table = {pplayer: gds_remap.get(gds_tpl, gds_tpl) for pplayer, gds_tpl in original_layer_table.items()}

# also add a mapping for our custom layer
remapped_layer_table[CUSTOM_PROCESS, i3.TECH.PURPOSE.DRAWING] = (42, 2)

output_layer_map = GenericGdsiiPPLayerOutputMap(pplayer_map=remapped_layer_table)
layout.write_gdsii("my_cell_remapped.gds", layer_map=output_layer_map)
Catched error: write_gdsii doesn't know how to export CUSTOM_LAYER

The same layer_table can be used to create an input map which you can use to import GDS-files that use different (GDS-layer, GDS-datatype) pairs Below we import the gds which we exported with our custom layer map above:

from ipkiss.process.layer_map import GenericGdsiiPPLayerInputMap  # noqa

input_layer_map = GenericGdsiiPPLayerInputMap(pplayer_map=remapped_layer_table)

layout = i3.GDSCell(filename="my_cell_remapped.gds").Layout(layer_map=input_layer_map)
layout.visualize()
plot gdsii remap

With a custom input layer map we can also map the GDS-layers to different IPKISS-Layers let’s try to ‘switch’ the layers of the 2 rectangles in our example:

layer_table = {
    (i3.TECH.PROCESS.SI, i3.TECH.PURPOSE.DRAWING): (42, 2),
    (CUSTOM_PROCESS, i3.TECH.PURPOSE.DRAWING): (42, 1),
}

input_layer_map2 = GenericGdsiiPPLayerInputMap(pplayer_map=layer_table)

layout = i3.GDSCell(filename="my_cell_remapped.gds").Layout(layer_map=input_layer_map2)
layout.visualize()
plot gdsii remap