Skip to content

Scripted Layout

Lukas Chrostowski edited this page Nov 20, 2023 · 13 revisions

Scripted Layout using KLayout & SiEPIC-Tools

Create a new layout

This function works within the KLayout GUI, and in headless batch mode.

from SiEPIC.utils.layout import new_layout
cell, ly = new_layout('EBeam', 'topcell_example', GUI=True, overwrite = True)

for help on individual functions, please type in the console:

> from SiEPIC.utils.layout import new_layout, floorplan
> help(new_layout)

Create a Floor Plan for your design

from SiEPIC.utils.layout import new_layout, floorplan
floorplan(cell, 605e3, 410e3)

Note the units are in database units (nm, in the EBeam PDK)

Load the technology information from the PDK:

from SiEPIC.utils import get_layout_variables
TECHNOLOGY, lv, ly, cell = get_layout_variables()

or

from SiEPIC.utils import get_technology_by_name
TECHNOLOGY = get_technology_by_name('EBeam')

or if the layout is created using "new_layout" above,

TECHNOLOGY = ly.TECHNOLOGY

Adding a component

Load a Cell from a library:

cell_ebeam_gc = ly.create_cell('ebeam_gc_te1550', 'EBeam')

Then create a cell Instance at a specific location:

t = pya.Trans.from_s('r0 0,0')
instGC1 = cell.insert(pya.CellInstArray(cell_ebeam_gc.cell_index(), t))

Adding text labels, for automated measurements:

text = pya.Text ("opt_in_TE_1550_device_MZI_script", t)
shape = cell.shapes(ly.layer(TECHNOLOGY['Text'])).insert(text)
shape.text_size = 3*ly.dbu

Zoom out and show full hierarchy

from SiEPIC.scripts import zoom_out
zoom_out(topcell)

Connecting two components together (snapping pins together)

If you would like to connect two components together directly (without a waveguide between them), the following function creates a new instance of a cell, and connects it to an existing instance. The function will automatically rotate the new instance so that the specified pins get connected correctly:

connect_cell(instanceA, pinA, cellB, pinB, mirror = False, verbose=True)

Instantiate, Move & rotate cellB to connect to instanceA, such that their pins (pinB, pinA) match

Example code, for the EBeam PDK:

cell_crossing = ly.create_cell('ebeam_crossing4', 'EBeam')
t = pya.Trans.from_s('r270 230175,190500')
inst_crossing = cell.insert(pya.CellInstArray(cell_crossing.cell_index(), t))

cell_bragg = ly.create_cell('ebeam_bragg_te1550', 'EBeam', {'r': 10.0, 'w': 0.35, 'g': 0.12, 'gmon': 0.5})

from SiEPIC.scripts import connect_cell
instanceB = connect_cell(inst_crossing, 'opt2', cell_bragg, 'pin1')

Moving an Instance

The following moves the component using a Transformation, with x and y values provided in database units:

instanceB.transform(Trans(20000,-10000))

Adding a waveguide between components

Create a Waveguide connecting instanceA:pinA to instanceB:pinB. Each instance is a pya.Instance, and each pin is a string, e.g. 'pin1'. The Waveguide will have a type waveguide_type = [string] name, as defined in the PDK in WAVEGUIDES.XML, e.g., 'Strip TE 1550 nm, w=500 nm'

connect_pins_with_waveguide(instanceA, pinA, instanceB, pinB, waveguide = None, waveguide_type = None, turtle_A=None, turtle_B=None, verbose=False, debug_path=False, r=None, error_min_bend_radius=True, relaxed_pinnames=True)

The waveguide location is determined using one of the following approaches:

  • fewer than 4 vertices (including endpoints): automatic, no need to specify turtles
  • turtle_A: list of Turtle (forward x microns, turn left -1 or right 1), starting from the pinA end, except for the first and last e.g. [5, -90, 10, 90]
  • turtle_B: list of Turtle (forward x microns, turn left -1 or right 1), starting from the pinA end, except for the first and last
    • both turtle_A and turtle_B: relative from both pinA and pinB sides
  • the script automatically completes the path as long as the turtles are:
    • going in the same direction, or
    • having their paths crossing
  • doesn't work if they are on diverging paths; in that case add vertices.

Example code:

cell_ebeam_gc = ly.create_cell('ebeam_gc_te1550', 'EBeam')
cell_ebeam_y = ly.create_cell('ebeam_y_1550', 'EBeam')

# place at absolute positions
t = pya.Trans.from_s('r0 0,0')
instGC1 = cell.insert(pya.CellInstArray(cell_ebeam_gc.cell_index(), t))
t = pya.Trans.from_s('r0 20000,10000')
instY1 = cell.insert(pya.CellInstArray(cell_ebeam_y.cell_index(), t))

# Waveguides:
waveguide_type='Strip TE 1550 nm, w=500 nm'
from SiEPIC.scripts import connect_pins_with_waveguide
connect_pins_with_waveguide(instGC1, 'opt1', instY1, 'opt1', waveguide_type=waveguide_type)

For trouble-shooting, you may turn off the bend radius check, by using error_min_bend_radius=False

Querying components to find their Pin positions

This returns the (x,y) coordinates of the specific pin for an instance:

instGC1_pin1 = instGC1.pinPoint('opt1')
instY1_pin1 = instY1.pinPoint('opt1')

x = instY1_pin1.x
y = instY1_pin1.y

to_itype

Convert x in microns (float) to database units (integers); do it carefully to avoid rounding errors due to float representation in Python

Usage:

from SiEPIC.extend import to_itype
to_itype(x,dbu)
  • x is a float
  • dbu is the database, pya.Layout().dbu
  • returns, value in integers

Exporting the layout

from SiEPIC.scripts import export_layout
import os
path = os.path.dirname(os.path.realpath(__file__))
export_layout(cell, path, filename, relative_path = '', format='oas', screenshot=False)

This will create a GDS or OASIS file, without the PCell information, and can optionally create a screenshot of the layout. The file will be saved in the same folder as the Python file.

Examples:

Example scripted layouts are provided in each PDK, for example:

Avoiding KLayout crashes

  • A common way for KLayout to crash is if a GUI cell or shape selection is deleted by the script. To avoid this, clear the object selection before this script, by using the following at the beginning of the script:
from SiEPIC.utils import get_layout_variables
TECHNOLOGY, lv, ly, cell = get_layout_variables()
lv.clear_object_selection()
  • A crash can occur if objects are deleted (or the order changed) but referred to later. Be careful with variables.

  • A crash can occur if PCell parameters are added or removed from a PCell, and the library loaded while a layout is open.