class EulerBend(i3.PCell): """ An Euler Bend for IPKISS """ _name_prefix = "EULER_BEND" trace_template = i3.WaveguideTemplateProperty( doc="trace template for the waveguide" ) def _default_trace_template(self): return i3.TECH.PCELLS.WG.DEFAULT waveguide = i3.ChildCellProperty(doc="waveguide") def _default_waveguide(self): return i3.RoundedWaveguide(trace_template=self.trace_template) class Layout(i3.LayoutView): """ Layout for the IPKISS Euler Bend """ min_radius = i3.PositiveNumberProperty(doc="minimum Euler bend radius") def _default_min_radius(self): if self.end_point is None: return 10 x, y = self.end_point # the final angle is twice the angle between start and finish. theta = 2 * np.arctan2(y, x) x_final = _euler_bend_center_line_shape(R=1, theta=theta, num_points=4)[-1][0] return x / x_final end_angle = i3.PositiveNumberProperty(doc="angle (in degrees) at the end of the Euler bend.") def _default_end_angle(self): if self.end_point is None: return 90 x, y = self.end_point return 2 * np.arctan2(y, x) * i3.RAD2DEG num_points = i3.PositiveNumberProperty( doc="resolution of the euler bend shape.", default=1000, ) end_point = i3.Coord2Property( doc=( "(optional) coordinates of the end of the Euler bend.\n" "if given, this will override `min_radius` and `end_angle`." ), default=None, ) core_width = i3.PositiveNumberProperty( doc="default core width of the waveguide", default=i3.TECH.WG.WIRE_WIDTH, ) cladding_width = i3.PositiveNumberProperty( doc="default cladding width of the waveguide", default=i3.TECH.WG.CLADDING_WIDTH, ) def _default_trace_template(self): trace = self.cell.trace_template.get_default_view(i3.LayoutView) trace.set( core_width=self.core_width, cladding_width=self.cladding_width, ) return trace def _default_waveguide(self): waveguide = self.cell.waveguide.get_default_view(i3.LayoutView) center_line = _euler_bend_center_line_shape( R=self.min_radius, theta=self.end_angle * i3.DEG2RAD, num_points=self.num_points, ) waveguide.set( shape=center_line, trace_template=self.trace_template, bend_radius=self.min_radius, ) return waveguide def _generate_instances(self, insts): insts += i3.SRef(reference=self.waveguide) return insts def _generate_ports(self, ports): ports += self.waveguide.ports return ports
class v8(PlaceAndAutoRoute): wg_t1 = i3.WaveguideTemplateProperty() wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() WGSM = i3.ChildCellProperty() widtha = i3.PositiveNumberProperty(doc="width of ports", default=15) mmi22 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() # # start_id = None start_id = i3.PositiveNumberProperty(doc="name", default=1) # start_id = current_id param_num = 5 def _default_links(self): links = [ ("MMI1b:out2", "WGuptaper2:out"), ("MMI1b:out1", "WGdowntaper2:out"), # ("MMI1b:out","MMI1a:in"), ("WGuptaper:out", "MMI1b:in2"), ("WGdowntaper:out", "MMI1b:in1"), ("DWGuptaper:out", "DWGuptaper2:out"), ("DWGdowntaper:out", "dummy1:in"), ("DWGdowntaper2:out", "dummy1:out") ] return links def _default_child_cells(self): child_cells = { "dummy1": self.WGSM, "MMI1b": self.mmi22, "WGup": self.WG1, "WGdown": self.WG1, "WGup2": self.WG1, "WGdown2": self.WG1, "WGuptaper": self.WG2, "WGdowntaper": self.WG2, "WGuptaper2": self.WG2, "WGdowntaper2": self.WG2, "DWGup": self.WG1, "DWGdown": self.WG1, "DWGup2": self.WG1, "DWGdown2": self.WG1, "DWGuptaper": self.WG2, "DWGdowntaper": self.WG2, "DWGuptaper2": self.WG2, "DWGdowntaper2": self.WG2 } return child_cells def _default_trace_template(self): trace_template = self.wg_sm return trace_template def _default_mmi22(self): mmi22 = 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.wg_sm, ) return mmi22 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear( name="Dongbo{}".format(str(self.start_id)), start_trace_template=self.wg_t1, end_trace_template=self.wg_sm, ) return WG2 def _default_WG1(self): WG1 = i3.Waveguide(name="Dongbo{}".format(str(self.start_id + 1)), trace_template=self.wg_t1) return WG1 def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.widtha))) wg_t1.Layout(core_width=self.widtha, cladding_width=self.widtha + 16.0, core_process=i3.TECH.PROCESS.WG) return wg_t1 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate( name="dongbo{}".format(str(self.start_id + 3))) wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_WGSM(self): WGSM = i3.Waveguide(name="SM", trace_template=self.trace_template) return WGSM def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate( name="dongbo{}".format(str(self.start_id + 4))) mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate( name="dongbo{}".format(str(self.start_id + 5))) mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=398) # width = i3.PositiveNumberProperty(doc="width of ports", default=15) # def _default_wg_t1(self): # layout_wg_t1 = self.cell.wg_t1.get_default_view(i3.LayoutView) # layout_wg_t1.set(core_width=self.width, # cladding_width=self.width + 16.0, # core_process=i3.TECH.PROCESS.WG) # return layout_wg_t1 def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(150.0, 0.0), end_position=(450.0, 0.0)) return layout_WG2 def _default_WGSM(self): layout_WGSM = self.cell.WGSM.get_default_view(i3.LayoutView) layout_WGSM.set(shape=[(0.0, 0.0), (400.0, 0.0)]) return layout_WGSM def _default_mmi22(self): layout_mmi22 = self.cell.mmi22.get_default_view(i3.LayoutView) layout_mmi22.set(name="MMI22_l_{}".format(str(self.length)), transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi22 def _default_child_transformations(self): child_transformations = { "MMI1b": (1300, 0), "WGup": (0, 4000), "WGuptaper": (0, 4000), "WGdown": (0, -4000), "WGdowntaper": (0, -4000), "WGuptaper2": i3.HMirror() + i3.Translation((3000, 2000)), "WGdowntaper2": i3.HMirror() + i3.Translation((3000, -6000)), "WGup2": (2850, 2000), "WGdown2": (2850, -6000), "dummy1": (1300, -300), "DWGup": (0, 20900), "DWGuptaper": (0, 20900), "DWGdown": (0, -4300), "DWGdowntaper": (0, -4300), "DWGuptaper2": i3.HMirror() + i3.Translation((3000, 20900)), "DWGdowntaper2": i3.HMirror() + i3.Translation((3000, -6300)), "DWGup2": (2850, 20900), "DWGdown2": (2850, -6300) } return child_transformations 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) 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 StraightWgLossEbeam(PlaceAndAutoRoute): taper = i3.ChildCellProperty() wg = i3.ChildCellProperty() wg_right = i3.ChildCellProperty() expanded_wg = i3.ChildCellProperty() trace_template = i3.WaveguideTemplateProperty() expanded_wg_template = i3.WaveguideTemplateProperty() gc_taper = i3.ChildCellProperty() gc_slab = i3.ChildCellProperty() gc_slab_template = i3.WaveguideTemplateProperty() wg_SM_template = i3.WaveguideTemplateProperty() wg_SM = i3.ChildCellProperty() taper_expanded_wg2wg_SM = i3.ChildCellProperty() wg_width = i3.PositiveNumberProperty(default=2.0) trench_width = i3.PositiveNumberProperty(default=3.0) _wg_width_indesign = i3.PositiveNumberProperty() expanded_wg_width = i3.PositiveNumberProperty(default=3.0) _expanded_wg_width_indesign = i3.PositiveNumberProperty() gc_slab_width = i3.PositiveNumberProperty(default=10.0) wg_SM_width = i3.PositiveNumberProperty(default=0.5) def _default__wg_width_indesign(self): return self.wg_width def _default__expanded_wg_width_indesign(self): return self.expanded_wg_width def _default_trace_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.wg_width * 0.5, end_offset=self.wg_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.wg_width + self.trench_width) * 0.5, end_offset=-(self.wg_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.wg_width + self.trench_width) * 0.5, end_offset=(self.wg_width + self.trench_width) * 0.5, line_width=0) wg_t = i3.WindowWaveguideTemplate() wg_t.Layout(windows=[wstart1, wstart2, wstart3]) return wg_t def _default_expanded_wg_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.expanded_wg_width * 0.5, end_offset=self.expanded_wg_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.expanded_wg_width + self.trench_width) * 0.5, end_offset=-(self.expanded_wg_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.expanded_wg_width + self.trench_width) * 0.5, end_offset=(self.expanded_wg_width + self.trench_width) * 0.5, line_width=0) expanded_wg_template = i3.WindowWaveguideTemplate() expanded_wg_template.Layout(windows=[wstart1, wstart2, wstart3]) return expanded_wg_template def _default_wg(self): wg = i3.RoundedWaveguide(trace_template=self.trace_template) return wg def _default_wg_right(self): wg_right = i3.RoundedWaveguide(trace_template=self.trace_template) return wg_right def _default_expanded_wg(self): expanded_wg = i3.RoundedWaveguide( trace_template=self.expanded_wg_template) return expanded_wg def _default_taper(self): taper = i3.LinearWindowWaveguideTransition( start_trace_template=self.trace_template, end_trace_template=self.expanded_wg_template) return taper def _default_gc_slab_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.gc_slab_width * 0.5, end_offset=self.gc_slab_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.gc_slab_width + self.trench_width) * 0.5, end_offset=-(self.gc_slab_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.gc_slab_width + self.trench_width) * 0.5, end_offset=(self.gc_slab_width + self.trench_width) * 0.5, line_width=0) wg_t = i3.WindowWaveguideTemplate() wg_t.Layout(windows=[wstart1, wstart2, wstart3]) return wg_t def _default_gc_taper(self): taper = i3.LinearWindowWaveguideTransition( start_trace_template=self.wg_SM_template, end_trace_template=self.gc_slab_template) return taper def _default_gc_slab(self): slab = i3.RoundedWaveguide(trace_template=self.gc_slab_template) return slab def _default_wg_SM_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.wg_SM_width * 0.5, end_offset=self.wg_SM_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.wg_SM_width + self.trench_width) * 0.5, end_offset=-(self.wg_SM_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.wg_SM_width + self.trench_width) * 0.5, end_offset=(self.wg_SM_width + self.trench_width) * 0.5, line_width=0) wg_t = i3.WindowWaveguideTemplate() wg_t.Layout(windows=[wstart1, wstart2, wstart3]) return wg_t def _default_wg_SM(self): wg = i3.RoundedWaveguide(trace_template=self.wg_SM_template) return wg def _default_taper_expanded_wg2wg_SM(self): taper = i3.LinearWindowWaveguideTransition( start_trace_template=self.expanded_wg_template, end_trace_template=self.wg_SM_template) return taper def _default_child_cells(self): child_cells = dict() child_cells["taper_left"] = self.taper child_cells["taper_right"] = self.taper child_cells["wg_left"] = self.wg child_cells["wg_right"] = self.wg_right child_cells["expanded_wg_left"] = self.expanded_wg child_cells["expanded_wg_right"] = self.expanded_wg child_cells[ "taper_expanded_wg2wg_SM_left"] = self.taper_expanded_wg2wg_SM child_cells["wg_SM_left"] = self.wg_SM child_cells["wg_SM_right"] = self.wg_SM child_cells[ "taper_expanded_wg2wg_SM_right"] = self.taper_expanded_wg2wg_SM child_cells["gc_taper_left"] = self.gc_taper child_cells["gc_taper_right"] = self.gc_taper child_cells["gc_slab_left"] = self.gc_slab child_cells["gc_slab_right"] = self.gc_slab return child_cells def _default_external_port_names(self): ports = dict() ports["expanded_wg_right:out"] = "in" ports["expanded_wg_left:out"] = "out" return ports class Layout(PlaceAndAutoRoute.Layout): spiral_width = i3.PositiveNumberProperty( doc="total width of spiral structure", default=6000.0) right_wg_length = i3.PositiveNumberProperty( doc="length of narrow wg on the right side of spiral", default=500.0) expanded_wg_length = i3.PositiveNumberProperty(default=1000.0) taper_length = i3.PositiveNumberProperty(default=100.0) bend_radius = i3.PositiveNumberProperty(default=100.0) gc_taper_length = i3.PositiveNumberProperty(default=300.0) gc_slab_length = i3.PositiveNumberProperty(default=50.0) wg_SM_length = i3.PositiveNumberProperty(default=50.0) def _default_wg(self): wg_lo = self.cell.wg.get_default_view(i3.LayoutView) wg_lo.set(shape=[(0.0, 0.0), (self.spiral_width, 0)]) return wg_lo def _default_wg_right(self): wg_right_lo = self.cell.wg_right.get_default_view(i3.LayoutView) wg_right_lo.set(shape=[(0.0, 0.0), (self.right_wg_length, 0)]) return wg_right_lo def _default_taper(self): taper_lo = self.cell.taper.get_default_view(i3.LayoutView) taper_lo.set(start_position=(0.0, 0.0), end_position=(self.taper_length, 0.0)) return taper_lo def _default_expanded_wg(self): expanded_wg_lo = self.cell.expanded_wg.get_default_view( i3.LayoutView) expanded_wg_lo.set(shape=[(0.0, 0.0), (self.expanded_wg_length, 0.0)]) return expanded_wg_lo def _default_gc_taper(self): gc_taper_lo = self.cell.gc_taper.get_default_view(i3.LayoutView) gc_taper_lo.set(start_position=(0.0, 0.0), end_position=(self.gc_taper_length, 0.0)) return gc_taper_lo def _default_gc_slab(self): slab_lo = self.cell.gc_slab.get_default_view(i3.LayoutView) slab_lo.set(shape=[(0.0, 0.0), (self.gc_slab_length, 0.0)]) return slab_lo def _default_wg_SM(self): wg_lo = self.cell.wg_SM.get_default_view(i3.LayoutView) wg_lo.set(shape=[(0.0, 0.0), (self.wg_SM_length, 0)]) return wg_lo def _default_taper_expanded_wg2wg_SM(self): taper_lo = self.cell.taper_expanded_wg2wg_SM.get_default_view( i3.LayoutView) taper_lo.set(start_position=(0.0, 0.0), end_position=(self.taper_length, 0.0)) return taper_lo def _default_child_transformations(self): trans = dict() trans["wg_right"] = (0.0, 0.0) trans["taper_right"] = i3.Translation((self.right_wg_length, 0)) start_x_expanded_wg_right = self.right_wg_length + self.taper_length trans["expanded_wg_right"] = i3.Translation( (start_x_expanded_wg_right, 0)) start_x_taper_wg_SM2expanded_wg_right = start_x_expanded_wg_right + self.expanded_wg_length trans["taper_expanded_wg2wg_SM_right"] = i3.Translation( (start_x_taper_wg_SM2expanded_wg_right, 0.0)) start_x_wg_SM_right = start_x_taper_wg_SM2expanded_wg_right + self.taper_length trans["wg_SM_right"] = i3.Translation((start_x_wg_SM_right, 0.0)) start_x_gc_taper_right = start_x_wg_SM_right + self.wg_SM_length trans["gc_taper_right"] = i3.Translation( (start_x_gc_taper_right, 0)) start_x_gc_slab_right = start_x_gc_taper_right + self.gc_taper_length trans["gc_slab_right"] = i3.Translation((start_x_gc_slab_right, 0)) trans["wg_left"] = i3.HMirror(mirror_plane_x=0.0) trans["taper_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation((-self.spiral_width, 0)) start_x_expanded_wg_left = -self.spiral_width - self.taper_length trans["expanded_wg_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation( (start_x_expanded_wg_left, 0)) start_x_taper_expanded_wg2wg_SM_left = start_x_expanded_wg_left - self.expanded_wg_length trans["taper_expanded_wg2wg_SM_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation( (start_x_taper_expanded_wg2wg_SM_left, 0)) start_x_wg_SM_left = start_x_taper_expanded_wg2wg_SM_left - self.taper_length trans["wg_SM_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation((start_x_wg_SM_left, 0)) start_x_gc_taper_left = start_x_wg_SM_left - self.wg_SM_length trans["gc_taper_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation( (start_x_gc_taper_left, 0)) start_x_gc_slab_left = start_x_gc_taper_left - self.gc_taper_length trans["gc_slab_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation((start_x_gc_slab_left, 0)) return trans def get_true_length(self): return self.spiral_width + self.right_wg_length
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_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 v8(PlaceAndAutoRoute): wg_t1 = i3.WaveguideTemplateProperty() wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() mmi1_12 = i3.ChildCellProperty() mmi1_21 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() def _default_links(self): links = [("MMI1a:out2", "WGuptaper2:out"), ("MMI1a:out1", "WGdowntaper2:out"), ("MMI1b:out", "MMI1a:in"), ("WGuptaper:out", "MMI1b:in2"), ("WGdowntaper:out", "MMI1b:in1")] return links def _default_child_cells(self): child_cells = { "MMI1a": self.mmi1_12, "MMI1b": self.mmi1_21, "WGup": self.WG1, "WGdown": self.WG1, "WGup2": self.WG1, "WGdown2": self.WG1, "WGuptaper": self.WG2, "WGdowntaper": self.WG2, "WGuptaper2": self.WG2, "WGdowntaper2": self.WG2 } return child_cells def _default_trace_template(self): trace_template = self.wg_sm return trace_template def _default_mmi1_12(self): mmi12 = MMI1x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, ) return mmi12 def _default_mmi1_21(self): mmi21 = MMI2x1Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, ) return mmi21 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear(start_trace_template=self.wg_t1, end_trace_template=self.wg_sm) return WG2 def _default_WG1(self): WG1 = i3.Waveguide(name="Dongbo", trace_template=self.wg_t1) return WG1 def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate() wg_t1.Layout(core_width=15.0, cladding_width=15.0 + 16.0, core_process=i3.TECH.PROCESS.WG) return wg_t1 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(name="MMI length", default=97) def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(150.0, 0.0), end_position=(450.0, 0.0)) return layout_WG2 def _default_mmi1_12(self): layout_mmi1_12 = self.cell.mmi1_12.get_default_view(i3.LayoutView) layout_mmi1_12.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi1_12 def _default_mmi1_21(self): layout_mmi1_21 = self.cell.mmi1_21.get_default_view(i3.LayoutView) layout_mmi1_21.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi1_21 def _default_child_transformations(self): child_transformations = { "MMI1a": (1887, 0), "MMI1b": (1300, 0), "WGup": (0, 4000), "WGuptaper": (0, 4000), "WGdown": (0, -4000), "WGdowntaper": (0, -4000), "WGuptaper2": i3.HMirror() + i3.Translation((3400, 4000)), "WGdowntaper2": i3.HMirror() + i3.Translation((3400, -4000)), "WGup2": (3250, 4000), "WGdown2": (3250, -4000) } return child_transformations def _default_bend_radius(self): bend_radius = 300 return bend_radius
class SpiralWgLossEbeam(PlaceAndAutoRoute): ## generate segmented FBMS line spiral = i3.ChildCellProperty() taper = i3.ChildCellProperty() wg = i3.ChildCellProperty() wg_right = i3.ChildCellProperty() expanded_wg = i3.ChildCellProperty() trace_template = i3.WaveguideTemplateProperty() expanded_wg_template = i3.WaveguideTemplateProperty() wg_width = i3.PositiveNumberProperty(default=2.0) trench_width = i3.PositiveNumberProperty(default=3.0) _wg_width_indesign = i3.PositiveNumberProperty() expanded_wg_width = i3.PositiveNumberProperty(default=3.0) _expanded_wg_width_indesign = i3.PositiveNumberProperty() spiral_length = i3.PositiveNumberProperty(default=10000.0) n_o_loops = i3.IntProperty(default=2) def _default__wg_width_indesign(self): return self.wg_width def _default__expanded_wg_width_indesign(self): return self.expanded_wg_width def _default_trace_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.wg_width * 0.5, end_offset=self.wg_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.wg_width + self.trench_width) * 0.5, end_offset=-(self.wg_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.wg_width + self.trench_width) * 0.5, end_offset=(self.wg_width + self.trench_width) * 0.5, line_width=0) wg_t = i3.WindowWaveguideTemplate() wg_t.Layout(windows=[wstart1, wstart2, wstart3]) return wg_t def _default_expanded_wg_template(self): wstart1 = PathTraceWindow(layer=i3.TECH.PPLAYER.WG.CORE, start_offset=-self.expanded_wg_width * 0.5, end_offset=self.expanded_wg_width * 0.5) wstart2 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=-(self.expanded_wg_width + self.trench_width) * 0.5, end_offset=-(self.expanded_wg_width + self.trench_width) * 0.5, line_width=0) wstart3 = PathTraceWindow( layer=i3.TECH.PPLAYER.WG.CLADDING, start_offset=(self.expanded_wg_width + self.trench_width) * 0.5, end_offset=(self.expanded_wg_width + self.trench_width) * 0.5, line_width=0) expanded_wg_template = i3.WindowWaveguideTemplate() expanded_wg_template.Layout(windows=[wstart1, wstart2, wstart3]) return expanded_wg_template def _default_wg(self): wg = i3.RoundedWaveguide(trace_template=self.trace_template) return wg def _default_wg_right(self): wg_right = i3.RoundedWaveguide(trace_template=self.trace_template) return wg_right def _default_spiral(self): spiral = FixedLengthSpiralRounded(total_length=self.spiral_length, n_o_loops=self.n_o_loops, trace_template=self.trace_template) return spiral def _default_expanded_wg(self): expanded_wg = i3.RoundedWaveguide( trace_template=self.expanded_wg_template) return expanded_wg def _default_taper(self): taper = LinearWindowWaveguideTransition( start_trace_template=self.trace_template, end_trace_template=self.expanded_wg_template) return taper def _default_child_cells(self): child_cells = dict() child_cells["spiral"] = self.spiral child_cells["taper_left"] = self.taper child_cells["taper_right"] = self.taper child_cells["wg_left"] = self.wg child_cells["wg_right"] = self.wg_right child_cells["expanded_wg_left"] = self.expanded_wg child_cells["expanded_wg_right"] = self.expanded_wg return child_cells def _default_external_port_names(self): ports = dict() ports["expanded_wg_right:out"] = "in" ports["expanded_wg_left:out"] = "out" return ports class Layout(PlaceAndAutoRoute.Layout): spiral_width = i3.PositiveNumberProperty( doc="total width of spiral structure", default=6000.0) right_wg_length = i3.PositiveNumberProperty( doc="length of narrow wg on the right side of spiral", default=500.0) expanded_wg_length = i3.PositiveNumberProperty(default=5000.0) taper_length = i3.PositiveNumberProperty(default=300.0) bend_radius = i3.PositiveNumberProperty(default=100.0) gap = i3.PositiveNumberProperty(doc="distance between two trenches", default=3.0) _spacing_indesign = i3.PositiveNumberProperty() def _default__spacing_indesign(self): return self.gap + self.trench_width * 2 + self.wg_width def _default_spiral(self): spiral_lo = self.cell.spiral.get_default_view(i3.LayoutView) spiral_lo.set(incoupling_length=0, bend_radius=self.bend_radius, spacing=self._spacing_indesign, growth_direction="H", stub_direction="H") return spiral_lo def _default_wg(self): wg_lo = self.cell.wg.get_default_view(i3.LayoutView) wg_lo.set(shape=[( 0.0, 0.0), (self.spiral_width - self._spiral_in_out_distance(), 0)]) return wg_lo def _spiral_in_out_distance(self): return self.spiral.ports["out"].position.x - self.spiral.ports[ "in"].position.x def _default_wg_right(self): wg_right_lo = self.cell.wg_right.get_default_view(i3.LayoutView) wg_right_lo.set(shape=[(0.0, 0.0), (self.right_wg_length, 0)]) return wg_right_lo def _default_taper(self): taper_lo = self.cell.taper.get_default_view(i3.LayoutView) taper_lo.set(start_position=(0.0, 0.0), end_position=(self.taper_length, 0.0)) return taper_lo def _default_expanded_wg(self): expanded_wg_lo = self.cell.expanded_wg.get_default_view( i3.LayoutView) expanded_wg_lo.set(shape=[(0.0, 0.0), (self.expanded_wg_length, 0.0)]) return expanded_wg_lo def _default_child_transformations(self): trans = dict() trans["spiral"] = (-self._spiral_in_out_distance(), 0.0) trans["wg_right"] = (0.0, 0.0) trans["taper_right"] = i3.Translation((self.right_wg_length, 0)) trans["expanded_wg_right"] = i3.Translation( (self.right_wg_length + self.taper_length, 0)) trans["wg_left"] = i3.HMirror(mirror_plane_x=0.0) + i3.Translation( (-self._spiral_in_out_distance(), 0)) trans["taper_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation((-self.spiral_width, 0)) trans["expanded_wg_left"] = i3.HMirror( mirror_plane_x=0.0) + i3.Translation( (-self.spiral_width - self.taper_length, 0)) return trans def get_true_length(self): return self.spiral_width - self._spiral_in_out_distance( ) + self.right_wg_length + self.spiral_length
class my_dc(PlaceAndAutoRoute): dc = i3.ChildCellProperty() dc2 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() WGSM = 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, core_process=i3.TECH.PROCESS.WG) 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_wg_dc2(self): wg_dc2 = WireWaveguideTemplate(name="dc2_template") wg_dc2.Layout(core_width=2.8, cladding_width=2.8 + 16.0) return wg_dc2 def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) return WG1 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear( name="taper{}".format(str(self.width)), start_trace_template=self.wg_t1, end_trace_template=self.trace_template) return WG2 def _default_WGSM(self): WGSM = i3.Waveguide(name="SM", trace_template=self.trace_template) return WGSM def _default_dc(self): dc = BendDirectionalCoupler(name="DC_gap_1.5_l_923", trace_template1=self.trace_template, coupler_length=923.0) dc.Layout( coupler_spacing=1.5 + 3.8, bend_radius=300.0, # manhattan=True, # straight_after_bend=600.0, bend_angle=90.0) return dc def _default_dc2(self): dc2 = BendDirectionalCoupler(name="DC_gap_2_l_888", trace_template1=self.wg_dc2, coupler_length=888.0) dc2.Layout( coupler_spacing=2 + 2.8, bend_radius=300.0, # manhattan=True, bend_angle=90.0) return dc2 def _default_child_cells(self): child_cells = dict() for counter in range(8, 16, 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["dummy1"] = self.WGSM child_cells["dummy2"] = self.WGSM return child_cells def _default_links(self): links = [ # ("taper0:out", "dircoup1:in2"), # ("taper1:out", "dircoup1:in1"), # ("taper2:out", "dircoup1:out2"), # ("taper3:out", "dircoup1:out1"), # ("taper4:out", "dircoup2:in2"), # ("taper5:out", "dircoup2:in1"), # ("taper6:out", "dircoup2:out2"), # ("taper7:out", "dircoup2:out1"), ("taper8:out", "taper10:out"), ("taper12:out", "taper14:out"), ("taper9:out", "dummy1:in"), ("taper11:out", "dummy1:out"), ("taper13:out", "dummy2:in"), ("taper15:out", "dummy2:out") ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(0.0, 0.0), end_position=(300.0, 0.0)) return layout_WG2 def _default_WGSM(self): layout_WGSM = self.cell.WGSM.get_default_view(i3.LayoutView) layout_WGSM.set(shape=[(0.0, 0.0), (400.0, 0.0)]) return layout_WGSM # def _default_dc(self): # layout_dc = self.cell.dc.get_default_view(i3.LayoutView) # layout_dc.set(coupler_spacing=2.5 + 3.8, # bend_radius=300.0, # manhattan=True, # # straight_after_bend=6.0, # bend_angle=90.0) # return layout_dc def _default_child_transformations(self): trans = dict() # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) trans["dummy1"] = (1450, -300 + 8300 * 2) trans["dummy2"] = (4750, -300 + 8300 * 2) # for counter in range(0, 8, 1): # print counter # trans['straight' + str(counter)] = (2000 * (counter + 1), 0) # trans["taper" + str(counter)] = (0, 2000 * (counter + 1)) # trans["straight0"] = (0, 4000) # trans["straight1"] = (0, -4000) # trans["straight2"] = (3150, 2000) # trans["straight3"] = (3150, -6000) # trans["straight4"] = (3300, 2000) # trans["straight5"] = (3300, -6000) # trans["straight6"] = (6450, 4000) # trans["straight7"] = (6450, -4000) # trans["taper0"] = (150, 4000) # trans["taper1"] = (150, -4000) # trans["taper2"] = i3.HMirror(150) + i3.Translation((2850, 2000)) # trans["taper3"] = i3.HMirror(150) + i3.Translation((2850, -6000)) # trans["taper4"] = (3450, 2000) # trans["taper5"] = (3450, -6000) # trans["taper6"] = i3.HMirror(150) + i3.Translation((6150, 4000)) # trans["taper7"] = i3.HMirror(150) + i3.Translation((6150, -4000)) trans["straight8"] = (0, 21050) trans["straight9"] = (0, -4150 + 8300 * 2) trans["straight10"] = (3150, 21050) trans["straight11"] = (3150, -6150 + 8300 * 2) trans["straight12"] = (3300, 21050) trans["straight13"] = (3300, -6150 + 8300 * 2) trans["straight14"] = (6450, 21050) trans["straight15"] = (6450, -4150 + 8300 * 2) trans["taper8"] = (150, 21050) trans["taper9"] = (150, -4150 + 8300 * 2) trans["taper10"] = i3.HMirror(150) + i3.Translation((2850, 21050)) trans["taper11"] = i3.HMirror(150) + i3.Translation( (2850, -6150 + 8300 * 2)) trans["taper12"] = (3450, 21050) trans["taper13"] = (3450, -6150 + 8300 * 2) trans["taper14"] = i3.HMirror(150) + i3.Translation((6150, 21050)) trans["taper15"] = i3.HMirror(150) + i3.Translation( (6150, -4150 + 8300 * 2)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius
class edge(PlaceAndAutoRoute): wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() WG2 = i3.ChildCellProperty() narro = i3.ChildCellProperty() # def _default_links(self): # links = [("taper:out", "taper2:out")] # return links def _default_child_cells(self): child_cells = dict() for counter in range(0, 48, 1): # Routing dummy print counter child_cells['edge1' + str(counter)] = self.narro child_cells['edge2' + str(counter)] = self.WG2 return child_cells def _default_trace_template(self): wg_sm2 = WireWaveguideTemplate() wg_sm2.Layout(core_width=15, cladding_width=15 + 24.0) return wg_sm2 def _default_WG2(self): WG2 = i3.Waveguide(name="20", trace_template=self.wg_sm) return WG2 def _default_narro(self): WGnarrow = i3.Waveguide(name="15", trace_template=self.trace_template) return WGnarrow def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=20, cladding_width=20 + 24.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 24.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 24.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=97) def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(shape=[(0.0, 0.0), (300.0, 0.0)]) return layout_WG2 def _default_narro(self): layout = self.cell.narro.get_default_view(i3.LayoutView) layout.set(shape=[(0.0, 0.0), (300.0, 0.0)]) return layout def _default_child_transformations(self): trans = dict() for counter in range(0, 24, 1): trans['edge1' + str(counter)] = i3.Translation( translation=(-300, counter * 150)) trans['edge2' + str(counter)] = i3.Translation( translation=(-300, counter * 150 + 7500)) for counter in range(24, 48, 1): trans['edge1' + str(counter)] = i3.Translation( translation=(18600, counter * 150 - 2600)) trans['edge2' + str(counter)] = i3.Translation( translation=(18600, counter * 150 + 7500 - 2600)) return trans
class PhaseShifterTemplate(PhaseShifterWaveguideTemplate): ''' PN junction trace template with parameters to set up the implants and the contact. ''' trace_template = i3.WaveguideTemplateProperty(locked=True) def _default_trace_template(self): return SiWireWaveguideTemplate(name="{}_wg_tt".format(self.name)) class Layout(PhaseShifterWaveguideTemplate.Layout): core_width = i3.PositiveNumberProperty(doc="width of the core") p_width = i3.PositiveNumberProperty(doc="width of low dose P implant") p_offset = i3.NumberProperty( doc="offset from the center line of low dose P implant") n_width = i3.PositiveNumberProperty(doc="width of low dose N implant") n_offset = i3.NumberProperty( doc="offset from the center line of low dose N implant") high_dose_p_width = i3.PositiveNumberProperty( doc="width of high dose P implant") high_dose_p_offset = i3.NumberProperty( doc="offset from the center line of high dose P implant") high_dose_n_width = i3.PositiveNumberProperty( doc="width of high dose N implant") high_dose_n_offset = i3.NumberProperty( doc="offset from the center line of high dose N implant") con_width = i3.PositiveNumberProperty( doc="width of contacts etch (same on both side of the center line)" ) con_p_offset = i3.NumberProperty( doc="offset from the center line of contacts etch on P implant") con_n_offset = i3.NumberProperty( doc="offset from the center line of contacts etch on N implant") def _default_core_width(self): return 0.45 def _default_p_width(self): return 3. def _default_p_offset(self): return self.p_width / 2. def _default_n_width(self): return self.p_width def _default_n_offset(self): return -self.n_width / 2. def _default_high_dose_p_width(self): return 2. def _default_high_dose_p_offset(self): return self.p_width + self.high_dose_p_width / 2. def _default_high_dose_n_width(self): return self.high_dose_p_width def _default_high_dose_n_offset(self): return -self.high_dose_p_offset def _default_con_width(self): return self.high_dose_p_width / 2. def _default_con_p_offset(self): return self.high_dose_p_offset def _default_con_n_offset(self): return self.high_dose_n_offset def _default_trace_template(self): lv = self.cell.trace_template.get_default_view(self) lv.set(core_width=self.core_width) return lv def _default_trace_template_for_ports(self): port_tt = SiWireWaveguideTemplate( name="{}_wg_port_tt".format(self.name)) port_tt_lv = port_tt.Layout(core_width=self.core_width) return port_tt_lv def _default_implant_windows(self): core_half_width = 0.5 * self.core_width p_half_width = 0.5 * self.p_width n_half_width = 0.5 * self.n_width high_dose_p_half_width = 0.5 * self.high_dose_p_width high_dose_n_half_width = 0.5 * self.high_dose_n_width p_offset = self.p_offset n_offset = self.n_offset high_dose_p_offset = self.high_dose_p_offset high_dose_n_offset = self.high_dose_n_offset windows = [] # core windows.append( i3.PathTraceWindow(layer=i3.TECH.PPLAYER.SI, start_offset=-core_half_width, end_offset=+core_half_width)) # low_dose_p windows.append( i3.PathTraceWindow(layer=i3.TECH.PPLAYER.P, start_offset=p_offset - p_half_width, end_offset=p_offset + p_half_width)) # low_dose_n windows.append( i3.PathTraceWindow(layer=i3.TECH.PPLAYER.N, start_offset=n_offset - n_half_width, end_offset=n_offset + n_half_width)) # high_dose_p windows.append( i3.PathTraceWindow( layer=i3.TECH.PPLAYER.PPLUS, start_offset=high_dose_p_offset - high_dose_p_half_width, end_offset=high_dose_p_offset + high_dose_p_half_width)) # high_dose_n windows.append( i3.PathTraceWindow( layer=i3.TECH.PPLAYER.NPLUS, start_offset=high_dose_n_offset - high_dose_n_half_width, end_offset=high_dose_n_offset + high_dose_n_half_width)) return windows def _default_contact_windows(self): con_half_width = 0.5 * self.con_width con_p_offset = self.con_p_offset con_n_offset = self.con_n_offset windows = [] # Contact on P++ windows.append( i3.ExtendedPathTraceWindow( layer=i3.TECH.PPLAYER.CON, start_offset=con_p_offset - con_half_width, end_offset=con_p_offset + con_half_width, extension=(-0.5, -0.5))) # Contact on N++ windows.append( i3.ExtendedPathTraceWindow( layer=i3.TECH.PPLAYER.CON, start_offset=con_n_offset - con_half_width, end_offset=con_n_offset + con_half_width, extension=(-0.5, -0.5))) return windows def _default_metal_windows(self): windows = [] return windows def _default_windows(self): windows = self.implant_windows + self.contact_windows + self.metal_windows return windows class CircuitModel(PhaseShifterWaveguideTemplate.CircuitModel): VpiLpi = i3.PositiveNumberProperty( default=1.0, doc="Voltage to get pi-shift for 1 cm of phase modulator [V.cm]") def _default_loss_dB_m(self): return 300.0 def _default_neff(self): return 2.5 def _default_n_g(self): return 4.1
class v8(PlaceAndAutoRoute): wg_t1 = i3.WaveguideTemplateProperty() wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() widtha = i3.PositiveNumberProperty(doc="width of ports", default=15) mmi22 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() # # start_id = None # # start_id = current_id # param_num= 6 def _default_links(self): links = [ ("MMI1b:out2", "WGuptaper2:out"), ("MMI1b:out1", "WGdowntaper2:out"), # ("MMI1b:out","MMI1a:in"), ("WGuptaper:out", "MMI1b:in2"), ("WGdowntaper:out", "MMI1b:in1") ] return links def _default_child_cells(self): child_cells = { "MMI1b": self.mmi22, "WGup": self.WG1, "WGdown": self.WG1, "WGup2": self.WG1, "WGdown2": self.WG1, "WGuptaper": self.WG2, "WGdowntaper": self.WG2, "WGuptaper2": self.WG2, "WGdowntaper2": self.WG2 } return child_cells def _default_trace_template(self): trace_template = self.wg_sm return trace_template def _default_mmi22(self): mmi22 = 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.wg_sm, ) return mmi22 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear( name="dongbo{}".format(str(np.random.randint(0, 10000))), start_trace_template=self.wg_t1, end_trace_template=self.wg_sm, ) return WG2 def _default_WG1(self): WG1 = i3.Waveguide(name="dongbo{}".format( str(np.random.randint(0, 10000))), trace_template=self.wg_t1) return WG1 def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate( name="dongbo{}".format(str(np.random.randint(0, 10000)))) wg_t1.Layout(core_width=self.widtha, cladding_width=self.widtha + 16.0, core_process=i3.TECH.PROCESS.WG) return wg_t1 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate(name="Dongbo") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=398) # width = i3.PositiveNumberProperty(doc="width of ports", default=15) # def _default_wg_t1(self): # layout_wg_t1 = self.cell.wg_t1.get_default_view(i3.LayoutView) # layout_wg_t1.set(core_width=self.width, # cladding_width=self.width + 16.0, # core_process=i3.TECH.PROCESS.WG) # return layout_wg_t1 def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(150.0, 0.0), end_position=(450.0, 0.0)) return layout_WG2 def _default_mmi22(self): layout_mmi22 = self.cell.mmi22.get_default_view(i3.LayoutView) layout_mmi22.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi22 def _default_child_transformations(self): child_transformations = { "MMI1b": (1300, 0), "WGup": (0, 4000), "WGuptaper": (0, 4000), "WGdown": (0, -4000), "WGdowntaper": (0, -4000), "WGuptaper2": i3.HMirror() + i3.Translation((3000, 2000)), "WGdowntaper2": i3.HMirror() + i3.Translation((3000, -6000)), "WGup2": (2850, 2000), "WGdown2": (2850, -6000) } return child_transformations def _default_bend_radius(self): bend_radius = 300 return bend_radius
class _Splitter(Coupler1x2): """ Abstract splitter class just places 3 waveguides. """ wg_template = i3.WaveguideTemplateProperty(doc="Waveguide template used.") wgs_straights = i3.ChildCellListProperty( doc="Childcells used for the waveguides.") def _default_wg_template(self): return WireWaveguideTemplate() def _default_wgs_straights(self): wgs = [] for cnt in xrange(0, 3): wg = i3.RoundedWaveguide(trace_template=self.wg_template) wgs.append(wg) return wgs class Layout(i3.LayoutView): length_splitting_shape = i3.PositiveNumberProperty( default=10.0, doc="Length of the splitting section.") length_straights = i3.PositiveNumberProperty( default=0.2, doc="Length of the straights at the input and output.") spacing = i3.PositiveNumberProperty( default=2.0, doc="Spacing between the two output waveguides.") def _default_wg_template(self): wgt = self.cell.wg_template.get_default_view(i3.LayoutView) return wgt def _default_wgs_straights(self): wgs_cells = self.cell.wgs_straights wgs_layout = [] for wgc in wgs_cells: wg_layout = wgc.get_default_view(i3.LayoutView) wg_layout.set(shape=i3.Shape( points=[(0, 0), (self.length_straights, 0)])) wgs_layout.append(wg_layout) return wgs_layout def _generate_instances(self, insts): insts += i3.SRef(reference=self.wgs_straights[0], name="in") insts += i3.SRef( reference=self.wgs_straights[1], name="out1", position=(self.length_straights + self.length_splitting_shape, -self.spacing / 2)) insts += i3.SRef( reference=self.wgs_straights[2], name="out2", position=(self.length_straights + self.length_splitting_shape, +self.spacing / 2)) return insts def _get_cladding_elem(self): shape_cladding = i3.Shape( points=[(self.length_straights, self.wg_template.width / 2), (self.length_straights + self.length_splitting_shape, self.spacing / 2 + self.wg_template.width / 2)]) shape_cladding_m = i3.Shape( points=[(self.length_straights, -self.wg_template.width / 2), (self.length_straights + self.length_splitting_shape, -self.spacing / 2 - self.wg_template.width / 2)]) shape_elem = shape_cladding + shape_cladding_m.reversed() elem = i3.Boundary(layer=self.wg_template.windows[1].layer, shape=shape_elem) return elem def _generate_ports(self, ports): ports += self.instances["in"].ports["in"] ports += self.instances["out1"].ports["out"].modified_copy( name="out1") ports += self.instances["out2"].ports["out"].modified_copy( name="out2") return ports def _get_splitting_elem(self): raise NotImplementedError( "This is an abstract class in which _get_splitting_elem was not implemented." ) def _generate_elements(self, elems): elems += self._get_splitting_elem() elems += self._get_cladding_elem() return elems class CapheModelCST(CapheModelCST): """ CapheModel based on a CST simulation """ def _default_additional_commands_path(self): return r"{}\simulation_files\additional_commands.mod".format( os.path.dirname(__file__)) class CapheModel(Coupler1x2.CapheModel): """ Simple Analytic CapheModel """ pass
class SerpGratingArray(i3.PCell): """Sidewall Grating Waveguide: Waveguide with rectangular sidewall gratings """ _name_prefix = "SerpGrating" wg_temp = i3.WaveguideTemplateProperty( doc= "Waveguide template to use for flyback waveguides, bends, and tapers") bend_type = i3.StringProperty( default="manual", doc= "String denoting type of bend to use for connecting arcs (options: 'default', 'manual')" ) taper_type = i3.StringProperty( default="default", doc= "String denoting type of taper to use for connecting tapers (options: 'default', 'manual')" ) bend = i3.ChildCellProperty( doc="Bend cell to use for connecting arc waveguides") taper_swg = i3.ChildCellProperty( doc= "Taper cell to use for taper connectors between sidewall grating waveguides and bends" ) taper_flyback = i3.ChildCellProperty( doc= "Taper cell to use for taper connectors between flyback waveguides and bends" ) swg = i3.ChildCellProperty(doc="Sidewall grating waveguide cell") flyback = i3.ChildCellProperty(doc="Flyback waveguide cell") def _default_wg_temp(self): wg_temp = StripWgTemplate(name=self.name + "_WgTemplate") return wg_temp def _default_bend(self): if self.bend_type is "default": bend = i3.Waveguide(name=self.name + "_Bend", trace_template=self.wg_temp) else: from Custom_Waveguide import CustomWaveguide bend = CustomWaveguide(name=self.name + "_Bend") return bend def _default_taper_swg(self): if self.taper_type is "default": from Linear_Taper import LinearTaper taper = LinearTaper(name=self.name + "_SwgTaper") else: from Custom_Waveguide import CustomWaveguide taper = CustomWaveguide(name=self.name + "_SwgTaper") return taper def _default_taper_flyback(self): if self.taper_type is "default": from Linear_Taper import LinearTaper taper = LinearTaper(name=self.name + "_FlybackTaper") else: from Custom_Waveguide import CustomWaveguide taper = CustomWaveguide(name=self.name + "_FlybackTaper") return taper def _default_swg(self): swg = SidewallGratingWg(name=self.name + "_SidewallGratingWg") return swg def _default_flyback(self): flyback = i3.Waveguide(name=self.name + "_FlybackWg", trace_template=self.wg_temp) return flyback # -------------------------- # Layout # -------------------------- class Layout(i3.LayoutView): """ List of properties: period duty_cycle absolute length of the grating section, not percentage grating_amp grat_wg_width flyback_wg_width pitch spacing length numrows taper_length taper_path_flyback taper_width_flyback taper_path_swg taper_width_swg bend_width arc_path arc_width TO GENERATE CUSTOM BENDS: set pitch to either 16.0 or 16.516 """ from ipkiss.technology import get_technology TECH = get_technology() # ----------- # Properties # Sidewall grating waveguide properties period = i3.PositiveNumberProperty(default=.3, doc="Period of sidewall grating") duty_cycle = i3.PositiveNumberProperty( default=.1, doc="Length of grating teeth (along periodic direction)") grating_amp = i3.NumberProperty( default=.01, doc= "Width/amplitude of grating teeth (normal to periodic direction)") grat_wg_width = i3.PositiveNumberProperty( default=1.0, doc= "Width of sidewall grating waveguide core (if grating_amp=0 width of waveguide)" ) # Flyback waveguide properites flyback_wg_width = i3.PositiveNumberProperty( default=0.4, doc="Width of flyback waveguide core") # Grating array properties pitch = i3.PositiveNumberProperty( default=16.0, doc= "Sidewall grating pitch (center-to-center distance of sidewall grating waveguides)" ) spacing = i3.PositiveNumberProperty( doc="Gap between sidewall grating waveguides and flyback waveguides" ) def _default_spacing(self): spacing = (self.pitch - self.grat_wg_width - self.flyback_wg_width) / 2 return spacing length = i3.PositiveNumberProperty( default=800.0, doc="Length of straight (untapered) waveguide sections") numrows = i3.PositiveIntProperty( default=32, doc= "Number of sidewall grating/flyback waveguide pairs in the array") # Taper properties # Properties used for taper_type = "default" taper_length = i3.PositiveNumberProperty(default=10.0, doc="Taper length") # Properties used for taper_type = "manual" taper_path_flyback = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the taper (bend to flyback waveguide)" ) taper_width_flyback = i3.NumpyArrayProperty( doc= "List of taper widths normal to each point on the path (bend to flyback waveguide)" ) taper_path_swg = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the taper (bend to sidewall grating waveguide)" ) taper_width_swg = i3.NumpyArrayProperty( doc= "List of taper widths normal to each point on the path (bend to sidewall grating waveguide)" ) # REDEFINING TAPER HERE # taper_swg = i3.ViewProperty( default='', doc='Taper layout that connects grating waveguide to the bends') # taper_flyback = i3.ViewProperty( default='', doc='Taper layout that connects flyback waveguide to the bends') # Pick grating type: # 'one_sidewall', 'two_sidewalls', 'nitride_vertical_top', 'nitride_vertical_bottom', # 'nitride_one_sidewall_top', 'nitride_one_sidewall_bottom', grating_type = i3.StringProperty(default='', doc='Grating type to draw') def _default_taper_path_flyback(self): #Default is a straight linear taper path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_) return path def _default_taper_width_flyback(self): # Default is a straight linear taper widths = np.array([self.bend_width, self.flyback_wg_width], np.float_) return widths def _default_taper_path_swg(self): #Default is a straight linear taper path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_) return path def _default_taper_width_swg(self): # Default is a straight linear taper widths = np.array([self.bend_width, self.grat_wg_width], np.float_) return widths # Bend properties # Properties used for bend_type = "default" bend_width = i3.PositiveNumberProperty( default=TECH.WG.CORE_WIDTH, doc="Width of waveguides in bend sections") # Properties used for bend_type = "manual" arc_path = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the arc connectors (going from sidewall grating waveguide to flyback waveguide" ) arc_width = i3.NumpyArrayProperty( doc= "List of arc widths normal to each point on the path (going from sidewall grating waveguide to flyback waveguide" ) def _default_arc_path(self): if self.pitch == 16.0: #Use pregenerated adiabatic bends (TX) pathwidth = np.loadtxt("../nathan/bend_data/txbend.txt", np.float_) arc_path = pathwidth[:, :2] elif self.pitch == 16.516: # Use pregenerated adiabatic bends (RX) pathwidth = np.loadtxt("../nathan/bend_data/rxbend.txt", np.float_) arc_path = pathwidth[:, :2] else: # Default is 180 arc arc_path = np.zeros([181, 2], np.float_) bend_rad = (self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2) / 2 for ii in range(181): angle = np.pi / 180.0 * ii arc_path[ii, :] = bend_rad * np.array( [-np.sin(angle), np.cos(angle)], np.float_) return arc_path def _default_arc_width(self): if self.pitch == 16.0: #Use pregenerated adiabatic bends (TX) pathwidth = np.loadtxt("../nathan/bend_data/txbend.txt", np.float_) arc_width = pathwidth[:, 2] elif self.pitch == 16.516: #Use pregenerated adiabatic bends (RX) pathwidth = np.loadtxt("../nathan/bend_data/rxbend.txt", np.float_) arc_width = pathwidth[:, 2] else: #Default is uniform width with default core_width arc_width = np.ones([181], np.float_) arc_width = arc_width * self.bend_width return arc_width def validate_properties(self): """Check whether the combination of properties is valid.""" if (self.grat_wg_width + self.flyback_wg_width + 2 * self.spacing) != self.pitch: raise i3.PropertyValidationError( self, "Array incorrectly overspecified (pitch=/=wg_widths+spacing", {"pitch": self.pitch}) return True @i3.cache() def _get_components(self): # Make waveguides # Pick grating type: # 'one_sidewall', 'two_sidewalls', 'nitride_vertical_top', 'nitride_vertical_bottom', # 'nitride_one_sidewall_top', 'nitride_one_sidewall_bottom', if self.grating_type == 'one_sidewall': # single sidewall grating swg_l = self.cell.swg.get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, both_sides=False) elif self.grating_type == 'two_sidewalls': # double sidewall grating swg_l = self.cell.swg.get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, both_sides=True) elif self.grating_type == 'nitride_vertical_top': # nitride vertical grating, top layer swg_l = NitrideGratingWg().get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, grating_type='vertical', nitride_layer='top') elif self.grating_type == 'nitride_vertical_bottom': # nitride vertical grating, top layer swg_l = NitrideGratingWg().get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, grating_type='vertical', nitride_layer='bottom') elif self.grating_type == 'nitride_one_sidewall_top': # nitride vertical grating, top layer swg_l = NitrideGratingWg().get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, grating_type='one_sidewall', nitride_layer='top') elif self.grating_type == 'nitride_one_sidewall_bottom': # nitride vertical grating, top layer swg_l = NitrideGratingWg().get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length, grating_type='one_sidewall', nitride_layer='bottom') # end making grating if statement # flyback and stuff flyback_l = self.cell.flyback.get_default_view(i3.LayoutView) flyback_path = [(0.0, 0.0), (self.length, 0.0)] wg_temp_flyback = self.cell.wg_temp.get_default_view(i3.LayoutView) wg_temp_flyback.set(core_width=self.flyback_wg_width) flyback_l.set(trace_template=wg_temp_flyback, shape=flyback_path) # Center-to-center distance between sidewall grating waveguide and flyback waveguide flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2 # Make bends bend_l = self.cell.bend.get_default_view(i3.LayoutView) if self.cell.bend_type is "default": # Default waveguide 180 arc bend_rad = flyback_offset / 2 arc = i3.ShapeArc(center=(0.0, 0.0), radius=bend_rad, start_angle=89.0, end_angle=270.0) wg_temp_bend = self.cell.wg_temp.get_default_view( i3.LayoutView) wg_temp_bend.set(core_width=self.bend_width) bend_l.set(trace_template=wg_temp_bend, shape=arc) else: # Custom bend pcell bend_l.set(wg_path=self.arc_path, wg_width=self.arc_width, start_angle=180.0, end_angle=0.0) # Make tapers taper_flyback_l = self.cell.taper_flyback.get_default_view( i3.LayoutView) taper_swg_l = self.cell.taper_swg.get_default_view(i3.LayoutView) if self.cell.taper_type is "default": # Linear taper pcell if self.cell.bend_type is "default": flyback_bend_width = self.bend_width swg_bend_width = self.bend_width else: arcsize = self.arc_width.shape arclength = arcsize[0] flyback_bend_width = self.arc_width[arclength - 1] swg_bend_width = self.arc_width[0] taper_flyback_l.set(length=self.taper_length, wg_width_in=flyback_bend_width, wg_width_out=self.flyback_wg_width) taper_swg_l.set(length=self.taper_length, wg_width_in=swg_bend_width, wg_width_out=self.grat_wg_width) else: # Custom taper pcell taper_flyback_l.set(wg_path=self.taper_path_flyback, wg_width=self.taper_width_flyback, start_angle=0.0, end_angle=0.0) taper_swg_l.set(wg_path=self.taper_path_swg, wg_width=self.taper_width_swg, start_angle=0.0, end_angle=0.0) return swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l def _generate_instances(self, insts): swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l = self._get_components( ) # Hard code the tapers into here: (I hate hardcoding stuff, but no choice here) taper_length = 79.0 # 79 is the best according to deniz' sims width_etch = 4.0 wg_width = 0.5 taper_swg = ParabolicTaper( name=self.name + '_TAPER').get_default_view(i3.LayoutView) taper_swg.set(length=taper_length, width1=wg_width, width2=self.grat_wg_width, width_etch=width_etch) taper_flyback = ParabolicTaper( name=self.name + '_OTHERTAPER').get_default_view(i3.LayoutView) taper_flyback.set(length=taper_length, width1=wg_width, width2=self.flyback_wg_width, width_etch=width_etch) for ii in range(self.numrows): # Find component translations (for all numrows) t_swg = i3.Translation((0.0, ii * self.pitch)) # t_taper_swg_w = vector_match_transform(taper_swg_l.ports["out"], swg_l.ports['in']) + t_swg # t_taper_swg_e = vector_match_transform(taper_swg_l.ports["out"], swg_l.ports['out'], mirrored=True) + t_swg t_taper_swg_w = vector_match_transform( taper_swg.ports["right"], swg_l.ports['in']) + t_swg t_taper_swg_e = vector_match_transform( taper_swg.ports["right"], swg_l.ports['out'], mirrored=True) + t_swg # Add grating rows + grating row tapers insts += i3.SRef(reference=swg_l, name="SidewallGratWg" + str(ii), transformation=t_swg) # insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_West" + str(ii), transformation=t_taper_swg_w) # insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_East" + str(ii), transformation=t_taper_swg_e) insts += i3.SRef(reference=taper_swg, name="SwgTaper_West" + str(ii), transformation=t_taper_swg_w) insts += i3.SRef(reference=taper_swg, name="SwgTaper_East" + str(ii), transformation=t_taper_swg_e) if ii < (self.numrows - 1): # Find component translations (for numrows-1) flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2 t_flyback = i3.Translation( (0.0, ii * self.pitch + flyback_offset)) # t_taper_flyback_w = vector_match_transform(taper_flyback_l.ports["out"], flyback_l.ports['in']) + t_flyback # t_taper_flyback_e = vector_match_transform(taper_flyback_l.ports["out"], flyback_l.ports['out'], # mirrored=True) + t_flyback t_taper_flyback_w = vector_match_transform( taper_flyback.ports["right"], flyback_l.ports['in'] ) \ + t_flyback t_taper_flyback_e = vector_match_transform( taper_flyback.ports["right"], flyback_l.ports['out'], mirrored = True ) \ + t_flyback # t_bend_e = i3.VMirror() + vector_match_transform(bend_l.ports['in'], taper_swg_l.ports["in"],mirrored=True) + t_taper_swg_e t_bend_e = i3.VMirror() \ + vector_match_transform( bend_l.ports['in'], taper_swg.ports["left"], mirrored = True ) \ + t_taper_swg_e t_bend_w = i3.VMirror() \ + vector_match_transform( bend_l.ports['out'], taper_flyback.ports["left"] ) \ + t_taper_flyback_w \ + i3.Translation( (0.0, self.pitch) ) # Add instances (for numrows-1) # flyback waveguide insts += i3.SRef(reference=flyback_l, name="FlybackWg" + str(ii), transformation=t_flyback) # flyback tapers # insts += i3.SRef( reference = taper_flyback_l, # name = "FlybackTaper_West" + str(ii), # transformation = t_taper_flyback_w ) # insts += i3.SRef( reference = taper_flyback_l, # name = "FlybackTaper_East" + str(ii), # transformation = t_taper_flyback_e ) insts += i3.SRef(reference=taper_flyback, name="FlybackTaper_West" + str(ii), transformation=t_taper_flyback_w) insts += i3.SRef(reference=taper_flyback, name="FlybackTaper_East" + str(ii), transformation=t_taper_flyback_e) # bends insts += i3.SRef(reference=bend_l, name="Bend_West" + str(ii), transformation=t_bend_w) insts += i3.SRef(reference=bend_l, name="Bend_East" + str(ii), transformation=t_bend_e) # end if # end for loop return insts def _generate_ports(self, ports): """ THIS NEEDS TO BE UPDATED TO REFLECT INPUT OUTPUT TAPERS """ # ports += self.instances["SidewallGratWg0"].ports["in"] # ports += self.instances["SidewallGratWg"+str(self.numrows-1)].ports["out"] ports += i3.OpticalPort(name='in', position=self.instances["SwgTaper_West0"]. ports["left"].position, angle=180.0) ports += i3.OpticalPort( name='out', position=self.instances["SwgTaper_East" + str(self.numrows - 1)].ports["left"].position, angle=0.0) return ports
class CROW_1D(i3.PCell): """ A single resonator test class """ _name_prefix = "CROW_1D" # defining the resonator as child cell with input and output waveguides resonator = i3.ChildCellProperty(restriction=i3.RestrictType(i3.PCell), doc="the input resonator") # define waveguide template and waveguide cells wg_coupler_template = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wg_ring_template = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wgs = i3.ChildCellListProperty(doc="list of waveguides") # define default MMI for class def _default_resonator(self): """ Internal resonator which is repeated later """ resonator = RingRect(name=self.name + "_resonator", ring_trace_template=self.wg_ring_template) return resonator # define rounded waveguides for the inputs and outputs of CROW def _default_wgs(self): wg_in = i3.RoundedWaveguide(name=self.name + "_wg_in", trace_template=self.wg_coupler_template) wg_pass = i3.RoundedWaveguide(name=self.name + "_wg_pass", trace_template=self.wg_coupler_template) # wg_ring = i3.RoundedWaveguide(name=self.name+"_wg_ring", trace_template=self.wg_coupler_template) return wg_in, wg_pass # , wg_pass, wg_ring 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 class Netlist(i3.NetlistView): def _generate_terms(self, terms): terms += i3.OpticalTerm(name="in") # terms += i3.OpticalTerm(name="pass") return terms
class SerpGratingArray(i3.PCell): """Sidewall Grating Waveguide: Waveguide with rectangular sidewall gratings """ _name_prefix = "SerpGrating" wg_temp = i3.WaveguideTemplateProperty( doc= "Waveguide template to use for flyback waveguides, bends, and tapers") bend_type = i3.StringProperty( default="manual", doc= "String denoting type of bend to use for connecting arcs (options: 'default', 'manual')" ) taper_type = i3.StringProperty( default="default", doc= "String denoting type of taper to use for connecting tapers (options: 'default', 'manual')" ) bend = i3.ChildCellProperty( doc="Bend cell to use for connecting arc waveguides") taper_swg = i3.ChildCellProperty( doc= "Taper cell to use for taper connectors between sidewall grating waveguides and bends" ) taper_flyback = i3.ChildCellProperty( doc= "Taper cell to use for taper connectors between flyback waveguides and bends" ) swg = i3.ChildCellProperty(doc="Sidewall grating waveguide cell") flyback = i3.ChildCellProperty(doc="Flyback waveguide cell") def _default_wg_temp(self): wg_temp = StripWgTemplate(name=self.name + "_WgTemplate") return wg_temp def _default_bend(self): if self.bend_type is "default": bend = i3.Waveguide(name=self.name + "_Bend", trace_template=self.wg_temp) else: from Custom_Waveguide import CustomWaveguide bend = CustomWaveguide(name=self.name + "_Bend") return bend def _default_taper_swg(self): if self.taper_type is "default": from Linear_Taper import LinearTaper taper = LinearTaper(name=self.name + "_SwgTaper") else: from Custom_Waveguide import CustomWaveguide taper = CustomWaveguide(name=self.name + "_SwgTaper") return taper def _default_taper_flyback(self): if self.taper_type is "default": from Linear_Taper import LinearTaper taper = LinearTaper(name=self.name + "_FlybackTaper") else: from Custom_Waveguide import CustomWaveguide taper = CustomWaveguide(name=self.name + "_FlybackTaper") return taper def _default_swg(self): swg = SidewallGratingWg(name=self.name + "_SidewallGratingWg") return swg def _default_flyback(self): flyback = i3.Waveguide(name=self.name + "_FlybackWg", trace_template=self.wg_temp) return flyback class Layout(i3.LayoutView): from ipkiss.technology import get_technology TECH = get_technology() # Sidewall grating waveguide properties period = i3.PositiveNumberProperty(default=.3, doc="Period of sidewall grating") duty_cycle = i3.PositiveNumberProperty( default=.1, doc="Length of grating teeth (along periodic direction)") grating_amp = i3.PositiveNumberProperty( default=.01, doc= "Width/amplitude of grating teeth (normal to periodic direction)") grat_wg_width = i3.PositiveNumberProperty( default=1.0, doc= "Width of sidewall grating waveguide core (if grating_amp=0 width of waveguide)" ) # Flyback waveguide properites flyback_wg_width = i3.PositiveNumberProperty( default=0.4, doc="Width of flyback waveguide core") # Grating array properties pitch = i3.PositiveNumberProperty( default=16.0, doc= "Sidewall grating pitch (center-to-center distance of sidewall grating waveguides)" ) spacing = i3.PositiveNumberProperty( doc="Gap between sidewall grating waveguides and flyback waveguides" ) def _default_spacing(self): spacing = (self.pitch - self.grat_wg_width - self.flyback_wg_width) / 2 return spacing length = i3.PositiveNumberProperty( default=800.0, doc="Length of straight (untapered) waveguide sections") numrows = i3.PositiveIntProperty( default=32, doc= "Number of sidewall grating/flyback waveguide pairs in the array") # Taper properties # Properties used for taper_type = "default" taper_length = i3.PositiveNumberProperty(default=10.0, doc="Taper length") # Properties used for taper_type = "manual" taper_path_flyback = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the taper (bend to flyback waveguide)" ) taper_width_flyback = i3.NumpyArrayProperty( doc= "List of taper widths normal to each point on the path (bend to flyback waveguide)" ) taper_path_swg = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the taper (bend to sidewall grating waveguide)" ) taper_width_swg = i3.NumpyArrayProperty( doc= "List of taper widths normal to each point on the path (bend to sidewall grating waveguide)" ) def _default_taper_path_flyback(self): #Default is a straight linear taper path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_) return path def _default_taper_width_flyback(self): # Default is a straight linear taper widths = np.array([self.bend_width, self.flyback_wg_width], np.float_) return widths def _default_taper_path_swg(self): #Default is a straight linear taper path = np.array([[0.0, 0.0], [self.taper_length, 0.0]], np.float_) return path def _default_taper_width_swg(self): # Default is a straight linear taper widths = np.array([self.bend_width, self.grat_wg_width], np.float_) return widths # Bend properties # Properties used for bend_type = "default" bend_width = i3.PositiveNumberProperty( default=TECH.WG.CORE_WIDTH, doc="Width of waveguides in bend sections") # Properties used for bend_type = "manual" arc_path = i3.NumpyArrayProperty( doc= "List of coordinates denoting the center path of the arc connectors (going from sidewall grating waveguide to flyback waveguide" ) arc_width = i3.NumpyArrayProperty( doc= "List of arc widths normal to each point on the path (going from sidewall grating waveguide to flyback waveguide" ) def _default_arc_path(self): if self.pitch == 16.0: #Use pregenerated adiabatic bends (TX) pathwidth = np.loadtxt("./bend_data/txbend.txt", np.float_) arc_path = pathwidth[:, :2] elif self.pitch == 16.516: # Use pregenerated adiabatic bends (RX) pathwidth = np.loadtxt("./bend_data/rxbend.txt", np.float_) arc_path = pathwidth[:, :2] else: # Default is 180 arc arc_path = np.zeros([181, 2], np.float_) bend_rad = (self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2) / 2 for ii in range(181): angle = np.pi / 180.0 * ii arc_path[ii, :] = bend_rad * np.array( [-np.sin(angle), np.cos(angle)], np.float_) return arc_path def _default_arc_width(self): if self.pitch == 16.0: #Use pregenerated adiabatic bends (TX) pathwidth = np.loadtxt("./bend_data/txbend.txt", np.float_) arc_width = pathwidth[:, 2] elif self.pitch == 16.516: #Use pregenerated adiabatic bends (RX) pathwidth = np.loadtxt("./bend_data/rxbend.txt", np.float_) arc_width = pathwidth[:, 2] else: #Default is uniform width with default core_width arc_width = np.ones([181], np.float_) arc_width = arc_width * self.bend_width return arc_width def validate_properties(self): """Check whether the combination of properties is valid.""" if (self.grat_wg_width + self.flyback_wg_width + 2 * self.spacing) != self.pitch: raise i3.PropertyValidationError( self, "Array incorrectly overspecified (pitch=/=wg_widths+spacing", {"pitch": self.pitch}) return True @i3.cache() def _get_components(self): # Make waveguides swg_l = self.cell.swg.get_default_view(i3.LayoutView) swg_l.set(period=self.period, duty_cycle=self.duty_cycle, grating_amp=self.grating_amp, wg_width=self.grat_wg_width, length=self.length) flyback_l = self.cell.flyback.get_default_view(i3.LayoutView) flyback_path = [(0.0, 0.0), (self.length, 0.0)] wg_temp_flyback = self.cell.wg_temp.get_default_view(i3.LayoutView) wg_temp_flyback.set(core_width=self.flyback_wg_width) flyback_l.set(trace_template=wg_temp_flyback, shape=flyback_path) # Center-to-center distance between sidewall grating waveguide and flyback waveguide flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2 # Make bends bend_l = self.cell.bend.get_default_view(i3.LayoutView) if self.cell.bend_type is "default": # Default waveguide 180 arc bend_rad = flyback_offset / 2 arc = i3.ShapeArc(center=(0.0, 0.0), radius=bend_rad, start_angle=89.0, end_angle=270.0) wg_temp_bend = self.cell.wg_temp.get_default_view( i3.LayoutView) wg_temp_bend.set(core_width=self.bend_width) bend_l.set(trace_template=wg_temp_bend, shape=arc) else: # Custom bend pcell bend_l.set(wg_path=self.arc_path, wg_width=self.arc_width, start_angle=180.0, end_angle=0.0) # Make tapers taper_flyback_l = self.cell.taper_flyback.get_default_view( i3.LayoutView) taper_swg_l = self.cell.taper_swg.get_default_view(i3.LayoutView) if self.cell.taper_type is "default": # Linear taper pcell if self.cell.bend_type is "default": flyback_bend_width = self.bend_width swg_bend_width = self.bend_width else: arcsize = self.arc_width.shape arclength = arcsize[0] flyback_bend_width = self.arc_width[arclength - 1] swg_bend_width = self.arc_width[0] taper_flyback_l.set(length=self.taper_length, wg_width_in=flyback_bend_width, wg_width_out=self.flyback_wg_width) taper_swg_l.set(length=self.taper_length, wg_width_in=swg_bend_width, wg_width_out=self.grat_wg_width) else: # Custom taper pcell taper_flyback_l.set(wg_path=self.taper_path_flyback, wg_width=self.taper_width_flyback, start_angle=0.0, end_angle=0.0) taper_swg_l.set(wg_path=self.taper_path_swg, wg_width=self.taper_width_swg, start_angle=0.0, end_angle=0.0) return swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l def _generate_instances(self, insts): swg_l, flyback_l, bend_l, taper_swg_l, taper_flyback_l = self._get_components( ) for ii in range(self.numrows): # Find component translations (for all numrows) t_swg = i3.Translation((0.0, ii * self.pitch)) t_taper_swg_w = vector_match_transform( taper_swg_l.ports["out"], swg_l.ports['in']) + t_swg t_taper_swg_e = vector_match_transform( taper_swg_l.ports["out"], swg_l.ports['out'], mirrored=True) + t_swg # Add instances (for all numrows) insts += i3.SRef(reference=swg_l, name="SidewallGratWg" + str(ii), transformation=t_swg) insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_West" + str(ii), transformation=t_taper_swg_w) insts += i3.SRef(reference=taper_swg_l, name="SwgTaper_East" + str(ii), transformation=t_taper_swg_e) if ii < (self.numrows - 1): # Find component translations (for numrows-1) flyback_offset = self.grat_wg_width / 2 + self.spacing + self.flyback_wg_width / 2 t_flyback = i3.Translation( (0.0, ii * self.pitch + flyback_offset)) t_taper_flyback_w = vector_match_transform( taper_flyback_l.ports["out"], flyback_l.ports['in']) + t_flyback t_taper_flyback_e = vector_match_transform( taper_flyback_l.ports["out"], flyback_l.ports['out'], mirrored=True) + t_flyback t_bend_e = i3.VMirror() + vector_match_transform( bend_l.ports['in'], taper_swg_l.ports["in"], mirrored=True) + t_taper_swg_e t_bend_w = i3.VMirror() + vector_match_transform( bend_l.ports['out'], taper_flyback_l.ports["in"] ) + t_taper_flyback_w + i3.Translation((0.0, self.pitch)) # Add instances (for numrows-1) insts += i3.SRef(reference=flyback_l, name="FlybackWg" + str(ii), transformation=t_flyback) insts += i3.SRef(reference=taper_flyback_l, name="FlybackTaper_West" + str(ii), transformation=t_taper_flyback_w) insts += i3.SRef(reference=taper_flyback_l, name="FlybackTaper_East" + str(ii), transformation=t_taper_flyback_e) insts += i3.SRef(reference=bend_l, name="Bend_West" + str(ii), transformation=t_bend_w) insts += i3.SRef(reference=bend_l, name="Bend_East" + str(ii), transformation=t_bend_e) return insts def _generate_ports(self, ports): ports += self.instances["SidewallGratWg0"].ports["in"] ports += self.instances["SidewallGratWg" + str(self.numrows - 1)].ports["out"] return ports
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 Bent_Coupler_Symm(i3.PCell): """ A coupler with symmetric bends on each of the ports. Used with generic PCell """ _name_prefix = "Bent_Coupler_Symm" # defining MMI as child cell with input and output waveguides coupler = i3.ChildCellProperty(restriction=i3.RestrictType(i3.PCell)) # define waveguide template and waveguide cells # for the access bent waveguides connected to the straight couple ## add another waveguide template # coupler_length = i3.PositiveNumberProperty(default=i3.TECH.WG.SHORT_STRAIGHT, # doc="length of the directional coupler") wg_template1 = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wg_template2 = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) # wg_template = i3.WaveguideTemplateProperty(default=i3.TECH.PCELLS.WG.DEFAULT) wgs = i3.ChildCellListProperty(doc="list of waveguides") def _default_wg_template2(self): return self.wg_template1 # define default coupler for class # a straight directional coupler by default # can also insert a tapered MMI by assigning a MMI PCell ### pass the templates for the directional coupler def _default_coupler(self): ### waveguide templates for DC must be defined in this instantiance ### otherwise trace_template1 and trace_template2 will be set bundled to be equal coupler = StraightDirectionalCoupler( name=self.name + "_dir_coup", coupler_length=self.coupler_length) return coupler # define rounded waveguides for the inputs and outputs ## can consider for loop tp reduce the code length def _default_wgs(self): wgs = [] name_list = ["_wg_in1", "_wg_in2", "_wg_out1", "_wg_out2"] template_list = [ self.wg_template1, self.wg_template2, self.wg_template1, self.wg_template2 ] for idx, name in enumerate(name_list): wg = i3.RoundedWaveguide(name=self.name + name_list[idx], trace_template=template_list[idx]) wgs.append(wg) return wgs class Layout(i3.LayoutView): # specified parameters used for layout purposes ## coupling spacing? ## move to the coupler level bend_radius = i3.PositiveNumberProperty( default=10., doc="bend radius of 90 degree bends") in1_offset = i3.PositiveNumberProperty( default=10., doc="offset between 90 degree bends input 1") in2_offset = i3.PositiveNumberProperty( default=10., doc="offset between 90 degree bends input 2") out1_offset = i3.PositiveNumberProperty( default=1., doc="offset between 90 degree bends output 1") out2_offset = i3.PositiveNumberProperty( default=1., doc="offset between 90 degree bends output 2") rounding_algorithm = DefinitionProperty( default=ShapeRound, doc="rounding algorithm for every individual bend") # define default of tapered MMI child cell def _default_coupler(self): ### error to be corrected. the Child Layout view needs to point to coupler first, end get the default view # wg_template1 = self.wg_template1 coupler = self.cell.coupler.get_default_view( i3.LayoutView) # Retrieve layout view following examples ### go to upper level then to define the waveguide template, as the waveguide template of DC is NOT ### defined in layout level # self.cell.coupler.trace_template1 = self.wg_template1 # self.cell.coupler.trace_template2 = self.wg_template2 return coupler # grabbing properties of child cell and setting appropriate transforms, by default do none def _get_components(self): coupler = i3.SRef(reference=self.coupler, name="coupler") return coupler # 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 to grab positions coupler = self._get_components() ## wgcell ? for loop operation wg_in1_cell, wg_in2_cell, wg_out1_cell, wg_out2_cell = self.cell.wgs wg_template1 = self.wg_template1 wg_template2 = self.wg_template2 bend_radius = self.bend_radius # setting variable for round_alg = self.rounding_algorithm # defining bottom left waveguide, using port from MMI and bus length wg_in1_layout = wg_in1_cell.get_default_view(i3.LayoutView) in1_port_pos = coupler.ports["in1"].position in1_shape = [ in1_port_pos, (in1_port_pos[0] - bend_radius, in1_port_pos[1]), (in1_port_pos[0] - bend_radius, in1_port_pos[1] - 2. * bend_radius - self.in1_offset), (in1_port_pos[0] - 2. * bend_radius, in1_port_pos[1] - 2. * bend_radius - self.in1_offset) ] wg_in1_layout.set(trace_template=wg_template1, shape=in1_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # repeat above for other ports, first in2 wg_in2_layout = wg_in2_cell.get_default_view(i3.LayoutView) in2_port_pos = coupler.ports["in2"].position in2_shape = [ in2_port_pos, (in2_port_pos[0] - bend_radius, in2_port_pos[1]), (in2_port_pos[0] - bend_radius, in2_port_pos[1] + 2. * bend_radius + self.in2_offset), (in2_port_pos[0] - 2. * bend_radius, in2_port_pos[1] + 2. * bend_radius + self.in2_offset) ] wg_in2_layout.set(trace_template=wg_template2, shape=in2_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # out1 wg_out1_layout = wg_out1_cell.get_default_view(i3.LayoutView) out1_port_pos = coupler.ports["out1"].position out1_shape = [ out1_port_pos, (out1_port_pos[0] + bend_radius, out1_port_pos[1]), (out1_port_pos[0] + bend_radius, out1_port_pos[1] - 2. * bend_radius - self.out1_offset), (out1_port_pos[0] + 2. * bend_radius, out1_port_pos[1] - 2. * bend_radius - self.out1_offset) ] wg_out1_layout.set(trace_template=wg_template1, shape=out1_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # and out2 wg_out2_layout = wg_out2_cell.get_default_view(i3.LayoutView) out2_port_pos = coupler.ports["out2"].position out2_shape = [ out2_port_pos, (out2_port_pos[0] + bend_radius, out2_port_pos[1]), (out2_port_pos[0] + bend_radius, out2_port_pos[1] + 2. * bend_radius + self.out2_offset), (out2_port_pos[0] + 2. * bend_radius, out2_port_pos[1] + 2. * bend_radius + self.out2_offset) ] wg_out2_layout.set(trace_template=wg_template2, shape=out2_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # returning layouts return wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout def _generate_instances(self, insts): # includes the get components and the new waveguides insts += self._get_components() wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout = self.wgs insts += i3.SRef(reference=wg_in1_layout, name="wg_in1") insts += i3.SRef(reference=wg_in2_layout, name="wg_in2") insts += i3.SRef(reference=wg_out1_layout, name="wg_out1") insts += i3.SRef(reference=wg_out2_layout, name="wg_out2") return insts def _generate_ports(self, prts): # use output ports of all waveguides as I define shapes from the base of the coupler structure outwards instances = self.instances prts += instances["wg_in1"].ports["out"].modified_copy(name="in1") prts += instances["wg_in2"].ports["out"].modified_copy(name="in2") prts += instances["wg_out1"].ports["out"].modified_copy( name="out1") prts += instances["wg_out2"].ports["out"].modified_copy( name="out2") return prts ### an simple example to use Ben_Coupler_Symm class @i3.example_plot() def __example_layout(self): from technologies import silicon_photonics from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate import ipkiss3.all as i3 import numpy as np from euler_rounding_algorithm import Euler90Algorithm from SplittersAndCascades import Bent_Coupler_Symm # set waveguide templates for # the north waveguide (wg_t1) # and the south waveguide (wg_t2) wg_t1 = WireWaveguideTemplate(name="south_arm") wg_t1.Layout(core_width=2.400, cladding_width=i3.TECH.WG.CLADDING_WIDTH, core_process=i3.TECH.PROCESS.WG) wg_t2 = WireWaveguideTemplate(name="north arm") wg_t2.Layout(core_width=1.500, cladding_width=i3.TECH.WG.CLADDING_WIDTH, core_process=i3.TECH.PROCESS.WG) # set the directional coupler (can also be MMI) # and then pass it as an child PCell to Bend_Coupler PCell C = Bent_Coupler_Symmr(name="my_dircoup_2", trace_template1=wg_t1, trace_template2=wg_t2, coupler_length=20.0) layout = C.Layout(bend_radius=10.0, straight_after_bend=6.0, bend_angle=60.0) layout.visualize()
class my_dc(PlaceAndAutoRoute): dc = i3.ChildCellProperty() dc2 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() 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, core_process=i3.TECH.PROCESS.WG) 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_wg_dc2(self): wg_dc2 = WireWaveguideTemplate(name="dc2_template") wg_dc2.Layout(core_width=2.8, cladding_width=2.8 + 16.0) return wg_dc2 def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) return WG1 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear( name="taper{}".format(str(self.width)), start_trace_template=self.wg_t1, end_trace_template=self.trace_template) return WG2 def _default_dc(self): dc = BendDirectionalCoupler(name="DC_gap_1.5_l_923", trace_template1=self.trace_template, coupler_length=923.0) dc.Layout( coupler_spacing=1.5 + 3.8, bend_radius=300.0, # manhattan=True, # straight_after_bend=600.0, bend_angle=90.0) return dc def _default_dc2(self): dc2 = BendDirectionalCoupler(name="DC_gap_2_l_888", trace_template1=self.wg_dc2, coupler_length=888.0) dc2.Layout( coupler_spacing=2 + 2.8, bend_radius=300.0, # manhattan=True, bend_angle=90.0) return dc2 def _default_child_cells(self): child_cells = dict() for counter in range(0, 8, 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 return child_cells def _default_links(self): links = [ ("taper0:out", "dircoup1:in2"), ("taper1:out", "dircoup1:in1"), ("taper2:out", "dircoup1:out2"), ("taper3:out", "dircoup1:out1"), ("taper4:out", "dircoup2:in2"), ("taper5:out", "dircoup2:in1"), ("taper6:out", "dircoup2:out2"), ("taper7:out", "dircoup2:out1") ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(0.0, 0.0), end_position=(300.0, 0.0)) return layout_WG2 # def _default_dc(self): # layout_dc = self.cell.dc.get_default_view(i3.LayoutView) # layout_dc.set(coupler_spacing=2.5 + 3.8, # bend_radius=300.0, # manhattan=True, # # straight_after_bend=6.0, # bend_angle=90.0) # return layout_dc def _default_child_transformations(self): trans = dict() trans["dircoup1"] = (1650, 0) trans["dircoup2"] = (4950, 0) # for counter in range(0, 8, 1): # print counter # trans['straight' + str(counter)] = (2000 * (counter + 1), 0) # trans["taper" + str(counter)] = (0, 2000 * (counter + 1)) trans["straight0"] = (0, 4000) trans["straight1"] = (0, -4000) trans["straight2"] = (3150, 2000) trans["straight3"] = (3150, -6000) trans["straight4"] = (3300, 2000) trans["straight5"] = (3300, -6000) trans["straight6"] = (6450, 4000) trans["straight7"] = (6450, -4000) trans["taper0"] = (150, 4000) trans["taper1"] = (150, -4000) trans["taper2"] = i3.HMirror(150) + i3.Translation((2850, 2000)) trans["taper3"] = i3.HMirror(150) + i3.Translation((2850, -6000)) trans["taper4"] = (3450, 2000) trans["taper5"] = (3450, -6000) trans["taper6"] = i3.HMirror(150) + i3.Translation((6150, 4000)) trans["taper7"] = i3.HMirror(150) + i3.Translation((6150, -4000)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius # def _default_start_straight(self): # start_straight = 100.0 # return start_straight 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 MMI2112(PlaceAndAutoRoute): wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() mmi1_12 = i3.ChildCellProperty() mmi1_21 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() # def _default_external_port_names(self): # ports = dict() # ports["MMI1b:in1"] = "vertical_in" # ports["MMI1b:in2"] = "out" # return ports def _default_links(self): links = [("taper:out", "taper2:out")] return links def _default_child_cells(self): child_cells = { "MMI1a": self.mmi1_12, "MMI1b": self.mmi1_21, "taper": self.WG2, "taper2": self.WG2 } return child_cells def _default_trace_template(self): wg_sm2 = WireWaveguideTemplate() wg_sm2.Layout(core_width=3.1, cladding_width=3.1 + 16.0) return wg_sm2 def _default_mmi1_12(self): mmi12 = MMI1x2Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["out1", "out2"], ) return mmi12 def _default_mmi1_21(self): mmi21 = MMI2x1Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["in1", "in2"], ) return mmi21 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear(start_trace_template=self.mmi_access_template, end_trace_template=self.trace_template) return WG2 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=97) # def _default_WG1(self): # layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) # layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) # return layout_WG1 # def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(0.0, 0.0), end_position=(200.0, 0.0)) return layout_WG2 def _default_mmi1_12(self): layout_mmi1_12 = self.cell.mmi1_12.get_default_view(i3.LayoutView) layout_mmi1_12.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi1_12 def _default_mmi1_21(self): layout_mmi1_21 = self.cell.mmi1_21.get_default_view(i3.LayoutView) layout_mmi1_21.set(transition_length=200.0, length=self.length, trace_spacing=11.0) # print layout_mmi1_21.ports['in1'].x return layout_mmi1_21 def _default_child_transformations(self): # print self.cell.mmi1_12.get_default_view(i3.LayoutView).length # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['in1'].x # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x # a = self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x - self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['in1'].x a = self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x child_transformations = {"MMI1a": (a + 490, 0), "taper": (a, 0), "taper2": i3.HMirror(0.0) + i3.Translation((a + 490, 0)) # "WGup": (0, 4000), # "WGuptaper": (0, 4000), # "WGdown": (0, -4000), # "WGdowntaper": (0, -4000), # "WGuptaper2": i3.HMirror() + i3.Translation((3400, 4000)), # "WGdowntaper2": i3.HMirror() + i3.Translation((3400, -4000)), # "WGup2": (3250, 4000), # "WGdown2": (3250, -4000) } return child_transformations # mmi1 = MMI2112() # mmi1_layout = mmi1.Layout(length=120) # mmi1_layout.visualize(annotate=True) # print mmi1_layout.ports # mmi1_layout.write_gdsii("MMI2112_V5.gds")
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_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) 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 MMI2112(PlaceAndAutoRoute): wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() mmi1_12 = i3.ChildCellProperty() mmi1_21 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() # def _default_external_port_names(self): # ports = dict() # ports["MMI1b:in1"] = "vertical_in" # ports["MMI1b:in2"] = "out" # return ports def _default_links(self): links = [("taper:out", "taper2:out")] return links def _default_child_cells(self): child_cells = { "MMI1a": self.mmi1_12, "MMI1b": self.mmi1_21, "taper": self.WG2, "taper2": self.WG2 } return child_cells def _default_trace_template(self): wg_sm2 = WireWaveguideTemplate() wg_sm2.Layout(core_width=3.1, cladding_width=3.1 + 16.0) return wg_sm2 def _default_mmi1_12(self): mmi12 = MMI1x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["out1", "out2"], ) return mmi12 def _default_mmi1_21(self): mmi21 = MMI2x1Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["in1", "in2"], ) return mmi21 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear( start_trace_template=self.mmi_access_template, end_trace_template=self.trace_template) return WG2 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=97) # def _default_WG1(self): # layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) # layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) # return layout_WG1 # def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(0.0, 0.0), end_position=(200.0, 0.0)) return layout_WG2 def _default_mmi1_12(self): layout_mmi1_12 = self.cell.mmi1_12.get_default_view(i3.LayoutView) layout_mmi1_12.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi1_12 def _default_mmi1_21(self): layout_mmi1_21 = self.cell.mmi1_21.get_default_view(i3.LayoutView) layout_mmi1_21.set(name="MMI2112_l_{}".format(str(self.length)), transition_length=200.0, length=self.length, trace_spacing=11.0) # print layout_mmi1_21.ports['in1'].x return layout_mmi1_21 def _default_child_transformations(self): # print self.cell.mmi1_12.get_default_view(i3.LayoutView).length # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['in1'].x # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x # a = self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x - self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['in1'].x a = self.cell.mmi1_21.get_default_view( i3.LayoutView).ports['out'].x child_transformations = { "MMI1a": (a + 490, 0), "taper": (a, 0), "taper2": i3.HMirror(0.0) + i3.Translation((a + 490, 0)) # "WGup": (0, 4000), # "WGuptaper": (0, 4000), # "WGdown": (0, -4000), # "WGdowntaper": (0, -4000), # "WGuptaper2": i3.HMirror() + i3.Translation((3400, 4000)), # "WGdowntaper2": i3.HMirror() + i3.Translation((3400, -4000)), # "WGup2": (3250, 4000), # "WGdown2": (3250, -4000) } return child_transformations def _generate_elements(self, elems): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Name={}_port_20'.format( self.cell.mmi1_21.get_default_view(i3.LayoutView).name), coordinate=(200.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) return elems
class MMI2112(PlaceAndAutoRoute): wg_t1 = i3.WaveguideTemplateProperty() wg_sm = i3.WaveguideTemplateProperty() wg_sm2 = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() mmi1_12 = i3.ChildCellProperty() mmi1_21 = i3.ChildCellProperty() # mmi1_12_taper = i3.ChildCellProperty() # mmi1_21_taper = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() length = i3.PositiveNumberProperty(doc="MMI length", default=97) def _default_links(self): links = [ # ("MMI1a:out2", "WGuptaper2:out"), # ("MMI1a:out1", "WGdowntaper2:out"), ("MMI1b:out", "MMI1a:in"), # ("WGuptaper:out", "MMI1b:in2"), # ("WGdowntaper:out", "MMI1b:in1") ] return links def _default_child_cells(self): child_cells = { "MMI1a": self.mmi1_12, "MMI1b": self.mmi1_21, # "WGup": self.WG1, # "WGdown": self.WG1, # "WGup2": self.WG1, # "WGdown2": self.WG1, # "WGuptaper": self.WG2, # "WGdowntaper": self.WG2, # "WGuptaper2": self.WG2, # "WGdowntaper2": self.WG2 } return child_cells def _default_trace_template(self): trace_template = self.wg_sm2 return trace_template def _default_mmi1_12(self): mmi12 = MMI1x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["out1", "out2"], ) mmi12.Layout(transition_length=200.0, length=self.length, trace_spacing=11.0) mmi1_12_taper = AutoTransitionPorts(name="MMI12", contents=mmi12, port_labels=['in'], trace_template=self.wg_sm2) mmi1_12_taper.Layout(transition_length=200.0) return mmi1_12_taper # def _default_mmi1_12_taper(self): # mmi1_12_taper = AutoTransitionPorts(contents=self.mmi1_12, # port_labels=['in'], # trace_template=self.wg_sm2) # mmi1_12_taper.Layout(transition_length=200.0) # return mmi1_12_taper def _default_mmi1_21(self): mmi21 = MMI2x1Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["in1", "in2"], ) mmi21.Layout(transition_length=200.0, length=self.length, trace_spacing=11.0) mmi1_12_taper = AutoTransitionPorts(name="MMI21", contents=mmi21, port_labels=['out'], trace_template=self.wg_sm2) mmi1_12_taper.Layout(transition_length=200.0) return mmi1_12_taper # def _default_mmi1_21_taper(self): # mmi1_21_taper = AutoTransitionPorts(contents=self.mmi1_21, # port_labels=['out'], # trace_template=self.wg_sm2) # return mmi1_21_taper def _default_WG2(self): WG2 = WireWaveguideTransitionLinear(start_trace_template=self.wg_t1, end_trace_template=self.wg_sm) return WG2 def _default_WG1(self): WG1 = i3.Waveguide(name="Dongbo", trace_template=self.wg_t1) return WG1 def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate() wg_t1.Layout(core_width=15.0, cladding_width=15.0 + 16.0, core_process=i3.TECH.PROCESS.WG) return wg_t1 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_wg_sm2(self): wg_sm2 = WireWaveguideTemplate() wg_sm2.Layout(core_width=3.1, cladding_width=3.1 + 16.0) return wg_sm2 def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template # def _default_child_transformations(self): # child_transformations = {"MMI1a": (500 + self.length, 0) # # "MMI1b": (1300, 0), # # "WGup": (0, 4000), # # "WGuptaper": (0, 4000), # # "WGdown": (0, -4000), # # "WGdowntaper": (0, -4000), # # "WGuptaper2": i3.HMirror() + i3.Translation((3400, 4000)), # # "WGdowntaper2": i3.HMirror() + i3.Translation((3400, -4000)), # # "WGup2": (3250, 4000), # # "WGdown2": (3250, -4000) # } # return child_transformations class Layout(PlaceAndAutoRoute.Layout): # def _default_WG1(self): # layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) # layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) # return layout_WG1 # # def _default_WG2(self): # layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) # layout_WG2.set(start_position=(150.0, 0.0), end_position=(450.0, 0.0)) # return layout_WG2 # def _default_mmi1_12(self): # layout_mmi1_12 = self.cell.mmi1_12.get_default_view(i3.LayoutView) # layout_mmi1_12.set(transition_length=200.0, length=self.length, trace_spacing=11.0) # return layout_mmi1_12 # def _default_mmi1_12_taper(self): # layout_mmi1_12_taper = self.cell.mmi1_12_taper.get_default_view(i3.LayoutView) # layout_mmi1_12_taper.set(transition_length=200.0) # return layout_mmi1_12_taper # def _default_mmi1_21(self): # layout_mmi1_21 = self.cell.mmi1_21.get_default_view(i3.LayoutView) # layout_mmi1_21.set(transition_length=200.0, length=self.length, trace_spacing=11.0) # # print layout_mmi1_21.ports['in1'].x # return layout_mmi1_21 def _default_child_transformations(self): # print self.cell.mmi1_12.get_default_view(i3.LayoutView).length # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['in1'].x # print self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x a = self.cell.mmi1_21.get_default_view( i3.LayoutView ).ports['out'].x - self.cell.mmi1_21.get_default_view( i3.LayoutView).ports['in1'].x child_transformations = { "MMI1a": (a + 90, 0), # "MMI1b": (1300, 0), # "WGup": (0, 4000), # "WGuptaper": (0, 4000), # "WGdown": (0, -4000), # "WGdowntaper": (0, -4000), # "WGuptaper2": i3.HMirror() + i3.Translation((3400, 4000)), # "WGdowntaper2": i3.HMirror() + i3.Translation((3400, -4000)), # "WGup2": (3250, 4000), # "WGdown2": (3250, -4000) } return child_transformations def _default_bend_radius(self): bend_radius = 300 return bend_radius
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 MMI2112(PlaceAndAutoRoute): wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() mmi1_12 = i3.ChildCellProperty() mmi1_21 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() def _default_links(self): links = [("taper:out", "taper2:out")] return links def _default_child_cells(self): child_cells = { "MMI1a": self.mmi1_12, "MMI1b": self.mmi1_21, "taper": self.WG2, "taper2": self.WG2 } return child_cells def _default_trace_template(self): wg_sm2 = WireWaveguideTemplate() wg_sm2.Layout(core_width=3.1, cladding_width=3.1 + 24.0) return wg_sm2 def _default_mmi1_12(self): mmi12 = MMI1x2Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["out1", "out2"], ) return mmi12 def _default_mmi1_21(self): mmi21 = MMI2x1Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.wg_sm, port_labels=["in1", "in2"], ) return mmi21 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear(start_trace_template=self.mmi_access_template, end_trace_template=self.trace_template) return WG2 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 24.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 24.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 24.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): length = i3.PositiveNumberProperty(doc="MMI length", default=97) def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(0.0, 0.0), end_position=(200.0, 0.0)) return layout_WG2 def _default_mmi1_12(self): layout_mmi1_12 = self.cell.mmi1_12.get_default_view(i3.LayoutView) layout_mmi1_12.set(transition_length=200.0, length=self.length, trace_spacing=11.0) return layout_mmi1_12 def _default_mmi1_21(self): layout_mmi1_21 = self.cell.mmi1_21.get_default_view(i3.LayoutView) layout_mmi1_21.set(name="MMI2112_l_{}".format(str(self.length)), transition_length=200.0, length=self.length, trace_spacing=11.0) # print layout_mmi1_21.ports['in1'].x return layout_mmi1_21 def _default_child_transformations(self): a = self.cell.mmi1_21.get_default_view(i3.LayoutView).ports['out'].x child_transformations = {"MMI1a": (a + 490, 0), "taper": (a, 0), "taper2": i3.HMirror(0.0) + i3.Translation((a + 490, 0)) } return child_transformations
class SingleResonator(i3.PCell): """ A single resonator test class """ _name_prefix = "single_resonator" # defining the resonator as child cell with input and output waveguides resonator = i3.ChildCellProperty(restriction=i3.RestrictType(i3.PCell), doc="the input resonator") # define waveguide template and waveguide cells wg_coupler_template = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wg_ring_template = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wgs = i3.ChildCellListProperty(doc="list of waveguides") # define default MMI for class def _default_resonator(self): """ Internal resonator which is repeated later """ resonator = RingRect(name=self.name + "_resonator", ring_trace_template=self.wg_ring_template) return resonator # define rounded waveguides for the inputs and outputs of CROW def _default_wgs(self): wg_in = i3.RoundedWaveguide(name=self.name + "_wg_in", trace_template=self.wg_coupler_template) wg_pass = i3.RoundedWaveguide(name=self.name + "_wg_pass", trace_template=self.wg_coupler_template) # wg_ring = i3.RoundedWaveguide(name=self.name+"_wg_ring", trace_template=self.wg_coupler_template) return wg_in, wg_pass # , wg_pass, wg_ring 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=0.5, doc="gap between outside waveguides and resonator") # external_radius = i3.PositiveNumberProperty(default=bend_radius_ring, doc="radius of outside coupler") use_rounding = i3.BoolProperty(default=False, doc="use non default bending algorithm") rounding_algorithm = i3.DefinitionProperty( default=SplineRoundingAlgorithm(), doc="secondary rounding algorithm") # 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 if self.use_rounding is True: res_layout.set(bend_radius=self.bend_radius_ring, straights=(self.ring_x_straight, self.ring_y_straight), rounding_algorithm=self.rounding_algorithm) else: res_layout.set( bend_radius=self.bend_radius_ring, straights=(self.ring_x_straight, self.ring_y_straight)) # , shape=ring_shape return res_layout # now we take the resonator which was just defined and stick it in the main *get components thing def _get_components(self): resonator = i3.SRef(name="another_res", reference=self.resonator) return resonator # 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 to grab positions resonator = self._get_components() 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) if self.use_rounding is True: wg_in_layout.set(trace_template=wg_template, shape=wg_shape, bend_radius=external_rad, rounding_algorithm=self.rounding_algorithm) else: wg_in_layout.set(trace_template=wg_template, shape=wg_shape, bend_radius=external_rad) 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 def _generate_instances(self, insts): # includes the get components and the new waveguides insts += self._get_components() wg_in_layout, wg_pass_layout = self.wgs # wg_pass_layout, wg_ring_layout insts += i3.SRef(reference=wg_in_layout, name="wg_in") # insts += i3.SRef(reference=wg_pass_layout, name="wg_pass") # insts += i3.SRef(reference=wg_ring_layout, name="wg_ring") 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="in") prts += instances["wg_in"].ports["out"].modified_copy(name="pass") return prts class Netlist(i3.NetlistView): def _generate_terms(self, terms): terms += i3.OpticalTerm(name="in") # terms += i3.OpticalTerm(name="pass") return terms
class v9(PlaceAndAutoRoute): wg_t1 = i3.WaveguideTemplateProperty() wg_sm = i3.WaveguideTemplateProperty() mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() length2 = i3.PositiveNumberProperty(doc="MMI2 length", default=97) mmi22 = i3.ChildCellProperty() WG1 = i3.ChildCellProperty() WG2 = i3.ChildCellProperty() def _default_links(self): links = [ ("MMI1b:MMI1a_out2", "WGuptaper2:out"), ("MMI1b:MMI1a_out1", "WGdowntaper2:out"), # ("MMI1b:out","MMI1a:in"), ("WGuptaper:out", "MMI1b:MMI1b_in2"), ("WGdowntaper:out", "MMI1b:MMI1b_in1") ] return links def _default_child_cells(self): child_cells = { "MMI1b": self.mmi22, "WGup": self.WG1, "WGdown": self.WG1, "WGup2": self.WG1, "WGdown2": self.WG1, "WGuptaper": self.WG2, "WGdowntaper": self.WG2, "WGuptaper2": self.WG2, "WGdowntaper2": self.WG2 } return child_cells def _default_trace_template(self): trace_template = self.wg_sm return trace_template def _default_mmi22(self): mmi22 = MMI2112(length=self.length2) # mmi22 = MMI2112() return mmi22 def _default_WG2(self): WG2 = WireWaveguideTransitionLinear(start_trace_template=self.wg_t1, end_trace_template=self.wg_sm) return WG2 def _default_WG1(self): WG1 = i3.Waveguide(name="Dongbo", trace_template=self.wg_t1) return WG1 def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate() wg_t1.Layout(core_width=15.0, cladding_width=15.0 + 16.0, core_process=i3.TECH.PROCESS.WG) return wg_t1 def _default_wg_sm(self): wg_sm = WireWaveguideTemplate() wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate() mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 16.0) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate() mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 16.0) return mmi_access_template class Layout(PlaceAndAutoRoute.Layout): # length2 = i3.PositiveNumberProperty(doc="MMI2 length", default=97) def _default_WG1(self): layout_WG1 = self.cell.WG1.get_default_view(i3.LayoutView) layout_WG1.set(shape=[(0.0, 0.0), (150.0, 0.0)]) return layout_WG1 def _default_WG2(self): layout_WG2 = self.cell.WG2.get_default_view(i3.LayoutView) layout_WG2.set(start_position=(150.0, 0.0), end_position=(450.0, 0.0)) return layout_WG2 # def _default_mmi22(self): # # layout_mmi22 = self.cell.mmi22.get_default_view(i3.LayoutView) # self.cell.mmi22.length = self.length2 # layout_mmi22 = self.cell.mmi22.get_default_view(i3.LayoutView) # return layout_mmi22 def _default_child_transformations(self): child_transformations = { "MMI1b": (1300, 0), "WGup": (0, 4000), "WGuptaper": (0, 4000), "WGdown": (0, -4000), "WGdowntaper": (0, -4000), "WGuptaper2": i3.HMirror() + i3.Translation((3300, 2000)), "WGdowntaper2": i3.HMirror() + i3.Translation((3300, -6000)), "WGup2": (3150, 2000), "WGdown2": (3150, -6000) } return child_transformations def _default_bend_radius(self): bend_radius = 300 return bend_radius
class tapered_GratingCoupler_extension(PlaceAndAutoRoute): gc = i3.ChildCellProperty() tapered_gc = i3.ChildCellProperty() wg_socket = i3.WaveguideTemplateProperty() wg = i3.ChildCellProperty() def _default_trace_template(self): wg_t = WireWaveguideTemplate() wg_t.Layout(core_width=0.8, cladding_width=6.8) return wg_t def _default_wg(self): wg = i3.RoundedWaveguide(trace_template=self.trace_template) return wg def _default_wg_socket(self): wg_socket = WireWaveguideTemplate() wg_socket.Layout(core_width=12.0, cladding_width=18.0) return wg_socket def _default_gc(self): gc = UniformLineGrating(trace_template=self.wg_socket) return gc def _default_tapered_gc(self): tapered_gc = AutoTransitionPorts(contents=self.gc, trace_template=self.trace_template, port_labels=["out"]) return tapered_gc def _default_child_cells(self): child_cells = dict() child_cells["tapered_gc"] = self.tapered_gc child_cells["wg"] = self.wg return child_cells def _default_links(self): links = [("tapered_gc:out", "wg:in")] return links def _default_external_port_names(self): ports = dict() ports["tapered_gc:vertical_in"] = "vertical_in" ports["wg:out"] = "out" return ports class Layout(PlaceAndAutoRoute.Layout): period = i3.PositiveNumberProperty(doc="period of grating", default=0.95) n_o_periods = i3.PositiveIntProperty(doc="number of periods of grating", default=16) line_width = i3.PositiveNumberProperty(doc="width of the grating") line_length = i3.PositiveNumberProperty(doc="length of the grating", default=13.0) socket_length = i3.PositiveNumberProperty(doc="length of socket") # transition_length = i3.PositiveNumberProperty(doc="length of the taper") transition_length = i3.PositiveNumberProperty(doc="taper length", default=100.0) extension_length = i3.PositiveNumberProperty(doc="extra straight length", default=100.0) def _default_line_width(self): return self.period * 0.5 def _default_socket_length(self): return self.period * self.n_o_periods + 2.0 def _default_gc(self): gc_lo = self.cell.gc.get_default_view(i3.LayoutView) gc_lo.set(period=self.period, n_o_periods=self.n_o_periods, line_width=self.line_width, line_length=self.line_length) return gc_lo def _default_tapered_gc(self): tapered_gc_lo = self.cell.tapered_gc.get_default_view(i3.LayoutView) tapered_gc_lo.set(transition_length=self.transition_length) return tapered_gc_lo def _default_wg(self): wg_lo = self.cell.wg.get_default_view(i3.LayoutView) wg_lo.set(shape=[(0.0, 0.0), (self.extension_length, 0.0)]) return wg_lo def _default_child_transformations(self): trans = dict() trans["tapered_gc"] = (0, 0) trans["wg"] = i3.Translation(self.tapered_gc.ports["out"].position) + i3.Translation((10, 0)) return trans