-
-
Notifications
You must be signed in to change notification settings - Fork 90
Scripted 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)
from SiEPIC.utils.layout import new_layout, floorplan
floorplan(cell, 605e3, 410e3)
Note the units are in database units (nm, in the EBeam 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
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))
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
from SiEPIC.scripts import zoom_out
zoom_out(topcell)
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')
The following moves the component using a Transformation, with x and y values provided in database units:
instanceB.transform(Trans(20000,-10000))
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
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
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
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.
Example scripted layouts are provided in each PDK, for example:
- "MZI" in the SiEPIC_EBeam_PDK, is accessed via the menu SiEPIC > Example Layouts > Simple MZI, https://github.com/SiEPIC/SiEPIC_EBeam_PDK/tree/master/klayout_dot_config/tech/EBeam/pymacros/Example_scripted_layouts
- "Test_structures_ring_resonators" in the SiEPIC_EBeam_PDK, is accessed via the menu SiEPIC > Example Layouts > Test Structures: Double-bus ring resonators, https://github.com/SiEPIC/SiEPIC_EBeam_PDK/tree/master/klayout_dot_config/tech/EBeam/pymacros/Example_scripted_layouts
![](https://github.com/SiEPIC/SiEPIC_EBeam_PDK/raw/master/klayout_dot_config/tech/EBeam/pymacros/Example_scripted_layouts/mzi.png)
![](https://github.com/SiEPIC/SiEPIC_EBeam_PDK/raw/master/klayout_dot_config/tech/EBeam/pymacros/Example_scripted_layouts/Test_structures_ring_resonators.png)
- "Test structures - microring filter" for the AMF technology (private repository), https://github.com/SiEPIC/SiEPIC_AMF_Library/tree/master/SiEPIC_AMF_Library_KLayout/Example_Scripted_Layouts
- 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.