luceda ipkiss教程 38:等长波导布线

这次介绍通过调整圆弧角度实现等长弯曲波导布线的案例:
在这里插入图片描述
四段波导的长度分别为:
在这里插入图片描述

所有代码如下:

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),
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值