这次介绍通过调整圆弧角度实现等长弯曲波导布线的案例:
四段波导的长度分别为:
所有代码如下:
from si_fab import all as pdk
from ipkiss3 import all as i3
class MMI1x4(i3.PCell):
_name_prefix = "MMI1x4" # adding a name that will be added to every instance of this class
trace_template = i3.TraceTemplateProperty(doc="Trace template of the access waveguide.")
width = i3.PositiveNumberProperty(default=15.0, doc="Width of the MMI section.")
length = i3.PositiveNumberProperty(default=20.0, doc="Length of the MMI section.")
taper_width = i3.PositiveNumberProperty(default=1.0, doc="Width of the taper.")
taper_length = i3.PositiveNumberProperty(default=5.0, doc="Length of the taper.")
waveguide_spacing = i3.PositiveNumberProperty(default=2.0, doc="Spacing between the waveguides.")
def _default_trace_template(self):
return pdk.SiWireWaveguideTemplate()
class Layout(i3.LayoutView):
def _generate_elements(self, elems):
# 2. Similar to the circuit, here we are creating some local variables to improve the readability of
# the code.
length = self.length
width = self.width
taper_length = self.taper_length
taper_width = self.taper_width
half_waveguide_spacing = 0.5 * self.waveguide_spacing
core_layer = self.trace_template.core_layer
cladding_layer = self.trace_template.cladding_layer
core_width = self.trace_template.core_width
# Si core
elems += i3.Rectangle(
layer=core_layer,
center=(0.5 * length, 0.0),
box_size=(length, width),
)
elems += i3.Wedge(
layer=core_layer,
begin_coord=(-taper_length, 0.0),
end_coord=(0.0, 0.0),
begin_width=core_width,
end_width=taper_width,
)
elems += i3.Wedge(
layer=core_layer,
begin_coord=(length, half_waveguide_spacing),
end_coord=(length + taper_length, half_waveguide_spacing),
begin_width=taper_width,
end_width=core_width,
)
elems += i3.Wedge(
layer=core_layer,
begin_coord=(length, half_waveguide_spacing * 3),
end_coord=(length + taper_length, half_waveguide_spacing * 3),
begin_width=taper_width,
end_width=core_width,
)
elems += i3.Wedge(
layer=core_layer,
begin_coord=(length, -half_waveguide_spacing),
end_coord=(length + taper_length, -half_waveguide_spacing),
begin_width=taper_width,
end_width=core_width,
)
elems += i3.Wedge(
layer=core_layer,
begin_coord=(length, -half_waveguide_spacing * 3),
end_coord=(length + taper_length, -half_waveguide_spacing * 3),
begin_width=taper_width,
end_width=core_width,
)
return elems
def _generate_ports(self, ports):
length = self.length
taper_length = self.taper_length
trace_template = self.trace_template
half_waveguide_spacing = 0.5 * self.waveguide_spacing
# 3. Using parameters allows us to place the ports automatically. This is important as otherwise it would
# be easy to change the geometries of a component but not the ports. This would not raise errors, but the
# design would not work after fabrication, as you would incur in waveguide misalignments.
ports += i3.OpticalPort(
name="in",
position=(-taper_length, 0.0),
angle=180.0,
trace_template=trace_template,
)
ports += i3.OpticalPort(
name="out3",
position=(length + taper_length, -half_waveguide_spacing),
angle=0.0,
trace_template=trace_template,
)
ports += i3.OpticalPort(
name="out2",
position=(length + taper_length, half_waveguide_spacing),
angle=0.0,
trace_template=trace_template,
)
ports += i3.OpticalPort(
name="out4",
position=(length + taper_length, -half_waveguide_spacing * 3),
angle=0.0,
trace_template=trace_template,
)
ports += i3.OpticalPort(
name="out1",
position=(length + taper_length, half_waveguide_spacing * 3),
angle=0.0,
trace_template=trace_template,
)
return ports
class Netlist(i3.NetlistFromLayout):
pass
class demo(i3.Circuit):
_name_prefix = "demo" # adding a name that will be added to every instance of this class
mmi = i3.ChildCellProperty()
def _default_mmi(self):
return MMI1x4()
def _default_insts(self):
def wg(end_angle):
arc = i3.RoundedWaveguide(trace_template=pdk.SWG450())
arc.Layout(shape=i3.ShapeArc(radius=50,
start_angle=0,
end_angle=end_angle,
start_face_angle=90,
end_face_angle=end_angle + 90), )
return arc
insts = {
"mmi1": self.mmi.modified_copy(waveguide_spacing=4),
"mmi2": self.mmi.modified_copy(waveguide_spacing=2),
"wg1": wg(end_angle=18.0015),
"wg2": wg(end_angle=19.07135),
"wg3": wg(end_angle=19.988),
"wg4": wg(end_angle=20.75-0.00005),
}
return insts
def _default_specs(self):
specs = []
specs += [
i3.Place("mmi1:in", (0, 0)),
i3.Place("mmi2:in", (200, 0), 0),
i3.Join("wg1:in", "mmi1:out1"),
i3.Join("wg2:in", "mmi1:out2"),
i3.Join("wg3:in", "mmi1:out3"),
i3.Join("wg4:in", "mmi1:out4"),
i3.ConnectBend("wg1:out", "mmi2:out4", bend_radius=50),
i3.ConnectBend("wg2:out", "mmi2:out3", bend_radius=50),
i3.ConnectBend("wg3:out", "mmi2:out2", bend_radius=50),
i3.ConnectBend("wg4:out", "mmi2:out1", bend_radius=50),
]
return specs
if __name__ == "__main__":
demo_layout = demo().Layout()
l1 = demo().Layout().instances["wg1"].reference.trace_length() + demo().Layout().instances[
"wg1_out_to_mmi2_out4"].reference.trace_length()
l2 = demo().Layout().instances["wg2"].reference.trace_length() + demo().Layout().instances[
"wg2_out_to_mmi2_out3"].reference.trace_length()
l3 = demo().Layout().instances["wg3"].reference.trace_length() + demo().Layout().instances[
"wg3_out_to_mmi2_out2"].reference.trace_length()
l4 = demo().Layout().instances["wg4"].reference.trace_length() + demo().Layout().instances[
"wg4_out_to_mmi2_out1"].reference.trace_length()
print(l1)
print(l2)
print(l3)
print(l4)
demo_layout.visualize()
代码的核心是调整四段圆弧的角度:
"wg1": wg(end_angle=18.0015),
"wg2": wg(end_angle=19.07135),
"wg3": wg(end_angle=19.988),
"wg4": wg(end_angle=20.75-0.00005),