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

Component min spacing #210

Merged
merged 5 commits into from
May 3, 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
2 changes: 1 addition & 1 deletion .github/workflows/run-layout-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: install python 3.9 packages
run: |
python -m pip install --upgrade pip
pip install klayout==0.28.17 numpy scipy pytest pytest-cov
pip install klayout numpy scipy pytest pytest-cov

- name: Test with pytest, python 3.9
run: pytest klayout_dot_config/tech
1 change: 1 addition & 0 deletions klayout_dot_config/python/SiEPIC/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
load_Waveguides_by_Tech
load_Calibre
load_Monte_Carlo
load_Verification
load_DFT
load_FDTD_settings
load_GC_settings
Expand Down
38 changes: 36 additions & 2 deletions klayout_dot_config/python/SiEPIC/verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ def layout_check(cell=None, verbose=False, GUI=False, timing=False, file_rdb = N
rdb_cat_id_GCarrayconfig.description = "Circuit must be connected such that there is at most %s Grating Coupler(s) %s the opt_in label (laser injection port) and at most %s Grating Coupler(s) %s the opt_in label. \nGrating couplers must be on a %s micron pitch, %s arranged." % (
int(DFT['design-for-test']['grating-couplers']['detectors-above-laser']), dir1,int(DFT['design-for-test']['grating-couplers']['detectors-below-laser']), dir2,float(DFT['design-for-test']['grating-couplers']['gc-pitch']),dir3)

# minimum-gc-spacing
if 'minimum-gc-spacing' in DFT['design-for-test']['grating-couplers'].keys():
rdb_cat_id_GC_min_spacing= rdb.create_category(rdb_cat_id, "Grating coupler: minimum spacing")
rdb_cat_id_GC_min_spacing.description = "The grating coupler spacing (pitch) must be at least %s microns." % float(DFT['design-for-test']['grating-couplers']['minimum-gc-spacing'])


else:
if verbose:
print(' No DFT rules found.')
Expand Down Expand Up @@ -338,6 +344,9 @@ def layout_check(cell=None, verbose=False, GUI=False, timing=False, file_rdb = N
rdb_item = rdb.create_item(rdb_cell.rdb_id(), rdb_cat_id_comp_shapesoutside.rdb_id())
rdb_item.add_value(pya.RdbItemValue(e[0].dpolygon.transformed(e[1].to_trans().to_itrans(dbu))))




if timing:
print("*** layout_check(), timing; done shapes in component ")
print(' Time elapsed: %s' % (time() - time1))
Expand Down Expand Up @@ -441,6 +450,28 @@ def layout_check(cell=None, verbose=False, GUI=False, timing=False, file_rdb = N
rdb_item.add_value(pya.RdbItemValue( "Cell %s should be %s degrees" % (ci,DFT_GC_angle) ))
rdb_item.add_value(pya.RdbItemValue(c.polygon.to_dtype(dbu)))

# minimum-gc-spacing
# grating couplers need to be far enough apart for the automated probe station so it doesn't get confused
# check if the component "c" in the loop is a grating coupler:
if 'minimum-gc-spacing' in DFT['design-for-test']['grating-couplers'].keys():
test = [ci.startswith(k) for k in DFT['design-for-test']['grating-couplers']['gc-orientation'].keys()]
if any(test):
min_gc_spacing = float(DFT['design-for-test']['grating-couplers']['minimum-gc-spacing']) / dbu
for i2 in range(i + 1, len(components)):
c2 = components[i2]
c2i = c2.basic_name
# check if the 2nd component "c2" in the loop is a grating coupler:
test = [c2i.startswith(k) for k in DFT['design-for-test']['grating-couplers']['gc-orientation'].keys()]
if any(test):
# compare two grating coupler distances, versus the rule
dist = (c.trans.disp-c2.trans.disp).abs()
# print('dist: %s, %s' % (dist, min_gc_spacing))
if dist < min_gc_spacing:
rdb_item = rdb.create_item(rdb_cell.rdb_id(), rdb_cat_id_GC_min_spacing.rdb_id())
rdb_item.add_value(pya.RdbItemValue( "Grating couplers should be at least %s microns apart (center-to-center pitch)" % (min_gc_spacing) ))
rdb_item.add_value(pya.RdbItemValue(c.polygon.to_dtype(dbu)))
rdb_item.add_value(pya.RdbItemValue(c2.polygon.to_dtype(dbu)))


# Pre-simulation check: do components have models?
# disabled by lukasc, 2021/05
Expand Down Expand Up @@ -497,7 +528,7 @@ def layout_check(cell=None, verbose=False, GUI=False, timing=False, file_rdb = N
# find the GC closest to the opt_in label.
components_sorted = sorted([c for c in components if [p for p in c.pins if p.type == _globals.PIN_TYPES.OPTICALIO]],
key=lambda x: x.trans.disp.to_p().distance(pya.Point(t.x, t.y).to_dtype(1)))
# GC too far check:
# GC opt_in label too far check:
if components_sorted:
dist_optin_c = components_sorted[0].trans.disp.to_p(
).distance(pya.Point(t.x, t.y).to_dtype(1))
Expand All @@ -510,7 +541,10 @@ def layout_check(cell=None, verbose=False, GUI=False, timing=False, file_rdb = N
(components_sorted[0].instance, opt_in[ti1]['opt_in']))
rdb_item = rdb.create_item(rdb_cell.rdb_id(), rdb_cat_id_optin_toofar.rdb_id())
rdb_item.add_value(pya.RdbItemValue(pya.Polygon(box).to_dtype(dbu)))

rdb_item.add_value(pya.RdbItemValue(components_sorted[0].polygon.to_dtype(dbu)))
# it would be nice to highlight the entire text, but bbox returns a point https://www.klayout.de/doc-qt5/code/class_DText.html#method18
# rdb_item.add_value(pya.RdbItemValue(t.bbox()))

# starting with each opt_in label, identify the sub-circuit, then GCs, and
# check for GC spacing
trimmed_nets, trimmed_components = trim_netlist(
Expand Down
Loading