Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project 1 Design #307

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added submissions/ELEC413_AndrewBishop_1.oas
Binary file not shown.
Binary file added submissions/ELEC413_AndrewBishop_2.oas
Binary file not shown.
213 changes: 213 additions & 0 deletions submissions/KLayout Python/EBeam_AndrewB_Cavities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
'''
Scripted layout for ring resonators using SiEPIC-Tools
in the SiEPIC-EBeam-PDK "EBeam" technology
by Lukas Chrostowski, 2023
Use instructions:
Run in Python, e.g., VSCode
pip install required packages:
- klayout, SiEPIC, siepic_ebeam_pdk, numpy
'''

designer_name = 'AndrewB'
top_cell_name = 'EBeam_%s_Cavities1' % designer_name
export_type = 'PCell' # static: for fabrication, PCell: include PCells in file

import pya
from pya import *

import SiEPIC
from SiEPIC._globals import Python_Env
from SiEPIC.scripts import zoom_out, export_layout
from SiEPIC.verification import layout_check
import os
import numpy

if Python_Env == 'Script':
try:
# For external Python mode, when installed using pip install siepic_ebeam_pdk
import siepic_ebeam_pdk
except:
# Load the PDK from a folder, e.g, GitHub, when running externally from the KLayout Application
import os, sys
path_GitHub = os.path.expanduser('~/Documents/GitHub/')
sys.path.insert(0,os.path.join(path_GitHub, 'SiEPIC_EBeam_PDK/klayout'))
import siepic_ebeam_pdk

tech_name = 'EBeam'

# Example layout function
def cavities():

# Import functions from SiEPIC-Tools
from SiEPIC.extend import to_itype
from SiEPIC.scripts import connect_cell, connect_pins_with_waveguide
from SiEPIC.utils.layout import new_layout, floorplan

# Create a layout for testing a double-bus ring resonator.
# uses:
# - the SiEPIC EBeam Library
# creates the layout in the presently selected cell
# deletes everything first

# Configure parameter sweep
pol = 'TE'
sweep_n = [45, 60, 75]
period = 0.27
sweep_dW = [0.05]
# cavity_length = 50_000
cavity_lengths = [50_000, 100_000, 150_000]
taper_length_um = 20

'''
Create a new layout using the EBeam technology,
with a top cell
and Draw the floor plan
'''
cell, ly = new_layout(tech_name, top_cell_name, GUI=True, overwrite = True)
floorplan(cell, 605e3, 410e3)

if SiEPIC.__version__ < '0.5.1':
raise Exception("Errors", "This example requires SiEPIC-Tools version 0.5.1 or greater.")

# Layer mapping:
LayerSiN = ly.layer(ly.TECHNOLOGY['Si'])
fpLayerN = cell.layout().layer(ly.TECHNOLOGY['FloorPlan'])
TextLayerN = cell.layout().layer(ly.TECHNOLOGY['Text'])


# Create a sub-cell for our Ring resonator layout
top_cell = cell
dbu = ly.dbu
cell = cell.layout().create_cell("Cavities")
t = Trans(Trans.R0, 40 / dbu, 12 / dbu)

# place the cell in the top cell
top_cell.insert(CellInstArray(cell.cell_index(), t))

# Import cell from the SiEPIC EBeam Library
cell_ebeam_gc = ly.create_cell("GC_%s_1310_8degOxide_BB" % pol, "EBeam")
# get the length of the grating coupler from the cell
gc_length = cell_ebeam_gc.bbox().width()*dbu
# spacing of the fibre array to be used for testing
GC_pitch = 127

#cell_terminator = ly.create_cell("ebeam_terminator_te1310", "EBeam")

cell_taper_cavity = ly.create_cell('ebeam_taper_te1550', "EBeam", {
'wg_width1': 0.350,
'wg_width2': 2.000,
'wg_length': taper_length_um})

cell_y = ly.create_cell('ebeam_y_1310', 'EBeam_Beta')

# Loop through the parameter sweep
#for i in range(len(sweep_gap)):
# for i in range(len(sweep_period)):
for index_1, n in enumerate(sweep_n):
for index_2, dW in enumerate(sweep_dW):
for index_3, cavity_length in enumerate(cavity_lengths):

p = period

i = index_1 + index_2 + index_3
# place layout at location:
if i==0:
x=0
else:
# next device is placed at the right-most element + length of the grating coupler
x = inst_bragg1.bbox().right*dbu + gc_length + 10

# get the parameters
# n = sweep_n[i]
# p = sweep_period[i]

# Grating couplers, Ports 0, 1, 2, 3 (from the bottom up)
instGCs = []
for j in range(0,4):
if j == 1:
instGCs.append(0)
continue; # Don't create the 2nd GC

t = Trans(Trans.R0, to_itype(x,dbu), j*127/dbu + 3/dbu)
instGCs.append( cell.insert(CellInstArray(cell_ebeam_gc.cell_index(), t)) )

# Label for automated measurements, laser on Port 2, detectors on Ports 1, 3, 4
t = Trans(Trans.R90, to_itype(x,dbu), to_itype(GC_pitch*2,dbu))
# text = Text ("opt_in_%s_1310_device_%s_FPPeriodn%sp%s" % (pol.upper(), designer_name,n,int(round(p*1000))), t)
text = Text(f"opt_in_{designer_name}_1310_device_n{n}_dW{int(dW*100)}_L{int(cavity_length/10_000)}", t)
text.halign = 1
cell.shapes(TextLayerN).insert(text).text_size = 5/dbu

#cell_splitter = ly.create_cell('ebeam_splitter_swg_assist_te1310', "EBeam")

cell_bragg = ly.create_cell('ebeam_bragg_te1550', "EBeam", {
'number_of_periods': n,
'grating_period': p,
'corrugation_width': dW,
'wg_width': 0.350,
'sinusoidal': True})

if i == 0:
inst_y = connect_cell(instGCs[2], 'opt1', cell_y, 'opt1')
first_GC2 = instGCs[2]
else:
inst_y = connect_cell(first_GC2, 'opt1', cell_y, 'opt1')

inst_y.transform(Trans(Trans.R90, 270000 + x*1000, 200000))

inst_bragg1 = connect_cell(inst_y, 'opt1', cell_bragg, 'pin1')

inst_taper_cavity1 = connect_cell(inst_bragg1, 'pin2', cell_taper_cavity, 'pin1')

inst_taper_cavity2 = connect_cell(inst_taper_cavity1, 'pin1', cell_taper_cavity, 'pin1')
inst_taper_cavity2.transform(Trans(0, -cavity_length))

inst_bragg2 = connect_cell(inst_taper_cavity2, 'pin1', cell_bragg, 'pin2')

# Ring resonator from directional coupler PCells
#cell_dc = ly.create_cell("ebeam_dc_halfring_straight", "EBeam", { "r": r, "w": wg_width, "g": g, "bustype": 0 } )
#y_ring = GC_pitch*3/2
# first directional coupler
#t1 = Trans(Trans.R270, to_itype(x+wg_bend_radius, dbu), to_itype(y_ring, dbu))
#inst_dc1 = cell.insert(CellInstArray(cell_dc.cell_index(), t1))
# add 2nd directional coupler, snapped to the first one
#inst_dc2 = connect_cell(inst_dc1, 'pin2', cell_dc, 'pin4')

connect_pins_with_waveguide(inst_taper_cavity1, 'pin2', inst_taper_cavity2, 'pin2', waveguide_type='Multimode Strip TE 1550 nm, w=2000 nm')

# Create paths for waveguides, with the type defined in WAVEGUIDES.xml in the PDK
waveguide_type='Strip TE 1310 nm, w=350 nm'

# GC1 to bottom-left of ring pin3
#connect_pins_with_waveguide(instGCs[1], 'opt1', inst_bragg1, 'pin2', waveguide_type=waveguide_type)

# GC2 to top-left of ring pin1
connect_pins_with_waveguide(instGCs[2], 'opt1', inst_y, 'opt2', waveguide_type=waveguide_type)

# GC0 to top-right of ring
connect_pins_with_waveguide(instGCs[0], 'opt1', inst_bragg2, 'pin1', waveguide_type=waveguide_type)

# GC3 to bottom-right of ring
connect_pins_with_waveguide(instGCs[3], 'opt1', inst_y, 'opt3', waveguide_type=waveguide_type)

# Introduce an error, to demonstrate the Functional Verification
# inst_dc2.transform(Trans(1000,-1000))

return ly, cell

ly, cell = cavities()

# Zoom out
zoom_out(cell)

# Save
path = os.path.dirname(os.path.realpath(__file__))
filename = os.path.splitext(os.path.basename(__file__))[0]
file_out = export_layout(cell, path, filename, relative_path = '..', format='oas', screenshot=False)

print('layout script done')
Loading
Loading