案例分享:画微环调制器
luceda ipkiss教程 57:画微环调制器-LMLPHP
全部代码如下:

from si_fab import all as pdk
from ipkiss3 import all as i3

class DC(i3.PCell):
    straight_length = i3.PositiveNumberProperty(default=200)
    radius = i3.PositiveNumberProperty(default=50)
    spacing = i3.PositiveNumberProperty(default=1)
    straight_waveguide = i3.ChildCellProperty()
    arc_waveguide = i3.ChildCellProperty()
    trace_template = i3.TraceTemplateProperty(
        default=pdk.SWG450(), doc="The trace template for waveguide and heater"
    )

    def _default_straight_waveguide(self):
        wg = i3.Waveguide(trace_template=self.trace_template)
        wg.Layout(shape=i3.Shape([(0, 0), (self.straight_length, 0)]))
        return wg

    def _default_arc_waveguide(self):
        wg = i3.RoundedWaveguide(trace_template=self.trace_template)
        wg.Layout(shape=i3.ShapeArc(radius=self.radius, start_angle=0, start_face_angle=90, end_angle=180,
                                    end_face_angle=270))
        return wg
    class Layout(i3.LayoutView):
        def _generate_instances(self, insts):
            insts += i3.place_and_route(
                insts={
                    "wg1": self.straight_waveguide,
                    "wg2": self.arc_waveguide,
                },
                specs=[
                    i3.Place("wg1:in", (-self.straight_length / 2, 0)),
                ]
            )
            insts = i3.place_and_route(
                insts=insts,
                specs=[
                    i3.PlaceRelative("wg2:out", "wg1:in",
                                     (self.straight_length / 2 - self.radius, -self.radius - self.spacing))

                ]
            )
            return insts

        def _generate_ports(self, ports):
            ports += i3.expose_ports(
                instances=self.instances,
                port_name_map={
                    "wg1:in": "in1",
                    "wg2:in": "out2",
                    "wg1:out": "out1",
                    "wg2:out": "in2",
                }
            )
            return ports

    class Netlist(i3.NetlistFromLayout):
        pass

class Ring_modulator(i3.Circuit):
    _name_prefix = "Ring_modulator"
    dc = i3.ChildCellProperty()
    heater = i3.ChildCellProperty()
    radius = i3.PositiveNumberProperty(default=50)
    dc_distance = i3.PositiveNumberProperty(default=300)
    heater_length = i3.PositiveNumberProperty(default=100)
    trace_template = i3.TraceTemplateProperty(
        default=pdk.SWG450(), doc="The trace template for waveguide and heater"
    )
    straight_length = i3.PositiveNumberProperty(default=200)
    spacing = i3.PositiveNumberProperty(default=0.8)

    # Set the default value for the heater
    def _default_dc(self):
        return DC(straight_length=self.straight_length,
                  radius=self.radius,
                  trace_template=self.trace_template,
                  spacing=self.spacing)

    def _default_heater(self):
        ht = pdk.HeatedWaveguide(trace_template=self.trace_template)
        ht.Layout(shape=i3.Shape([(0, 0), (self.heater_length, 0)]))
        return ht

    def _default_insts(self):  # element naming
        insts = {
            "heater1": self.heater,
            "heater2": self.heater,
            "dc1": self.dc,
            "dc2": self.dc,
        }
        return insts

    def _default_specs(self):  # coordinate
        specs = [
            i3.Place("dc1", (0.0, 0.0)),
            i3.PlaceRelative("dc2", "dc1", (0.0, -self.dc_distance)),
            i3.FlipV("dc2"),
            i3.Place("heater1", (-self.radius, -self.dc_distance / 2 - self.heater_length / 2), 90),
            i3.Place("heater2", (self.radius, -self.dc_distance / 2 - self.heater_length / 2), 90),
            i3.ConnectManhattan("dc1:in2", "heater1:out"),
            i3.ConnectManhattan("dc1:out2", "heater2:out"),
            i3.ConnectManhattan("dc2:in2", "heater1:in"),
            i3.ConnectManhattan("dc2:out2", "heater2:in"),
        ]
        return specs

    def _default_exposed_ports(self):  # port definition
        exposed_ports = {
                "heater1:elec1": "elec1",
                "heater1:elec2": "elec2",
                "heater2:elec1": "elec3",
                "heater2:elec2": "elec4",
                "dc1:in1": "in1",
                "dc2:in1": "in2",
                "dc1:out1": "out1",
                "dc2:out1": "out2",
        }
        return exposed_ports

if __name__ == "__main__":
    Ring_modulator().Layout().visualize(annotate=True,legacy=True)

01-25 15:15