class Layout(TraceChain.Layout): center_line_shape = i3.ListProperty(locked=True) def validate_properties(self): for cnt, t in enumerate(self.traces): if not hasattr(t, "center_line_shape"): raise i3.PropertyValidationError( self, "Trace {} has not center_line_shape", { "trace": t, "type t": type(t), "Position in trace": cnt }) return True def _default_center_line_shape(self): shape = [] for t in self.traces: shape += t.center_line_shape return shape
class my_dc(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) # gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") gap_inc_vec2 = i3.ListProperty(default=[], doc="length of 12mmi") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) cleave = i3.PositiveNumberProperty(doc="tolerance", default=150) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}_{}".format(str(self.width), str(self.cleave)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (self.cleave, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}_{}".format( str(self.width), str(self.cleave)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] # cell = MMI2x2Tapered(mmi_trace_template=self.mmi_trace_template, # input_trace_template=self.mmi_access_template, # output_trace_template=self.mmi_access_template, # trace_template=self.trace_template, # ) # # cell.Layout(name="MMI22_l_430", transition_length=200.0, # length=430, trace_spacing=11.0 # ) # # MMI22_list.append(cell) # # print 'cell name ' + str(cell.name) # print '__________________________' for l, dl in enumerate(self.gap_inc_vec2): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2112() cell.Layout(name="MMI2112_l_{}".format(str(self.gap_inc_vec2[l])), length=self.gap_inc_vec2[l]) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 11, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ # ("taper0:out", "ring0:in2"), # ("taper1:out", "ring0:in1"), # ("taper2:out", "ring0:out2"), # ("taper3:out", "ring0:out1"), ("taper0:out", "ring0:narrow_in"), ("taper1:out", "ring0:MMI1a_out1"), ("taper2:out", "ring0:MMI1a_out2"), ("taper3:out", "ring1:narrow_in"), ("taper4:out", "ring1:MMI1a_out1"), ("taper5:out", "ring1:MMI1a_out2"), ("taper6:out", "ring2:narrow_in"), ("taper7:out", "ring2:MMI1a_out1"), ("taper8:out", "ring2:MMI1a_out2"), ("taper9:out", "taper10:out") ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 6000 trans['ring0'] = (600, 0) trans['ring1'] = (600, 1 * column) trans['ring2'] = (600, 2 * column) # trans['ring3'] = (1300, 8000 + 2 * column ) trans["taper0"] = (0, 0) trans["taper1"] = i3.HMirror(0) + i3.Translation((2500, -1500)) trans["taper2"] = i3.HMirror(0) + i3.Translation((2500, 1500)) trans["taper3"] = (0, 1 * column) trans["taper4"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 1 * column)) trans["taper5"] = i3.HMirror(0) + i3.Translation( (2500, 1500 + 1 * column)) trans["taper6"] = (0, 2 * column) trans["taper7"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 2 * column)) trans["taper8"] = i3.HMirror(0) + i3.Translation( (2500, 1500 + 2 * column)) trans["taper9"] = (0, 3800 + 2 * column) trans["taper10"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 3 * column)) # trans["taper11"] = i3.HMirror(0) + i3.Translation((3000, 6500+ 2 * column)) # trans["taper12"] = i3.HMirror(0) + i3.Translation((3000, 9500+ 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=30.0, transformation=i3.Translation((600, 100 + 6000 * counter))) for i in range(1, 8, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(i), coordinate=(400, -4400 + 3000 * i), font=2, height=200.0, ) for j in range(-1, 2, 1): for i in range(0, 4, 1): elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 + 100 + 6000 * i), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 - 100 + 6000 * i), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 - 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -3000 - 100), box_size=(100, 100)) return elems
class my_dc(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) MMI_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") length_inc_vec = i3.ListProperty(default=[], doc="length of MMI2112") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() WG3 = i3.ChildCellProperty( doc="dummy SM waveguide") # define this to guide route wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") wg_dc = i3.WaveguideTemplateProperty(doc="dc WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_wg_dc(self): wg_t1 = WireWaveguideTemplate(name="dc") wg_t1.Layout( core_width=2.8, cladding_width=2.8 + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): wg1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) wg1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return wg1 def _default_WG3(self): wg3 = i3.Waveguide(name="route", trace_template=self.trace_template) wg3.Layout(shape=[(0.0, 0.0), (1.0, 0.0)]) return wg3 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.trace_template, ) cell.Layout(name="MMI22_l_{}".format(str(self.gap_inc_vec[l])), transition_length=200.0, length=self.gap_inc_vec[l], trace_spacing=11.0) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_MMI_list(self): print '____________ MMI 2112 ______________' MMI2112_list = [] for l, dl in enumerate(self.length_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2112() cell.Layout(name="MMI2112_l_{}".format(str( self.length_inc_vec[l])), length=self.length_inc_vec[l]) MMI2112_list.append(cell) print 'cell name ' + str(cell.name) return MMI2112_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 16, 1): print counter child_cells['straight1' + str(counter)] = self.WG3 for counter in range(0, 24, 1): child_cells['taper_in' + str(counter)] = self.WG2 for counter in range(0, 24, 1): # child_cells['straight2' + str(counter)] = self.WG3 child_cells['taper_out' + str(counter)] = self.WG2 for counter in range(0, 16, 1): child_cells['straight2' + str(counter)] = self.WG3 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child for counter, child in enumerate(self.MMI_list): print 'child number' + str(counter) child_cells['mmi' + str(counter)] = child print 'child name ' + str(child.name) print child child = SBendDirectionalCoupler(name="dc3", trace_template1=self.trace_template, coupler_length=923) child.Layout( coupler_spacing=1.5 + 3.8, straight_after_bend=970, # bend_angle=30.0, bend_angles1=(20, 20), bend_angles2=(40, 40), bend_radius=100) child_cells['dc3'] = child child = SBendDirectionalCoupler(name="dc2", trace_template1=self.wg_dc, coupler_length=888) child.Layout( coupler_spacing=2 + 2.8, straight_after_bend=860, # bend_angle=30.0, bend_angles1=(20, 20), bend_angles2=(40, 40), bend_radius=100, # manhattan=True, ) child_cells['dc2'] = child child = SBendDirectionalCoupler(name="dc1", trace_template1=self.wg_dc, coupler_length=868) child.Layout( coupler_spacing=2 + 2.8, straight_after_bend=750, # bend_angle=30.0, bend_angles1=(20, 20), bend_angles2=(40, 40), bend_radius=100, # manhattan=True, ) child_cells['dc1'] = child child = SBendDirectionalCoupler(name="dc4", trace_template1=self.trace_template, coupler_length=923) child.Layout( coupler_spacing=100 + 3.8, straight_after_bend=1150, # bend_angle=30.0, bend_angles1=(1, 1), bend_angles2=(40, 40), bend_radius=100) child_cells['dc4'] = child return child_cells def _default_links(self): links = [] for counter in range(0, 10, 1): # in_port = "Spiral{}:in".format(counter) in_port = "taper_in{}:out".format(counter) # links.append((in_port, out_port)) # in_port = "Spiral{}:out".format(counter) out_port = "straight1{}:in".format(counter) links.append((in_port, out_port)) in_port = "taper_out{}:out".format(counter) # links.append((in_port, out_port)) # in_port = "Spiral{}:out".format(counter) out_port = "straight2{}:out".format(counter) links.append((in_port, out_port)) # for counter in range(0, 11, 1): if counter % 2 == 0: i_port = "straight1{}:out".format(counter) o_port = "ring{}:in1".format(counter // 2) links.append((i_port, o_port)) i_port = "straight2{}:in".format(counter) o_port = "ring{}:out1".format(counter // 2) links.append((i_port, o_port)) else: ii_port = "straight1{}:out".format(counter) oo_port = "ring{}:in2".format(counter // 2) links.append((ii_port, oo_port)) ii_port = "straight2{}:in".format(counter) oo_port = "ring{}:out2".format(counter // 2) links.append((ii_port, oo_port)) for counter in range(10, 16, 1): # in_port = "Spiral{}:in".format(counter) in_port = "taper_in{}:out".format(counter) # links.append((in_port, out_port)) # in_port = "Spiral{}:out".format(counter) out_port = "straight1{}:in".format(counter) links.append((in_port, out_port)) in_port = "taper_out{}:out".format(counter) # links.append((in_port, out_port)) # in_port = "Spiral{}:out".format(counter) out_port = "straight2{}:out".format(counter) links.append((in_port, out_port)) if counter % 2 == 0: i_port = "straight1{}:out".format(counter) o_port = "mmi{}:MMI1b_in1".format((counter - 10) // 2) links.append((i_port, o_port)) i_port = "straight2{}:in".format(counter) o_port = "mmi{}:MMI1a_out1".format((counter - 10) // 2) links.append((i_port, o_port)) else: ii_port = "straight1{}:out".format(counter) oo_port = "mmi{}:MMI1b_in2".format((counter - 10) // 2) links.append((ii_port, oo_port)) ii_port = "straight2{}:in".format(counter) oo_port = "mmi{}:MMI1a_out2".format((counter - 10) // 2) links.append((ii_port, oo_port)) links.append(("taper_in16:out", "dc1:in1")), links.append(("taper_in17:out", "dc1:in2")), links.append(("taper_out16:out", "dc1:out1")), links.append(("taper_out17:out", "dc1:out2")), links.append(("taper_in18:out", "dc2:in1")), links.append(("taper_in19:out", "dc2:in2")), links.append(("taper_out18:out", "dc2:out1")), links.append(("taper_out19:out", "dc2:out2")), links.append(("taper_in20:out", "dc3:in1")), links.append(("taper_in21:out", "dc3:in2")), links.append(("taper_out20:out", "dc3:out1")), links.append(("taper_out21:out", "dc3:out2")), links.append(("taper_in22:out", "dc4:in1")), links.append(("taper_in23:out", "dc4:in2")), links.append(("taper_out22:out", "dc4:out1")), links.append(("taper_out23:out", "dc4:out2")), # links.append( # ("taper_in0:out", "ring0:in2"), # ("taper_in1:out", "ring0:in1"), # # ("taper_in2:out", "ring0:out2"), # # ("taper_in3:out", "ring0:out1"), # # ("taper_in2:out", "ring1:in2"), # ("taper_in3:out", "ring1:in1"), # # ("taper6:out", "ring1:out2"), # # ("taper7:out", "ring1:out1"), # # # ("taper_in4:out", "ring2:in2"), # ("taper_in5:out", "ring2:in1"), # # ("taper10:out", "ring2:out2"), # # ("taper11:out", "ring2:out1"), # ("taper_in6:out", "ring3:in2"), # ("taper_in7:out", "ring3:in1"), # ("taper_in8:out", "ring4:in2"), # ("taper_in9:out", "ring4:in1"), # # ) return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 150 # a = self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x for counter in range(0, 24, 1): trans['taper_in' + str(counter)] = i3.Translation( translation=(0, counter * column)) trans['taper_out' + str(counter)] = i3.HMirror(0) + i3.Translation( translation=(6000, 1000 + counter * column)) # trans['straight1' + str(counter)] = i3.Translation( # translation=(1490 - counter * 30, 1670 + counter * 150), rotation=90) # trans['straight2'] # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) for counter in range(0, 5, 1): trans['ring' + str(counter)] = i3.Translation( translation=(3000, 5000 + counter * column / 1.5)) for counter in range(0, 3, 1): trans['mmi' + str(counter)] = i3.Translation( translation=(3000, 5500 + counter * column / 1.5)) trans['dc1'] = i3.Translation((3000 + 200, 5800)) trans['dc2'] = i3.Translation((3000 + 200, 5950)) trans['dc3'] = i3.Translation((3000 + 200, 6100)) trans['dc4'] = i3.Translation((3000 + 200, 6300)) for counter, child in enumerate(self.DC_list): a = (child.ports['in1'].x, child.ports['in1'].y) b = (child.ports['in2'].x, child.ports['in2'].y) c = (child.ports['out1'].x, child.ports['out1'].y) d = (child.ports['out2'].x, child.ports['out2'].y) n = counter * 2 m = counter * 2 + 1 trans['straight1' + str(n)] = i3.Translation( translation=a) + i3.Translation(translation=( 3000, 5000 + counter * column / 1.5)) + i3.Translation( (-2 - 50 * n, 0)) trans['straight1' + str(m)] = i3.Translation( translation=b) + i3.Translation(translation=( 3000, 5000 + counter * column / 1.5)) + i3.Translation( (-2 - 50 * m, 0)) trans['straight2' + str(n)] = i3.Translation( translation=c) + i3.Translation(translation=( 3000, 5000 + counter * column / 1.5)) + i3.Translation( (2 + 50 * n, 0)) trans['straight2' + str(m)] = i3.Translation( translation=d) + i3.Translation(translation=( 3000, 5000 + counter * column / 1.5)) + i3.Translation( (2 + 50 * m, 0)) print a, b for counter, child in enumerate(self.MMI_list): a = (child.ports['MMI1b_in1'].x, child.ports['MMI1b_in1'].y) b = (child.ports['MMI1b_in2'].x, child.ports['MMI1b_in2'].y) c = (child.ports['MMI1a_out1'].x, child.ports['MMI1a_out1'].y) d = (child.ports['MMI1a_out2'].x, child.ports['MMI1a_out2'].y) n = 10 + counter * 2 m = 10 + counter * 2 + 1 trans['straight1' + str(n)] = i3.Translation( translation=a) + i3.Translation(translation=( 3000, 5500 + counter * column / 1.5)) + i3.Translation( (-2 - 50 * n, 0)) trans['straight1' + str(m)] = i3.Translation( translation=b) + i3.Translation(translation=( 3000, 5500 + counter * column / 1.5)) + i3.Translation( (-2 - 50 * m, 0)) trans['straight2' + str(n)] = i3.Translation( translation=c) + i3.Translation(translation=( 3000, 5500 + counter * column / 1.5)) + i3.Translation( (2 + 50 * n - 250, 0)) trans['straight2' + str(m)] = i3.Translation( translation=d) + i3.Translation(translation=( 3000, 5500 + counter * column / 1.5)) + i3.Translation( (2 + 50 * m - 250, 0)) print a, b # trans['ring0'] = (2000, 2000) # trans['ring1'] = (2000, 2000 + column) # trans['ring2'] = (2000, 2000 + 2 * column) # trans['ring3'] = (2000, 2000 + 3 * column) # trans['ring4'] = (2000, 2000 + 4 * column) # trans['ring0'] = (2000, 2000) # trans['ring1'] = (2000, 2000 + column) # trans['ring2'] = (2000, 2000 + 2 * column) # trans['ring3'] = (2000, 2000 + 3 * column) # trans['ring4'] = (2000, 2000 + 4 * column) # trans["taper0"] = (0, 4000) # trans["taper1"] = (0, -4000) # trans["taper2"] = i3.HMirror(0) + i3.Translation((5000, 2500)) # trans["taper3"] = i3.HMirror(0) + i3.Translation((5000, -2500)) # # trans["taper4"] = (0, 4000 + column) # trans["taper5"] = (0, -4000 + column) # trans["taper6"] = i3.HMirror(0) + i3.Translation((5000, 2500 + column)) # trans["taper7"] = i3.HMirror(0) + i3.Translation((5000, -2500 + column)) # # trans["taper8"] = (0, 4000 + 2 * column) # trans["taper9"] = (0, -4000 + 2 * column) # trans["taper10"] = i3.HMirror(0) + i3.Translation((5000, 2500 + 2 * column)) # trans["taper11"] = i3.HMirror(0) + i3.Translation((5000, -2500 + 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter in range(0, 24, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(str(counter)), # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=70.0, transformation=i3.Translation((300, 100 + 150 * counter))) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(str(counter)), # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=70.0, transformation=i3.Translation( (5700, 1100 + 150 * counter))) return elems
class Spirals_w(PlaceComponents): Spirals_w_list = i3.ChildCellListProperty( doc="List containing the different routed masks") width_vec = i3.ListProperty(default=[10000.0, 20000.0]) s_length_vec = i3.ListProperty(default=[50000.0]) n = i3.PositiveNumberProperty(default=1, doc="Radius of curvature") tipo = i3.PositiveNumberProperty(default=1, doc="Radius of curvature") def _default_n(self): for counter, cell in enumerate(self.width_vec): numero = counter + 1 #print 'number of legths: ', self.n return numero def _default_Spirals_w_list(self): Spirals_w_list = [] for w, width in enumerate(self.width_vec): print 'The core width is: ', width wg_t = WireWaveguideTemplate() wg_t.Layout( core_width=width, cladding_width=width, ) Spirals_w_list.append( Spirals(s_length_vec=self.s_length_vec, waveguide_template=wg_t, tipo=self.tipo, width=w + 1, n=self.n, name='Spirals_w_' + str(width)) #.Layout(local_mbend_radius = radius) ) return Spirals_w_list def _default_child_cells(self): child_cells = {} for counter, width in enumerate(self.Spirals_w_list): child_cells['Spirals{}'.format(counter)] = width print 'child_cells:', child_cells return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): d = {} for counter, child in enumerate(self.child_cells): # We get the layoutview of the childcell spiral = self.child_cells[child].get_default_view(self) isz_0 = spiral.instances['Spiral0'].reference.inner_size sx = isz_0[1] + 200 print 'sx = ', sx #print("inner_size = {}".format(isz_0, isz_1)) number = self.n if self.tipo == 1: d['Spirals' + str(counter)] = i3.Translation( translation=(0.0, (counter) * sx)) #+i3.HMirror()+i3.VMirror() if self.tipo == 2: d['Spirals' + str(counter)] = i3.Translation(translation=( 0.0, -(counter) * sx)) + i3.HMirror() + i3.VMirror() return d
class Spirals(PlaceAndAutoRoute): _name_prefix = 'LSpiral' tipo = i3.PositiveNumberProperty(doc="Number loops", default=1) waveguide_template = i3.DefinitionProperty(doc="Trace template used") R = i3.PositiveNumberProperty(default=200, doc="Radius of curvature") spacing = i3.PositiveNumberProperty(default=100, doc="Radius of curvature") n_loops = i3.IntProperty(doc="Number loops", default=2) n_loops_vec = i3.ListProperty(default=[4, 8]) s_length_vec = i3.ListProperty(default=[0.0]) Spiral_list = i3.ChildCellListProperty( doc="List containing the 90 degree angle child cells") #chip_length = i3.PositiveNumberProperty(default=2500.0, doc="Radius of curvature") chip_length = i3.PositiveNumberProperty(default=3000.0, doc="Radius of curvature") Port = i3.ChildCellProperty(doc="Used for ports") Port2 = i3.ChildCellProperty(doc="Used for ports") tlport = i3.PositiveNumberProperty(default=1000.0, doc="Transition legth to ports") couplingWG = i3.ChildCellProperty(doc="", locked=True) couplingWG_l = i3.PositiveNumberProperty(default=5000.0, doc="Length of the coupling WG ") tt_port = i3.TraceTemplateProperty( doc="Wide trace template used for the contacts") tt_port2 = i3.TraceTemplateProperty( doc="Wide trace template used for the contacts") #width_vec = i3.ListProperty(default=[1]) n = i3.PositiveNumberProperty(default=1, doc="") width = i3.PositiveNumberProperty(default=1, doc="") lengths = i3.PositiveNumberProperty(default=1, doc="") def _default_lengths(self): for counter, cell in enumerate(self.s_length_vec): numero = counter + 1 return numero #template for Autorute def _default_trace_template(self): return self.waveguide_template def _default_tt(self): return self.waveguide_template def _default_tt_port(self): tt_port = WireWaveguideTemplate() tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0) return tt_port def _default_tt_port2(self): tt_port = WireWaveguideTemplate() tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0) return tt_port def _default_Spiral_list(self): Spiral_list = [] # empty list print ' I am in _Spiral_list' for l, length in enumerate(self.s_length_vec): loops = 1 print length cell = FixedLengthSpiralRounded( trace_template=self.waveguide_template, #total_length=length-self.chip_length, total_length=length, n_o_loops=loops, name=self.name + '_Spiral_' + str(l)) cell.Layout( incoupling_length=0, bend_radius=self.R, spacing=self.spacing, stub_direction="H", growth_direction="H", ) #.visualize(annotate=True) print 'The legth of the spiral is: ', cell.total_length print 'Cell: ', cell.name Spiral_list.append(cell) return Spiral_list def _default_couplingWG(self): rect = i3.Waveguide(trace_template=self.tt_port) layout_rect = rect.Layout(shape=[(0.0, 0.0), (self.couplingWG_l, 0.0)]) return rect def _default_Port(self): Port = AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout( transition_length=self.tlport) #.visualize(annotate=True) return Port def _default_Port2(self): Port = AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout( transition_length=self.tlport) #.visualize(annotate=True) return Port def _default_child_cells(self): child_cells = { } # First we define the property "child_cells" as an empty dictionary for counter, spiral in enumerate( self.Spiral_list ): # the iteration starts in the first element of the list and follows element by element to the last element. child_cells['Spiral{}'.format(counter)] = spiral print spiral print 'name of spiral:', spiral.name child_cells['InPort' + str(counter)] = self.Port child_cells['OutPort' + str(counter)] = self.Port print 'child_cells:', child_cells return child_cells def _default_links(self): links = [] for counter, spiral in enumerate(self.Spiral_list): print counter in_port = "Spiral{}:in".format(counter) out_port = "InPort{}:in".format(counter) links.append((in_port, out_port)) in_port = "Spiral{}:out".format(counter) out_port = "OutPort{}:in".format(counter) links.append((in_port, out_port)) return links class Layout(PlaceAndAutoRoute.Layout): #tipo=1 def _default_bend_radius(self): return self.R def _default_child_transformations(self): d = {} for counter, child in enumerate(self.Spiral_list): ip = child.ports["in"].position #print self.child_cells['InPort' + str(counter)].ports["out"].position #print self.child_cells['OutPort' + str(counter)].ports.position print '----------------' print 'spiral length:', child.total_length print 'counter: ', counter #print ip op = child.ports["out"].position #print op print 'The lateral size of the spiral is', op[0] - ip[0] print 'The type of mask is: ', self.tipo print 'The number of widths is: ', self.n print 'The number of lengths is: ', self.lengths print 'The width number is: ', self.width print '----------------' iz = child.inner_size sx = iz[1] + 200 #sx=1200 if self.tipo == 1: d['Spiral' + str(counter)] = i3.Translation( translation=(-(op[0] - ip[0]) / 2, self.n * counter * sx)) d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length / 2.0 - self.couplingWG_l, self.n * counter * sx)) d['OutPort' + str(counter)] = i3.Translation( translation=(self.chip_length / 2.0 + self.couplingWG_l, self.n * counter * sx)) if self.tipo == 2: d['Spiral' + str(counter)] = i3.Translation( translation=(-(op[0] - ip[0]) / 2, -(self.n + 0.5) * counter * sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4)-self.couplingWG_l, -(self.n+0.5)*counter*sx)) #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R+(((self.n+0.5)*counter+self.width)*sx/4), self.chip_length*(3/4)+(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx)) d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * (1 / 2) - 2000, -(self.n + 0.5) * counter * sx)) d['OutPort' + str(counter)] = i3.Rotation( rotation=90) + i3.Translation(translation=( (op[0] - ip[0]) / 2 + 2 * self.R + (((self.n + 0.5) * counter + self.width) * sx / 4), 3000 + self.chip_length * (3 / 4) + (self.width + counter - (((counter + 1) - 1.0) % self.lengths)) * sx)) #For awg's #if self.tipo==2: #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+0.5)*counter*sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4.0), -(self.n+0.5)*counter*sx)) #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R #+(((self.n+0.5)*counter+self.width)*sx/100.0) #, self.chip_length*(2/4.0)+ #(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx)) return d # Fabio's addition def _generate_elements(self, elems): # We calculate the lengths of the 2 spirals in this pcell. # Note that we assume that there are exactly 2 spirals in this list. #assert len(self.Spiral_list) == 2 lengths = get_lengths(self) iz = self.Spiral_list[0].inner_size sx = iz[1] + 200 for counter, (child, length) in enumerate(zip(self.Spiral_list, lengths)): ip = child.ports["in"].position op = child.ports["out"].position width = child.ports["in"].trace_template.core_width #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width #i3.TECH.PPLAYER.NONE.LOGOTXT when using isipp50g if self.tipo == 2: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}_Length={}_R={}'.format( width, length, self.R), coordinate=((op[0] - ip[0]) / 2 - 1000.0, (self.n + 0.5) * counter * sx - 50.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) if self.tipo == 1: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}_Length={}_R={}'.format( width, length, self.R), coordinate=(-(op[0] - ip[0]) / 2 - 1000.0, -(self.n + 0.5) * counter * sx - 50.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) return elems
class Lspiral(PlaceAndAutoRoute): rectV_list = i3.ChildCellListProperty(default=[]) rectH_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") gap_inc_vec2 = i3.ListProperty(default=[], doc="length of 12mmi") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") wg_t2 = i3.WaveguideTemplateProperty(doc="change WG") # mmi_trace_template = i3.WaveguideTemplateProperty() # mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) # cleave = i3.PositiveNumberProperty(doc="tolerance", default=150) offset = i3.NumberProperty(doc="count", default=0) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port20") wg_t1.Layout( core_width=20, cladding_width=20 + 2 * 12.0, ) return wg_t1 def _default_wg_t2(self): wg_t2 = WireWaveguideTemplate( name="port_{}_{}".format(str(self.width), str(self.offset))) wg_t2.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t2 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(-200.0, 0.0), (600.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.wg_t2) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port # def _default_mmi_trace_template(self): # mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") # mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width # return mmi_trace_template # # def _default_mmi_access_template(self): # mmi_access_template = WireWaveguideTemplate(name="MMI_at") # mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) # return mmi_access_template def _default_rectH_list(self): MMI22_list = [] for l in range(0, 5, 1): cell = i3.Waveguide(name="rectH{}_{}".format( str(l), str(self.offset)), trace_template=self.wg_t2) cell.Layout(shape=[(0.0, 0.0), (17000 - 4000 * l, 0.0)]) # cell = i3.Waveguide(name="rectV{}".format(str(l)), # trace_template=self.wg_t2) # cell.Layout(shape=[(18000 - 4000 * l, 0.0), (0.0, 0.0)]) MMI22_list.append(cell) return MMI22_list def _default_rectV_list(self): print '____________ MMI 2x2 ______________' MMI22_list2 = [] for l in range(0, 5, 1): # cell = i3.Waveguide(name="rectH{}".format(str(l)), # trace_template=self.wg_t2) # cell.Layout(shape=[(0.0, 0.0), (18000-4000*l, 0.0)]) cell = i3.Waveguide(name="rectV{}_{}".format( str(l), str(self.offset)), trace_template=self.wg_t2) cell.Layout(shape=[(0.0, 0.0), (0.0, -1000 - 4000 * l)]) MMI22_list2.append(cell) return MMI22_list2 def _default_child_cells(self): child_cells = dict() for counter in range(0, 5, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taperH' + str(counter)] = self.WG2 child_cells['taperV' + str(counter)] = self.WG2 for counter, child in enumerate(self.rectH_list): print 'child number' + str(counter) child_cells['recH' + str(counter)] = child print 'child name ' + str(child.name) for counter, child in enumerate(self.rectV_list): print 'child number' + str(counter) child_cells['recV' + str(counter)] = child print 'child name ' + str(child.name) return child_cells def _default_links(self): links = [ ("recH0:out", "recV4:out"), ("recH1:out", "recV3:out"), ("recH2:out", "recV2:out"), ("recH3:out", "recV1:out"), ("recH4:out", "recV0:out"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 4000 # trans['ring0'] = (600, 0) # trans['ring1'] = (600, 1 * column) # trans['ring2'] = (600, 2 * column) # # trans['ring3'] = (1300, 8000 + 2 * column ) for i in range(0, 5, 1): trans["taperH{}".format(i)] = (0, column * i + 100 * self.offset) trans["taperV{}".format(i)] = i3.Rotation( rotation=-90) + i3.Translation( (4000 + column * i - 100 * self.offset, 20000)) trans["recH{}".format(i)] = (900, column * i + 100 * self.offset) trans["recV{}".format(i)] = (4000 + column * i - 100 * self.offset, 20000 - 900) # trans["taper0"] = (0, 0) # trans["taper1"] = i3.HMirror(0) + i3.Translation((2500, -1500)) # trans["taper2"] = i3.HMirror(0) + i3.Translation((2500, 1500)) # # trans["taper3"] = (0, 1 * column) # trans["taper4"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 1 * column)) # # trans["taper5"] = i3.HMirror(0) + i3.Translation((2500, 1500 + 1 * column)) # # trans["taper6"] = (0, 2 * column) # trans["taper7"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 2 * column)) # trans["taper8"] = i3.HMirror(0) + i3.Translation((2500, 1500 + 2 * column)) # # trans["taper9"] = (0, 3800 + 2 * column) # # trans["taper10"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 3 * column)) # # trans["taper11"] = i3.HMirror(0) + i3.Translation((3000, 6500+ 2 * column)) # # trans["taper12"] = i3.HMirror(0) + i3.Translation((3000, 9500+ 2 * column)) return trans def _default_bend_radius(self): bend_radius = 500 return bend_radius def _generate_elements(self, elems): for i in range(0, 5, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="WITDH={}_length={}*2_R=500".format( str(self.width), 17000 - 4000 * i), coordinate=(900, 55 + 4000 * i + 100 * self.offset), font=2, height=20.0, ) for j in range(0, 13, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(str(i), str(j)), coordinate=(550, 63 + 4000 * i + 100 * j), font=2, height=30.0, ) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(str(i), str(j)), # coordinate=(), font=2, height=30.0, transformation=i3.Rotation(rotation=-90) + i3.Translation( (20000 - 4000 * i - 100 * j + 63, 20000 - 550)), ) for i in range(0, 6, 1): elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 4000 * i - 1000 + 700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, 4000 * i - 1000 + 700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(4000 * i + 300, 19700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(4000 * i + 300, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(-100, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(500, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 19500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 20100), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(-100, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(500, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 20100), box_size=(100, 100)) return elems
class MZI(CircuitCell): control_points = i3.ListProperty( doc="Position of the control point for the longer arm of the MZI") bend_radius = i3.PositiveNumberProperty( default=5.0, doc="Bend radius of the waveguides") fgc = i3.ChildCellProperty(locked=True, doc="PCell for the fiber grating coupler") splitter = i3.ChildCellProperty(locked=True, doc="PCell for the Y-Branch") dir_coupler = i3.ChildCellProperty(locked=True, doc="PCell for the directional coupler") def _default_control_points(self): return [(100.0, 220.0)] def _default_fgc(self): return pdk.EbeamGCTE1550() def _default_splitter(self): return pdk.EbeamY1550() def _default_dir_coupler(self): return pdk.EbeamBDCTE1550() def _default_child_cells(self): child_cells = { "fgc_1": self.fgc, "fgc_2": self.fgc, "fgc_3": self.fgc, "yb": self.splitter, "dc": self.dir_coupler, } return child_cells def _default_joins(self): joins = [("fgc_3:opt1", "yb:opt1")] return joins def _default_connectors(self): br = self.bend_radius connectors = [ ("yb:opt3", "dc:opt2", manhattan, { "bend_radius": br }), ("yb:opt2", "dc:opt1", partial(manhattan, control_points=self.control_points), { "bend_radius": br }), ("dc:opt4", "fgc_2:opt1", manhattan, { "bend_radius": br }), ("dc:opt3", "fgc_1:opt1", manhattan, { "bend_radius": br }), ] return connectors def _default_place_specs(self): place_specs = [ i3.Place("fgc_1:opt1", (0, 0)), i3.PlaceRelative("fgc_2:opt1", "fgc_1:opt1", (0.0, 120.0)), i3.PlaceRelative("fgc_3:opt1", "fgc_2:opt1", (0.0, 120.0)), i3.PlaceRelative("dc:opt1", "yb:opt2", (20.0, -40.0), angle=90), ] return place_specs def _default_external_port_names(self): epn = { "fgc_3:fib1": "in", "fgc_2:fib1": "out1", "fgc_1:fib1": "out2", } return epn
class MZI_12_21(PlaceAndAutoRoute): _name_prefix = 'MZIs' #delay_length = i3.PositiveNumberProperty(default=132.0, doc="Delay length used in the mzi") delay_length = i3.PositiveNumberProperty(default=0.00001, doc="Delay length used in the mzi") R = i3.PositiveNumberProperty(default=200, doc="Radius of curvature") #MMI12_list = i3.ChildCellListProperty(default=[]) MMI12 = i3.ChildCellProperty(default=[]) MMI21_list = i3.ChildCellListProperty(default=[]) MMI22_list = i3.ChildCellListProperty(default=[]) #MZI_12_21_list = i3.ChildCellListProperty(default=[]) MZI_12_22_list = i3.ChildCellListProperty(default=[]) MZI_22_22_list = i3.ChildCellListProperty(default=[]) #MMI22_list = i3.ChildCellListProperty() wg_t = i3.TraceTemplateProperty(doc="trace template used") wg_t_MM = i3.TraceTemplateProperty(doc="Trace template used in the MM part") wg_t_port = i3.TraceTemplateProperty(doc="Trace template used in the ports") width_inc_vec = i3.ListProperty(default=[]) length_inc_vec = i3.ListProperty(default=[]) l_taper =i3.PositiveNumberProperty(default=200.0, doc="Length of the tapers") width=i3.PositiveNumberProperty(default=20.0, doc="width of MM") length_12 =i3.PositiveNumberProperty(default=110.0, doc="Length of MMI 1x2") length_22 =i3.PositiveNumberProperty(default=435.0, doc="Length of MMI 2x2") ts_12=i3.PositiveNumberProperty(default=11.25, doc="trace spacing") #ts for 12 is 7.0 --> MM=5 () L12=39.0 L22=158.0 #ts for 20 is 11 -->MM=9 (ts=11.25, MM=8.75) L12=110.0, L22=435.0 #ts for 30 is 16 -->MM=14 (ts=16.25, MM=13.75) L12=245.0, L22=980.0 chip_length = i3.PositiveNumberProperty(default=10000.0, doc="Radius of curvature") #chip_length = i3.PositiveNumberProperty(default=7100.0, doc="Radius of curvature") Port = i3.ChildCellProperty( doc="Used for ports") tlport = i3.PositiveNumberProperty(default=200.0, doc="Transition legth to ports") couplingWG = i3.ChildCellProperty(doc="", locked=True) couplingWG_l=i3.PositiveNumberProperty(default=3000.0, doc="Length of the coupling WG ") tt_port = i3.TraceTemplateProperty(doc="Wide trace template used for the contacts") tipo = i3.PositiveNumberProperty(default=1, doc="type of out-couplers tipo==1, straight, tipo==2, 90 degree bend") #template for Autorute def _default_trace_template(self): return self.wg_t def _default_wg_t_MM(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=self.width, cladding_width=self.width+2*8, ) return tt_w def _default_wg_t_port(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=8.75, cladding_width=8.75+2*8, ) return tt_w def _default_wg_t(self): tt_n = WireWaveguideTemplate() tt_n.Layout(core_width=3.3, cladding_width=3.3+2*8, ) return tt_n def _default_tt_port(self): tt_port = WireWaveguideTemplate() tt_port_layout=tt_port.Layout(core_width=15.0, cladding_width=15.0+2*8) return tt_port def _default_couplingWG(self): rect=i3.Waveguide(trace_template=self.tt_port) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.couplingWG_l,0.0)] ) return rect def _default_Port(self): Port=AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.wg_t) layout_Port = Port.Layout(transition_length=self.tlport)#.visualize(annotate=True) return Port def _default_MMI12(self): mmi12 = MMI1x2Tapered(mmi_trace_template=self.wg_t_MM, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t, name = 'MMI12_w_{}_L_{}'.format(self.width,self.length_12 ),) mmi12.Layout(transition_length=self.l_taper, length=self.length_12, trace_spacing=self.ts_12)#.visualize(annotate=True) return mmi12 ################################################################################# def _default_MMI22_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.length_inc_vec): print 'length number ' +str(l) print 'dl ' + str(dl) print 'MM length ' + str(self.length_22+dl) cell = MMI2x2Tapered(mmi_trace_template=self.wg_t_MM, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t , name = 'MMI22_w_'+str(self.width) +'_l_'+str(self.length_22+dl)) cell.Layout(transition_length=self.l_taper, length=self.length_22+dl, trace_spacing=self.ts_12) MMI22_list.append(cell) print 'cell name '+str(cell.name) print '__________________________' for w, dw in enumerate(self.width_inc_vec): MM_w=self.width+dw print 'width number ' +str(w) print 'dw ' + str(dw) print 'MM width ' + str(MM_w) wg_t_MM_w = WireWaveguideTemplate() wg_t_MM_w.Layout(core_width=MM_w, cladding_width=MM_w+2*8, ) cell = MMI2x2Tapered(mmi_trace_template=wg_t_MM_w, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t, name = 'MMI22_w_'+str(self.width+dw) +'_l_'+str(self.length_22)) cell.Layout(transition_length=self.l_taper, length=self.length_22, trace_spacing=self.ts_12+dw)#.visualize(annotate=True) print cell MMI22_list.append(cell) print 'cell name '+str(cell.name) print '__________________________' print 'last MMI22 done' print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MMI22_list def _default_MZI_12_22_list(self): print '____________ MZI_1x2_2x2 ______________' MZI_12_22_list = [] counter=1 print '____________ MZI_1x2_2x2 list ______________' for i, m in enumerate(self.MMI22_list): print 'MZI number ' + str(counter) cell = MZIWaveguides(name='MZI_12_22:'+str(self.MMI12.name)+str(m.name), trace_template=self.wg_t, splitter=self.MMI12, combiner=m, splitter_port_names=['out1','out2'], combiner_port_names=['in1','in2']) cell.Layout(bend_radius=self.R, delay_length=self.delay_length)#.visualize(annotate=True) MZI_12_22_list.append(cell) counter=counter+1 print 'splitter '+ cell.splitter.name print 'combiner '+ cell.combiner.name print cell.name print '__________________________' print "Last MMI_12_22 done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MZI_12_22_list def _default_MZI_22_22_list(self): print '____________ MZI_2x2_2x2 ______________' MZI_22_22_list = [] counter=1 print '____________ MZI_2x2_2x2 list ______________' for i, m in enumerate(self.MMI22_list): print 'MZI number ' + str(counter) cell = MZIWaveguides(name='MZI_22_22:'+str(m.name), trace_template=self.wg_t, splitter=m, combiner=m, splitter_port_names=['out1','out2'], combiner_port_names=['in1','in2']) cell.Layout(bend_radius=self.R,delay_length=self.delay_length)#.visualize(annotate=True) MZI_22_22_list.append(cell) counter=counter+1 print 'splitter '+ cell.splitter.name print 'combiner '+ cell.combiner.name print cell.name print '__________________________' print "Last MMI_22_22 done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MZI_22_22_list ################################################################################# def _default_child_cells(self): print '____________ Child cells ______________' child_cells = {} for counter, child in enumerate(self.MZI_22_22_list): print 'child number'+str(counter) child_cells['mzi_22_22_' + str(counter)] = child child_cells['InPort1_' + str(counter)] = self.Port child_cells['OutPort1_' + str(counter)]= self.Port child_cells['InPort2_' + str(counter)] = self.Port child_cells['OutPort2_' + str(counter)]= self.Port print 'child name ' +str(child.name) print child ################# for counter2, child in enumerate(self.MZI_12_22_list): print 'child number'+str(counter+1+counter2) child_cells['mzi_12_22_' + str(counter+1+counter2)] = child child_cells['InPort_' + str(counter+1+counter2)] = self.Port child_cells['OutPort1_' + str(counter+1+counter2)]= self.Port child_cells['OutPort2_' + str(counter+1+counter2)]= self.Port print 'child name ' +str(child.name) print child ################### print '__________________________' child_cells['InPortWG1'] = self.Port child_cells['OutPortWG1'] = self.Port child_cells['InPortWG2'] = self.Port child_cells['OutPortWG2'] = self.Port child_cells['InPortWG3'] = self.Port child_cells['OutPortWG3'] = self.Port print "Last child cell done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return child_cells def _default_links(self): links = [] for counter, child in enumerate(self.MZI_22_22_list): print counter in_port = "InPort1_{}:in".format(counter) print 'in_port', in_port out_port = 'mzi_22_22_{}:splitter_in1'.format(counter) print 'out_port', in_port links.append((in_port, out_port)) in_port = "InPort2_{}:in".format(counter) print 'in_port', in_port out_port = 'mzi_22_22_{}:splitter_in2'.format(counter) links.append((in_port, out_port)) out_port = "OutPort1_{}:in".format(counter) in_port = 'mzi_22_22_{}:combiner_out1'.format(counter) print 'in_port', in_port links.append((in_port, out_port)) out_port = "OutPort2_{}:in".format(counter) in_port = 'mzi_22_22_{}:combiner_out2'.format(counter) print 'in_port', in_port links.append((in_port, out_port)) for counter2, child in enumerate(self.MZI_12_22_list): out_port = "InPort_{}:in".format(counter+1+counter2) in_port = 'mzi_12_22_{}:splitter_in'.format(counter+1+counter2) links.append((in_port, out_port)) in_port = "OutPort1_{}:in".format(counter+1+counter2) out_port = 'mzi_12_22_{}:combiner_out1'.format(counter+1+counter2) links.append((in_port, out_port)) in_port = "OutPort2_{}:in".format(counter+1+counter2) out_port = 'mzi_12_22_{}:combiner_out2'.format(counter+1+counter2) links.append((in_port, out_port)) links.append(("InPortWG1:in", "OutPortWG1:in")) links.append(("InPortWG2:in", "OutPortWG2:in")) links.append(("InPortWG3:in", "OutPortWG3:in")) return links class Layout(PlaceAndAutoRoute.Layout): def _default_bend_radius(self): return self.R def _default_start_straight(self): return 1.0 print '____________ Layout mask ______________' def _default_child_transformations(self): d={} a=2.2 for counter, child in enumerate(self.MZI_22_22_list): if self.tipo==1: d['mzi_22_22_' + str(counter)] = i3.Translation(translation=((-1)**counter*2*self.R,counter*5*self.R)) d['InPort1_' + str(counter)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, counter*5*self.R-2.2*self.R)) d['OutPort1_' + str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5, counter*5*self.R-2.2*self.R)) d['InPort2_' + str(counter)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, counter*5*self.R+2.2*self.R)) d['OutPort2_' + str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5, counter*5*self.R+2.2*self.R)) print 'transformation ' +str(counter) + ' is ' +str(d) if self.tipo==2: #l_coupling=self.child_cells['Coupler'].l_coupling #radius=self.child_cells['Coupler'].local_bend_radius print 'R= ',self.R #print 'translation port: ' ##For w=20 d['mzi_22_22_' + str(counter)] = i3.Translation(translation=(counter*850+1200+1000+200,-counter*5*self.R)) d['InPort1_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter-a*self.R)) d['OutPort1_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+counter*50+counter*4*self.R+a*self.R-100, self.R*a)) d['InPort2_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter+a*self.R)) d['OutPort2_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+counter*50+counter*4*self.R-100, self.R*a)) d['InPortWG1'] = i3.HMirror()+i3.Translation(translation=(1500, 1000.0)) d['OutPortWG1']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5-500, self.R*a)) d['InPortWG2'] = i3.HMirror()+i3.Translation(translation=(1500, -3400+670)) d['OutPortWG2']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+2500, self.R*a)) d['InPortWG3'] = i3.HMirror()+i3.Translation(translation=(1500, -6500)) d['OutPortWG3']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+5600, self.R*a)) #d['mzi_22_22_' + str(counter)] = i3.Translation(translation=(counter*850+1200+1000+200,-counter*5*self.R)) #d['InPort1_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter-a*self.R)) #d['OutPort1_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1100+counter*50+counter*4*self.R+a*self.R-100, self.R*a)) #d['InPort2_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter+a*self.R)) #d['OutPort2_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1100+counter*50+counter*4*self.R-100, self.R*a)) #d['InPortWG1'] = i3.HMirror()+i3.Translation(translation=(1500, 1000.0)) #d['OutPortWG1']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5-500+1200, self.R*a)) #d['InPortWG2'] = i3.HMirror()+i3.Translation(translation=(1500, -3400+670)) #d['OutPortWG2']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+2500+1100, self.R*a)) #d['InPortWG3'] = i3.HMirror()+i3.Translation(translation=(1500, -6500)) #d['OutPortWG3']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+5600+1400, self.R*a)) ################ for counter2, child in enumerate(self.MZI_12_22_list): if self.tipo==1: d['mzi_12_22_' + str(counter+1+counter2)] = i3.Translation(translation=((-1)**counter2*2*self.R-self.length_22+counter*50+counter*4*self.R,(counter+1+counter2)*5*self.R)) d['InPort_' + str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, (counter+1+counter2)*5*self.R)) d['OutPort1_' + str(counter+1+counter2)]= i3.Translation(translation=(self.chip_length*0.5-self.bend_radius*counter*0.2-a*self.R-550, (counter+1+counter2)*5*self.R-2.2*self.R)) d['OutPort2_' + str(counter+1+counter2)]= i3.Translation(translation=(self.chip_length*0.5-self.bend_radius*counter*0.2-550, (counter+1+counter2)*5*self.R+2.2*self.R)) if self.tipo==2: #l_coupling=self.child_cells['Coupler'].l_coupling #radius=self.child_cells['Coupler'].local_bend_radius print 'R= ',self.R a=2.2 b=500 d['mzi_12_22_'+ str(counter+1+counter2)] = i3.Translation(translation=((counter+2+counter2)*850+1200+200+580,-(counter+1+counter2)*5*self.R-b)) d['InPort_'+ str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(1500, -(5*self.R)*(counter+1+counter2)-b)) d['OutPort1_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+(counter+1+counter2)*50+a*self.R+(counter+1+counter2)*4*self.R+b, self.R*a)) d['OutPort2_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+(counter+1+counter2)*50+(counter+1+counter2)*4*self.R+b,self.R*a)) #d['mzi_12_22_'+ str(counter+1+counter2)] = i3.Translation(translation=((counter+2+counter2)*850+1200+200+580+1000,-(counter+1+counter2)*5*self.R-b)) #d['InPort_'+ str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(1500, -(5*self.R)*(counter+1+counter2)-b)) #d['OutPort1_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1200+(counter+1+counter2)*50+a*self.R+(counter+1+counter2)*4*self.R+b, self.R*a)) #d['OutPort2_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1200+(counter+1+counter2)*50+(counter+1+counter2)*4*self.R+b,self.R*a)) ################ print '__________________________' print "Last layout child cell done" print d print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return d def _generate_elements(self, elems): for counter, child in enumerate(self.MZI_22_22_list): name=child.name print name elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), coordinate=(0.0, -counter*5*self.R+2*self.R-50.0#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), coordinate=(0.0, -counter*5*self.R-2*self.R+50.0#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) for counter2, child in enumerate(self.MZI_12_22_list): name=child.name print name elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}'.format(name), coordinate=(0.0, -(counter+1+counter2)*5*self.R-90.0-500#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) return elems
class Spirals(PlaceAndAutoRoute): _name_prefix = 'LSpiral' tipo = i3.PositiveNumberProperty(doc="Number loops", default=1) waveguide_template = i3.DefinitionProperty(doc="Trace template used") R = i3.PositiveNumberProperty(default=500, doc="Radius of curvature") spacing = i3.PositiveNumberProperty(default=100, doc="Radius of curvature") n_loops = i3.IntProperty(doc="Number loops", default=2) n_loops_vec = i3.ListProperty(default=[4, 8]) s_length_vec = i3.ListProperty(default=[0.0]) #Spiral_list = i3.ChildCellListProperty(doc="List containing the 90 degree angle child cells") #chip_length = i3.PositiveNumberProperty(default=12000.0, doc="") chip_length = i3.PositiveNumberProperty(default=13000.0, doc="") Port = i3.ChildCellProperty(doc="Used for ports") tlport = i3.PositiveNumberProperty(default=2000.0, doc="Transition legth to ports") couplingWG = i3.ChildCellProperty(doc="", locked=True) couplingWG_l = i3.PositiveNumberProperty(default=5000.0, doc="Length of the coupling WG ") tt_port = i3.TraceTemplateProperty( doc="Wide trace template used for the contacts") #width_vec = i3.ListProperty(default=[1]) n = i3.PositiveNumberProperty(default=1, doc="") width = i3.PositiveNumberProperty(default=1, doc="") lengths = i3.PositiveNumberProperty(default=1, doc="") def _default_lengths(self): for counter, cell in enumerate(self.s_length_vec): numero = counter + 1 return numero #template for Autorute def _default_trace_template(self): return self.waveguide_template def _default_tt(self): return self.waveguide_template def _default_tt_port(self): tt_port = WireWaveguideTemplate() tt_port_layout = tt_port.Layout(core_width=15.0, cladding_width=15.0 + 2 * 8.0) return tt_port def _default_couplingWG(self): rect = i3.Waveguide(trace_template=self.tt_port) layout_rect = rect.Layout(shape=[(0.0, 0.0), (self.couplingWG_l, 0.0)]) return rect def _default_Port(self): Port = AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout( transition_length=self.tlport) #.visualize(annotate=True) return Port def _default_child_cells(self): child_cells = { } # First we define the property "child_cells" as an empty dictionary for counter, length in enumerate( self.s_length_vec ): # the iteration starts in the first element of the list and follows element by element to the last element. #child_cells['Spiral{}'.format(counter)] = spiral #print spiral #print 'name of spiral:', spiral.name child_cells['InPort' + str(counter)] = self.Port child_cells['OutPort' + str(counter)] = self.Port print 'child_cells:', child_cells return child_cells def _default_links(self): links = [] for counter, spiral in enumerate(self.s_length_vec): print counter #in_port = "Spiral{}:in".format(counter) in_port = "InPort{}:in".format(counter) #links.append((in_port, out_port)) #in_port = "Spiral{}:out".format(counter) out_port = "OutPort{}:in".format(counter) links.append((in_port, out_port)) return links class Layout(PlaceAndAutoRoute.Layout): #tipo=1 def _default_bend_radius(self): return self.R def _default_child_transformations(self): d = {} for counter, child in enumerate(self.s_length_vec): #ip= child.ports["in"].position #print self.child_cells['InPort' + str(counter)].ports["out"].position #print self.child_cells['OutPort' + str(counter)].ports.position print '----------------' #print 'spiral length:', child.total_length print 'counter: ', counter print 'self.n = ', self.n print 'self.width: ', self.width #print 'sx: ', sx if self.tipo == 1: sx = 70 a = 0.5 print 2 * (22362 * 0.5 - self.couplingWG_l) print 'tipo = ', self.tipo #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, self.n*counter*sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*0.5, (self.n+a)*counter*sx)) #d['OutPort' + str(counter)] = i3.Translation(translation=(self.chip_length*0.5, (self.n+a)*counter*sx)) d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-22362 * 0.5 + self.couplingWG_l, (self.n + a) * counter * sx)) d['OutPort' + str(counter)] = i3.Translation( translation=(22362 * 0.5 - self.couplingWG_l, (self.n + a) * counter * sx)) #if self.tipo==2: #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+0.5)*counter*sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4)-self.couplingWG_l, -(self.n+0.5)*counter*sx)) #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R+(((self.n+0.5)*counter+self.width)*sx/4), self.chip_length*(3/4)+(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx)) if self.tipo == 2: sx = 100 #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+1)*counter*sx)) a = 7.0 print 'increment of length between waveguides of same width: ', ( self.n + a) * 1 * sx + ((self.n + a) * 1 + 0) * sx print 'increment of length between waveguides of same length group: ', ( self.n + a) * 0 * sx + ( (self.n + a) * 0 + self.width) * sx d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(0.0 - self.chip_length * 0.5, -(self.n + a) * counter * sx)) d['OutPort' + str(counter)] = i3.Rotation( rotation=90) + i3.Translation(translation=( (((self.n + a) * counter + self.width) * sx), self.chip_length * 0.5 + (self.width + counter - (((counter + 1) - 1.0) % self.lengths)) * sx)) return d # Fabio's addition def _generate_elements(self, elems): # We calculate the lengths of the 2 spirals in this pcell. # Note that we assume that there are exactly 2 spirals in this list. #assert len(self.Spiral_list) == 2 lengths = get_lengths(self)[0] print lengths Link = get_lengths(self)[1] print Link if self.tipo == 1: sx = 70 for counter, (child, length) in enumerate( zip(self.s_length_vec, lengths)): #ip= child.ports["in"].position #op= child.ports["out"].position width = Link.trace_template.core_width #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width a = 0.5 #i3.TECH.PPLAYER.NONE.LOGOTXT when using isipp50g elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}'.format(width, ), coordinate=(-self.chip_length * 0.5 + 2 * self.tlport, (self.n + a) * counter * sx - 15.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}'.format(width, ), coordinate=(0.0, (self.n + a) * counter * sx - 15.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}'.format(width, ), coordinate=(self.chip_length * 0.5 - 2 * self.tlport, (self.n + a) * counter * sx - 15.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) if self.tipo == 2: sx = 100 for counter, (child, length) in enumerate( zip(self.s_length_vec, lengths)): #ip= child.ports["in"].position #op= child.ports["out"].position width = Link.trace_template.core_width #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width a = 7.0 #i3.TECH.PPLAYER.NONE.LOGOTXT when using isipp50g elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}_Length={}_R={}'.format( width, length, self.R), coordinate=(-1500, -(self.n + a) * counter * sx - 55.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) return elems
class CombinedCircuit(PlaceAndAutoRoute): L1=i3.PositiveNumberProperty(default=100,doc="radius or curvature of circuit") incoupler = i3.ChildCellProperty(doc="coupler used", locked=True) outcoupler = i3.ChildCellProperty(doc="coupler used", locked=True) aligningmark=i3.ChildCellProperty(doc="aligning mark") lens=i3.ChildCellProperty(doc="flowcellbox") flowcellbox=i3.ChildCellProperty(doc="lens") aligningmark_h=i3.ChildCellProperty(doc="aligning mark for heater") coupling_l=i3.PositiveNumberProperty(default=5+2*270, doc="length of coupling WG") coupling_win = i3.PositiveNumberProperty(default=15, doc="width of the coupling WG") coupling_wout = i3.PositiveNumberProperty(default=15, doc="width of the coupling WG") chip_length=i3.PositiveNumberProperty(default=20000,doc="length of the chip") radius=i3.PositiveNumberProperty(default=100,doc="radius or curvature of circuit") core=i3.PositiveNumberProperty(default=3.3, doc="core width") width=i3.PositiveNumberProperty(default=3.3, doc="narrow width of heaters") tipo =i3.NumberProperty(default=2, doc="1=spiral, 2=wide waveguide") wide_wg_l = i3.NumberProperty(default=20, doc="Wide Waveguide") coupler_p=i3.NumberProperty(default=20, doc="position of the grating coupler with respect to the edge") ctipoin=i3.PositiveNumberProperty(default=2, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper") ctipoout=i3.PositiveNumberProperty(default=1, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper") transition_length_couplerin=i3.PositiveNumberProperty(default=500, doc="transition length of the coupler") transition_length_couplerout=i3.PositiveNumberProperty(default=500, doc="transition length of the coupler") aligningmark=i3.ChildCellProperty(doc="aligning mark for circuit used") increment=i3.NumberProperty(default=0, doc="core width") periodin=i3.PositiveNumberProperty(default=1.73, doc="core width") dutyin=i3.PositiveNumberProperty(default=0.5, doc="core width") nperiodsin=i3.PositiveNumberProperty(default=8, doc="core width") periodout=i3.PositiveNumberProperty(default=2.566, doc="core width") dutyout=i3.PositiveNumberProperty(default=0.403, doc="core width") nperiodsout=i3.PositiveNumberProperty(default=20, doc="core width") Loc = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam Lec = i3.ListProperty(default=[]) #Etched part layName_h = i3.StringProperty(default = 'standard', doc = 'options: standard, new') layName_h2 = i3.StringProperty(default = 'standard', doc = 'options: standard, new') layName_c = i3.StringProperty(default = 'standard', doc = 'options: standard, new') layName_f = i3.StringProperty(default = 'standard', doc = 'options: standard, new') separation=i3.NumberProperty(default=100.0, doc="separation between cross and gratings") size=i3.NumberProperty(default=250.0, doc="Size of the cross of aligning marks") print 'core width',core print 'heater width', width def _default_trace_template(self): return self.incoupler.inPort.trace_template def _default_Lec(self): #Loc=[2.175,2.122,2.07,2.016,1.963,1.908,1.854,1.798,1.743,1.687,1.63,1.573, #1.515,1.457,1.398,1.339,1.279,1.219,1.158,1.096] #version A Loc=[2.043,1.643] #1um etch for 2um GOS #Loc=[1,1,1,1,1,1,1] Loc.reverse() return Loc def _default_Loc(self): #Lec=[0.242,0.301,0.361,0.421,0.482,0.543,0.605,0.667,0.73,0.794,0.858,0.922, #0.988,1.054,1.12,1.187,1.255,1.323,1.392,1.462] #version A Lec=[0.511,0.949] #1um etch for 2um GOS #Lec=[0.4,0.5,0.6,0.7,0.8,0.9,1] Lec.reverse() return Lec def _default_child_cells(self): child_cells={ "incoupling1" : self.incoupler, "outcoupling1" : self.outcoupler, # "am1" : self.aligningmark, # "am2" : self.aligningmark, # "am3" : self.aligningmark, # "am4" : self.aligningmark, # "inlens1" : self.lens, # "outlens1" : self.lens, # "chip" : self.flowcellbox } return child_cells def _default_links(self): links = [( "incoupling1:InPort_in","outcoupling1:InPort_in"), ] return links def _default_aligningmark(self): am=AligningMarks(layName='metal2', separation=self.separation, size=self.size) return am def _default_aligningmark_h(self): am=AligningMarks(layName=self.layName_h, separation=self.separation, size=self.size) return am def _default_aligningmark_h2(self): am=AligningMarks(layName=self.layName_h2, separation=self.separation, size=self.size) return am def _default_outcoupler(self): print 'I am in the coupler' coupler = GratingCoupler1Band(coupling_l=self.coupling_l+self.increment, chirp=self.ctipoout, coupling_w=self.coupling_wout,core=self.core, layName = self.layName_c, period=self.periodout, duty=self.dutyout, nperiods=self.nperiodsout, Loc=self.Loc, Lec=self.Lec, transition_length_coupler=self.transition_length_couplerout, ) #layout_coupler=coupler.Layout(transition_length_coupler=self.transition_length_couplerout, #)#.visualize(annotate=True) return coupler def _default_incoupler(self): print 'I am in the coupler' coupler = GratingCoupler1Band(coupling_l=self.coupling_l, chirp=self.ctipoin, coupling_w=self.coupling_win,core=self.core, layName = self.layName_c, period=self.periodin, duty=self.dutyin, nperiods=self.nperiodsin, Loc=self.Loc, Lec=self.Lec, transition_length_coupler=self.transition_length_couplerin, ) ##layout_coupler=coupler.Layout(transition_length_coupler=self.transition_length_couplerin, #)#.visualize(annotate=True) return coupler def _default_lens(self): lens=Lens() return lens def _default_flowcellbox(self): fl=flowcellbox() return fl class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): incoupler_t =fc_t1 = i3.Rotation(rotation=00.0) #+ i3.Translation(translation=(-(self.chip_length*0.5-self.coupler_p),0.0)) outcoupler_t = i3.Rotation(rotation=180.0) #+ i3.Translation(translation=(self.chip_length*0.5-self.coupler_p,0.0)) L1=self.L1 #s=270 s=0 #z=2500 z=0 #socket_length=2*self.period*int(self.nperiods)+2*10 socket_lengthout=2*(sum(self.Lec)+sum(self.Loc))+2*self.periodout*int(self.nperiodsout)+1*10 socket_lengthin=2*self.periodin*int(self.nperiodsin)+0*10 xin=0.75*self.periodin*int(self.nperiodsin) xout=0.75*(self.periodout*int(self.nperiodsout)+sum(self.Lec)+sum(self.Loc)) print "socket_lengthout: ", socket_lengthout print "socket_lengthin: ", socket_lengthin #print self.child_cells['incoupling1'].FGC.Layout.socket_length child_transformations={ #"incoupling1" : i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z-socket_lengthin#-50.0#-self.transition_length_couplerin #,-s)), #"outcoupling1" : i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1#+50.0#+self.transition_length_couplerout+self.increment-z #,-s)), "incoupling1" : i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z#-socket_lengthin#-50.0#-self.transition_length_couplerin ,-s)), "outcoupling1" : i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1+socket_lengthout-100#+50.0#+self.transition_length_couplerout+self.increment-z ,-s)), # "inlens1" : i3.Rotation(rotation=00.0) +i3.Translation(translation=(-z-self.transition_length_couplerin-socket_lengthin+xin,-s)), #"outlens1" : i3.Rotation(rotation=180.0) +i3.Translation(translation=(L1+self.transition_length_couplerin+self.increment-z-xin,-s)), # "am1" : i3.Translation(translation=(self.chip_length*0.5-1000,0.0)), # "am2" : i3.Translation(translation=(-self.chip_length*0.5+1000,0.0)), # "am3" : i3.Translation(translation=(-self.chip_length*0.5+5000,0.0)), # "am4" : i3.Translation(translation=(self.chip_length*0.5-5000,0.0)) , } return child_transformations def _generate_elements(self, elems): elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='period={}_duty={}_n={}_width={}'.format(self.periodin, self.dutyin, self.nperiodsin, self.core), #coordinate=(-(op[0]-ip[0])/2-1000.0, -(self.n+0.5)*counter*sx-50.0), #alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), #font = 2, #height=20.0) coordinate=(0.0, -20), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) return elems def _default_bend_radius(self): return self.radius+self.core*0.5
class GratingCoupler1Band(PlaceComponents): core=i3.PositiveNumberProperty(default=3.3, doc="core width") period=i3.PositiveNumberProperty(default=2.566, doc="core width") duty=i3.PositiveNumberProperty(default=0.403, doc="core width") nperiods=i3.PositiveNumberProperty(default=7, doc="core width") wg_coupler= i3.TraceTemplateProperty(doc="Wide trace template used") #FGC= i3.ChildCellProperty(doc="grating used") ctipo=i3.PositiveNumberProperty(default=1, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper") coupling_l=i3.PositiveNumberProperty(default=5000, doc="length of coupling WG") coupler_template= i3.TraceTemplateProperty(doc="Wide trace template used for coupler tipo2") waveguide_template= i3.TraceTemplateProperty(doc="Wide trace template used on routing") coupling_w = i3.PositiveNumberProperty(default=20, doc="width of the coupling WG") transition_length_coupler=i3.PositiveNumberProperty(default=300, doc="transition length of the coupler") Grating_list = i3.ChildCellListProperty(doc="List containing the non etched parts of gratings") inPort = i3.ChildCellProperty( doc="Used for ports") outPort = i3.ChildCellProperty( doc="Used for ports") incouplingWG = i3.ChildCellProperty( doc="Used for ports") outcouplingWG = i3.ChildCellProperty( doc="Used for ports") chirp=i3.NumberProperty(default=1, doc="1=chirped") socket_length=i3.PositiveNumberProperty(default=2.2, doc="length of coupling WG") layName = i3.StringProperty(default = 'waveguide') layNameg = i3.StringProperty(default = 'metal') print 'the name of the layer is', layName props = i3.DictProperty() def _default_props(self): return AssignProcess(self.layName) propsg = i3.DictProperty() def _default_propsg(self): return AssignProcess(self.layNameg) Lo = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam Le = i3.ListProperty(default=[]) #Etched part Loc = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam Lec = i3.ListProperty(default=[]) #Etched part #def _default_transition_length(self): #return self.transition_length_coupler def _default_socket_length(self): a=sum(self.Lo)+sum(self.Le) #if self.chirp==1: #A=a=self.period * int(self.nperiods)+sum(self.Loc)) return a def _default_Loc(self): #Loc=[2.175,2.122,2.07,2.016,1.963,1.908,1.854,1.798,1.743,1.687,1.63,1.573, #1.515,1.457,1.398,1.339,1.279,1.219,1.158,1.096] Loc=self.Loc Loc.reverse() return Loc def _default_Lec(self): #Lec=[0.242,0.301,0.361,0.421,0.482,0.543,0.605,0.667,0.73,0.794,0.858,0.922, #0.988,1.054,1.12,1.187,1.255,1.323,1.392,1.462] Lec=self.Lec Lec.reverse() return Lec def _default_Lo(self): A=[None] * int(self.nperiods) if self.chirp==1: A=[None] * int(self.nperiods+len(self.Loc)) for x in range(0,int(self.nperiods)): A[x]=self.period*self.duty if self.chirp==1: for x in range(0,int(len(self.Loc))): print x print len(self.Loc) A[int(self.nperiods)+x]=self.Loc[x] print 'Lo: ',A return A def _default_Le(self): Le=[None] * int(self.nperiods) if self.chirp==1: Le=[None] * int(self.nperiods+len(self.Loc)) for x in range(0,int(self.nperiods)): Le[x]=self.period*(1-self.duty) if self.chirp==1: for x in range(0,int(len(self.Loc))): Le[int(self.nperiods)+x]=self.Lec[x] print 'Le: ',Le return Le def _default_Grating_list(self): Grating_list = [] for x in range(0,int(len(self.Lo))): #rect=i3.Waveguide(trace_template=self.wg_coupler) rect=i3.Waveguide(trace_template=self.coupler_template) #layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True) Grating_list.append(rect) return Grating_list def _default_incouplingWG(self): rect=i3.Waveguide(trace_template=self.wg_coupler) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.coupling_l,0.0)] ) return rect def _default_outcouplingWG(self): rect=i3.Waveguide(trace_template=self.wg_coupler) layout_rect = rect.Layout(shape=[(0.0, 0.0),(50+self.socket_length,0.0)] ) return rect def _default_inPort(self): Port=AutoTransitionPorts(contents=self.incouplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout(transition_length=self.transition_length_coupler)#.visualize(annotate=True) return Port def _default_outPort(self): Port=AutoTransitionPorts(contents=self.outcouplingWG, port_labels=["in"], trace_template=self.wg_coupler) layout_Port = Port.Layout(transition_length=10)#.visualize(annotate=True) return Port def _default_child_cells(self): child_cells = {} # First we define the property "child_cells" as an empty dictionary for counter, pillar in enumerate(self.Grating_list): child_cells['pillar{}'.format(counter)] = pillar print pillar print 'name of pillar:', pillar.name child_cells['InPort'] = self.inPort child_cells['OutPort']= self.outPort print 'child_cells:', child_cells return child_cells def _default_props(self): return AssignProcess(self.layName) def _default_wg_coupler(self): wg_coupler = WireWaveguideTemplate() wg_coupler.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w+2*8, **self.props) return wg_coupler def _default_waveguide_template(self): wg_t = WireWaveguideTemplate() wg_t_layout=wg_t.Layout(core_width=self.core, cladding_width=self.core+2*8, **self.props) return wg_t def _default_coupler_template(self): wg_t = WireWaveguideTemplate() wg_t_layout=wg_t.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w, **self.propsg) return wg_t def _default_trace_template(self): return self.waveguide_template def _default_contents(self): return self.FGC def _default_port_labels(self): return ["out"] class Layout(PlaceComponents.Layout): #def _default_transition_length(self): #return self.transition_length_coupler def _default_child_transformations(self): d={} position=0 for counter, child in enumerate(self.Grating_list): d['pillar{}'.format(counter)] = i3.Translation(translation=(position, 0.0)) position=position+self.Lo[counter]+self.Le[counter] print 'pillar position: ', position print 'counter= ', counter print 'Lo: ', self.Lo[counter] print 'Le: ', self.Le[counter] #d['InPort'] = i3.HMirror()+ i3.Translation(translation=(position+10,0)) d['InPort'] = i3.HMirror()+ i3.Translation(translation=(self.coupling_l+self.socket_length,0)) d['OutPort'] = i3.Translation(translation=(-50,0.0)) return d
class Mask(APAC): grating_coupler = i3.ChildCellProperty(doc="Grating couplers used in order") modulators = i3.ChildCellListProperty(doc="Modulators used") m_spacing = i3.ListProperty(default=[3.5, 4.0, 4.5, 5.0], doc="Metal spacings") def _default_grating_coupler(self): return FC_TE_1550() def _default_modulators(self): mods = [] for w in self.m_spacing: cell = TW_MZM(name=self.name + "Modulator_{}".format(w)) cell.Layout(modulator_length=1500, metal_spacing=w) mods.append(cell) return mods def _default_child_cells(self): childs = dict() for cnt, mod in enumerate(self.modulators): # Iterates over self.m_spacing and uses cnt as a counter. This is a python construct. childs["grating_in_{}".format(cnt)] = self.grating_coupler childs["mod_{}".format(cnt)] = mod childs["grating_out_{}".format(cnt)] = self.grating_coupler return childs def _default_connectors(self): conn = [] for cnt, mod in enumerate(self.modulators): in_port = "grating_in_{}:out".format(cnt) out_port = "mod_{}:in".format(cnt) conn.append((in_port, out_port, wide_manhattan)) in_port = "grating_out_{}:out".format(cnt) out_port = "mod_{}:out".format(cnt) conn.append((in_port, out_port, wide_manhattan)) return conn def _default_electrical_links(self): el_links = [] #shorting the ground for cnt, mod in enumerate(self.modulators): for arm_name in ["1", "5"]: p1 = "mod_{}:elec_right_{}".format(cnt, arm_name) p2 = "mod_{}:elec_right_{}".format(cnt, "3") el_links.append((p1, p2)) p1 = "mod_{}:elec_left_{}".format(cnt, arm_name) p2 = "mod_{}:elec_left_{}".format(cnt, "3") el_links.append((p1, p2)) return el_links def _default_external_port_names(self): epn = dict() for cnt, mod in enumerate(self.modulators): epn["grating_in_{}:vertical_in".format(cnt)] = "in{}".format(cnt) epn["grating_out_{}:vertical_in".format(cnt)] = "out{}".format(cnt) return epn def _default_propagated_electrical_ports(self): pp = [] for cnt, mod in enumerate(self.modulators): for arm_name in [2,3,4]: pp.append("mod_{}_elec_right_{}".format(cnt, arm_name)) pp.append("mod_{}_elec_left_{}".format(cnt, arm_name)) return pp class Layout(APAC.Layout): grating_coupler_spacing = i3.PositiveNumberProperty(default=800, doc="Spacing between the grating couplers") center_grating_coupler_y = i3.PositiveNumberProperty(doc="Start position of the first grating coupler") def _default_metal1_width(self): return 20.0 def _default_center_bp(self): return 2500 / 2.0 def _default_center_grating_coupler_y(self): return 5150.0 / 2.0 def _default_child_transformations(self): trans = dict() nw = len(self.m_spacing) for cnt, mod in enumerate(self.modulators): t = (100.0, self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing) trans["grating_in_{}".format(cnt)] = i3.Translation(translation=t) t = (2500/2.0 , self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing) trans["mod_{}".format(cnt)] = i3.Translation(translation=t) trans["grating_out_{}".format(cnt)] = i3.Rotation(rotation=180.0) + i3.Translation(translation=(2500, self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing)) return trans @i3.cache() def _default_electrical_routes(self): routes = [] for c in self.electrical_links: inst1, port1 = self._resolve_inst_port(c[0]) inst2, port2 = self._resolve_inst_port(c[1]) if "left" in port1.name: r = i3.RouteManhattan(input_port=port1, output_port=port2, min_straight=100.0, angle_out=0.0, angle_in=180.0, rounding_algorithm=None) else: r = i3.RouteManhattan(input_port=port1, output_port=port2, min_straight=100.0, angle_out=180.0, angle_in=0.0, rounding_algorithm=None) routes.append(r) return routes
class Layout(AutoPlaceAndConnect.Layout): metal1_layer = i3.LayerProperty( doc="layer used for the electrical links") metal1_width = i3.PositiveNumberProperty( default=5, doc="Width of the metal1 paths") electrical_routes = i3.ListProperty( doc= "routes used for the electical connections. Is has the same length as electical links. None will use Routemanhatan" ) def _default_metal1_layer(self): return i3.TECH.PPLAYER.M1.LINE def _default_electrical_routes(self): return [None] * len(self.electrical_links) @i3.cache() def _get_final_electrical_routes(self): final_routes = [] for c, r in zip(self.electrical_links, self.electrical_routes): if r is None: inst1, port1 = self._resolve_inst_port(c[0]) inst2, port2 = self._resolve_inst_port(c[1]) route = i3.RouteManhattan(input_port=port1, output_port=port2, angle_out=0.0, angle_in=0.0, rounding_algorithm=None) final_routes.append(route) else: final_routes.append(r) return final_routes @i3.cache() def _get_electrical_route_elements(self): els = [] for r in self._get_final_electrical_routes(): els += i3.Path(layer=self.metal1_layer, shape=r, line_width=self.metal1_width) return els def _generate_elements(self, elems): elems = super(APAC.Layout, self)._generate_elements(elems) elems.extend(self._get_electrical_route_elements()) return elems def _generate_ports(self, ports): connected_links = [p[0].replace(':', '_') for p in self.links] + [ p[1].replace(':', '_') for p in self.links ] connected_links.extend( [p[0].replace(':', '_') for p in self.connectors] + [p[1].replace(':', '_') for p in self.connectors]) for key, val in self._get_child_cell_instances().iteritems(): if key in self.child_cells.keys(): for p in val.ports: name = "{}_{}".format(key, p.name) if name not in connected_links: ext_key = '{}:{}'.format(key, p.name) if ext_key in self.cell.external_port_names: name = self.cell.external_port_names[ext_key] if p.domain is i3.ElectricalDomain and name not in self.propagated_electrical_ports: pass else: ports.append(p.modified_copy(name=name)) return ports
class APAC(AutoPlaceAndConnect): connectors = i3.ListProperty( doc= "list of tuples that need to be replaced by connectors. Format is [('inst1:term1','inst2:term2', connector_func=None, connector_kwargs, ...]", restriction=i3.RestrictTypeList(allowed_types=[collections.Sequence])) connector_function = i3.CallableProperty( doc="Connector function used by default if nothing is specified") connector_kwargs = i3.DictProperty( doc="Routing kwargs passed if nothing is specified") electrical_links = i3.ListProperty(default=[], doc="List of electrical links") propagated_electrical_ports = i3.ListProperty( default=[], doc= "List of electrical ports that are propagated to the next level. By default None are propagated" ) def connector_less_apac(self): """ generete a connectorless apac to get the location of all the instances. """ lv = self.get_default_view(i3.LayoutView) temp_apac = APAC(name="{}_connectorless".format(self.name), child_cells=self.child_cells, links=self.links) temp_apac_lv = temp_apac.Layout( child_transformations=lv.child_transformations, mirror_children=lv.mirror_children) return temp_apac_lv @i3.cache() def get_child_instances(self): return self.connector_less_apac().instances def _default_connector_function(self): return manhattan def _default_connector_kwargs(self): return {} def _default__connector_cells(self): connector_cells = [] if len(self.connectors) > 0: clv = self.connector_less_apac() for cnt, c in enumerate(self.connectors): connector_function = self.connector_function connector_kwargs = self.connector_kwargs start_port = get_port_from_interface(port_id=c[0], lv=clv) end_port = get_port_from_interface(port_id=c[1], lv=clv) if len(c) > 2: if c[2] is not None: connector_function = c[2] if len(c) == 4: if c[3] is not None: connector_kwargs = c[3] name = self.name + "_connector_{}".format(cnt) cell = connector_function(start_port=start_port, end_port=end_port, name=name, connector_kwargs=connector_kwargs) connector_cells.append(cell) return connector_cells class Layout(AutoPlaceAndConnect.Layout): metal1_layer = i3.LayerProperty( doc="layer used for the electrical links") metal1_width = i3.PositiveNumberProperty( default=5, doc="Width of the metal1 paths") electrical_routes = i3.ListProperty( doc= "routes used for the electical connections. Is has the same length as electical links. None will use Routemanhatan" ) def _default_metal1_layer(self): return i3.TECH.PPLAYER.M1.LINE def _default_electrical_routes(self): return [None] * len(self.electrical_links) @i3.cache() def _get_final_electrical_routes(self): final_routes = [] for c, r in zip(self.electrical_links, self.electrical_routes): if r is None: inst1, port1 = self._resolve_inst_port(c[0]) inst2, port2 = self._resolve_inst_port(c[1]) route = i3.RouteManhattan(input_port=port1, output_port=port2, angle_out=0.0, angle_in=0.0, rounding_algorithm=None) final_routes.append(route) else: final_routes.append(r) return final_routes @i3.cache() def _get_electrical_route_elements(self): els = [] for r in self._get_final_electrical_routes(): els += i3.Path(layer=self.metal1_layer, shape=r, line_width=self.metal1_width) return els def _generate_elements(self, elems): elems = super(APAC.Layout, self)._generate_elements(elems) elems.extend(self._get_electrical_route_elements()) return elems def _generate_ports(self, ports): connected_links = [p[0].replace(':', '_') for p in self.links] + [ p[1].replace(':', '_') for p in self.links ] connected_links.extend( [p[0].replace(':', '_') for p in self.connectors] + [p[1].replace(':', '_') for p in self.connectors]) for key, val in self._get_child_cell_instances().iteritems(): if key in self.child_cells.keys(): for p in val.ports: name = "{}_{}".format(key, p.name) if name not in connected_links: ext_key = '{}:{}'.format(key, p.name) if ext_key in self.cell.external_port_names: name = self.cell.external_port_names[ext_key] if p.domain is i3.ElectricalDomain and name not in self.propagated_electrical_ports: pass else: ports.append(p.modified_copy(name=name)) return ports class Netlist(AutoPlaceAndConnect.Netlist): def _generate_terms(self, terms): from ipkiss3.pcell.netlist.term import TermDict terms = super(AutoPlaceAndConnect.Netlist, self)._generate_terms(terms) new_terms = TermDict() for key, val in terms.iteritems(): if val.domain is i3.ElectricalDomain and val.name not in self.propagated_electrical_ports: pass else: new_terms[key] = val return new_terms
class my_dc(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.trace_template, ) cell.Layout(name="MMI22_l_{}".format(str(self.gap_inc_vec[l])), transition_length=200.0, length=self.gap_inc_vec[l], trace_spacing=11.0) # cell = RingRectSymm180DropFilter(name='ring' + str(dl) + str(self.length), # ring_trace_template=self.trace_template) # cell.Layout(bend_radius=200, # coupler_lengths=[self.length, self.length], # coupler_radii=[300.0, 300.0], # coupler_angles=[90.0, 90.0], # coupler_spacings=[3.8 + self.gap_inc_vec[l], 3.8 + self.gap_inc_vec[l]], # straights=(self.length, 0.0), # # manhattan=True, # ) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 12, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:in2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:out2"), ("taper3:out", "ring0:out1"), ("taper4:out", "ring1:in2"), ("taper5:out", "ring1:in1"), ("taper6:out", "ring1:out2"), ("taper7:out", "ring1:out1"), ("taper8:out", "ring2:in2"), ("taper9:out", "ring2:in1"), ("taper10:out", "ring2:out2"), ("taper11:out", "ring2:out1"), # ("taper12:out", "ring3:out2"), # ("taper13:out", "ring3:in1"), # ("taper14:out", "ring3:in2"), # ("taper15:out", "ring3:out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 10000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (2500, 0) trans['ring1'] = (2500, 0 + column) trans['ring2'] = (2500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 4000) trans["taper1"] = (0, -4000) trans["taper2"] = i3.HMirror(0) + i3.Translation((5000, 2500)) trans["taper3"] = i3.HMirror(0) + i3.Translation((5000, -2500)) trans["taper4"] = (0, 4000 + column) trans["taper5"] = (0, -4000 + column) trans["taper6"] = i3.HMirror(0) + i3.Translation( (5000, 2500 + column)) trans["taper7"] = i3.HMirror(0) + i3.Translation( (5000, -2500 + column)) trans["taper8"] = (0, 4000 + 2 * column) trans["taper9"] = (0, -4000 + 2 * column) trans["taper10"] = i3.HMirror(0) + i3.Translation( (5000, 2500 + 2 * column)) trans["taper11"] = i3.HMirror(0) + i3.Translation( (5000, -2500 + 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius # def _generate_elements(self, elems): # # # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.mmi22.get_default_view(i3.LayoutView).name, # self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.mmi22.get_default_view(i3.LayoutView).name, # self.cell.wg_t1.name), # coordinate=(-2000.0, -150.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=200.0, # transformation=i3.Rotation((0.0, 0.0), 90.0)) # # return elems def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0, transformation=i3.Translation( (2500, 100 + 10000 * counter))) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(-2000, -150), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=200.0, transformation=i3.Rotation( (0.0, 0.0), 90.0) + i3.Translation( (450, -2000 + 10000 * counter))) return elems
class my_dc(PlaceAndAutoRoute): # dc = i3.ChildCellProperty() # dc2 = i3.ChildCellProperty() DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="gap") # length = i3.PositiveNumberProperty(default=60.0, doc="Length of coupler") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty() # wg_dc2 = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) sm_width = i3.PositiveNumberProperty(doc="width of waveguide", default=3.8) # start_id = i3.PositiveNumberProperty(doc="name_id", default=1) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 16, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template" + str(self.sm_width)) wg_sm.Layout(core_width=self.sm_width, cladding_width=self.sm_width + 16.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.sm_width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): # print 'length number ' + str(l) # print 'dl ' + str(dl) cell = DoubleSpiralRounded( name='spiral' + str(dl) + str(self.sm_width), trace_template=self.trace_template, n_o_loops=8, ) layout = cell.Layout( angle_step=30, inner_size=[700, 1400], bend_radius=self.gap_inc_vec[l], manhattan=False, spacing=2 * 8 + self.sm_width + 5, ) print layout.trace_length() MMI22_list.append(cell) return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 4, 1): # print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 # child_cells["dircoup1"] = self.dc # child_cells["dircoup2"] = self.dc2 # child_cells["straight"] = self.WG2 for counter, child in enumerate(self.DC_list): # print 'child number' + str(counter) child_cells['ring' + str(counter)] = child # print 'child name ' + str(child.name) # print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:in"), ("taper1:out", "ring0:out"), ("taper2:out", "ring1:in"), ("taper3:out", "ring1:out"), # ("taper4:out", "ring1:out2"), # ("taper5:out", "ring1:in1"), # ("taper6:out", "ring1:in2"), # ("taper7:out", "ring1:out1"), # # ("taper8:out", "ring2:out2"), # ("taper9:out", "ring2:in1"), # ("taper10:out", "ring2:in2"), # ("taper11:out", "ring2:out1"), # ("taper12:out", "ring3:out2"), # ("taper13:out", "ring3:in1"), # ("taper14:out", "ring3:in2"), # ("taper15:out", "ring3:out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 3000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1300, -2000) # trans['ring1'] = i3.VMirror(0) + i3.Translation((1300, 2000)) trans['ring1'] = (1300 + column, -2000) # trans['ring2'] = (1500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, -4000) trans["taper1"] = i3.HMirror(0) + i3.Translation((3000, -3500)) trans["taper2"] = (0 + column, -3500) trans["taper3"] = i3.HMirror(0) + i3.Translation( (3000 + column, -4000)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.dc.name, self.cell.wg_t1.name), # coordinate=(1350.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.dc2.name, self.cell.wg_t1.name), # coordinate=(4650.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), # # coordinate=(0.0, -counter * 5 * self.R - 2 * self.R + 50.0 # -100 # ), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) return elems
class my_dc3(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout(core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts( name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2x2Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.trace_template, ) cell.Layout(name="MMI22_l_{}".format(str(self.gap_inc_vec[l])), transition_length=200.0, length=self.gap_inc_vec[l], trace_spacing=11.0 ) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 4, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:in2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:out2"), ("taper3:out", "ring0:out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 10000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1500, 0) # trans['ring1'] = (2500, 0 + column) # trans['ring2'] = (2500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 2500) trans["taper1"] = (0, -2500) trans["taper2"] = i3.Rotation(rotation=-90) + i3.Translation((2500, 5000)) trans["taper3"] = i3.HMirror(0) + i3.Translation((4000, -5.5)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text="{}_{}".format(name, self.cell.wg_t1.name), # # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0, # transformation=i3.Translation((1500, 100 + 10000 * counter)) # ) # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text="{} {}".format(name, self.cell.wg_t1.name), # # coordinate=(-2000, -150), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=200.0, # transformation=i3.Rotation((0.0, 0.0), 90.0) # + i3.Translation((450+2900, -2000 + 10000 * counter)) # ) # for j in range (-1,2,1): # for i in range(0,4,1): # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000+100+10000*i),box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 - 100 + 10000 * i), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 + 100 + 6000 * 3+3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 - 100 + 6000 * 3+3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 300, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 300, -3000 - 100 ), box_size=(100, 100)) return elems
class my_dc(PlaceAndAutoRoute): # dc = i3.ChildCellProperty() # dc2 = i3.ChildCellProperty() DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="gap") length = i3.PositiveNumberProperty(default=60.0, doc="Length of coupler") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty() # wg_dc2 = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) # start_id = i3.PositiveNumberProperty(doc="name_id", default=1) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 16, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2112(name='DC_gap_2_l_' + str(dl) + str(self.length), start_id=dl + self.length) cell.Layout(gap=self.gap_inc_vec[l], length=self.length) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 24, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 # child_cells["dircoup1"] = self.dc # child_cells["dircoup2"] = self.dc2 # child_cells["straight"] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [("taper0:out", "ring0:MMI1b_out2"), ("taper1:out", "ring0:MMI1a_in1"), ("taper2:out", "ring0:MMI1b_in2"), ("taper3:out", "ring0:MMI1a_out1"), ("taper4:out", "ring0:MMI1b_out1"), ("taper5:out", "ring0:MMI1a_in2"), ("taper6:out", "ring1:MMI1b_out2"), ("taper7:out", "ring1:MMI1a_in1"), ("taper8:out", "ring1:MMI1b_in2"), ("taper9:out", "ring1:MMI1a_out1"), ("taper10:out", "ring1:MMI1b_out1"), ("taper11:out", "ring1:MMI1a_in2"), ("taper12:out", "ring2:MMI1b_out2"), ("taper13:out", "ring2:MMI1a_in1"), ("taper14:out", "ring2:MMI1b_in2"), ("taper15:out", "ring2:MMI1a_out1"), ("taper16:out", "ring2:MMI1b_out1"), ("taper17:out", "ring2:MMI1a_in2"), ("taper18:out", "ring3:MMI1b_out2"), ("taper19:out", "ring3:MMI1a_in1"), ("taper20:out", "ring3:MMI1b_in2"), ("taper21:out", "ring3:MMI1a_out1"), ("taper22:out", "ring3:MMI1b_out1"), ("taper23:out", "ring3:MMI1a_in2")] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 8500 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1500, 0) trans['ring1'] = (1500, 0 + column) trans['ring2'] = (1500, 0 + 2 * column) trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 4000) trans["taper1"] = (0, -4000) trans["taper2"] = i3.HMirror(0) + i3.Translation((3000, 3500)) trans["taper3"] = i3.HMirror(0) + i3.Translation((3000, -3500)) trans["taper4"] = i3.HMirror(0) + i3.Translation((3000, 1500)) trans["taper5"] = i3.HMirror(0) + i3.Translation((3000, 1000)) trans["taper6"] = (0, 4000 + column) trans["taper7"] = (0, -4000 + column) trans["taper8"] = i3.HMirror(0) + i3.Translation( (3000, 3500 + column)) trans["taper9"] = i3.HMirror(0) + i3.Translation( (3000, -3500 + column)) trans["taper10"] = i3.HMirror(0) + i3.Translation( (3000, 1500 + column)) trans["taper11"] = i3.HMirror(0) + i3.Translation( (3000, 1000 + column)) trans["taper12"] = (0, 4000 + 2 * column) trans["taper13"] = (0, -4000 + 2 * column) trans["taper14"] = i3.HMirror(0) + i3.Translation( (3000, 3500 + 2 * column)) trans["taper15"] = i3.HMirror(0) + i3.Translation( (3000, -3500 + 2 * column)) trans["taper16"] = i3.HMirror(0) + i3.Translation( (3000, 1500 + 2 * column)) trans["taper17"] = i3.HMirror(0) + i3.Translation( (3000, 1000 + 2 * column)) trans["taper18"] = (0, 4000 + 3 * column) trans["taper19"] = (0, -4000 + 3 * column) trans["taper20"] = i3.HMirror(0) + i3.Translation( (3000, 3500 + 3 * column)) trans["taper21"] = i3.HMirror(0) + i3.Translation( (3000, -3500 + 3 * column)) trans["taper22"] = i3.HMirror(0) + i3.Translation( (3000, 1500 + 3 * column)) trans["taper23"] = i3.HMirror(0) + i3.Translation( (3000, 1000 + 3 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.dc.name, self.cell.wg_t1.name), # coordinate=(1350.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.dc2.name, self.cell.wg_t1.name), # coordinate=(4650.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), # # coordinate=(0.0, -counter * 5 * self.R - 2 * self.R + 50.0 # -100 # ), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) return elems
class my_dc(PlaceAndAutoRoute): # dc = i3.ChildCellProperty() # dc2 = i3.ChildCellProperty() DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="gap") length = i3.PositiveNumberProperty(default=80.0, doc="Length of coupler") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty() # wg_dc2 = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) # start_id = i3.PositiveNumberProperty(doc="name_id", default=1) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 16, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = RingRectSymm180DropFilter( name='SR_GAP={}_L={}'.format(str(dl), str(self.length)), ring_trace_template=self.trace_template) cell.Layout( bend_radius=200, coupler_lengths=[self.length, self.length], coupler_radii=[300.0, 300.0], coupler_angles=[90.0, 90.0], coupler_spacings=[ 3.8 + self.gap_inc_vec[l], 3.8 + self.gap_inc_vec[l] ], straights=(self.length, 0.0), # manhattan=True, ) cell2 = RingRectSymmNotchFilter( name='ring_s' + str(dl) + str(self.length), ring_trace_template=self.trace_template) cell2.Layout( bend_radius=200, coupler_lengths=[self.length, self.length], coupler_radii=[300, 300], coupler_angles=[90.0, 90], coupler_spacings=[(3.8 + self.gap_inc_vec[l])], straights=(self.length, 0.0), # manhattan=True, ) MMI22_list.append(cell) MMI22_list.append(cell2) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 24, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 # child_cells["dircoup1"] = self.dc # child_cells["dircoup2"] = self.dc2 # child_cells["straight"] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:out2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:in2"), ("taper3:out", "ring0:out1"), ("taper4:out", "ring1:in"), ("taper5:out", "ring1:out"), ("taper6:out", "ring2:out2"), ("taper7:out", "ring2:in1"), ("taper8:out", "ring2:in2"), ("taper9:out", "ring2:out1"), ("taper10:out", "ring3:in"), ("taper11:out", "ring3:out"), ("taper12:out", "ring4:out2"), ("taper13:out", "ring4:in1"), ("taper14:out", "ring4:in2"), ("taper15:out", "ring4:out1"), ("taper16:out", "ring5:in"), ("taper17:out", "ring5:out"), ("taper18:out", "ring6:out2"), ("taper19:out", "ring6:in1"), ("taper20:out", "ring6:in2"), ("taper21:out", "ring6:out1"), ("taper22:out", "ring7:in"), ("taper23:out", "ring7:out"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 4500 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1500, -3000) trans['ring4'] = (1500, -3000 + 2 * column) trans['ring1'] = (1500, -300) trans['ring5'] = (1500, -300 + 2 * column) trans['ring2'] = (1500, -3000 + column) trans['ring6'] = (1500, -3000 + 3 * column) trans['ring3'] = (1500, -300 + column) trans['ring7'] = (1500, -300 + 3 * column) trans["taper0"] = (0, -2100) trans["taper1"] = (0, -3850) trans["taper2"] = i3.HMirror(0) + i3.Translation((3000, -1500)) trans["taper3"] = i3.Translation((0, -4000)) trans["taper4"] = (0, -1950) trans["taper5"] = i3.HMirror(0) + i3.Translation((3000, -1350)) trans["taper6"] = (0, -2100 + column) trans["taper7"] = (0, -3850 + column) trans["taper8"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + column)) trans["taper9"] = i3.Translation((0, -4000 + column)) trans["taper10"] = (0, -1950 + column) trans["taper11"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + column)) trans["taper12"] = (0, -2100 + 2 * column) trans["taper13"] = (0, -3850 + 2 * column) trans["taper14"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + 2 * column)) trans["taper15"] = i3.Translation((0, -4000 + 2 * column)) trans["taper16"] = (0, -1950 + 2 * column) trans["taper17"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + 2 * column)) trans["taper18"] = (0, -2100 + 3 * column) trans["taper19"] = (0, -3850 + 3 * column) trans["taper20"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + 3 * column)) trans["taper21"] = i3.Translation((0, -4000 + 3 * column)) trans["taper22"] = (0, -1950 + 3 * column) trans["taper23"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + 3 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): if (counter % 2 == 0): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(name[0:10]), # coordinate=(4650.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=200.0, transformation=i3.Rotation( (0.0, 0.0), -90.0) + i3.Translation( (3000 - 450, -2000 + 4500 * counter / 2))) else: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="R=200_L=80", alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=80.0, transformation=i3.Rotation( (0.0, 0.0), -90.0) + i3.Translation( (3000 - 450, -2700 + 4500 * counter / 2))) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, # center=(0, 0), # box_size=(500, 300)) return elems
class my_MMI2112(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout(core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts( name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2112() cell.Layout(name="MMI2112_l_{}".format(str(self.gap_inc_vec[l])), length=self.gap_inc_vec[l] ) # cell = RingRectSymm180DropFilter(name='ring' + str(dl) + str(self.length), # ring_trace_template=self.trace_template) # cell.Layout(bend_radius=200, # coupler_lengths=[self.length, self.length], # coupler_radii=[300.0, 300.0], # coupler_angles=[90.0, 90.0], # coupler_spacings=[3.8 + self.gap_inc_vec[l], 3.8 + self.gap_inc_vec[l]], # straights=(self.length, 0.0), # # manhattan=True, # ) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 12, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:MMI1b_in2"), ("taper1:out", "ring0:MMI1b_in1"), ("taper2:out", "ring0:MMI1a_out2"), ("taper3:out", "ring0:MMI1a_out1"), ("taper4:out", "ring1:MMI1b_in2"), ("taper5:out", "ring1:MMI1b_in1"), ("taper6:out", "ring1:MMI1a_out2"), ("taper7:out", "ring1:MMI1a_out1"), ("taper8:out", "ring2:MMI1b_in2"), ("taper9:out", "ring2:MMI1b_in1"), ("taper10:out", "ring2:MMI1a_out2"), ("taper11:out", "ring2:MMI1a_out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 10000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (2500, 0) trans['ring1'] = (2500, 0 + column) trans['ring2'] = (2500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 4000) trans["taper1"] = (0, -4000) trans["taper2"] = i3.HMirror(0) + i3.Translation((5000, 2500)) trans["taper3"] = i3.HMirror(0) + i3.Translation((5000, -2500)) trans["taper4"] = (0, 4000 + column) trans["taper5"] = (0, -4000 + column) trans["taper6"] = i3.HMirror(0) + i3.Translation((5000, 2500 + column)) trans["taper7"] = i3.HMirror(0) + i3.Translation((5000, -2500 + column)) trans["taper8"] = (0, 4000 + 2 * column) trans["taper9"] = (0, -4000 + 2 * column) trans["taper10"] = i3.HMirror(0) + i3.Translation((5000, 2500 + 2 * column)) trans["taper11"] = i3.HMirror(0) + i3.Translation((5000, -2500 + 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius
class Layout(i3.LayoutView): # specified parameters used for layout, lengths of various waveguides # using some default values if standard ring shape is used bend_radius_ring = i3.PositiveNumberProperty(default=10., doc="bend radius of ring") ring_x_straight = i3.PositiveNumberProperty( default=15., doc="straight between bends in x ring") ring_y_straight = i3.PositiveNumberProperty( default=25., doc="straight between bends in y ring") external_straights = i3.PositiveNumberProperty( default=10., doc="extra straight for outside structure") external_gap = i3.PositiveNumberProperty( default=1., doc="gap between outside waveguides and resonator") # external_radius = i3.PositiveNumberProperty(default=bend_radius_ring, doc="radius of outside coupler") rounding_algorithm = i3.DefinitionProperty( default=SplineRoundingAlgorithm(), doc="secondary rounding algorithm") # extra layouting for the CROW num_rings = i3.IntProperty(default=3, doc="number of rings") ring_gap = i3.PositiveNumberProperty(default=0.5, doc="gap between internal rings") use_gap_list = i3.BoolProperty(default=False, doc="use non default bending algorithm") ring_gap_list = i3.ListProperty( default=[], doc="list of gaps for manual swapping, default empty!") # define the layout of the internal coupler which we SRef below def _default_resonator(self): res_layout = self.cell.resonator.get_default_view( i3.LayoutView) # Retrieve layout view following example # make the shape of the layout from the previous values. Assume (0, 0) is bottom middle!) # will do each corner for clarity # bottom_left = (-self.bend_radius_ring - self.ring_x_straight/2., 0.) # top_left = (-self.bend_radius_ring - self.ring_x_straight/2., # self.bend_radius_ring*2. + self.ring_y_straight) # top_right = (self.bend_radius_ring + self.ring_x_straight/2., # self.bend_radius_ring*2. + self.ring_y_straight) # bottom_right = (self.bend_radius_ring + self.ring_x_straight/2., 0.) # ring_shape = [bottom_left, top_left, top_right, bottom_right, bottom_left] # print ring_shape # tried to use generic round ring, but failed :P. Using ring rect instead # set the layout of the resonator. Stuck a bool for non default rounding algorithm res_layout.set(bend_radius=self.bend_radius_ring, straights=(self.ring_x_straight, self.ring_y_straight), rounding_algorithm=self.rounding_algorithm) return res_layout def _dummy_resonator(self): dummy_res = i3.SRef(name="just_a_dummy", reference=self.resonator) return dummy_res # make a function for determining the distance between core size and def _resonator_size_core_to_core(self): # calls the get components function and then does math on the pulled in layout resonator = self._dummy_resonator() wg_ring_template = self.wg_ring_template # grabbing the position of the resonator to layout the rest of the coupler properly resonator_west_side = resonator.size_info().west resonator_east_side = resonator.size_info().east resonator_core_width = wg_ring_template.core_width resonator_clad_width = wg_ring_template.cladding_width resonator_x_dim = (resonator_east_side - resonator_west_side) - resonator_clad_width return resonator_x_dim # setting the output shape of the access waveguides using a shape defined by ports from MMI (hopefully..) def _default_wgs(self): # bring in parts from rest of PCell Layout, used dummy resonator to grab positions resonator = self._dummy_resonator() wg_in_cell, wg_pass_cell = self.cell.wgs wg_template = self.wg_coupler_template wg_ring_template = self.wg_ring_template # using the ring radius for the external radius external_rad = self.bend_radius_ring external_str = self.external_straights # grabbing the position of the resonator to layout the rest of the coupler properly resonator_west_side = resonator.size_info().west resonator_south_side = resonator.size_info().south resonator_core_width = wg_ring_template.core_width resonator_clad_width = wg_ring_template.cladding_width coupler_core_width = wg_template.core_width # calculate the x position for center of input coupling waveguide when coupling, and make shape x_coup_spot = resonator_west_side + resonator_clad_width/2. - resonator_core_width/2. - self.external_gap \ - coupler_core_width/2. # get bottom using the south and cladding information again bottom_left = (x_coup_spot - external_str - external_rad, resonator_south_side + resonator_clad_width / 2.) bottom_right = (x_coup_spot, resonator_south_side + resonator_clad_width / 2.) top_right = (x_coup_spot, bottom_right[1] + 2. * external_rad + self.ring_y_straight) top_left = (bottom_left[0], top_right[1]) wg_shape = [bottom_left, bottom_right, top_right, top_left] # now make the instance using this shape info wg_in_layout = wg_in_cell.get_default_view(i3.LayoutView) wg_in_layout.set(trace_template=wg_template, shape=wg_shape, bend_radius=external_rad, rounding_algorithm=self.rounding_algorithm) # other waveguide for reference, can put in shape or mirror later wg_pass_layout = wg_pass_cell.get_default_view(i3.LayoutView) # wg_in_layout.set() return wg_in_layout, wg_pass_layout # wg_ring_layout # A few functions for grabbing waveguide parameters to determine lengths for FSR checking # def wg_lengths(self): # # grab the lengths of internal waveguides to use for calculations later # wg_in_layout, wg_pass_layout, wg_ring_layout = self.wgs # # straights_and_bends = wg_ring_layout.trace_length() # return straights_and_bends # now we take the resonator and perform multiple translations for the CROW def _get_components(self): res_x_dim = self._resonator_size_core_to_core() ring_gap = self.ring_gap ring_core_width = self.wg_ring_template.core_width ring_gap_list = self.ring_gap_list shifting_list = [0.] + ring_gap_list all_components = [] # and now crank an SRef for each Ring in a loop for ring in range(self.num_rings): # will translate the original ring over to the correct position, and iterate for number of rings # use an if statement for external gap list or not. Need an error if self.use_gap_list is False: this_transform = i3.Translation( ((res_x_dim + ring_gap + ring_core_width) * ring, 0.)) this_resonator = i3.SRef(name="R_" + str(ring), reference=self.resonator, transformation=this_transform) all_components.append(this_resonator) else: # sum previous elements of the shifting list for correct relative translation total_shift = sum(shifting_list[:(ring + 1)]) this_transform = i3.Translation( ((res_x_dim + ring_core_width) * ring + total_shift, 0.)) this_resonator = i3.SRef(name="R_" + str(ring), reference=self.resonator, transformation=this_transform) all_components.append(this_resonator) return all_components def _generate_instances(self, insts): # includes the get components and the waveguides the_rings = self._get_components() insts += the_rings wg_in_layout, wg_pass_layout = self.wgs # wg_pass_layout, wg_ring_layout insts += i3.SRef(reference=wg_in_layout, name="wg_in") # ok so now I grab the last ring from the rings and use it to determine its position last_ring = the_rings[-1] east_side_ring = last_ring.size_info().east # and I get the waveguide properties for ring and coupler, to give correct outside gap ring_core_width = self.wg_ring_template.core_width ring_clad_width = self.wg_ring_template.cladding_width bus_wg_core_width = self.wg_coupler_template.core_width bus_wg_clad_width = self.wg_coupler_template.cladding_width final_x_spot = (east_side_ring - ring_clad_width/2.) + ring_core_width/2. \ + self.external_gap + bus_wg_core_width/2. # rather than making a new waveguide we can mirror the previous structure into the final position # thus we need to determine the difference in the core position of the original structure # with the *negative* position of the final x position, and then the mirror will flip it around bus_core_pos = wg_in_layout.size_info( ).east - bus_wg_clad_width / 2. # now we translate the original structure to the desired negative position, and horizontally mirror around 0 output_transformation = i3.HMirror() + i3.Translation( (-1. * (-final_x_spot - bus_core_pos), 0.)) # finally we perform the SRef on the previous layout and transform it with a new name insts += i3.SRef(reference=wg_in_layout, name="wg_out", transformation=output_transformation) return insts def _generate_ports(self, prts): # try to reuse the output waveguides following the example and change the names, looks good instances = self.instances prts += instances["wg_in"].ports["in"].modified_copy(name="in1") prts += instances["wg_in"].ports["out"].modified_copy(name="in2") prts += instances["wg_out"].ports["in"].modified_copy(name="out1") prts += instances["wg_out"].ports["out"].modified_copy(name="out2") return prts