Skip to content

Commit

Permalink
updated merge, improved designs
Browse files Browse the repository at this point in the history
merging system ensures FaML are on a 127 µm pitch
  • Loading branch information
lukasc-ubc committed Oct 27, 2024
1 parent 7722ffe commit e588651
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 229 deletions.
34 changes: 29 additions & 5 deletions DFT.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@

# Design for Test rules

- All design submissions must follow the Design for Test (DFT) rules. Two optical interfaces are available: surface grating couplers (GC), and facet-attached micro-lenses (FaML)
- All design submissions must follow the Design for Test (DFT) rules. Three optical interfaces are available: surface grating couplers (GC), facet-attached micro-lenses (FaML), and facet-attached vertical emitters (FAVE).

## Grating Couplers

- area maximum: 610 µm wide, 405 µm high
- area design maximum: 1000 µm wide, 500 µm high
- grating coupler cells:
- SiEPIC_EBeam_PDK -> EBeam-SiN ->
- GC_SiN_TE_1310_8degOxide_BB
- GC_SiN_TE_1550_8degOxide_BB
- 127 µm pitch, verically aligned, single column, connected circuits
- up to 4 grating couplers
- opt_in label format: opt_in_TE_1550_device_designerUniqueIndentifier
Expand All @@ -18,12 +22,32 @@

## Facet-attached Micro-Lenses (FaML)

- area maximum: 1000 µm wide, 244 µm high
- area design maximum: 1000 µm wide, 500 µm high
- FaML coupler cells:
- SiEPIC_EBeam_PDK -> EBeam-Dream ->
- ebeam_dream_FaML_SiN_1550_BB
- 127 µm pitch, verically aligned, single column, connected circuits
- up to 3 lenses
- up to 4 lenses
- opt_in label format: opt_in_TE_1550_FaML_designerUniqueIndentifier
- opt_in label location: the lens and chip edge (0,0) of the FaML cell at the input
- Fiber Array test consists of:
- 1 (top FaML): input, laser
- 2 (middle FaML): output, to detector
- 3 (bottom FaML): output, to detector
- 3 (middle FaML): output, to detector
- 4 (bottom FaML): output, to detector

## Facet-attached Vertical Emitters (FAVE)

- area design maximum: 1000 µm wide, 500 µm high
- FaML coupler cells:
- SiEPIC_EBeam_PDK -> EBeam-Dream ->
- ebeam_dream_FAVE_SiN_1550_BB
- 127 µm pitch, verically aligned, single column, connected circuits
- up to 4 lenses
- opt_in label format: opt_in_TE_1550_FAVE_designerUniqueIndentifier
- opt_in label location: the edge (0,0) of the FAVE cell at the input
- Fiber Array test consists of:
- 1 (top FAVE): input, laser
- 2 (middle FAVE): output, to detector
- 3 (middle FAVE): output, to detector
- 4 (bottom FAVE): output, to detector
142 changes: 112 additions & 30 deletions merge/EBeam_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
tech_name = 'EBeam'
top_cell_name = 'EBeam_2024_10_SiN'
cell_Width = 1000e3
cell_Height = 410000
cell_Gap_Width = 8000
cell_Gap_Height = 8000
cell_FaML_width_extra = 100e3
cell_Height = 500e3
cell_Gap_Width = 8e3
cell_Gap_Height = 8e3
chip_Width = 8650000
chip_Height1 = 8490000
chip_Height2 = 8780000
Expand All @@ -32,7 +33,7 @@
tr_cutout_y = 8494000

filename_out = 'EBeam'
layers_keep = ['1/5', '4/0', '1/10', '68/0', '81/0', '10/0', '99/0', '26/0', '31/0', '32/0', '33/0', '998/0']
layers_keep = ['1/5', '4/0', '1/10', '68/0', '81/0', '10/0', '99/0', '26/0', '31/0', '32/0', '33/0', '201/0','998/0']
layer_text = '10/0'
layer_SEM = '200/0'
layer_SEM_allow = ['edXphot1x', 'ELEC413','SiEPIC_Passives'] # which submission folder is allowed to include SEM images
Expand All @@ -51,7 +52,7 @@

# KLayout
import pya
from pya import *
from pya import Trans, CellInstArray, Text

# SiEPIC-Tools
import SiEPIC
Expand Down Expand Up @@ -115,12 +116,18 @@ def log(text):
path2 = os.path.abspath(os.path.join(path,"../submissions"))
_, _, files = next(os.walk(path2), (None, None, []))
for f in sorted(files):
files_in.append(os.path.join(path2,f))
if 'FaML' in f:
files_in.append(os.path.join(path2,f))
for f in sorted(files):
if 'FaML' not in f:
files_in.append(os.path.join(path2,f))

# Create course cells using the folder name under the top cell
cell_edXphot1x = layout.create_cell("edX")
t = Trans(Trans.R0, 0,0)
top_cell.insert(CellInstArray(cell_edXphot1x.cell_index(), t))
cell_FaML = layout.create_cell("FaML")
top_cell.insert(CellInstArray(cell_FaML.cell_index(), t))
cell_ELEC413 = layout.create_cell("ELEC413")
top_cell.insert(CellInstArray(cell_ELEC413.cell_index(), t))
cell_SiEPIC_Passives = layout.create_cell("SiEPIC_Passives")
Expand All @@ -137,6 +144,7 @@ def log(text):

# Origins for the layouts
x,y = 110e3,cell_Height+cell_Gap_Height
previous_top_FaML = None

import subprocess
import pandas as pd
Expand All @@ -160,16 +168,17 @@ def log(text):
layout2 = pya.Layout()
layout2.read(f)

course = 'openEBL'
if 'ebeam' in basefilename.lower():
course = 'edXphot1x'
elif 'elec413' in basefilename.lower():
if 'faml' in basefilename.lower():
course = 'FaML'
if 'elec413' in basefilename.lower():
course = 'ELEC413'
elif 'openebl' in basefilename.lower():
if 'openebl' in basefilename.lower():
course = 'openEBL'
elif 'siepic_passives' in basefilename.lower():
if 'siepic_passives' in basefilename.lower():
course = 'SiEPIC_Passives'
else:
course = 'openEBL'

cell_course = eval('cell_' + course)
log(" - course name: %s" % (course) )
Expand All @@ -193,7 +202,15 @@ def log(text):
# check that there is one top cell in the layout
num_top_cells = len(layout2.top_cells())
if num_top_cells > 1:
log(' - layout should only contain one top cell; contains (%s): %s' % (num_top_cells, [c.name for c in layout2.top_cells()]) )
log(' - WARNING: layout should only contain one top cell; contains (%s): %s' % (num_top_cells, [c.name for c in layout2.top_cells()]) )
top_cells = layout2.top_cells()
top_cells.sort(key=lambda x: x.child_instances())
log(' - top cell (%s) has %s child_instances (highest one); renaming to "top".' % (top_cells[-1].name, top_cells[-1].child_instances()) )
top_cells[-1].name = 'top'
'''
for cell in layout2.top_cells():
log(' - top cell (%s) has %s hierarchy levels' % (cell.name, cell.hierarchy_levels()) )
'''
if num_top_cells == 0:
log(' - layout does not contain a top cell')

Expand Down Expand Up @@ -258,6 +275,7 @@ def log(text):
shapes_to_delete.append( s.shape() )
s.next()
for s in shapes_to_delete:
# need to delete the shapes all together, since the list of shapes in the shape recursive iterator changes if you delete one
s.delete()

# bounding box of the cell
Expand All @@ -269,24 +287,24 @@ def log(text):
t = Trans(Trans.R0, -bbox.left,-bbox.bottom)
subcell2.insert(CellInstArray(subcell.cell_index(), t))

# clip cells
cell2 = layout2.clip(cell.cell_index(), pya.Box(bbox.left,bbox.bottom,bbox.left+cell_Width,bbox.bottom+cell_Height))
# clip / crop cells
cell2 = layout2.clip(cell.cell_index(), pya.Box(bbox.left,bbox.bottom,bbox.left+cell_Width+(cell_FaML_width_extra if course == 'FaML' else 0),bbox.bottom+cell_Height))
bbox2 = layout2.cell(cell2).bbox()
if bbox != bbox2:
log(' - WARNING: Cell was clipped to maximum size of %s X %s' % (cell_Width, cell_Height) )
log(' - WARNING: Cell was clipped to maximum size of %s X %s' % (cell_Width +(cell_FaML_width_extra if course == 'FaML' else 0), cell_Height) )
log(' - clipped bounding box: %s' % bbox2.to_s() )

# copy
subcell.copy_tree(layout2.cell(cell2))

subcell.copy_tree(cell)
'''
if course is not 'FaML':
# copy
subcell.copy_tree(layout2.cell(cell2))
else:
subcell.copy_tree(cell)
'''

# Check if this cell would overlap with other Floorplans, then move if necessary
def next_position(x, y, subcell, cell_Gap_Height, cell_Gap_Width, chip_Height, cell_Height, cell_Width):
# Measure the height of the cell that was added, and move up
y += cell_Gap_Height
if y + cell_Height > chip_Height:
y = cell_Height + cell_Gap_Height
x += cell_Width + cell_Gap_Width
return x, y

# Get Floorplan regions for the entire chip so far
Layer_FP = layout.find_layer(99,0) # or use "layer"
iter1 = pya.RecursiveShapeIterator(layout, top_cell, Layer_FP )
Expand All @@ -297,23 +315,85 @@ def next_position(x, y, subcell, cell_Gap_Height, cell_Gap_Width, chip_Height, c
iter1.next()
r1.merge()
# print(" - Floorplan merged: %s" % r1)

# offset for the facet-attached micro lenses
if course == 'FaML':
x_offset = -100e3
# Find the FaML cells, and make sure they are on a 127 µm pitch
def sub_instances(instance,name):
found_instances = []
if type(instance) == pya.Cell:
cell = instance
else:
cell = instance.cell()
for inst in cell.each_inst():
# log(' - looking for FaML instance: %s' % (inst.to_s()))
if inst.cell.name == name:
found_instances.append(inst)
# log(' - Found FaML instance: %s, %s' % (inst.to_s(), inst.cell.name))
elif inst.cell.child_instances() > 0:
for f in sub_instances(inst,name):
if f.cell.name == name:
found_instances.append(f)
return found_instances

found_faml_instances = sub_instances(layout2.top_cells()[0], name = 'ebeam_dream_FaML_SiN_1550_BB')
#for f in found_faml_instances:
# log(' - Found FaML instance: %s, %s' % (f.to_s(), f.cell.name))
found_faml_instances.sort(key=lambda x: -x.cplx_trans.disp.y)
for f in found_faml_instances:
log(' - Found FaML instance (sorted): %s, %s' % (f.to_s(), f.cell.name))
top_FaML = found_faml_instances[0].cplx_trans.disp.y

else:
x_offset = 0

def next_position(x, y, cell_Gap_Height, cell_Gap_Width, chip_Height, cell_Height, cell_Width):
# Measure the height of the cell that was added, and move up
y += cell_Gap_Height
if y + cell_Height > chip_Height:
y = cell_Height + cell_Gap_Height
x += cell_Width + cell_Gap_Width
return x, y

interacting = True
while interacting:
r2 = pya.Region(pya.Box(x,y, x+bbox2.width(),y+bbox2.height()))
r2 = pya.Region(pya.Box(x+x_offset,y, x+x_offset+bbox2.width(),y+bbox2.height()))
interacting = r2.interacting(r1)
if interacting:
# print(" - Overlapping Floorplan: %s" % r2.interacting(r1))
x,y = next_position(x, y, subcell, cell_Gap_Height, cell_Gap_Width, chip_Height2, cell_Height, cell_Width)
x,y = next_position(x, y, cell_Gap_Height, cell_Gap_Width, chip_Height2, cell_Height, cell_Width)

if course == 'FaML':
# Check and snap to 127 µm pitch
if previous_top_FaML:
FaML_delta = top_FaML+y - previous_top_FaML
log(' - FaML count: %s' % (FaML_delta/127e3) )
if FaML_delta % 127e3 > 0:
# log(' - Adjancent designs do not have matching FaML pitch: %s error' % (FaML_delta) )
y_add = 127e3 - FaML_delta % 127e3
log(' - shifting design up by %s µm, to have matching FaML pitch.' % (y_add/1e3) )
y += y_add


# Insert cell instance in the chip
t = Trans(Trans.R0, x,y)
t = Trans(Trans.R0, x+x_offset,y)
cell_course.insert(CellInstArray(subcell2.cell_index(), t))

log(' - Placed at position: %s, %s' % (x,y) )
log(' - Design placed at position: %s, %s' % (x,y) )

if course == 'FaML':
# record placement of FaML
previous_top_FaML = found_faml_instances[0].cplx_trans.disp.y + y
log(' - top FaML position: %s' % (previous_top_FaML) )

# Measure the height of the cell that was added, and move up
y += max (cell_Height, subcell.bbox().height()) + cell_Gap_Height
#y += max (cell_Height, subcell.bbox().height()) + cell_Gap_Height
if course == 'FaML':
from math import ceil
y += ceil(subcell.bbox().height()/127e3)*127e3
else:
y += subcell.bbox().height() + cell_Gap_Height
# move right and bottom when we reach the top of the chip
if y + cell_Height > chip_Height1 and x == 0:
y = cell_Height + cell_Gap_Height
Expand All @@ -332,6 +412,8 @@ def next_position(x, y, subcell, cell_Gap_Height, cell_Gap_Width, chip_Height, c
# Check bottom right cutout #2 for PCM
if x + cell_Width > br_cutout2_x and y < br_cutout2_y:
y = br_cutout2_y
else:
log(" - WARNING: Top cell not merged (%s)" % cell.name)

'''
text_out,opt_in = find_automated_measurement_labels(topcell=top_cell, LayerTextN=layerTextN)
Expand Down
Binary file modified submissions/EBeam_LukasChrostowski_MZI1_1550_FaML.oas
Binary file not shown.
Binary file modified submissions/EBeam_LukasChrostowski_MZI2_1550_FaML.oas
Binary file not shown.
Binary file removed submissions/EBeam_LukasChrostowski_MZI_1550_FaML.oas
Binary file not shown.
Binary file not shown.
Binary file modified submissions/EBeam_LukasChrostowski_loopback_1550_FaML.oas
Binary file not shown.
Loading

0 comments on commit e588651

Please sign in to comment.