下图是一个简单的光子线路,一个方向耦合器与四个光栅耦合器相连:
具体实现步骤如下:
导入 PDK 和 IPKISS 函数库
1. 首先需要导入工艺信息 PDK,此处我们导入的是 Luceda 基于标准 SOI 工艺开发的通用示例PDK:
si_fab
。2. 接着导入 IPKISS 的函数库,里面包含了我们要用到的一系列函数,如线路设计函数
i3.Circuit
。from si_fab import all as pdk # 导入工艺信息,简写为pdk
from ipkiss3 import all as i3 # 导入函数库,简写为i3
构建类
构建一个继承自
i3.Circuit
的类 class RoutedDC()
class RoutedDC(i3.Circuit):
线路设计主要分为四部分:
- 定义线路属性
- 实例化线路中的器件
- 器件的摆放与连接
- 端口命名
定义线路属性
线路的属性包含线路中用到的器件类型、线路的结构参数等。
【器件类型】 本例用到的是方向耦合器
pdk.SiDirectionalCouplerSPower
和光栅耦合器 pdk.FC_TE_1550()
【结构参数】本例中,光栅耦合器在 x 方向和 y 方向上的间距为 spacing_x 和 spacing_y
【default】给线路属性赋默认值
dc = i3.ChildCellProperty(doc="Directional coupler in circuit")
fgc = i3.ChildCellProperty(doc="PCell of the fiber grating coupler")
spacing_x = i3.PositiveNumberProperty(default=200.0, doc="The spacing of fiber grating coupler in x direction")
spacing_y = i3.PositiveNumberProperty(default=100.0, doc="The spacing of fiber grating coupler in y direction")
bend_radius = i3.PositiveNumberProperty(default=20, doc="The bend radius of the routing waveguide")
def _default_dc(self):
return pdk.SiDirectionalCouplerSPower(power_fraction=0.5, target_wavelength=1.55)
def _default_fgc(self):
return pdk.FC_TE_1550()
线路中的子器件
线路中的子器件
insts{}
是一个字典集,有 1 个方向耦合器和 4 个光栅耦合器,他们的名称分别为 dc
、fgc_1
、fgc_2
、fgc_3
、fgc_4
。 def _default_insts(self):
insts = {
"dc": self.dc,
"fgc_1": self.fgc,
"fgc_2": self.fgc,
"fgc_3": self.fgc,
"fgc_4": self.fgc,
}
return insts
器件的放置与连接
实例化完的器件都放置在默认值位置(如原点),如需将器件放置在指定位置并连接相应的端口,还需要在
specs[]
列表中进行摆放与连接。 def _default_specs(self):
specs = [
i3.Place("dc", (0, 0)),
i3.PlaceRelative("fgc_1", "dc", (-self.spacing_x / 2, -self.spacing_y / 2)),
i3.PlaceRelative("fgc_2", "dc", (-self.spacing_x / 2, self.spacing_y / 2)),
i3.PlaceRelative("fgc_3", "dc", (self.spacing_x / 2, -self.spacing_y / 2), angle=180),
i3.PlaceRelative("fgc_4", "dc", (self.spacing_x / 2, self.spacing_y / 2), angle=180),
i3.ConnectManhattan("fgc_1:out", "dc:in1", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_2:out", "dc:in2", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_3:out", "dc:out1", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_4:out", "dc:out2", bend_radius=self.bend_radius)
]
return specs
简化端口命名
最后,需要将线路中还暴露在外的端口重新命名。一是为了简化端口的名称,避免名字过于冗长;二是便于后续的网表提取。
exposed_ports{}
也是一个字典集。 def _default_exposed_ports(self):
exposed_ports = {
"fgc_1:vertical_in": "in1",
"fgc_2:vertical_in": "in2",
"fgc_3:vertical_in": "out1",
"fgc_4:vertical_in": "out2",
}
return exposed_ports
通过这四步,一个简单的光子线路版图就完成了。
线路实例化及导出 GDSⅡ 版图
如果想要查看线路的版图,还需要对线路进行实例化:
if __name__ == '__main__':
dc = RoutedDC(bend_radius=20)
my_circuit = dc.Layout()
my_circuit.visualize(annotate=True)
my_circuit.write_gdsii("Rounted_dc.gds")
完整代码
from si_fab import all as pdk
from ipkiss3 import all as i3
class RoutedDC(i3.Circuit):
_name_prefix = "routed_dc"
dc = i3.ChildCellProperty(doc="Directional coupler in circuit")
fgc = i3.ChildCellProperty(doc="PCell of the fiber grating coupler")
spacing_x = i3.PositiveNumberProperty(default=200.0, doc="The spacing of fiber grating coupler in x direction")
spacing_y = i3.PositiveNumberProperty(default=100.0, doc="The spacing of fiber grating coupler in y direction")
bend_radius = i3.PositiveNumberProperty(default=20, doc="The bend radius of the routing waveguide")
def _default_dc(self):
return pdk.SiDirectionalCouplerSPower(power_fraction=0.5, target_wavelength=1.55)
def _default_fgc(self):
return pdk.FC_TE_1550()
def _default_insts(self):
insts = {
"dc": self.dc,
"fgc_1": self.fgc,
"fgc_2": self.fgc,
"fgc_3": self.fgc,
"fgc_4": self.fgc,
}
return insts
def _default_specs(self):
specs = [
i3.Place("dc", (0, 0)),
i3.PlaceRelative("fgc_1", "dc", (-self.spacing_x / 2, -self.spacing_y / 2)),
i3.PlaceRelative("fgc_2", "dc", (-self.spacing_x / 2, self.spacing_y / 2)),
i3.PlaceRelative("fgc_3", "dc", (self.spacing_x / 2, -self.spacing_y / 2), angle=180),
i3.PlaceRelative("fgc_4", "dc", (self.spacing_x / 2, self.spacing_y / 2), angle=180),
i3.ConnectManhattan("fgc_1:out", "dc:in1", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_2:out", "dc:in2", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_3:out", "dc:out1", bend_radius=self.bend_radius),
i3.ConnectManhattan("fgc_4:out", "dc:out2", bend_radius=self.bend_radius)
]
return specs
def _default_exposed_ports(self):
exposed_ports = {
"fgc_1:vertical_in": "in1",
"fgc_2:vertical_in": "in2",
"fgc_3:vertical_in": "out1",
"fgc_4:vertical_in": "out2",
}
return exposed_ports
if __name__ == '__main__':
dc = RoutedDC(bend_radius=20)
my_circuit = dc.Layout()
my_circuit.visualize(annotate=True)
my_circuit.write_gdsii("Rounted_dc.gds")