Skip to content

Commit

Permalink
Merge pull request #2 from SiEPIC/master
Browse files Browse the repository at this point in the history
Update to latest version

Former-commit-id: 936b49b
  • Loading branch information
connormosquera authored May 21, 2020
2 parents 188b9f2 + a8eaa22 commit 3a61215
Show file tree
Hide file tree
Showing 17 changed files with 1,270 additions and 154 deletions.
4 changes: 2 additions & 2 deletions klayout_dot_config/grain.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<salt-grain>
<name>siepic_ebeam_pdk</name>
<version>0.3.26</version>
<version>0.3.27</version>
<api-version>0.25</api-version>
<title>SiEPIC EBeam PDK</title>
<doc>A Process Design Kit for Silicon Photonics fabricated using Electron Beam Lithography</doc>
Expand All @@ -14,6 +14,6 @@
<depends>
<name>siepic_tools</name>
<url/>
<version>0.3.50</version>
<version>0.3.63</version>
</depends>
</salt-grain>
10 changes: 10 additions & 0 deletions klayout_dot_config/tech/EBeam/WAVEGUIDES.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<model>ebeam_wg_integral_1550</model>
<bezier>0.20</bezier>
<radius>5.0</radius>
<width>0.5</width>
<component>
<layer>Si</layer>
<width>0.5</width>
Expand All @@ -22,6 +23,7 @@
<CML>EBeam</CML>
<model>ebeam_wg_integral_1310</model>
<radius>5.0</radius>
<width>0.41</width>
<component>
<layer>Si</layer>
<width>0.41</width>
Expand All @@ -34,6 +36,7 @@
<model>ebeam_wg_integral_1310</model>
<bezier>0.20</bezier>
<radius>5.0</radius>
<width>0.35</width>
<component>
<layer>Si</layer>
<width>0.35</width>
Expand All @@ -45,6 +48,7 @@
<CML>EBeam</CML>
<model>ebeam_wg_integral_1550</model>
<radius>15.0</radius>
<width>0.5</width>
<component>
<layer>Si</layer>
<width>0.5</width>
Expand All @@ -61,6 +65,7 @@
<CML>EBeam</CML>
<model>ebeam_wg_integral_1550</model>
<radius>10.0</radius>
<width>0.45</width>
<component>
<layer>Si</layer>
<width>0.45</width>
Expand All @@ -78,6 +83,7 @@
<model>ebeam_wg_integral_1550</model>
<bezier>0.20</bezier>
<radius>300.0</radius>
<width>2.0</width>
<component>
<layer>Si</layer>
<width>2.0</width>
Expand All @@ -90,6 +96,7 @@
<model>ebeam_wg_integral_1550</model>
<bezier>0.20</bezier>
<radius>500.0</radius>
<width>3.0</width>
<component>
<layer>Si</layer>
<width>3.0</width>
Expand All @@ -101,6 +108,7 @@
<CML>EBeam_beta</CML>
<model>ebeam_wg_eskid_1550</model>
<radius>3.0</radius>
<width>1.31</width>
<bezier>0.20</bezier>
<component>
<layer>Si</layer>
Expand Down Expand Up @@ -153,6 +161,7 @@
<CML>EBeam</CML>
<model>ebeam_wg_rib_1550</model>
<radius>15.0</radius>
<width>0.5</width>
<component>
<layer>Si</layer>
<width>0.5</width>
Expand All @@ -169,6 +178,7 @@
<CML>EBeam</CML>
<model>ebeam_wg_rib_1550</model>
<radius>15.0</radius>
<width>0.35</width>
<component>
<layer>Si</layer>
<width>0.35</width>
Expand Down
76 changes: 55 additions & 21 deletions klayout_dot_config/tech/EBeam/drc/SiEPIC_EBeam_DRC.lydrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<dsl-interpreter-name>drc-dsl-xml</dsl-interpreter-name>
<text># Basic DRC deck for SiEPIC_EBeam_PDK
# Lukas Chrostowski, 2016
# Mustafa Hammood, 2020 update

# Read about DRC scripts in the User Manual under "Design Rule Check (DRC)"
# http://klayout.de/doc/manual/drc_basic.html
Expand All @@ -24,50 +25,83 @@ report("DRC")

# Layers:
LayerSi=input(1,0)
LayerSip6nm=input(31,0)
LayerSi_rib=input(2,0)
DevRec=input(68,0)
LayerFP=input(99)
LayerM1=input(11,0)
LayerM2=input(12,0)
LayerMLOpen=input(13,0)
LayerVC=input(40,0)
LayerN=input(20,0)
LayerNpp=input(24,0)

# minimum feature size of 60nm of silicon
LayerSi.width(0.06, angle_limit(80)).output("Si_width","Si minimum feature size violation; min 60 nm")
LayerSi.space(0.06).output("Si_space","Si minimum space violation; min 60 nm")
#################
# non-physical checks
#################

# Check device overlaps
# Check device overlaps (functional check)
overlaps = DevRec.merged(2)
output(overlaps, "Devices","Devices cannot be overlapping")

# make sure the devices are within the floor plan layer region;
LayerSi.outside(LayerFP).output("Boundary","devices are out of boundary")

# Metal rules based on the metalization process provided by Applied Nanotools.
# Based contact optical lithography
#################
# physical checks
#################

# minimum feature size of Si is 60 nm and minimum exclusion between Si is 60 nm
LayerSi.width(0.06, angle_limit(80)).output("Si_width","Si minimum feature size violation; min 60 nm")
LayerSip6nm.width(0.06, angle_limit(80)).output("Sip6nm_width","Si minimum feature size violation; min 60 nm")
LayerSi.space(0.06, angle_limit(80)).output("Si_space","Si minimum space violation; min 60 nm")
LayerSip6nm.space(0.06, angle_limit(80)).output("Sip6nm_space","Si minimum space violation; min 60 nm")

# minimum feature size of Si rib is 100 nm and minimum exclusion between Si is 60 nm
LayerSi_rib.width(0.1, angle_limit(80)).output("Si_rib_width","Si_rib minimum feature size violation; min 100 nm")

# Metal rules based on the metalization process provided by Applied Nanotools, based on contact optical lithography.
# Metal heater, M1
LayerM1.width(3.0).output("M1_width","M1 minimum feature size violation; min 3 micron")
LayerM1.space(3.0).output("M1_space","M1 minimum space violation; min 3 micron")
LayerM1.width(3.0, angle_limit(70)).output("M1_width","M1 minimum feature size violation; min 3 µm")
LayerM1.space(3.0).output("M1_space","M1 minimum space violation; min 3 µm")

# Metal routing/contact, M2
LayerM2.width(5.0).output("M2_width","M2 minimum feature size violation; min 5 micron")
LayerM2.space(10.0).output("M2_space","M2 minimum space violation; min 10 micron")
LayerM2.overlap(LayerM1,3.0).output("M2_M1_overlap","M2 minimum overlap with M1 violation; min 3 micron")
LayerM2.width(5.0, angle_limit(70)).output("M2_width","M2 minimum feature size violation; min 5 µm")
LayerM2.space(8.0).output("M2_space","M2 minimum space violation; min 8 µm")

# Metal pad air opening, MLOpen
LayerMLOpen=input(13,0)
LayerMLOpen.width(10.0).output("MLOpen_width","MLOpen minimum feature size violation; min 10 micron")
LayerMLOpen.space(10.0).output("MLOpen_space","MLOpen minimum space violation; min 10 micron")
LayerMLOpen.width(10.0).output("MLOpen_width","MLOpen minimum feature size violation; min 10 µm")
LayerMLOpen.space(10.0).output("MLOpen_space","MLOpen minimum space violation; min 10 µm")

# Doping rules based on the experimental process
# minimum feature size of 3 µm
LayerNpp.width(3.0, angle_limit(80)).output("Npp_width","Doping minimum feature size violation; min 3 µm")
LayerNpp.space(5.0).output("Npp_space","Doping minimum space violation; min 5 µm")
# Oxide contact vias
LayerVC.width(5.0, angle_limit(70)).output("VC_width","VC minimum feature size violation; min 5 µm")
LayerVC.space(5.0).output("VC_space","VC minimum space violation; min 5 µm")

# NPP Doping
LayerNpp.width(2.0, angle_limit(70)).output("Npp_width","Npp Doping minimum feature size violation; min 2 µm")
LayerNpp.space(2.0).output("Npp_space","Npp minimum space violation; min 2 µm")

# N Doping
LayerN.width(2.0, angle_limit(70)).output("N_width","N Doping minimum feature size violation; min 2 µm")
LayerN.space(2.0).output("N_space","N minimum space violation; min 2 µm")

# minimum separation between NPP and Si
LayerNpp.separation(LayerSi, 2.0).output("Npp_Si_separation","Npp-Si minimum separation violation; min 2 µm")

# minimum separation between VC and Si
LayerVC.separation(LayerSi, 3.0).output("VC_Si_separation","VC-Si minimum separation violation; min 3 µm")

# minimum overlap rules:
LayerM2.overlap(LayerM1,3.0).output("M2_M1_overlap","M2 minimum overlap with M1 violation; min 3 µm")
LayerM2.overlap(LayerVC, 5.0).output("M2_VC_overlap","Metal2-VC minimum overlap violation; min 5 µm")
LayerN.overlap(LayerNpp, 3.0).output("N_Npp_overlap","N-Npp minimum overlap violation; min 3 µm")
LayerVC.overlap(LayerNpp, 5.0).output("VC_Npp_overlap","VC-Npp minimum overlap violation; min 5 µm")

# minimum separation:
LayerNpp.separation(LayerSi, 4.0).output("Npp_Si_separation","Npp-Si minimum separation violation; min 4 µm")
# minimum inclusion rules:
LayerM2.enclosing(LayerVC, 1.0).output("M2_VC_enclosure","M2-VC minimum enclosure violation; min 1 µm")
LayerSi_rib.enclosing(LayerVC, 1.0).output("Si_rib_VC_enclosure","Si_rib-VC minimum enclosure violation; min 1 µm")

# minimum overlap:
LayerM2.overlap(LayerNpp, 7.0).output("M_Npp_overlap","Metal2-Npp minimum overlap violation; min 7 µm")

</text>
</klayout-macro>
Binary file not shown.
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_bdc_te1550.gds
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_crossing4.gds
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_gc_te1550.gds
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_gc_tm1550.gds
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_y_1550.gds
Binary file not shown.
Binary file modified klayout_dot_config/tech/EBeam/gds/mature/ebeam_y_adiabatic.gds
Binary file not shown.
89 changes: 26 additions & 63 deletions klayout_dot_config/tech/EBeam/pymacros/SiEPIC_EBeam Library.lym
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ class Waveguide(pya.PCellDeclarationHelper):

def produce_impl(self):

from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal
from SiEPIC.utils.layout import layout_waveguide2
from SiEPIC.utils import angle_vector
from math import cos, sin, pi, sqrt
import pya
from SiEPIC.extend import to_itype
Expand All @@ -181,47 +182,10 @@ class Waveguide(pya.PCellDeclarationHelper):
if not (len(self.layers)==len(self.widths) and len(self.layers)==len(self.offsets) and len(self.offsets)==len(self.widths)):
raise Exception("There must be an equal number of layers, widths and offsets")
path.unique_points()
turn=0
for lr in range(0, len(self.layers)):
layer = self.layout.layer(TECHNOLOGY[self.layers[lr]])

width = to_itype(self.widths[lr],dbu)
offset = to_itype(self.offsets[lr],dbu)

pts = path.get_points()
wg_pts = [pts[0]]
for i in range(1,len(pts)-1):
turn = ((angle_b_vectors(pts[i]-pts[i-1],pts[i+1]-pts[i])+90)%360-90)/90
dis1 = pts[i].distance(pts[i-1])
dis2 = pts[i].distance(pts[i+1])
angle = angle_vector(pts[i]-pts[i-1])/90
pt_radius = to_itype(self.radius,dbu)
# determine the radius, based on how much space is available
if len(pts)==3:
pt_radius = min (dis1, dis2, pt_radius)
else:
if i==1:
if dis1 &lt;= pt_radius:
pt_radius = dis1
elif dis1 &lt; 2*pt_radius:
pt_radius = dis1/2
if i==len(pts)-2:
if dis2 &lt;= pt_radius:
pt_radius = dis2
elif dis2 &lt; 2*pt_radius:
pt_radius = dis2/2
# waveguide bends:
if(self.adiab):
wg_pts += Path(arc_bezier(pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]), self.bezier, DevRec='DevRec' in self.layers[lr]), 0).transformed(Trans(angle, turn &lt; 0, pts[i])).get_points()
else:
wg_pts += Path(arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]),DevRec='DevRec' in self.layers[lr]), 0).transformed(Trans(angle, turn &lt; 0, pts[i])).get_points()
wg_pts += [pts[-1]]
wg_pts = pya.Path(wg_pts, 0).unique_points().get_points()
wg_polygon = Polygon(translate_from_normal(wg_pts, width/2 + (offset if turn &gt; 0 else - offset))+translate_from_normal(wg_pts, -width/2 + (offset if turn &gt; 0 else - offset))[::-1])
self.cell.shapes(layer).insert(wg_polygon)

if self.layout.layer(TECHNOLOGY['Waveguide']) == layer:
waveguide_length = wg_polygon.area() / self.width * dbu**2
pts = path.get_points()

# Draw the waveguide geometry, new in SiEPIC-Tools v0.3.64
waveguide_length = layout_waveguide2(TECHNOLOGY, self.layout, self.cell, self.layers, self.widths, self.offsets, pts, self.radius, self.adiab, self.bezier)

pts = path.get_points()
LayerPinRecN = self.layout.layer(TECHNOLOGY['PinRec'])
Expand All @@ -245,47 +209,46 @@ class Waveguide(pya.PCellDeclarationHelper):
if angle_vec == 0: # horizontal
halign = 2 # right
angle=0
pt2=pts[0] + Point(0, wg_width)
pt3=pts[0] + Point(0, -wg_width)
pt4=pts[0] + Point(0, -2*wg_width)
pt2=pts[0] + Point(0, 0.2*wg_width)
pt3=pts[0] + Point(0, -0.2*wg_width)
pt4=pts[0] + Point(0, -0.5*wg_width)
if angle_vec == 2: # horizontal
halign = 0 # left
angle = 0
pt2=pts[0] + Point(0, wg_width)
pt3=pts[0] + Point(0, -wg_width)
pt4=pts[0] + Point(0, -2*wg_width)
pt2=pts[0] + Point(0, 0.2*wg_width)
pt3=pts[0] + Point(0, -0.2*wg_width)
pt4=pts[0] + Point(0, -0.5*wg_width)
if angle_vec == 1: # vertical
halign = 2 # right
angle = 1
pt2=pts[0] + Point(wg_width,0)
pt3=pts[0] + Point(-wg_width,0)
pt4=pts[0] + Point(-2*wg_width,0)
pt2=pts[0] + Point(0.2*wg_width,0)
pt3=pts[0] + Point(-0.2*wg_width,0)
pt4=pts[0] + Point(-0.5*wg_width,0)
if angle_vec == -1: # vertical
halign = 0 # left
angle = 1
pt2=pts[0] + Point(wg_width,0)
pt3=pts[0] + Point(-wg_width,0)
pt4=pts[0] + Point(-2*wg_width,0)
pt2=pts[0] + Point(0.2*wg_width,0)
pt3=pts[0] + Point(-0.2*wg_width,0)
pt4=pts[0] + Point(-0.5*wg_width,0)

t = Trans(angle, False, pts[0])

text = Text ('Lumerical_INTERCONNECT_library=Design kits/%s' % self.CML, t, 0.1/dbu, -1)
t = Trans(angle, False, pt3)
text = Text ('Lumerical_INTERCONNECT_library=Design kits/%s' % self.CML, t, 0.1*wg_width, -1)
text.halign=halign
shape = self.cell.shapes(LayerDevRecN).insert(text)
t = Trans(angle, False, pt2)
text = Text ('Component=%s' % self.model, t, 0.1/dbu, -1)
text = Text ('Component=%s' % self.model, t, 0.1*wg_width, -1)
text.halign=halign
shape = self.cell.shapes(LayerDevRecN).insert(text)
t = Trans(angle, False, pt3)
t = Trans(angle, False, pts[0])
pts_txt = str([ [round(p.to_dtype(dbu).x,3), round(p.to_dtype(dbu).y,3)] for p in pts ]).replace(', ',',')
text = Text ( \
'Spice_param:wg_length=%.3fu wg_width=%.3fu points="%s" radius=%s' %\
(waveguide_length, self.width, pts_txt,self.radius ), t, 0.1/dbu, -1 )
(waveguide_length, self.width, pts_txt,self.radius ), t, 0.1*wg_width, -1 )
text.halign=halign
shape = self.cell.shapes(LayerDevRecN).insert(text)
t = Trans(angle, False, pt4)
text = Text ( \
'Length=%.3fu' %(waveguide_length), t, 0.5/dbu, -1 )
'Length=%.3fu' %(waveguide_length), t, 0.5*wg_width, -1 )
text.halign=halign
shape = self.cell.shapes(LayerDevRecN).insert(text)

Expand Down Expand Up @@ -1746,15 +1709,15 @@ class SiEPIC_EBeam(Library):
# windows only allows for a fixed width, short description
self.description = ""
# OSX does a resizing:
self.description = "Components with models"
self.description = "v0.3.28, Components with models"


# Import all the GDS files from the tech folder "gds"
import os, fnmatch
dir_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../gds/mature")
search_str = '*' + '.gds'
for root, dirnames, filenames in os.walk(dir_path, followlinks=True):
for filename in fnmatch.filter(filenames, search_str):
for filename in fnmatch.filter([f.lower() for f in filenames], search_str):
file1=os.path.join(root, filename)
print(" - reading %s" % file1 )
self.layout().read(file1)
Expand Down
Loading

0 comments on commit 3a61215

Please sign in to comment.