在ipkiss中,通常以i3.Circuit来设计线路(见教程2),以i3.Pcell的框架也可以来设计线路:
以SplitterTree为例:
线路仿真结果:
所有代码如下:
from si_fab import all as pdk
import ipkiss3.all as i3
class SplitterTree(i3.PCell):
class Layout(i3.LayoutView):
def _generate_instances(self, insts):
insts += i3.place_and_route(
insts={
"splitter1": pdk.MMI1x2Optimized1550(),
"splitter2": pdk.MMI1x2Optimized1550(),
"splitter3": pdk.MMI1x2Optimized1550(),
},
specs=[
i3.Place('splitter1', (0, 0)),
i3.Place('splitter2', (100, -30)),
i3.Place('splitter3', (100, 30)),
]
)
insts = i3.place_and_route(
insts=insts,
specs=[
i3.ConnectBend("splitter1:out1", "splitter2:in1", bend_radius=10),
i3.ConnectBend("splitter1:out2", "splitter3:in1", bend_radius=10),
]
)
return insts
def _generate_ports(self, ports):
ports += i3.expose_ports(
instances=self.instances,
port_name_map={
"splitter1:in1": "in1",
"splitter2:out1": "out1",
"splitter2:out2": "out2",
"splitter3:out1": "out3",
"splitter3:out2": "out4",
}
)
return ports
class Netlist(i3.NetlistFromLayout):
pass
class CircuitModel(i3.CircuitModelView):
def _generate_model(self):
return i3.HierarchicalModel.from_netlistview(self.netlist_view)
if __name__ == '__main__':
SplitterTree().Layout().visualize(annotate=True)
import numpy as np
from matplotlib import pyplot as plt
wavelengths = np.linspace(1.5, 1.6, 2001)
cm = SplitterTree().CircuitModel()
S = cm.get_smatrix(wavelengths=wavelengths)
plt.plot(wavelengths, i3.signal_power_dB(S["out1", "in1"]), label="in1 -> out1")
plt.plot(wavelengths, i3.signal_power_dB(S["out2", "in1"]), label="in1 -> out2")
plt.plot(wavelengths, i3.signal_power_dB(S["out3", "in1"]), label="in1 -> out3")
plt.plot(wavelengths, i3.signal_power_dB(S["out4", "in1"]), label="in1 -> out4")
plt.plot(wavelengths, i3.signal_power_dB(S["in1", "in1"]), label="in1 -> in1")
plt.legend()
plt.xlabel("Wavelengths [um]")
plt.ylabel("Transmission")
plt.show()
以pcell的方式定义线路需要分别定义:Layout、Netlist 以及CircuitModel
Layout给出线路的版图:
class Layout(i3.LayoutView):
def _generate_instances(self, insts):
insts += i3.place_and_route(
insts={
"splitter1": pdk.MMI1x2Optimized1550(),
"splitter2": pdk.MMI1x2Optimized1550(),
"splitter3": pdk.MMI1x2Optimized1550(),
},
specs=[
i3.Place('splitter1', (0, 0)),
i3.Place('splitter2', (100, -30)),
i3.Place('splitter3', (100, 30)),
]
)
insts = i3.place_and_route(
insts=insts,
specs=[
i3.ConnectBend("splitter1:out1", "splitter2:in1", bend_radius=10),
i3.ConnectBend("splitter1:out2", "splitter3:in1", bend_radius=10),
]
)
return insts
def _generate_ports(self, ports):
ports += i3.expose_ports(
instances=self.instances,
port_name_map={
"splitter1:in1": "in1",
"splitter2:out1": "out1",
"splitter2:out2": "out2",
"splitter3:out1": "out3",
"splitter3:out2": "out4",
}
)
return ports
Netlist 给出线路中的逻辑连接关系:
layout中定义了ports,Netlist可以直接从Layout继承
class Netlist(i3.NetlistFromLayout):
pass
CircuitModel 给出线路中的逻辑连接关系:
线路中的每个器件都有了CircuitModel,所有整个线路的CircuitModel可以通过HierarchicalModel来定义
class CircuitModel(i3.CircuitModelView):
def _generate_model(self):
return i3.HierarchicalModel.from_netlistview(self.netlist_view)
线路仿真:
import numpy as np
from matplotlib import pyplot as plt
wavelengths = np.linspace(1.5, 1.6, 2001)
cm = SplitterTree().CircuitModel()
S = cm.get_smatrix(wavelengths=wavelengths)
plt.plot(wavelengths, i3.signal_power_dB(S["out1", "in1"]), label="in1 -> out1")
plt.plot(wavelengths, i3.signal_power_dB(S["out2", "in1"]), label="in1 -> out2")
plt.plot(wavelengths, i3.signal_power_dB(S["out3", "in1"]), label="in1 -> out3")
plt.plot(wavelengths, i3.signal_power_dB(S["out4", "in1"]), label="in1 -> out4")
plt.plot(wavelengths, i3.signal_power_dB(S["in1", "in1"]), label="in1 -> in1")
plt.legend()
plt.xlabel("Wavelengths [um]")
plt.ylabel("Transmission")
plt.show()
线路仿真结果: