ipkiss的层级化设计,在调用子器件或者子线路时可以给它们赋值,那么同一子线路如何实现差异化的赋值呢,接下来,就以spiral的例子来进行讲解,这里会介绍调用同一个spiral子线路来画多个不同长度的spiral:
结果如下:
所有代码如下:
from si_fab import all as pdk
import ipkiss3.all as i3
class GenericSpiral(i3.Circuit):
_name_prefix = "GenericSpiral"
bend_radius = i3.PositiveNumberProperty(default=20.0, doc="the bend radius in the circuit")
Spiral = i3.ChildCellProperty(doc="Spiral in circuit")
gc_distance_x = i3.PositiveNumberProperty(default=1000.0, doc="distance between the grating couplers ")
gc_distance_y = i3.PositiveNumberProperty(default=400.0, doc="distance between the grating couplers ")
space_y = i3.PositiveNumberProperty(default=50, doc="gc space in y direction")
space_x = i3.PositiveNumberProperty(default=200, doc="space between gc and spiral ")
space_y_spiral = i3.PositiveNumberProperty(default=200, doc="spiral space in y direction")
space_x_spiral = i3.PositiveNumberProperty(default=500, doc="spiral space in x direction")
spiral_length = i3.PositiveNumberProperty(default=4000, doc="length of sigle spiral")
num_Spiral_y = i3.IntProperty(default=4, doc="number of spiral in y direction")
num_Spiral_x = i3.IntProperty(default=1, doc="number of spiral in x direction")
y_offset = i3.PositiveNumberProperty(default=5)
waveguide_space = i3.PositiveNumberProperty(default=20)
spiral_length_step = i3.PositiveNumberProperty(default=2000, doc="step length of waveguide under test")
def _default_Spiral(self):
return pdk.FixedPortWithLengthSpiral(total_length=self.spiral_length, n_o_loops=4)
def _default_insts(self):
insts = {}
for m in range(self.num_Spiral_y):
insts["gc_in_{}".format(m)] = pdk.GratingCoupler()
insts["gc_out_{}".format(m)] = pdk.GratingCoupler()
for n in range(self.num_Spiral_x):
insts["Spiral_{}_{}".format(m, n)] = self.Spiral.modified_copy(
total_length=self.spiral_length + self.spiral_length_step * m, n_o_loops=4 + m*2 )
return insts
def _default_specs(self):
specs = []
for m in range(self.num_Spiral_y):
for n in range(self.num_Spiral_x):
specs += [
i3.Place("Spiral_{}_{}:in".format(m, n), (self.space_x_spiral * n, self.space_y_spiral * m)),
]
for m in range(self.num_Spiral_y):
for n in range(self.num_Spiral_x - 1):
specs += [
i3.ConnectManhattan("Spiral_{}_{}:out".format(m, n), "Spiral_{}_{}:in".format(m, n + 1)),
]
for m in range(self.num_Spiral_y):
specs += [
i3.PlaceRelative("gc_in_{}:out".format(m), "Spiral_{}_{}:in".format(self.num_Spiral_y - 1, 0),
(-self.space_x, -m * self.space_y)),
i3.PlaceRelative("gc_out_{}:out".format(m), "gc_in_{}:out".format(self.num_Spiral_y - 1 - m),
(self.gc_distance_x, -self.gc_distance_y),
angle=180),
]
specs += [
i3.ConnectManhattan(
[
("gc_in_{}:out".format(m), "Spiral_{}_{}:in".format(self.num_Spiral_y - 1 - m, 0)),
],
bend_radius=self.bend_radius,
start_straight=10,
end_straight=10,
control_points=[i3.V(i3.END - 50 - self.waveguide_space * m)],
),
i3.ConnectManhattan(
[
("gc_out_{}:out".format(m), "Spiral_{}_{}:out".format(m, self.num_Spiral_x - 1)),
],
bend_radius=self.bend_radius,
start_straight=10,
end_straight=10,
control_points=[i3.V(i3.END + 50 + self.waveguide_space * m)],
)
]
return specs
if __name__ == '__main__':
Spiral_c_layout = GenericSpiral().Layout()
Spiral_c_layout.visualize(annotate=False)
整个线路还是i3.Circuit的框架,在定义线路中的子器件时用了两个for循环:
def _default_insts(self):
insts = {}
for m in range(self.num_Spiral_y):
insts["gc_in_{}".format(m)] = pdk.GratingCoupler()
insts["gc_out_{}".format(m)] = pdk.GratingCoupler()
for n in range(self.num_Spiral_x):
insts["Spiral_{}_{}".format(m, n)] = self.Spiral.modified_copy(
total_length=self.spiral_length + self.spiral_length_step * m, n_o_loops=4 + m*2 )
return insts
线路中用到的spiral都是si_fab库中:pdk.FixedPortWithLengthSpiral这个pdk,
为了给线路中多个spiral设定一个步长,除了前面有定义步长:spiral_length_step,在添加线路中的spiral的时候,通过modified_copy对定义的Spiral进行复制,就可以对每一个spiral设定不同的长度