参数化和层级化对于大型光子集成线路的设计尤为重要,参数化可以方便复杂线路的参数调整,而层级化可以简化代码结构
接下来,就以如下版图为例,来介绍ipkiss参数化和层级化的版图设计:
图一中的线路是目前光子集成线路光计算网络中常用到的一种结构,它是由多个可调的mzi连接而成。
按照惯例先分享整个线路的代码,再一一讲解代码结构和设计过程;
from si_fab import all as pdk
from ipkiss3 import all as i3
class MZI(i3.Circuit):
coupler = i3.ChildCellProperty(doc="The coupler used for the MZI")
phase_shifter = i3.ChildCellProperty(doc="The class used for the phase shifter")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length =i3.PositiveNumberProperty(default=30, doc="The length of the heater")
def _default_coupler(self):
return pdk.SiNDirectionalCouplerSPower(name=self.name + "_coupler")
def _default_phase_shifter(self):
trace_template = pdk.NWG900()
phase_shifter = pdk.HeatedWaveguide(name=self.name + "_phase_shifter",trace_template=trace_template,)
phase_shifter.Layout(shape=[(0, 0), (self.heater_length, 0)])
return phase_shifter
def _default_insts(self):
return {
"coupler_in": self.coupler,
"coupler_out": self.coupler,
"phase_shifter": self.phase_shifter,
}
def _default_specs(self):
return [
i3.Place("coupler_in:in1", (0, 0)),
i3.PlaceRelative(
"phase_shifter:in",
"coupler_in:out1",
(self.x_separation, 0),
),
i3.PlaceRelative(
"coupler_out:in1",
"phase_shifter:out",
(self.x_separation, 0),
),
i3.ConnectManhattan(
"phase_shifter:in",
"coupler_in:out1",
min_straight=0,
),
i3.ConnectManhattan(
"phase_shifter:out",
"coupler_out:in1",
min_straight=0,
),
i3.ConnectManhattan(
"coupler_in:out2",
"coupler_out:in2",
min_straight=0,
),
]
def _default_exposed_ports(self):
return {
"coupler_in:in1": "in1",
"coupler_in:in2": "in2",
"coupler_out:out1": "out1",
"coupler_out:out2": "out2",
"phase_shifter:elec1": "elec1",
"phase_shifter:elec2": "elec2",
}
class Five_MZI(i3.Circuit):
mzi = i3.ChildCellProperty(doc="The coupler used for the MZI")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
x_st = i3.PositiveNumberProperty(default=400)
y_st = i3.PositiveNumberProperty(default=200)
bend_radius = i3.PositiveNumberProperty(default=50)
def _default_mzi(self):
return MZI(x_separation=self.x_separation,heater_length=self.heater_length )
def _default_insts(self):
return {
"mzi1": self.mzi,
"mzi2": self.mzi,
"mzi3": self.mzi,
"mzi4": self.mzi,
"mzi5": self.mzi,
}
def _default_specs(self):
return [
i3.Place("mzi1:in1", (0, 0)),
i3.PlaceRelative(
"mzi2:in1",
"mzi1:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi3:in1",
"mzi1:in1",
(self.x_st, -self.y_st/2),
),
i3.PlaceRelative(
"mzi4:in1",
"mzi3:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi5:in1",
"mzi4:in1",
(0, self.y_st),
),
i3.ConnectBend(
"mzi1:out1",
"mzi3:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi1:out2",
"mzi4:in1",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out1",
"mzi4:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out2",
"mzi5:in1",
bend_radius=self.bend_radius
),
]
def _default_exposed_ports(self):
return {
"mzi1:in1": "in1",
"mzi1:in2": "in2",
"mzi2:in1": "in3",
"mzi2:in2": "in4",
"mzi3:out1": "out1",
"mzi3:out2": "out2",
"mzi4:out1": "out3",
"mzi4:out2": "out4",
"mzi5:out1": "out5",
"mzi5:out2": "out6",
}
if __name__ == '__main__':
# demo = MZI(x_separation=20, heater_length=40)
demo = Five_MZI(x_separation=20,heater_length=40 )
my_circuit = demo.Layout()
my_circuit.visualize(annotate=True)
图一版图中有五个mzi, 按照层级化的设计,首先应该画出mzi的版图,
所以首先构造了一个class MZI(i3.Circuit):的类,这类就是定义mzi, 至于i3.Circuit,可以参考教程2,它是ipkiss中常用的一个线路设计函数,大家可以通过简单的4步就能完成线路的设计,
将上述代码改为:
if __name__ == '__main__':
demo = MZI(x_separation=20, heater_length=40)
# demo = Five_MZI(x_separation=20,heater_length=40 )
my_circuit = demo.Layout()
my_circuit.visualize(annotate=True)
就就可以实例化mzi, 其线路版图如下,
如果不想看到端口的名称,可以设置annotate=False
my_circuit.visualize(annotate=False)
运行脚本,可以得到:
在class MZI(i3.Circuit)中定义mzi,时,也定义两个参数:
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length =i3.PositiveNumberProperty(default=30, doc="The length of the heater")
在实例化mzi时,就可以来调整加热器相对于方向耦合器的偏移(x_separation)和加热器的长度(heater_length)
比如,
if __name__ == '__main__':
demo = MZI(x_separation=50, heater_length=100)
# demo = Five_MZI(x_separation=20,heater_length=40 )
my_circuit = demo.Layout()
my_circuit.visualize(annotate=False)
运行代码得到:
版图参数就能快速进行了调整,这就是参数画的设计
mzi设计好之后,就可以用它来构建图一所示的版图。
代码中定义一个class Five_MZI(i3.Circuit):的类,线路设计还是用的i3.Circuit设计框架,
在线路中定义了五个结构参数:
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
x_st = i3.PositiveNumberProperty(default=400)
y_st = i3.PositiveNumberProperty(default=200)
bend_radius = i3.PositiveNumberProperty(default=50)
这里x_separation和heater_length又定义了一遍,是为了在实例化Five_MZI时,可以修改mzi的结构参数
在脚本中,参数可以如下传递:
def _default_mzi(self):
return MZI(x_separation=self.x_separation,heater_length=self.heater_length )
x_st,y_st ,以及bend_radius是Five_MZI的结构参数,分别对应5个mzi在x和y方向上的便宜,以及连接波导的最小弯曲半径。
在设计Five_MZI线路时,线路中的基本器件就是前面设计好的mzi,
def _default_insts(self):
return {
"mzi1": self.mzi,
"mzi2": self.mzi,
"mzi3": self.mzi,
"mzi4": self.mzi,
"mzi5": self.mzi,
}
这就是层级化的设计。