class Block_with_Vacuum(i3.PCell): """Parametric cell with several traps, which are stacked vertically """ _name_prefix = "BlockWithVacuum" block = i3.ChildCellProperty( ) # Generating block from Child Cell List Property #channel_template = i3.TraceTemplateProperty(doc="the trace template prop") vacuum = i3.ChildCellProperty() #vacuum channel class Layout(i3.LayoutView): def _get_components(self): # 1. calculate the transformations of the rings based on their properties #circuitWidth = block_layout.size_info() #circuit_x_gap = 2000.0 #separation = abs(circuitWidth.west) + abs(circuitWidth.east)+ circuit_x_gap t1 = i3.Translation( (0 * 0, 0.0)) # i3.Translation((separation*0, 0.0)) # 2. Generating the instances circuit_1 = i3.SRef(name="t_1", reference=self.block, transformation=t1) circuit_2 = i3.SRef(name="t_2", reference=self.vacuum, transformation=t1) return circuit_1, circuit_2 def _generate_instances(self, insts): insts += self._get_components() return insts
class FourMMIs(i3.PCell): mmi = i3.ChildCellProperty(doc="MMI that is replicated four times.") def _default_mmi(self): mmi = MMI_22(name=self.name + "_mmi") mmi.Layout(length=30.0) return mmi class Layout(i3.LayoutView): mmi_sep = i3.PositiveNumberProperty(default=20.0) def _generate_instances(self, insts): for cnt in range(4): trans = i3.Translation(translation=(0.0, cnt * self.mmi_sep)) insts += i3.SRef(name="MMI_{}".format(cnt), reference=self.mmi, transformation=trans) return insts def _generate_ports(self, ports): for cnt in range(4): mmip = self.instances["MMI_{}".format(cnt)] for p in mmip.ports: ports += p.modified_copy(name="{}_{}".format(p.name, cnt)) return ports
class DropRing(PlaceAndAutoRoute): """ Drop ring with the total ring length as a property. """ directional_coupler = i3.ChildCellProperty( doc="Directional couplers used for the ring resonator") total_ring_length = i3.PositiveNumberProperty(doc="Total ring length") def _default_trace_template(self): return SiWireWaveguideTemplate(name=self.name + "tt") def _default_total_ring_length(self): return 200.0 def _default_directional_coupler(self): dc = DirectionalCoupler(name=self.name + 'dc') return dc def _default_child_cells(self): return { 'dc1': self.directional_coupler, 'dc2': self.directional_coupler } def _default_links(self): return [('dc1:in2', 'dc2:in2'), ('dc1:out2', 'dc2:out2')] def _default_external_port_names(self): return { "dc1:in1": "in1", "dc1:out1": "out1", "dc2:out1": "in2", "dc2:in1": "out2", } class Layout(PlaceAndAutoRoute.Layout): def _get_distance_between_dc(self): # Get length of the curved section of the directional coupler. dc = self.directional_coupler waveguide_length = (self.total_ring_length - 2 * dc.get_length_ring_section()) / 2.0 height_out_port = dc.ports["out2"].y return 2 * height_out_port + waveguide_length def _default_child_transformations(self): return { "dc1": (0, 0), "dc2": i3.VMirror(0.0) + i3.Translation( (0, self._get_distance_between_dc())) }
class BlockWithTees(i3.PCell): """Parametric cell with trap and tee defined by the user """ _name_prefix = "BLOCK_W_TEES" # 1. # The trap and tee are defined as ChildCellProperties. This is a special property # that for hierarchical PCells. In each view of the PCell of a certain type (e.g. Layout) # the corresponding viewtype (e.g. Layout) of the ChildCell will automatically available. block = i3.ChildCellProperty( default=Block()) #(default=CellTrapSimple()) # tee = i3.ChildCellProperty(default=TeeSimple()) TECH = i3.get_technology() # Layout view class Layout(i3.LayoutView): def _generate_instances(self, insts): insts += i3.place_insts(insts={ 'inlet': self.tee, 'block': self.block, 'outlet': self.tee }, specs=[ i3.Place('block', (0, 0)), i3.Join([('inlet:out1', 'block:in1'), ('outlet:out1', 'block:out1') ]), i3.FlipH('outlet'), ]) return insts def _generate_ports(self, ports): return i3.expose_ports( self.instances, { 'inlet:in1': 'in1', 'inlet:in2': 'in2', 'outlet:in1': 'out1', 'outlet:in2': 'out2' })
class JoinedObstacles(i3.PCell): #(Structure): channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template for ports") mysingleObstacle = i3.ChildCellProperty( doc='the single Obstacle child cell, which will be clonned many times', default=Obstacle_BooleanBoundary()) wholeTrapX = i3.PositiveNumberProperty( default=500.0, doc="total X distance length of traps") wholeTrapY = i3.PositiveNumberProperty( default=500.0, doc="total Y distance length of traps") cInp = i3.Coord2Property(default=0.0, doc="") class Layout(i3.LayoutView): def _generate_instances(self, insts): x_inc = (self.mysingleObstacle.gap_btw_barriers + self.mysingleObstacle.obstacle_trap_length) * 2 y_inc = self.mysingleObstacle.channel_trap_width * 1.5 cycles_x = int(self.wholeTrapX / ((self.mysingleObstacle.gap_btw_barriers + self.mysingleObstacle.obstacle_trap_length) * 2)) cycles_y = int(self.wholeTrapY / (y_inc)) insts += i3.ARef(reference=self.mysingleObstacle, origin=(0, 0.0 * self.cell.wholeTrapY), period=(x_inc, y_inc), n_o_periods=(cycles_x, cycles_y)) print 'insts', insts return insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in', position=(0, self.wholeTrapY * 0.5), #position = (0, 'insts_0'.size_info().north*0.5), direction=i3.PORT_DIRECTION.IN, angle_deg=180, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='out', position=(self.wholeTrapX, self.wholeTrapY * 0.5), direction=i3.PORT_DIRECTION.OUT, angle_deg=0, trace_template=self.cell.channel_template) return ports
class Square(PlaceComponents): size=i3.PositiveNumberProperty(default=20.0, doc="simension of the square of aligning mark") separation=i3.PositiveNumberProperty(default=2.0, doc="simension of the square of aligning mark") square = i3.ChildCellProperty(doc="grating with pitch 1", locked=True) tt_square = i3.TraceTemplateProperty(doc="Wide trace template used ") layName = i3.StringProperty(default = 'new') props = i3.DictProperty() def _default_props(self): return AssignProcess(self.layName) def _default_tt_square(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=(self.size), cladding_width=(self.size), **self.props ) print 'ttw in Square is ', tt_w return tt_w def _default_square(self): rect=i3.Waveguide(trace_template=self.tt_square) layout_rect = rect.Layout(shape=[(0.0, self.size/2.0),(self.size,self.size/2.0)]) print 'The trace template of the hline of the cross ', rect.trace_template return rect def _default_child_cells(self): child_cells={"S1" : self.square, } return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): child_transformations={ "S1" : i3.Translation(translation=(-(self.size*0.5),(-self.size*0.5))), } return child_transformations
class BondPad(i3.PCell): """Base bondpad class used in our aeponyx PDK. A bondpad is a large rectangular area on the top metal layer for connecting external electrical wires, flip-chip bumps or probe needles. """ via = i3.ChildCellProperty() def _default_via(self): return VIA_M1_M2() class Layout(i3.LayoutView): metal1_size = i3.Size2Property(default=(50.0, 50.0)) metal2_size = i3.Size2Property(default=(50.0, 50.0)) via_pitch = i3.Size2Property(default=(2.0, 2.0)) metal1_layer = i3.LayerProperty(default=i3.TECH.PPLAYER.M1.LINE, locked=True) metal2_layer = i3.LayerProperty(default=i3.TECH.PPLAYER.M2.LINE, locked=True) def _generate_instances(self, insts): from numpy import floor via_span_x = min(self.metal1_size[0], self.metal2_size[0]) via_span_y = min(self.metal1_size[1], self.metal2_size[1]) periods_x = int(floor(via_span_x / self.via_pitch[0])) periods_y = int(floor(via_span_y / self.via_pitch[1])) insts += i3.ARef(reference=self.via, origin=(-0.5 * via_span_x + 0.5 * self.via_pitch[0], -0.5 * via_span_y + 0.5 * self.via_pitch[1]), period=self.via_pitch, n_o_periods=(periods_x, periods_y)) return insts def _generate_elements(self, elems): elems += i3.Rectangle(layer=self.metal1_layer, box_size=self.metal1_size) elems += i3.Rectangle(layer=self.metal2_layer, box_size=self.metal2_size) return elems def _generate_ports(self, ports): ports += i3.ElectricalPort(name="m1", position=(0.0, 0.0), shape=self.metal1_size, process=self.metal1_layer.process) ports += i3.ElectricalPort(name="m2", position=(0.0, 0.0), shape=self.metal2_size, process=self.metal2_layer.process) return ports class Netlist(i3.NetlistFromLayout): pass
class Splitter3(APAC): splitter = i3.ChildCellProperty(doc="splitter used") spacing_x = i3.PositiveNumberProperty(default=200.0) spacing_y = i3.PositiveNumberProperty(default=100.0) def _default_splitter(self): return MMI_12() def _default_child_cells(self): childs = dict() childs["sp_0_0"] = self.splitter childs["sp_1_0"] = self.splitter childs["sp_1_1"] = self.splitter return childs def _default_connectors(self): conn = [] conn.append(("sp_0_0:out1", "sp_1_0:in1", sbend)) conn.append(("sp_0_0:out2", "sp_1_1:in1", sbend)) return conn class Layout(APAC.Layout): def _default_child_transformations(self): trans = dict() from routing.transforms import relative_placer trans["sp_0_0"] = i3.Rotation(rotation=30.0) + i3.Translation( translation=(10.0, 10.0)) trans["sp_1_0"] = relative_placer( self.child_cells, trans, "sp_0_0:out1", "sp_1_0:in1", (self.spacing_x, -self.spacing_y / 2), 0.0) trans["sp_1_1"] = relative_placer( self.child_cells, trans, "sp_0_0:out2", "sp_1_1:in1", (self.spacing_x, +self.spacing_y / 2), 0.0) return trans
class Splitter3(APAC): splitter = i3.ChildCellProperty(doc="splitter used") spacing_x = i3.PositiveNumberProperty(default=100.0, doc="spacing port to port") spacing_y = i3.PositiveNumberProperty(default=200.0, doc="spacing port to port") def _default_splitter(self): return MMI_12(name=self.name + "_MMI") def _default_child_cells(self): childs = dict() childs["sp_0_0"] = self.splitter childs["sp_1_0"] = self.splitter childs["sp_1_1"] = self.splitter return childs def _default_connectors(self): conn = [] conn.append(("sp_0_0:out1", "sp_1_0:in1", sbend)) conn.append(("sp_0_0:out2", "sp_1_1:in1", sbend)) return conn class Layout(APAC.Layout): def _default_child_transformations(self): trans = dict() trans["sp_0_0"] = (0, 0) trans["sp_1_0"] = (self.spacing_x, -self.spacing_y / 2.0) trans["sp_1_1"] = (self.spacing_x, +self.spacing_y / 2.0) return trans
class MMI2112(PlaceAndAutoRoute): # wg_sm = i3.WaveguideTemplateProperty() # wg_t1 = i3.WaveguideTemplateProperty() # mmi_trace_template = i3.WaveguideTemplateProperty() # mmi_access_template = i3.WaveguideTemplateProperty() start_id = i3.PositiveNumberProperty(doc="name", default=1) ring1 = i3.ChildCellProperty() ring2 = i3.ChildCellProperty() # WG1 = i3.ChildCellProperty() # WG2 = i3.ChildCellProperty() def _default_links(self): links = [ # ("MMI1a:out2", "WGuptaper2:out"), # ("MMI1a:out1", "WGdowntaper2:out"), ("MMI1b:in1", "MMI1a:out2"), # ("WGuptaper:out", "MMI1b:in2"), # ("WGdowntaper:out", "MMI1b:in1") ] return links def _default_child_cells(self): child_cells = {"MMI1a": self.ring1, "MMI1b": self.ring2} return child_cells def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_connection") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_ring1(self): ring1 = RingRectSymm180DropFilter( name="my_rectsymm180dropring{}".format(str(self.start_id)), ring_trace_template=self.trace_template) return ring1 def _default_ring2(self): ring2 = RingRectSymm180DropFilter( name="my_rectsymm180dropring2{}".format(str(self.start_id)), ring_trace_template=self.trace_template) return ring2 class Layout(PlaceAndAutoRoute.Layout): radius = i3.PositiveNumberProperty(doc="radius", default=200.0) gap = i3.PositiveNumberProperty(doc="gap", default=1.0) length = i3.PositiveNumberProperty(doc="coupler_length", default=60.0) # 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_ring1(self): layout_ring1 = self.cell.ring1.get_default_view(i3.LayoutView) layout_ring1.set( bend_radius=self.radius, coupler_lengths=[self.length, self.length], coupler_radii=[300.0, 300.0], coupler_angles=[90.0, 90.0], coupler_spacings=[3.8 + self.gap, 3.8 + self.gap], straights=(self.length, 0.0), # manhattan=True, ) return layout_ring1 def _default_ring2(self): layout_ring1 = self.cell.ring2.get_default_view(i3.LayoutView) layout_ring1.set( bend_radius=self.radius + 20, coupler_lengths=[self.length, self.length], coupler_radii=[300.0, 300.0], coupler_angles=[90.0, 90.0], coupler_spacings=[3.8 + self.gap, 3.8 + self.gap], straights=(self.length, 0.0), # manhattan=True, ) return layout_ring1 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": (0, -2000), "MMI1b": (0, 2500)} return child_transformations def _default_bend_radius(self): bend_radius = 300 return bend_radius
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 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 MZI(CircuitCell): control_points = i3.ListProperty( doc="Position of the control point for the longer arm of the MZI") bend_radius = i3.PositiveNumberProperty( default=5.0, doc="Bend radius of the waveguides") fgc = i3.ChildCellProperty(locked=True, doc="PCell for the fiber grating coupler") splitter = i3.ChildCellProperty(locked=True, doc="PCell for the Y-Branch") dir_coupler = i3.ChildCellProperty(locked=True, doc="PCell for the directional coupler") def _default_control_points(self): return [(100.0, 220.0)] def _default_fgc(self): return pdk.EbeamGCTE1550() def _default_splitter(self): return pdk.EbeamY1550() def _default_dir_coupler(self): return pdk.EbeamBDCTE1550() def _default_child_cells(self): child_cells = { "fgc_1": self.fgc, "fgc_2": self.fgc, "fgc_3": self.fgc, "yb": self.splitter, "dc": self.dir_coupler, } return child_cells def _default_joins(self): joins = [("fgc_3:opt1", "yb:opt1")] return joins def _default_connectors(self): br = self.bend_radius connectors = [ ("yb:opt3", "dc:opt2", manhattan, { "bend_radius": br }), ("yb:opt2", "dc:opt1", partial(manhattan, control_points=self.control_points), { "bend_radius": br }), ("dc:opt4", "fgc_2:opt1", manhattan, { "bend_radius": br }), ("dc:opt3", "fgc_1:opt1", manhattan, { "bend_radius": br }), ] return connectors def _default_place_specs(self): place_specs = [ i3.Place("fgc_1:opt1", (0, 0)), i3.PlaceRelative("fgc_2:opt1", "fgc_1:opt1", (0.0, 120.0)), i3.PlaceRelative("fgc_3:opt1", "fgc_2:opt1", (0.0, 120.0)), i3.PlaceRelative("dc:opt1", "yb:opt2", (20.0, -40.0), angle=90), ] return place_specs def _default_external_port_names(self): epn = { "fgc_3:fib1": "in", "fgc_2:fib1": "out1", "fgc_1:fib1": "out2", } return epn
class 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 MZI_12_21(PlaceAndAutoRoute): _name_prefix = 'MZIs' #delay_length = i3.PositiveNumberProperty(default=132.0, doc="Delay length used in the mzi") delay_length = i3.PositiveNumberProperty(default=0.00001, doc="Delay length used in the mzi") R = i3.PositiveNumberProperty(default=200, doc="Radius of curvature") #MMI12_list = i3.ChildCellListProperty(default=[]) MMI12 = i3.ChildCellProperty(default=[]) MMI21_list = i3.ChildCellListProperty(default=[]) MMI22_list = i3.ChildCellListProperty(default=[]) #MZI_12_21_list = i3.ChildCellListProperty(default=[]) MZI_12_22_list = i3.ChildCellListProperty(default=[]) MZI_22_22_list = i3.ChildCellListProperty(default=[]) #MMI22_list = i3.ChildCellListProperty() wg_t = i3.TraceTemplateProperty(doc="trace template used") wg_t_MM = i3.TraceTemplateProperty(doc="Trace template used in the MM part") wg_t_port = i3.TraceTemplateProperty(doc="Trace template used in the ports") width_inc_vec = i3.ListProperty(default=[]) length_inc_vec = i3.ListProperty(default=[]) l_taper =i3.PositiveNumberProperty(default=200.0, doc="Length of the tapers") width=i3.PositiveNumberProperty(default=20.0, doc="width of MM") length_12 =i3.PositiveNumberProperty(default=110.0, doc="Length of MMI 1x2") length_22 =i3.PositiveNumberProperty(default=435.0, doc="Length of MMI 2x2") ts_12=i3.PositiveNumberProperty(default=11.25, doc="trace spacing") #ts for 12 is 7.0 --> MM=5 () L12=39.0 L22=158.0 #ts for 20 is 11 -->MM=9 (ts=11.25, MM=8.75) L12=110.0, L22=435.0 #ts for 30 is 16 -->MM=14 (ts=16.25, MM=13.75) L12=245.0, L22=980.0 chip_length = i3.PositiveNumberProperty(default=10000.0, doc="Radius of curvature") #chip_length = i3.PositiveNumberProperty(default=7100.0, doc="Radius of curvature") Port = i3.ChildCellProperty( doc="Used for ports") tlport = i3.PositiveNumberProperty(default=200.0, doc="Transition legth to ports") couplingWG = i3.ChildCellProperty(doc="", locked=True) couplingWG_l=i3.PositiveNumberProperty(default=3000.0, doc="Length of the coupling WG ") tt_port = i3.TraceTemplateProperty(doc="Wide trace template used for the contacts") tipo = i3.PositiveNumberProperty(default=1, doc="type of out-couplers tipo==1, straight, tipo==2, 90 degree bend") #template for Autorute def _default_trace_template(self): return self.wg_t def _default_wg_t_MM(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=self.width, cladding_width=self.width+2*8, ) return tt_w def _default_wg_t_port(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=8.75, cladding_width=8.75+2*8, ) return tt_w def _default_wg_t(self): tt_n = WireWaveguideTemplate() tt_n.Layout(core_width=3.3, cladding_width=3.3+2*8, ) return tt_n def _default_tt_port(self): tt_port = WireWaveguideTemplate() tt_port_layout=tt_port.Layout(core_width=15.0, cladding_width=15.0+2*8) return tt_port def _default_couplingWG(self): rect=i3.Waveguide(trace_template=self.tt_port) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.couplingWG_l,0.0)] ) return rect def _default_Port(self): Port=AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.wg_t) layout_Port = Port.Layout(transition_length=self.tlport)#.visualize(annotate=True) return Port def _default_MMI12(self): mmi12 = MMI1x2Tapered(mmi_trace_template=self.wg_t_MM, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t, name = 'MMI12_w_{}_L_{}'.format(self.width,self.length_12 ),) mmi12.Layout(transition_length=self.l_taper, length=self.length_12, trace_spacing=self.ts_12)#.visualize(annotate=True) return mmi12 ################################################################################# def _default_MMI22_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.length_inc_vec): print 'length number ' +str(l) print 'dl ' + str(dl) print 'MM length ' + str(self.length_22+dl) cell = MMI2x2Tapered(mmi_trace_template=self.wg_t_MM, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t , name = 'MMI22_w_'+str(self.width) +'_l_'+str(self.length_22+dl)) cell.Layout(transition_length=self.l_taper, length=self.length_22+dl, trace_spacing=self.ts_12) MMI22_list.append(cell) print 'cell name '+str(cell.name) print '__________________________' for w, dw in enumerate(self.width_inc_vec): MM_w=self.width+dw print 'width number ' +str(w) print 'dw ' + str(dw) print 'MM width ' + str(MM_w) wg_t_MM_w = WireWaveguideTemplate() wg_t_MM_w.Layout(core_width=MM_w, cladding_width=MM_w+2*8, ) cell = MMI2x2Tapered(mmi_trace_template=wg_t_MM_w, input_trace_template=self.wg_t_port, output_trace_template=self.wg_t_port, trace_template=self.wg_t, name = 'MMI22_w_'+str(self.width+dw) +'_l_'+str(self.length_22)) cell.Layout(transition_length=self.l_taper, length=self.length_22, trace_spacing=self.ts_12+dw)#.visualize(annotate=True) print cell MMI22_list.append(cell) print 'cell name '+str(cell.name) print '__________________________' print 'last MMI22 done' print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MMI22_list def _default_MZI_12_22_list(self): print '____________ MZI_1x2_2x2 ______________' MZI_12_22_list = [] counter=1 print '____________ MZI_1x2_2x2 list ______________' for i, m in enumerate(self.MMI22_list): print 'MZI number ' + str(counter) cell = MZIWaveguides(name='MZI_12_22:'+str(self.MMI12.name)+str(m.name), trace_template=self.wg_t, splitter=self.MMI12, combiner=m, splitter_port_names=['out1','out2'], combiner_port_names=['in1','in2']) cell.Layout(bend_radius=self.R, delay_length=self.delay_length)#.visualize(annotate=True) MZI_12_22_list.append(cell) counter=counter+1 print 'splitter '+ cell.splitter.name print 'combiner '+ cell.combiner.name print cell.name print '__________________________' print "Last MMI_12_22 done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MZI_12_22_list def _default_MZI_22_22_list(self): print '____________ MZI_2x2_2x2 ______________' MZI_22_22_list = [] counter=1 print '____________ MZI_2x2_2x2 list ______________' for i, m in enumerate(self.MMI22_list): print 'MZI number ' + str(counter) cell = MZIWaveguides(name='MZI_22_22:'+str(m.name), trace_template=self.wg_t, splitter=m, combiner=m, splitter_port_names=['out1','out2'], combiner_port_names=['in1','in2']) cell.Layout(bend_radius=self.R,delay_length=self.delay_length)#.visualize(annotate=True) MZI_22_22_list.append(cell) counter=counter+1 print 'splitter '+ cell.splitter.name print 'combiner '+ cell.combiner.name print cell.name print '__________________________' print "Last MMI_22_22 done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return MZI_22_22_list ################################################################################# def _default_child_cells(self): print '____________ Child cells ______________' child_cells = {} for counter, child in enumerate(self.MZI_22_22_list): print 'child number'+str(counter) child_cells['mzi_22_22_' + str(counter)] = child child_cells['InPort1_' + str(counter)] = self.Port child_cells['OutPort1_' + str(counter)]= self.Port child_cells['InPort2_' + str(counter)] = self.Port child_cells['OutPort2_' + str(counter)]= self.Port print 'child name ' +str(child.name) print child ################# for counter2, child in enumerate(self.MZI_12_22_list): print 'child number'+str(counter+1+counter2) child_cells['mzi_12_22_' + str(counter+1+counter2)] = child child_cells['InPort_' + str(counter+1+counter2)] = self.Port child_cells['OutPort1_' + str(counter+1+counter2)]= self.Port child_cells['OutPort2_' + str(counter+1+counter2)]= self.Port print 'child name ' +str(child.name) print child ################### print '__________________________' child_cells['InPortWG1'] = self.Port child_cells['OutPortWG1'] = self.Port child_cells['InPortWG2'] = self.Port child_cells['OutPortWG2'] = self.Port child_cells['InPortWG3'] = self.Port child_cells['OutPortWG3'] = self.Port print "Last child cell done" print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return child_cells def _default_links(self): links = [] for counter, child in enumerate(self.MZI_22_22_list): print counter in_port = "InPort1_{}:in".format(counter) print 'in_port', in_port out_port = 'mzi_22_22_{}:splitter_in1'.format(counter) print 'out_port', in_port links.append((in_port, out_port)) in_port = "InPort2_{}:in".format(counter) print 'in_port', in_port out_port = 'mzi_22_22_{}:splitter_in2'.format(counter) links.append((in_port, out_port)) out_port = "OutPort1_{}:in".format(counter) in_port = 'mzi_22_22_{}:combiner_out1'.format(counter) print 'in_port', in_port links.append((in_port, out_port)) out_port = "OutPort2_{}:in".format(counter) in_port = 'mzi_22_22_{}:combiner_out2'.format(counter) print 'in_port', in_port links.append((in_port, out_port)) for counter2, child in enumerate(self.MZI_12_22_list): out_port = "InPort_{}:in".format(counter+1+counter2) in_port = 'mzi_12_22_{}:splitter_in'.format(counter+1+counter2) links.append((in_port, out_port)) in_port = "OutPort1_{}:in".format(counter+1+counter2) out_port = 'mzi_12_22_{}:combiner_out1'.format(counter+1+counter2) links.append((in_port, out_port)) in_port = "OutPort2_{}:in".format(counter+1+counter2) out_port = 'mzi_12_22_{}:combiner_out2'.format(counter+1+counter2) links.append((in_port, out_port)) links.append(("InPortWG1:in", "OutPortWG1:in")) links.append(("InPortWG2:in", "OutPortWG2:in")) links.append(("InPortWG3:in", "OutPortWG3:in")) return links class Layout(PlaceAndAutoRoute.Layout): def _default_bend_radius(self): return self.R def _default_start_straight(self): return 1.0 print '____________ Layout mask ______________' def _default_child_transformations(self): d={} a=2.2 for counter, child in enumerate(self.MZI_22_22_list): if self.tipo==1: d['mzi_22_22_' + str(counter)] = i3.Translation(translation=((-1)**counter*2*self.R,counter*5*self.R)) d['InPort1_' + str(counter)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, counter*5*self.R-2.2*self.R)) d['OutPort1_' + str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5, counter*5*self.R-2.2*self.R)) d['InPort2_' + str(counter)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, counter*5*self.R+2.2*self.R)) d['OutPort2_' + str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5, counter*5*self.R+2.2*self.R)) print 'transformation ' +str(counter) + ' is ' +str(d) if self.tipo==2: #l_coupling=self.child_cells['Coupler'].l_coupling #radius=self.child_cells['Coupler'].local_bend_radius print 'R= ',self.R #print 'translation port: ' ##For w=20 d['mzi_22_22_' + str(counter)] = i3.Translation(translation=(counter*850+1200+1000+200,-counter*5*self.R)) d['InPort1_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter-a*self.R)) d['OutPort1_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+counter*50+counter*4*self.R+a*self.R-100, self.R*a)) d['InPort2_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter+a*self.R)) d['OutPort2_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+counter*50+counter*4*self.R-100, self.R*a)) d['InPortWG1'] = i3.HMirror()+i3.Translation(translation=(1500, 1000.0)) d['OutPortWG1']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5-500, self.R*a)) d['InPortWG2'] = i3.HMirror()+i3.Translation(translation=(1500, -3400+670)) d['OutPortWG2']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+2500, self.R*a)) d['InPortWG3'] = i3.HMirror()+i3.Translation(translation=(1500, -6500)) d['OutPortWG3']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+5600, self.R*a)) #d['mzi_22_22_' + str(counter)] = i3.Translation(translation=(counter*850+1200+1000+200,-counter*5*self.R)) #d['InPort1_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter-a*self.R)) #d['OutPort1_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1100+counter*50+counter*4*self.R+a*self.R-100, self.R*a)) #d['InPort2_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(1500, -5*self.R*counter+a*self.R)) #d['OutPort2_'+ str(counter)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1100+counter*50+counter*4*self.R-100, self.R*a)) #d['InPortWG1'] = i3.HMirror()+i3.Translation(translation=(1500, 1000.0)) #d['OutPortWG1']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5-500+1200, self.R*a)) #d['InPortWG2'] = i3.HMirror()+i3.Translation(translation=(1500, -3400+670)) #d['OutPortWG2']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+2500+1100, self.R*a)) #d['InPortWG3'] = i3.HMirror()+i3.Translation(translation=(1500, -6500)) #d['OutPortWG3']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+5600+1400, self.R*a)) ################ for counter2, child in enumerate(self.MZI_12_22_list): if self.tipo==1: d['mzi_12_22_' + str(counter+1+counter2)] = i3.Translation(translation=((-1)**counter2*2*self.R-self.length_22+counter*50+counter*4*self.R,(counter+1+counter2)*5*self.R)) d['InPort_' + str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.5, (counter+1+counter2)*5*self.R)) d['OutPort1_' + str(counter+1+counter2)]= i3.Translation(translation=(self.chip_length*0.5-self.bend_radius*counter*0.2-a*self.R-550, (counter+1+counter2)*5*self.R-2.2*self.R)) d['OutPort2_' + str(counter+1+counter2)]= i3.Translation(translation=(self.chip_length*0.5-self.bend_radius*counter*0.2-550, (counter+1+counter2)*5*self.R+2.2*self.R)) if self.tipo==2: #l_coupling=self.child_cells['Coupler'].l_coupling #radius=self.child_cells['Coupler'].local_bend_radius print 'R= ',self.R a=2.2 b=500 d['mzi_12_22_'+ str(counter+1+counter2)] = i3.Translation(translation=((counter+2+counter2)*850+1200+200+580,-(counter+1+counter2)*5*self.R-b)) d['InPort_'+ str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(1500, -(5*self.R)*(counter+1+counter2)-b)) d['OutPort1_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+(counter+1+counter2)*50+a*self.R+(counter+1+counter2)*4*self.R+b, self.R*a)) d['OutPort2_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+(counter+1+counter2)*50+(counter+1+counter2)*4*self.R+b,self.R*a)) #d['mzi_12_22_'+ str(counter+1+counter2)] = i3.Translation(translation=((counter+2+counter2)*850+1200+200+580+1000,-(counter+1+counter2)*5*self.R-b)) #d['InPort_'+ str(counter+1+counter2)] = i3.HMirror()+i3.Translation(translation=(1500, -(5*self.R)*(counter+1+counter2)-b)) #d['OutPort1_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1200+(counter+1+counter2)*50+a*self.R+(counter+1+counter2)*4*self.R+b, self.R*a)) #d['OutPort2_'+ str(counter+1+counter2)]= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+1200+(counter+1+counter2)*50+(counter+1+counter2)*4*self.R+b,self.R*a)) ################ print '__________________________' print "Last layout child cell done" print d print '_ _ _ _ _ _ _ _ _ _ _ _ _ ' return d def _generate_elements(self, elems): for counter, child in enumerate(self.MZI_22_22_list): name=child.name print name elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), coordinate=(0.0, -counter*5*self.R+2*self.R-50.0#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}_R={}_delay={}'.format(name, self.R, self.delay_length), coordinate=(0.0, -counter*5*self.R-2*self.R+50.0#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) for counter2, child in enumerate(self.MZI_12_22_list): name=child.name print name elems += i3.PolygonText(layer= i3.TECH.PPLAYER.WG.TEXT, text='Name={}'.format(name), coordinate=(0.0, -(counter+1+counter2)*5*self.R-90.0-500#-100 ), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font = 2, height=20.0) return elems
class my_dc(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2x2Tapered( mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.trace_template, ) cell.Layout(name="MMI22_l_{}".format(str(self.gap_inc_vec[l])), transition_length=200.0, length=self.gap_inc_vec[l], trace_spacing=11.0) # cell = RingRectSymm180DropFilter(name='ring' + str(dl) + str(self.length), # ring_trace_template=self.trace_template) # cell.Layout(bend_radius=200, # coupler_lengths=[self.length, self.length], # coupler_radii=[300.0, 300.0], # coupler_angles=[90.0, 90.0], # coupler_spacings=[3.8 + self.gap_inc_vec[l], 3.8 + self.gap_inc_vec[l]], # straights=(self.length, 0.0), # # manhattan=True, # ) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 12, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:in2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:out2"), ("taper3:out", "ring0:out1"), ("taper4:out", "ring1:in2"), ("taper5:out", "ring1:in1"), ("taper6:out", "ring1:out2"), ("taper7:out", "ring1:out1"), ("taper8:out", "ring2:in2"), ("taper9:out", "ring2:in1"), ("taper10:out", "ring2:out2"), ("taper11:out", "ring2:out1"), # ("taper12:out", "ring3:out2"), # ("taper13:out", "ring3:in1"), # ("taper14:out", "ring3:in2"), # ("taper15:out", "ring3:out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 10000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (2500, 0) trans['ring1'] = (2500, 0 + column) trans['ring2'] = (2500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 4000) trans["taper1"] = (0, -4000) trans["taper2"] = i3.HMirror(0) + i3.Translation((5000, 2500)) trans["taper3"] = i3.HMirror(0) + i3.Translation((5000, -2500)) trans["taper4"] = (0, 4000 + column) trans["taper5"] = (0, -4000 + column) trans["taper6"] = i3.HMirror(0) + i3.Translation( (5000, 2500 + column)) trans["taper7"] = i3.HMirror(0) + i3.Translation( (5000, -2500 + column)) trans["taper8"] = (0, 4000 + 2 * column) trans["taper9"] = (0, -4000 + 2 * column) trans["taper10"] = i3.HMirror(0) + i3.Translation( (5000, 2500 + 2 * column)) trans["taper11"] = i3.HMirror(0) + i3.Translation( (5000, -2500 + 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius # def _generate_elements(self, elems): # # # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.mmi22.get_default_view(i3.LayoutView).name, # self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0) # # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text='Name={}_{}'.format(self.cell.mmi22.get_default_view(i3.LayoutView).name, # self.cell.wg_t1.name), # coordinate=(-2000.0, -150.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=200.0, # transformation=i3.Rotation((0.0, 0.0), 90.0)) # # return elems def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0, transformation=i3.Translation( (2500, 100 + 10000 * counter))) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(-2000, -150), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=200.0, transformation=i3.Rotation( (0.0, 0.0), 90.0) + i3.Translation( (450, -2000 + 10000 * counter))) return elems
class my_dc(PlaceAndAutoRoute): # dc = i3.ChildCellProperty() # dc2 = i3.ChildCellProperty() DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="gap") length = i3.PositiveNumberProperty(default=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_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 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 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 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 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 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 Spirals(PlaceAndAutoRoute): _name_prefix = 'LSpiral' tipo = i3.PositiveNumberProperty(doc="Number loops", default=1) waveguide_template = i3.DefinitionProperty(doc="Trace template used") R = i3.PositiveNumberProperty(default=200, doc="Radius of curvature") spacing = i3.PositiveNumberProperty(default=100, doc="Radius of curvature") n_loops = i3.IntProperty(doc="Number loops", default=2) n_loops_vec = i3.ListProperty(default=[4, 8]) s_length_vec = i3.ListProperty(default=[0.0]) Spiral_list = i3.ChildCellListProperty( doc="List containing the 90 degree angle child cells") #chip_length = i3.PositiveNumberProperty(default=2500.0, doc="Radius of curvature") chip_length = i3.PositiveNumberProperty(default=3000.0, doc="Radius of curvature") Port = i3.ChildCellProperty(doc="Used for ports") Port2 = i3.ChildCellProperty(doc="Used for ports") tlport = i3.PositiveNumberProperty(default=1000.0, doc="Transition legth to ports") couplingWG = i3.ChildCellProperty(doc="", locked=True) couplingWG_l = i3.PositiveNumberProperty(default=5000.0, doc="Length of the coupling WG ") tt_port = i3.TraceTemplateProperty( doc="Wide trace template used for the contacts") tt_port2 = i3.TraceTemplateProperty( doc="Wide trace template used for the contacts") #width_vec = i3.ListProperty(default=[1]) n = i3.PositiveNumberProperty(default=1, doc="") width = i3.PositiveNumberProperty(default=1, doc="") lengths = i3.PositiveNumberProperty(default=1, doc="") def _default_lengths(self): for counter, cell in enumerate(self.s_length_vec): numero = counter + 1 return numero #template for Autorute def _default_trace_template(self): return self.waveguide_template def _default_tt(self): return self.waveguide_template def _default_tt_port(self): tt_port = WireWaveguideTemplate() tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0) return tt_port def _default_tt_port2(self): tt_port = WireWaveguideTemplate() tt_port_layout = tt_port.Layout(core_width=10.0, cladding_width=10.0) return tt_port def _default_Spiral_list(self): Spiral_list = [] # empty list print ' I am in _Spiral_list' for l, length in enumerate(self.s_length_vec): loops = 1 print length cell = FixedLengthSpiralRounded( trace_template=self.waveguide_template, #total_length=length-self.chip_length, total_length=length, n_o_loops=loops, name=self.name + '_Spiral_' + str(l)) cell.Layout( incoupling_length=0, bend_radius=self.R, spacing=self.spacing, stub_direction="H", growth_direction="H", ) #.visualize(annotate=True) print 'The legth of the spiral is: ', cell.total_length print 'Cell: ', cell.name Spiral_list.append(cell) return Spiral_list def _default_couplingWG(self): rect = i3.Waveguide(trace_template=self.tt_port) layout_rect = rect.Layout(shape=[(0.0, 0.0), (self.couplingWG_l, 0.0)]) return rect def _default_Port(self): Port = AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout( transition_length=self.tlport) #.visualize(annotate=True) return Port def _default_Port2(self): Port = AutoTransitionPorts(contents=self.couplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout( transition_length=self.tlport) #.visualize(annotate=True) return Port def _default_child_cells(self): child_cells = { } # First we define the property "child_cells" as an empty dictionary for counter, spiral in enumerate( self.Spiral_list ): # the iteration starts in the first element of the list and follows element by element to the last element. child_cells['Spiral{}'.format(counter)] = spiral print spiral print 'name of spiral:', spiral.name child_cells['InPort' + str(counter)] = self.Port child_cells['OutPort' + str(counter)] = self.Port print 'child_cells:', child_cells return child_cells def _default_links(self): links = [] for counter, spiral in enumerate(self.Spiral_list): print counter in_port = "Spiral{}:in".format(counter) out_port = "InPort{}:in".format(counter) links.append((in_port, out_port)) in_port = "Spiral{}:out".format(counter) out_port = "OutPort{}:in".format(counter) links.append((in_port, out_port)) return links class Layout(PlaceAndAutoRoute.Layout): #tipo=1 def _default_bend_radius(self): return self.R def _default_child_transformations(self): d = {} for counter, child in enumerate(self.Spiral_list): ip = child.ports["in"].position #print self.child_cells['InPort' + str(counter)].ports["out"].position #print self.child_cells['OutPort' + str(counter)].ports.position print '----------------' print 'spiral length:', child.total_length print 'counter: ', counter #print ip op = child.ports["out"].position #print op print 'The lateral size of the spiral is', op[0] - ip[0] print 'The type of mask is: ', self.tipo print 'The number of widths is: ', self.n print 'The number of lengths is: ', self.lengths print 'The width number is: ', self.width print '----------------' iz = child.inner_size sx = iz[1] + 200 #sx=1200 if self.tipo == 1: d['Spiral' + str(counter)] = i3.Translation( translation=(-(op[0] - ip[0]) / 2, self.n * counter * sx)) d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length / 2.0 - self.couplingWG_l, self.n * counter * sx)) d['OutPort' + str(counter)] = i3.Translation( translation=(self.chip_length / 2.0 + self.couplingWG_l, self.n * counter * sx)) if self.tipo == 2: d['Spiral' + str(counter)] = i3.Translation( translation=(-(op[0] - ip[0]) / 2, -(self.n + 0.5) * counter * sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4)-self.couplingWG_l, -(self.n+0.5)*counter*sx)) #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R+(((self.n+0.5)*counter+self.width)*sx/4), self.chip_length*(3/4)+(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx)) d['InPort' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * (1 / 2) - 2000, -(self.n + 0.5) * counter * sx)) d['OutPort' + str(counter)] = i3.Rotation( rotation=90) + i3.Translation(translation=( (op[0] - ip[0]) / 2 + 2 * self.R + (((self.n + 0.5) * counter + self.width) * sx / 4), 3000 + self.chip_length * (3 / 4) + (self.width + counter - (((counter + 1) - 1.0) % self.lengths)) * sx)) #For awg's #if self.tipo==2: #d['Spiral' + str(counter)] = i3.Translation(translation=(-(op[0]-ip[0])/2, -(self.n+0.5)*counter*sx)) #d['InPort' + str(counter)] = i3.HMirror()+ i3.Translation(translation=(-self.chip_length*(3/4.0), -(self.n+0.5)*counter*sx)) #d['OutPort' + str(counter)] = i3.Rotation(rotation=90) + i3.Translation(translation=((op[0]-ip[0])/2+2*self.R #+(((self.n+0.5)*counter+self.width)*sx/100.0) #, self.chip_length*(2/4.0)+ #(self.width+counter-(((counter+1)-1.0)%self.lengths))*sx)) return d # Fabio's addition def _generate_elements(self, elems): # We calculate the lengths of the 2 spirals in this pcell. # Note that we assume that there are exactly 2 spirals in this list. #assert len(self.Spiral_list) == 2 lengths = get_lengths(self) iz = self.Spiral_list[0].inner_size sx = iz[1] + 200 for counter, (child, length) in enumerate(zip(self.Spiral_list, lengths)): ip = child.ports["in"].position op = child.ports["out"].position width = child.ports["in"].trace_template.core_width #print 'child.ports["in"].trace_template.core_width: ', child.ports["in"].trace_template.core_width #i3.TECH.PPLAYER.NONE.LOGOTXT when using isipp50g if self.tipo == 2: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}_Length={}_R={}'.format( width, length, self.R), coordinate=((op[0] - ip[0]) / 2 - 1000.0, (self.n + 0.5) * counter * sx - 50.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) if self.tipo == 1: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text='Width={}_Length={}_R={}'.format( width, length, self.R), coordinate=(-(op[0] - ip[0]) / 2 - 1000.0, -(self.n + 0.5) * counter * sx - 50.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=20.0) return elems
class 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_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 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 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 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 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