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 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 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) 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='R={}_width={}'.format(str(dl), str(self.sm_width)), trace_template=self.trace_template, n_o_loops=8, ) layout = cell.Layout( angle_step=30, inner_size=[1400, 700], bend_radius=self.gap_inc_vec[l], manhattan=False, spacing=2 * 8 + self.sm_width + 5, stub_direction="V", ) print "{}_length={}".format(str(cell.name), str(layout.trace_length())) # print cell.name # print layout.trace_length() MMI22_list.append(cell) return MMI22_list 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 # 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", "ring2:in"), ("taper5:out", "ring2:out"), ("taper6:out", "ring3:in"), ("taper7:out", "ring3:out"), # ("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 = 3500 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1300, -2400) # trans['ring1'] = i3.VMirror(0) + i3.Translation((1300, 2000)) trans['ring1'] = (1300 + column, -2400) trans['ring2'] = (1300 + 2 * column, -2400) trans['ring3'] = (1300 + 3 * column, -2400) trans["taper0"] = (0, -4000) trans["taper1"] = i3.HMirror(0) + i3.Translation((column, -3500)) trans["taper2"] = (0 + column, -3500) trans["taper3"] = i3.HMirror(0) + i3.Translation( (2 * column, -4000)) trans["taper4"] = (0 + 2 * column, -4000) trans["taper5"] = i3.HMirror(0) + i3.Translation( (3 * column, -3500)) trans["taper6"] = (0 + 3 * column, -3500) trans["taper7"] = i3.HMirror(0) + i3.Translation( (4 * column, -4000)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius # def _default_start_straight(self): # end_straight = 10 # return end_straight def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name # aa = child.layout.trace_length() elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(name), # coordinate=(4650.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=150.0, transformation=i3.Translation( (300 + 3500 * counter, -3200))) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, # center=(0, 0), # box_size=(500, 300)) return elems
class my_dc(PlaceAndAutoRoute): # dc = i3.ChildCellProperty() # dc2 = i3.ChildCellProperty() DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="gap") length = i3.PositiveNumberProperty(default=80.0, doc="Length of coupler") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty() # wg_dc2 = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) # start_id = i3.PositiveNumberProperty(doc="name_id", default=1) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 16, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 16.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = RingRectSymm180DropFilter( name='SR_GAP={}_L={}'.format(str(dl), str(self.length)), ring_trace_template=self.trace_template) cell.Layout( bend_radius=200, coupler_lengths=[self.length, self.length], coupler_radii=[300.0, 300.0], coupler_angles=[90.0, 90.0], coupler_spacings=[ 3.8 + self.gap_inc_vec[l], 3.8 + self.gap_inc_vec[l] ], straights=(self.length, 0.0), # manhattan=True, ) cell2 = RingRectSymmNotchFilter( name='ring_s' + str(dl) + str(self.length), ring_trace_template=self.trace_template) cell2.Layout( bend_radius=200, coupler_lengths=[self.length, self.length], coupler_radii=[300, 300], coupler_angles=[90.0, 90], coupler_spacings=[(3.8 + self.gap_inc_vec[l])], straights=(self.length, 0.0), # manhattan=True, ) MMI22_list.append(cell) MMI22_list.append(cell2) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 24, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 # child_cells["dircoup1"] = self.dc # child_cells["dircoup2"] = self.dc2 # child_cells["straight"] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:out2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:in2"), ("taper3:out", "ring0:out1"), ("taper4:out", "ring1:in"), ("taper5:out", "ring1:out"), ("taper6:out", "ring2:out2"), ("taper7:out", "ring2:in1"), ("taper8:out", "ring2:in2"), ("taper9:out", "ring2:out1"), ("taper10:out", "ring3:in"), ("taper11:out", "ring3:out"), ("taper12:out", "ring4:out2"), ("taper13:out", "ring4:in1"), ("taper14:out", "ring4:in2"), ("taper15:out", "ring4:out1"), ("taper16:out", "ring5:in"), ("taper17:out", "ring5:out"), ("taper18:out", "ring6:out2"), ("taper19:out", "ring6:in1"), ("taper20:out", "ring6:in2"), ("taper21:out", "ring6:out1"), ("taper22:out", "ring7:in"), ("taper23:out", "ring7:out"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 4500 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1500, -3000) trans['ring4'] = (1500, -3000 + 2 * column) trans['ring1'] = (1500, -300) trans['ring5'] = (1500, -300 + 2 * column) trans['ring2'] = (1500, -3000 + column) trans['ring6'] = (1500, -3000 + 3 * column) trans['ring3'] = (1500, -300 + column) trans['ring7'] = (1500, -300 + 3 * column) trans["taper0"] = (0, -2100) trans["taper1"] = (0, -3850) trans["taper2"] = i3.HMirror(0) + i3.Translation((3000, -1500)) trans["taper3"] = i3.Translation((0, -4000)) trans["taper4"] = (0, -1950) trans["taper5"] = i3.HMirror(0) + i3.Translation((3000, -1350)) trans["taper6"] = (0, -2100 + column) trans["taper7"] = (0, -3850 + column) trans["taper8"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + column)) trans["taper9"] = i3.Translation((0, -4000 + column)) trans["taper10"] = (0, -1950 + column) trans["taper11"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + column)) trans["taper12"] = (0, -2100 + 2 * column) trans["taper13"] = (0, -3850 + 2 * column) trans["taper14"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + 2 * column)) trans["taper15"] = i3.Translation((0, -4000 + 2 * column)) trans["taper16"] = (0, -1950 + 2 * column) trans["taper17"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + 2 * column)) trans["taper18"] = (0, -2100 + 3 * column) trans["taper19"] = (0, -3850 + 3 * column) trans["taper20"] = i3.HMirror(0) + i3.Translation( (3000, -1500 + 3 * column)) trans["taper21"] = i3.Translation((0, -4000 + 3 * column)) trans["taper22"] = (0, -1950 + 3 * column) trans["taper23"] = i3.HMirror(0) + i3.Translation( (3000, -1350 + 3 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): if (counter % 2 == 0): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(name[0:10]), # coordinate=(4650.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=200.0, transformation=i3.Rotation( (0.0, 0.0), -90.0) + i3.Translation( (3000 - 450, -2000 + 4500 * counter / 2))) else: elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="R=200_L=80", alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=80.0, transformation=i3.Rotation( (0.0, 0.0), -90.0) + i3.Translation( (3000 - 450, -2700 + 4500 * counter / 2))) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, # center=(0, 0), # box_size=(500, 300)) return elems
class my_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 MZI_12_21(PlaceAndAutoRoute): _name_prefix = 'MZIs' delay_length = i3.PositiveNumberProperty( default=132.0, 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, MM8.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") 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=(-self.chip_length * 0.1, -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.couplingWG_l + self.R * a)) d['InPort2_' + str(counter)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * 0.1, -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.couplingWG_l + self.R * a)) d['InPortWG1'] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * 0.1, 1000.0)) d['OutPortWG1'] = i3.Rotation(rotation=90.0) + i3.Translation( translation=(self.chip_length * 0.5 - 500, self.couplingWG_l + self.R * a)) d['InPortWG2'] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * 0.1, -3400 + 670)) d['OutPortWG2'] = i3.Rotation(rotation=90.0) + i3.Translation( translation=(self.chip_length * 0.5 + 2500, self.couplingWG_l + self.R * a)) d['InPortWG3'] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * 0.1, -6500)) d['OutPortWG3'] = i3.Rotation(rotation=90.0) + i3.Translation( translation=(self.chip_length * 0.5 + 5600, self.couplingWG_l + self.R * a)) ###for w=30 #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=(-self.chip_length*0.1, -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.couplingWG_l+self.R*a)) #d['InPort2_'+ str(counter)] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.1, -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.couplingWG_l+self.R*a)) #d['InPortWG1'] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.1, 1000.0)) #d['OutPortWG1']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5-500+1200, self.couplingWG_l+self.R*a)) #d['InPortWG2'] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.1, -3400+670)) #d['OutPortWG2']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+2500+1100, self.couplingWG_l+self.R*a)) #d['InPortWG3'] = i3.HMirror()+i3.Translation(translation=(-self.chip_length*0.1, -6500)) #d['OutPortWG3']= i3.Rotation(rotation=90.0)+i3.Translation(translation=(self.chip_length*0.5+5600+1400, self.couplingWG_l+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 + 500, -(counter + 1 + counter2) * 5 * self.R - b)) d['InPort_' + str(counter + 1 + counter2)] = i3.HMirror() + i3.Translation( translation=(-self.chip_length * 0.1, -(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.couplingWG_l + 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.couplingWG_l + 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=(-self.chip_length*0.1, -(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.couplingWG_l+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.couplingWG_l+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 GratingCoupler1Band(PlaceComponents): core=i3.PositiveNumberProperty(default=3.3, doc="core width") period=i3.PositiveNumberProperty(default=2.566, doc="core width") duty=i3.PositiveNumberProperty(default=0.403, doc="core width") nperiods=i3.PositiveNumberProperty(default=7, doc="core width") wg_coupler= i3.TraceTemplateProperty(doc="Wide trace template used") #FGC= i3.ChildCellProperty(doc="grating used") ctipo=i3.PositiveNumberProperty(default=1, doc="type of coupler used ctipo=1 for grating and ctipo=2 for taper") coupling_l=i3.PositiveNumberProperty(default=5000, doc="length of coupling WG") coupler_template= i3.TraceTemplateProperty(doc="Wide trace template used for coupler tipo2") waveguide_template= i3.TraceTemplateProperty(doc="Wide trace template used on routing") coupling_w = i3.PositiveNumberProperty(default=20, doc="width of the coupling WG") transition_length_coupler=i3.PositiveNumberProperty(default=300, doc="transition length of the coupler") Grating_list = i3.ChildCellListProperty(doc="List containing the non etched parts of gratings") inPort = i3.ChildCellProperty( doc="Used for ports") outPort = i3.ChildCellProperty( doc="Used for ports") incouplingWG = i3.ChildCellProperty( doc="Used for ports") outcouplingWG = i3.ChildCellProperty( doc="Used for ports") chirp=i3.NumberProperty(default=1, doc="1=chirped") socket_length=i3.PositiveNumberProperty(default=2.2, doc="length of coupling WG") layName = i3.StringProperty(default = 'waveguide') layNameg = i3.StringProperty(default = 'metal') print 'the name of the layer is', layName props = i3.DictProperty() def _default_props(self): return AssignProcess(self.layName) propsg = i3.DictProperty() def _default_propsg(self): return AssignProcess(self.layNameg) Lo = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam Le = i3.ListProperty(default=[]) #Etched part Loc = i3.ListProperty(default=[]) #Non etched part, illuminated during e-beam Lec = i3.ListProperty(default=[]) #Etched part #def _default_transition_length(self): #return self.transition_length_coupler def _default_socket_length(self): a=sum(self.Lo)+sum(self.Le) #if self.chirp==1: #A=a=self.period * int(self.nperiods)+sum(self.Loc)) return a def _default_Loc(self): #Loc=[2.175,2.122,2.07,2.016,1.963,1.908,1.854,1.798,1.743,1.687,1.63,1.573, #1.515,1.457,1.398,1.339,1.279,1.219,1.158,1.096] Loc=self.Loc Loc.reverse() return Loc def _default_Lec(self): #Lec=[0.242,0.301,0.361,0.421,0.482,0.543,0.605,0.667,0.73,0.794,0.858,0.922, #0.988,1.054,1.12,1.187,1.255,1.323,1.392,1.462] Lec=self.Lec Lec.reverse() return Lec def _default_Lo(self): A=[None] * int(self.nperiods) if self.chirp==1: A=[None] * int(self.nperiods+len(self.Loc)) for x in range(0,int(self.nperiods)): A[x]=self.period*self.duty if self.chirp==1: for x in range(0,int(len(self.Loc))): print x print len(self.Loc) A[int(self.nperiods)+x]=self.Loc[x] print 'Lo: ',A return A def _default_Le(self): Le=[None] * int(self.nperiods) if self.chirp==1: Le=[None] * int(self.nperiods+len(self.Loc)) for x in range(0,int(self.nperiods)): Le[x]=self.period*(1-self.duty) if self.chirp==1: for x in range(0,int(len(self.Loc))): Le[int(self.nperiods)+x]=self.Lec[x] print 'Le: ',Le return Le def _default_Grating_list(self): Grating_list = [] for x in range(0,int(len(self.Lo))): #rect=i3.Waveguide(trace_template=self.wg_coupler) rect=i3.Waveguide(trace_template=self.coupler_template) #layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.Lo[x],0.0)])#.visualize(annotate=True) Grating_list.append(rect) return Grating_list def _default_incouplingWG(self): rect=i3.Waveguide(trace_template=self.wg_coupler) layout_rect = rect.Layout(shape=[(0.0, 0.0),(self.coupling_l,0.0)] ) return rect def _default_outcouplingWG(self): rect=i3.Waveguide(trace_template=self.wg_coupler) layout_rect = rect.Layout(shape=[(0.0, 0.0),(50+self.socket_length,0.0)] ) return rect def _default_inPort(self): Port=AutoTransitionPorts(contents=self.incouplingWG, port_labels=["in"], trace_template=self.waveguide_template) layout_Port = Port.Layout(transition_length=self.transition_length_coupler)#.visualize(annotate=True) return Port def _default_outPort(self): Port=AutoTransitionPorts(contents=self.outcouplingWG, port_labels=["in"], trace_template=self.wg_coupler) layout_Port = Port.Layout(transition_length=10)#.visualize(annotate=True) return Port def _default_child_cells(self): child_cells = {} # First we define the property "child_cells" as an empty dictionary for counter, pillar in enumerate(self.Grating_list): child_cells['pillar{}'.format(counter)] = pillar print pillar print 'name of pillar:', pillar.name child_cells['InPort'] = self.inPort child_cells['OutPort']= self.outPort print 'child_cells:', child_cells return child_cells def _default_props(self): return AssignProcess(self.layName) def _default_wg_coupler(self): wg_coupler = WireWaveguideTemplate() wg_coupler.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w+2*8, **self.props) return wg_coupler def _default_waveguide_template(self): wg_t = WireWaveguideTemplate() wg_t_layout=wg_t.Layout(core_width=self.core, cladding_width=self.core+2*8, **self.props) return wg_t def _default_coupler_template(self): wg_t = WireWaveguideTemplate() wg_t_layout=wg_t.Layout(core_width=self.coupling_w, cladding_width=self.coupling_w, **self.propsg) return wg_t def _default_trace_template(self): return self.waveguide_template def _default_contents(self): return self.FGC def _default_port_labels(self): return ["out"] class Layout(PlaceComponents.Layout): #def _default_transition_length(self): #return self.transition_length_coupler def _default_child_transformations(self): d={} position=0 for counter, child in enumerate(self.Grating_list): d['pillar{}'.format(counter)] = i3.Translation(translation=(position, 0.0)) position=position+self.Lo[counter]+self.Le[counter] print 'pillar position: ', position print 'counter= ', counter print 'Lo: ', self.Lo[counter] print 'Le: ', self.Le[counter] #d['InPort'] = i3.HMirror()+ i3.Translation(translation=(position+10,0)) d['InPort'] = i3.HMirror()+ i3.Translation(translation=(self.coupling_l+self.socket_length,0)) d['OutPort'] = i3.Translation(translation=(-50,0.0)) return d
class Bent_Coupler_Symm(i3.PCell): """ A coupler with symmetric bends on each of the ports. Used with generic PCell """ _name_prefix = "Bent_Coupler_Symm" # defining MMI as child cell with input and output waveguides coupler = i3.ChildCellProperty(restriction=i3.RestrictType(i3.PCell)) # define waveguide template and waveguide cells # for the access bent waveguides connected to the straight couple ## add another waveguide template # coupler_length = i3.PositiveNumberProperty(default=i3.TECH.WG.SHORT_STRAIGHT, # doc="length of the directional coupler") wg_template1 = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) wg_template2 = i3.WaveguideTemplateProperty( default=i3.TECH.PCELLS.WG.DEFAULT) # wg_template = i3.WaveguideTemplateProperty(default=i3.TECH.PCELLS.WG.DEFAULT) wgs = i3.ChildCellListProperty(doc="list of waveguides") def _default_wg_template2(self): return self.wg_template1 # define default coupler for class # a straight directional coupler by default # can also insert a tapered MMI by assigning a MMI PCell ### pass the templates for the directional coupler def _default_coupler(self): ### waveguide templates for DC must be defined in this instantiance ### otherwise trace_template1 and trace_template2 will be set bundled to be equal coupler = StraightDirectionalCoupler( name=self.name + "_dir_coup", coupler_length=self.coupler_length) return coupler # define rounded waveguides for the inputs and outputs ## can consider for loop tp reduce the code length def _default_wgs(self): wgs = [] name_list = ["_wg_in1", "_wg_in2", "_wg_out1", "_wg_out2"] template_list = [ self.wg_template1, self.wg_template2, self.wg_template1, self.wg_template2 ] for idx, name in enumerate(name_list): wg = i3.RoundedWaveguide(name=self.name + name_list[idx], trace_template=template_list[idx]) wgs.append(wg) return wgs class Layout(i3.LayoutView): # specified parameters used for layout purposes ## coupling spacing? ## move to the coupler level bend_radius = i3.PositiveNumberProperty( default=10., doc="bend radius of 90 degree bends") in1_offset = i3.PositiveNumberProperty( default=10., doc="offset between 90 degree bends input 1") in2_offset = i3.PositiveNumberProperty( default=10., doc="offset between 90 degree bends input 2") out1_offset = i3.PositiveNumberProperty( default=1., doc="offset between 90 degree bends output 1") out2_offset = i3.PositiveNumberProperty( default=1., doc="offset between 90 degree bends output 2") rounding_algorithm = DefinitionProperty( default=ShapeRound, doc="rounding algorithm for every individual bend") # define default of tapered MMI child cell def _default_coupler(self): ### error to be corrected. the Child Layout view needs to point to coupler first, end get the default view # wg_template1 = self.wg_template1 coupler = self.cell.coupler.get_default_view( i3.LayoutView) # Retrieve layout view following examples ### go to upper level then to define the waveguide template, as the waveguide template of DC is NOT ### defined in layout level # self.cell.coupler.trace_template1 = self.wg_template1 # self.cell.coupler.trace_template2 = self.wg_template2 return coupler # grabbing properties of child cell and setting appropriate transforms, by default do none def _get_components(self): coupler = i3.SRef(reference=self.coupler, name="coupler") return coupler # setting the output shape of the access waveguides using a shape defined by ports from MMI (hopefully..) def _default_wgs(self): # bring in parts from rest of PCell Layout, used to grab positions coupler = self._get_components() ## wgcell ? for loop operation wg_in1_cell, wg_in2_cell, wg_out1_cell, wg_out2_cell = self.cell.wgs wg_template1 = self.wg_template1 wg_template2 = self.wg_template2 bend_radius = self.bend_radius # setting variable for round_alg = self.rounding_algorithm # defining bottom left waveguide, using port from MMI and bus length wg_in1_layout = wg_in1_cell.get_default_view(i3.LayoutView) in1_port_pos = coupler.ports["in1"].position in1_shape = [ in1_port_pos, (in1_port_pos[0] - bend_radius, in1_port_pos[1]), (in1_port_pos[0] - bend_radius, in1_port_pos[1] - 2. * bend_radius - self.in1_offset), (in1_port_pos[0] - 2. * bend_radius, in1_port_pos[1] - 2. * bend_radius - self.in1_offset) ] wg_in1_layout.set(trace_template=wg_template1, shape=in1_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # repeat above for other ports, first in2 wg_in2_layout = wg_in2_cell.get_default_view(i3.LayoutView) in2_port_pos = coupler.ports["in2"].position in2_shape = [ in2_port_pos, (in2_port_pos[0] - bend_radius, in2_port_pos[1]), (in2_port_pos[0] - bend_radius, in2_port_pos[1] + 2. * bend_radius + self.in2_offset), (in2_port_pos[0] - 2. * bend_radius, in2_port_pos[1] + 2. * bend_radius + self.in2_offset) ] wg_in2_layout.set(trace_template=wg_template2, shape=in2_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # out1 wg_out1_layout = wg_out1_cell.get_default_view(i3.LayoutView) out1_port_pos = coupler.ports["out1"].position out1_shape = [ out1_port_pos, (out1_port_pos[0] + bend_radius, out1_port_pos[1]), (out1_port_pos[0] + bend_radius, out1_port_pos[1] - 2. * bend_radius - self.out1_offset), (out1_port_pos[0] + 2. * bend_radius, out1_port_pos[1] - 2. * bend_radius - self.out1_offset) ] wg_out1_layout.set(trace_template=wg_template1, shape=out1_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # and out2 wg_out2_layout = wg_out2_cell.get_default_view(i3.LayoutView) out2_port_pos = coupler.ports["out2"].position out2_shape = [ out2_port_pos, (out2_port_pos[0] + bend_radius, out2_port_pos[1]), (out2_port_pos[0] + bend_radius, out2_port_pos[1] + 2. * bend_radius + self.out2_offset), (out2_port_pos[0] + 2. * bend_radius, out2_port_pos[1] + 2. * bend_radius + self.out2_offset) ] wg_out2_layout.set(trace_template=wg_template2, shape=out2_shape, rounding_algorithm=round_alg, bend_radius=bend_radius, manhattan=True) # returning layouts return wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout def _generate_instances(self, insts): # includes the get components and the new waveguides insts += self._get_components() wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout = self.wgs insts += i3.SRef(reference=wg_in1_layout, name="wg_in1") insts += i3.SRef(reference=wg_in2_layout, name="wg_in2") insts += i3.SRef(reference=wg_out1_layout, name="wg_out1") insts += i3.SRef(reference=wg_out2_layout, name="wg_out2") return insts def _generate_ports(self, prts): # use output ports of all waveguides as I define shapes from the base of the coupler structure outwards instances = self.instances prts += instances["wg_in1"].ports["out"].modified_copy(name="in1") prts += instances["wg_in2"].ports["out"].modified_copy(name="in2") prts += instances["wg_out1"].ports["out"].modified_copy( name="out1") prts += instances["wg_out2"].ports["out"].modified_copy( name="out2") return prts ### an simple example to use Ben_Coupler_Symm class @i3.example_plot() def __example_layout(self): from technologies import silicon_photonics from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate import ipkiss3.all as i3 import numpy as np from euler_rounding_algorithm import Euler90Algorithm from SplittersAndCascades import Bent_Coupler_Symm # set waveguide templates for # the north waveguide (wg_t1) # and the south waveguide (wg_t2) wg_t1 = WireWaveguideTemplate(name="south_arm") wg_t1.Layout(core_width=2.400, cladding_width=i3.TECH.WG.CLADDING_WIDTH, core_process=i3.TECH.PROCESS.WG) wg_t2 = WireWaveguideTemplate(name="north arm") wg_t2.Layout(core_width=1.500, cladding_width=i3.TECH.WG.CLADDING_WIDTH, core_process=i3.TECH.PROCESS.WG) # set the directional coupler (can also be MMI) # and then pass it as an child PCell to Bend_Coupler PCell C = Bent_Coupler_Symmr(name="my_dircoup_2", trace_template1=wg_t1, trace_template2=wg_t2, coupler_length=20.0) layout = C.Layout(bend_radius=10.0, straight_after_bend=6.0, bend_angle=60.0) layout.visualize()
class my_exe2(PlaceComponents): DC_list = i3.ChildCellListProperty(default=[]) def _default_DC_list(self): MMI22_list = [] dc1_15 = my_dc(gap_inc_vec2=[110.0, 110.0, 110.0], name="ring1") dc2_15 = my_dc(gap_inc_vec2=[110.0, 110.0, 110.0], name="ring2") MMI22_list.append(dc1_15) MMI22_list.append(dc2_15) dc1_20 = my_dc(gap_inc_vec2=[100.0, 110.0, 120.0], name="ring3", width=20, cleave=250) dc2_20 = my_dc(gap_inc_vec2=[100.0, 110.0, 120.0], name="ring4", width=20, cleave=250) recess0 = NP_mmi12(pillar=True, pocket=False, tilt=False, width=133.0, length=210) recess1 = NP_mmi12(pillar=True, pocket=False, tilt=False, width=133.0, length=210) recess2 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess3 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess4 = NP_mmi12(pillar=True, pocket=True, tilt=False) recess5 = NP_mmi12(pillar=True, pocket=True, tilt=False) recess6 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess7 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess8 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess9 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess10 = NP_mmi12(pillar=True, pocket=False, tilt=False) recess11 = NP_mmi12(pillar=True, pocket=True, tilt=True) recess12 = NP_mmi12(pillar=True, pocket=True, tilt=True) recess13 = NP_mmi12(pillar=True, pocket=True, tilt=False) recess14 = NP_mmi12(pillar=True, pocket=False, tilt=False, width=133.0, length=210, double=False) recess15 = NP_mmi12(pillar=True, pocket=False, tilt=False, width=133.0, length=210, double=False) recess16 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess17 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess18 = NP_mmi12(pillar=True, pocket=True, tilt=False, double=False) recess19 = NP_mmi12(pillar=True, pocket=True, tilt=False, double=False) recess20 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess21 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess22 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess23 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess24 = NP_mmi12(pillar=True, pocket=False, tilt=False, double=False) recess25 = NP_mmi12(pillar=True, pocket=True, tilt=True, double=False) recess26 = NP_mmi12(pillar=True, pocket=True, tilt=True, double=False) recess27 = NP_mmi12(pillar=True, pocket=True, tilt=False, double=False) for i in range(0, 28, 1): print(i) _inst = locals()['recess{}'.format(i)] MMI22_list.append(_inst) MMI22_list.append(dc1_20) MMI22_list.append(dc2_20) # # Al0 = AL_NP(offset=5) Al1 = AL_NP(offset=5) Al2 = AL_NP() Al3 = AL_NP() Al4 = AL_NP() Al5 = AL_NP() Al6 = AL_NP() Al7 = AL_NP() Al8 = AL_NP() Al9 = AL_NP() Al10 = AL_NP() Al11 = AL_NP() Al12 = AL_NP() Al13 = AL_NP() Al14 = AL_NP(offset=5) Al15 = AL_NP(offset=5) Al16 = AL_NP() Al17 = AL_NP() Al18 = AL_NP() Al19 = AL_NP() Al20 = AL_NP() Al21 = AL_NP() Al22 = AL_NP() Al23 = AL_NP() Al24 = AL_NP() Al25 = AL_NP() Al26 = AL_NP() Al27 = AL_NP() for i in range(0, 28, 1): print(i) _inst = locals()['Al{}'.format(i)] MMI22_list.append(_inst) SiN0 = SiN_NP(width=92, length=210) SiN1 = SiN_NP(width=92, length=210) SiN2 = SiN_NP() SiN3 = SiN_NP() SiN4 = SiN_NP() SiN5 = SiN_NP() SiN6 = SiN_NP() SiN7 = SiN_NP() SiN8 = SiN_NP() SiN9 = SiN_NP() SiN10 = SiN_NP() SiN11 = SiN_NP(tilt=15) SiN12 = SiN_NP(tilt=15) SiN13 = SiN_NP() SiN14 = SiN_NP(width=92, length=210, double=False) SiN15 = SiN_NP(width=92, length=210, double=False) SiN16 = SiN_NP(double=False) SiN17 = SiN_NP(double=False) SiN18 = SiN_NP(double=False) SiN19 = SiN_NP(double=False) SiN20 = SiN_NP(double=False) SiN21 = SiN_NP(double=False) SiN22 = SiN_NP(double=False) SiN23 = SiN_NP(double=False) SiN24 = SiN_NP(double=False) SiN25 = SiN_NP(double=False, tilt=15) SiN26 = SiN_NP(double=False, tilt=15) SiN27 = SiN_NP(double=False) for i in range(0, 28, 1): print(i) _inst = locals()['SiN{}'.format(i)] MMI22_list.append(_inst) return MMI22_list def _default_child_cells(self): child_cells = dict() for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['CHILD' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): trans = dict() row = 3000 trans["CHILD0"] = (0, 0) #MMI trans["CHILD1"] = i3.HMirror(1250) - i3.Translation( (2500, 0)) #MMI trans['CHILD2'] = (-14500, -3000 + row * 0) trans['CHILD3'] = (-14500, -3000 + row * 1) trans['CHILD4'] = (-14500, -3000 + row * 2) trans['CHILD5'] = (-14500, -3000 + row * 3) trans['CHILD6'] = (-14500, -3000 + row * 4) trans['CHILD7'] = (-14500, -3000 + row * 5) trans['CHILD8'] = (-14500, -3000 + row * 6) trans['CHILD9'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 0)) trans['CHILD10'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 1)) trans['CHILD11'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 2)) trans['CHILD12'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 3)) trans['CHILD13'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 4)) trans['CHILD14'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 5)) trans['CHILD15'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 6)) trans['CHILD16'] = (-2500, -3000 + row * 0) trans['CHILD17'] = (-2500, -3000 + row * 1) trans['CHILD18'] = (-2500, -3000 + row * 2) trans['CHILD19'] = (-2500, -3000 + row * 3) trans['CHILD20'] = (-2500, -3000 + row * 4) trans['CHILD21'] = (-2500, -3000 + row * 5) trans['CHILD22'] = (-2500, -3000 + row * 6) trans['CHILD23'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 0)) trans['CHILD24'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 1)) trans['CHILD25'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 2)) trans['CHILD26'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 3)) trans['CHILD27'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 4)) trans['CHILD28'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 5)) trans['CHILD29'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 6)) trans["CHILD30"] = (12000, 0) #MMI trans["CHILD31"] = i3.HMirror(1250) + i3.Translation( (9500, 0)) #MMI trans['CHILD32'] = (-14500, -3000 + row * 0) trans['CHILD33'] = (-14500, -3000 + row * 1) trans['CHILD34'] = (-14500, -3000 + row * 2) trans['CHILD35'] = (-14500, -3000 + row * 3) trans['CHILD36'] = (-14500, -3000 + row * 4) trans['CHILD37'] = (-14500, -3000 + row * 5) trans['CHILD38'] = (-14500, -3000 + row * 6) trans['CHILD39'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 0)) trans['CHILD40'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 1)) trans['CHILD41'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 2)) trans['CHILD42'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 3)) trans['CHILD43'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 4)) trans['CHILD44'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 5)) trans['CHILD45'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 6)) trans['CHILD46'] = (-2500, -3000 + row * 0) trans['CHILD47'] = (-2500, -3000 + row * 1) trans['CHILD48'] = (-2500, -3000 + row * 2) trans['CHILD49'] = (-2500, -3000 + row * 3) trans['CHILD50'] = (-2500, -3000 + row * 4) trans['CHILD51'] = (-2500, -3000 + row * 5) trans['CHILD52'] = (-2500, -3000 + row * 6) trans['CHILD53'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 0)) trans['CHILD54'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 1)) trans['CHILD55'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 2)) trans['CHILD56'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 3)) trans['CHILD57'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 4)) trans['CHILD58'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 5)) trans['CHILD59'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 6)) trans['CHILD60'] = (-14500, -3000 + row * 0) trans['CHILD61'] = (-14500, -3000 + row * 1) trans['CHILD62'] = (-14500, -3000 + row * 2) trans['CHILD63'] = (-14500, -3000 + row * 3) trans['CHILD64'] = (-14500, -3000 + row * 4) trans['CHILD65'] = (-14500, -3000 + row * 5) trans['CHILD66'] = (-14500, -3000 + row * 6) trans['CHILD67'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 0)) trans['CHILD68'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 1)) trans['CHILD69'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 2)) trans['CHILD70'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 3)) trans['CHILD71'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 4)) trans['CHILD72'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 5)) trans['CHILD73'] = i3.Rotation(rotation=180) + i3.Translation( (14500, 0 + row * 6)) trans['CHILD74'] = (-2500, -3000 + row * 0) trans['CHILD75'] = (-2500, -3000 + row * 1) trans['CHILD76'] = (-2500, -3000 + row * 2) trans['CHILD77'] = (-2500, -3000 + row * 3) trans['CHILD78'] = (-2500, -3000 + row * 4) trans['CHILD79'] = (-2500, -3000 + row * 5) trans['CHILD80'] = (-2500, -3000 + row * 6) trans['CHILD81'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 0)) trans['CHILD82'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 1)) trans['CHILD83'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 2)) trans['CHILD84'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 3)) trans['CHILD85'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 4)) trans['CHILD86'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 5)) trans['CHILD87'] = i3.Rotation(rotation=180) + i3.Translation( (26500, 0 + row * 6)) return trans def _generate_elements(self, elems): elems += i3.Rectangle( layer=i3.TECH.PPLAYER.PPLUS.LINE, center=(0, 7500), # change box_size=(190, 21000)) elems += i3.Rectangle( layer=i3.TECH.PPLAYER.PPLUS.LINE, center=(6000, 7500), # change box_size=(190, 21000)) elems += i3.Rectangle( layer=i3.TECH.PPLAYER.SIL.LINE, center=(0, 7500), # change box_size=(210, 21000)) return elems
class my_exe(PlaceComponents): DC_list = i3.ChildCellListProperty(default=[]) def _default_DC_list(self): MMI22_list = [] dc_10 = my_dc(gap_inc_vec=[390, 398, 406], name="ring1") # dc_10_layout = dc_10.Layout() # dc_10_layout.visualize(annotate=True) # dc_10_layout.write_gdsii("DC_V4.gds") # dc_15 = my_dc(gap_inc_vec=[390, 398, 406], name="ring2") MMI22_list.append(dc_10) MMI22_list.append(dc_15) recess0 = NP(width=338) recess1 = NP(width=338, pocket=True, tilt=False) recess2 = NP(width=338, pocket=True, tilt=True) recess3 = NP(pillar=True) recess4 = NP(pillar=True, pocket=True, tilt=False) recess5 = NP(pillar=True, pocket=True, tilt=True) recess6 = NP() recess7 = NP(pocket=True, tilt=False) recess8 = NP(width=338, pillar=True, pocket=False, tilt=False) recess9 = NP(width=338, pillar=True, pocket=True, tilt=False) recess10 = PI(pocket=False, tilt=False) recess11 = PI(pocket=True, tilt=False) for i in range(0, 12, 1): print(i) _inst = locals()['recess{}'.format(i)] MMI22_list.append(_inst) # MMI22_list.append(recess0) # MMI22_list.append(recess1) # MMI22_list.append(recess2) # MMI22_list.append(recess3) # MMI22_list.append(recess4) # MMI22_list.append(recess5) # MMI22_list.append(recess6) # MMI22_list.append(recess7) # MMI22_list.append(recess8) # MMI22_list.append(recess9) # MMI22_list.append(recess10) # MMI22_list.append(recess11) Al0 = AL_NP(width=338) Al1 = AL_NP(width=338) Al2 = AL_NP(width=338) Al3 = AL_NP(pillar=True) Al4 = AL_NP(pillar=True) Al5 = AL_NP(pillar=True) Al6 = AL_NP() Al7 = AL_NP() Al8 = AL_NP(width=338, pillar=True) Al9 = AL_NP(width=338, pillar=True) Al10 = AL_PI() Al11 = AL_PI() # _ = [Al0, Al1, Al2, Al3, Al4, Al5, Al6, Al7, Al8, Al9, Al10, Al11] # # for i in range(0,12,1): # # _[i].append(i) # MMI22_list.append(_[i]) for i in range(0, 12, 1): print(i) _inst = locals()['Al{}'.format(i)] MMI22_list.append(_inst) SiN0 = SiN_NP(width=338) SiN1 = SiN_NP(width=338) SiN2 = SiN_NP(width=338, tilt_0=True) SiN3 = SiN_NP(pillar=True) SiN4 = SiN_NP(pillar=True) SiN5 = SiN_NP(pillar=True, tilt_0=True) SiN6 = SiN_NP() SiN7 = SiN_NP() SiN8 = SiN_NP(width=338, pillar=True) SiN9 = SiN_NP(width=338, pillar=True) SiN10 = SiN_PI() SiN11 = SiN_PI() for i in range(0, 12, 1): print(i) _inst = locals()['SiN{}'.format(i)] MMI22_list.append(_inst) return MMI22_list def _default_child_cells(self): child_cells = dict() for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['CHILD' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): trans = dict() row = 5000 trans["CHILD0"] = (0, 0) trans["CHILD1"] = i3.HMirror(2500) - i3.Translation((5000, 0)) trans['CHILD2'] = (-15000, 0 + row * -1) trans['CHILD3'] = (-15000, 0 + row * 0) trans['CHILD4'] = (-15000, 0 + row * 1) trans['CHILD5'] = (-15000, 0 + row * 2) trans['CHILD6'] = (-15000, 0 + row * 3) trans['CHILD7'] = (-15000, 0 + row * 4) trans['CHILD8'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 0)) trans['CHILD9'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 1)) trans['CHILD10'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 2)) trans['CHILD11'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 3)) trans['CHILD12'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 4)) trans['CHILD13'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 5)) trans['CHILD14'] = (-15000, 0 + row * -1) trans['CHILD15'] = (-15000, 0 + row * 0) trans['CHILD16'] = (-15000, 0 + row * 1) trans['CHILD17'] = (-15000, 0 + row * 2) trans['CHILD18'] = (-15000, 0 + row * 3) trans['CHILD19'] = (-15000, 0 + row * 4) trans['CHILD20'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 0)) trans['CHILD21'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 1)) trans['CHILD22'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 2)) trans['CHILD23'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 3)) trans['CHILD24'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 4)) trans['CHILD25'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 5)) trans['CHILD26'] = (-15000, 0 + row * -1) trans['CHILD27'] = (-15000, 0 + row * 0) trans['CHILD28'] = (-15000, 0 + row * 1) trans['CHILD29'] = (-15000, 0 + row * 2) trans['CHILD30'] = (-15000, 0 + row * 3) trans['CHILD31'] = (-15000, 0 + row * 4) trans['CHILD32'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 0)) trans['CHILD33'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 1)) trans['CHILD34'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 2)) trans['CHILD35'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 3)) trans['CHILD36'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 4)) trans['CHILD37'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0 + row * 5)) return trans
class Mask(APAC): grating_coupler = i3.ChildCellProperty(doc="Grating couplers used in order") modulators = i3.ChildCellListProperty(doc="Modulators used") m_spacing = i3.ListProperty(default=[3.5, 4.0, 4.5, 5.0], doc="Metal spacings") def _default_grating_coupler(self): return FC_TE_1550() def _default_modulators(self): mods = [] for w in self.m_spacing: cell = TW_MZM(name=self.name + "Modulator_{}".format(w)) cell.Layout(modulator_length=1500, metal_spacing=w) mods.append(cell) return mods def _default_child_cells(self): childs = dict() for cnt, mod in enumerate(self.modulators): # Iterates over self.m_spacing and uses cnt as a counter. This is a python construct. childs["grating_in_{}".format(cnt)] = self.grating_coupler childs["mod_{}".format(cnt)] = mod childs["grating_out_{}".format(cnt)] = self.grating_coupler return childs def _default_connectors(self): conn = [] for cnt, mod in enumerate(self.modulators): in_port = "grating_in_{}:out".format(cnt) out_port = "mod_{}:in".format(cnt) conn.append((in_port, out_port, wide_manhattan)) in_port = "grating_out_{}:out".format(cnt) out_port = "mod_{}:out".format(cnt) conn.append((in_port, out_port, wide_manhattan)) return conn def _default_electrical_links(self): el_links = [] #shorting the ground for cnt, mod in enumerate(self.modulators): for arm_name in ["1", "5"]: p1 = "mod_{}:elec_right_{}".format(cnt, arm_name) p2 = "mod_{}:elec_right_{}".format(cnt, "3") el_links.append((p1, p2)) p1 = "mod_{}:elec_left_{}".format(cnt, arm_name) p2 = "mod_{}:elec_left_{}".format(cnt, "3") el_links.append((p1, p2)) return el_links def _default_external_port_names(self): epn = dict() for cnt, mod in enumerate(self.modulators): epn["grating_in_{}:vertical_in".format(cnt)] = "in{}".format(cnt) epn["grating_out_{}:vertical_in".format(cnt)] = "out{}".format(cnt) return epn def _default_propagated_electrical_ports(self): pp = [] for cnt, mod in enumerate(self.modulators): for arm_name in [2,3,4]: pp.append("mod_{}_elec_right_{}".format(cnt, arm_name)) pp.append("mod_{}_elec_left_{}".format(cnt, arm_name)) return pp class Layout(APAC.Layout): grating_coupler_spacing = i3.PositiveNumberProperty(default=800, doc="Spacing between the grating couplers") center_grating_coupler_y = i3.PositiveNumberProperty(doc="Start position of the first grating coupler") def _default_metal1_width(self): return 20.0 def _default_center_bp(self): return 2500 / 2.0 def _default_center_grating_coupler_y(self): return 5150.0 / 2.0 def _default_child_transformations(self): trans = dict() nw = len(self.m_spacing) for cnt, mod in enumerate(self.modulators): t = (100.0, self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing) trans["grating_in_{}".format(cnt)] = i3.Translation(translation=t) t = (2500/2.0 , self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing) trans["mod_{}".format(cnt)] = i3.Translation(translation=t) trans["grating_out_{}".format(cnt)] = i3.Rotation(rotation=180.0) + i3.Translation(translation=(2500, self.center_grating_coupler_y + (-nw / 2.0 + 0.5 + cnt) * self.grating_coupler_spacing)) return trans @i3.cache() def _default_electrical_routes(self): routes = [] for c in self.electrical_links: inst1, port1 = self._resolve_inst_port(c[0]) inst2, port2 = self._resolve_inst_port(c[1]) if "left" in port1.name: r = i3.RouteManhattan(input_port=port1, output_port=port2, min_straight=100.0, angle_out=0.0, angle_in=180.0, rounding_algorithm=None) else: r = i3.RouteManhattan(input_port=port1, output_port=port2, min_straight=100.0, angle_out=180.0, angle_in=0.0, rounding_algorithm=None) routes.append(r) return routes
class _Splitter(Coupler1x2): """ Abstract splitter class just places 3 waveguides. """ wg_template = i3.WaveguideTemplateProperty(doc="Waveguide template used.") wgs_straights = i3.ChildCellListProperty( doc="Childcells used for the waveguides.") def _default_wg_template(self): return WireWaveguideTemplate() def _default_wgs_straights(self): wgs = [] for cnt in xrange(0, 3): wg = i3.RoundedWaveguide(trace_template=self.wg_template) wgs.append(wg) return wgs class Layout(i3.LayoutView): length_splitting_shape = i3.PositiveNumberProperty( default=10.0, doc="Length of the splitting section.") length_straights = i3.PositiveNumberProperty( default=0.2, doc="Length of the straights at the input and output.") spacing = i3.PositiveNumberProperty( default=2.0, doc="Spacing between the two output waveguides.") def _default_wg_template(self): wgt = self.cell.wg_template.get_default_view(i3.LayoutView) return wgt def _default_wgs_straights(self): wgs_cells = self.cell.wgs_straights wgs_layout = [] for wgc in wgs_cells: wg_layout = wgc.get_default_view(i3.LayoutView) wg_layout.set(shape=i3.Shape( points=[(0, 0), (self.length_straights, 0)])) wgs_layout.append(wg_layout) return wgs_layout def _generate_instances(self, insts): insts += i3.SRef(reference=self.wgs_straights[0], name="in") insts += i3.SRef( reference=self.wgs_straights[1], name="out1", position=(self.length_straights + self.length_splitting_shape, -self.spacing / 2)) insts += i3.SRef( reference=self.wgs_straights[2], name="out2", position=(self.length_straights + self.length_splitting_shape, +self.spacing / 2)) return insts def _get_cladding_elem(self): shape_cladding = i3.Shape( points=[(self.length_straights, self.wg_template.width / 2), (self.length_straights + self.length_splitting_shape, self.spacing / 2 + self.wg_template.width / 2)]) shape_cladding_m = i3.Shape( points=[(self.length_straights, -self.wg_template.width / 2), (self.length_straights + self.length_splitting_shape, -self.spacing / 2 - self.wg_template.width / 2)]) shape_elem = shape_cladding + shape_cladding_m.reversed() elem = i3.Boundary(layer=self.wg_template.windows[1].layer, shape=shape_elem) return elem def _generate_ports(self, ports): ports += self.instances["in"].ports["in"] ports += self.instances["out1"].ports["out"].modified_copy( name="out1") ports += self.instances["out2"].ports["out"].modified_copy( name="out2") return ports def _get_splitting_elem(self): raise NotImplementedError( "This is an abstract class in which _get_splitting_elem was not implemented." ) def _generate_elements(self, elems): elems += self._get_splitting_elem() elems += self._get_cladding_elem() return elems class CapheModelCST(CapheModelCST): """ CapheModel based on a CST simulation """ def _default_additional_commands_path(self): return r"{}\simulation_files\additional_commands.mod".format( os.path.dirname(__file__)) class CapheModel(Coupler1x2.CapheModel): """ Simple Analytic CapheModel """ pass
class AlignmentMark(i3.PCell): """ Alignment mark between two process layers. """ # List of Vernier scales and crosses for a basecell. They are locked properties and defined by default functions verniers = i3.ChildCellListProperty(locked=True, doc="Vernier scales") cross_marks = i3.ChildCellListProperty(locked=True, doc="Cross Marks") _name_prefix = "ALIGNMENT_MARKER" def _default_verniers(self): vern_1 = VernierScale() vern_2 = VernierScale() return [vern_1, vern_2] def _default_cross_marks(self): # Dark Cross on layer 1 dark_cross = CrossMark() # Open Cross on layer 1 open_cross = CrossMark() return [dark_cross, open_cross] class Layout(i3.LayoutView): """ Alignment mark layout view. """ # Specify two layers on which markers are drawn process1 = i3.ProcessProperty(default=i3.TECH.PPLAYER.CH2.TRENCH)#i3.TECH.PROCESS.CHANNEL_1, doc="Process Layer 1") #was i3.TECH.PROCESS.WG process2 = i3.ProcessProperty(default=i3.TECH.PPLAYER.CH1.TRENCH)#i3.TECH.PROCESS.CHANNEL_2, doc="Process Layer 2") # Properties of crosses dark_cross_bar_width = i3.PositiveNumberProperty(default=30, doc="width of the dark cross") open_cross_bar_width = i3.PositiveNumberProperty(default=40, doc="width of the open cross") cross_boundary_width = i3.PositiveNumberProperty(default=150, doc="width of the cross boundary box") # Basic properties of Vernier scales vern_spacing_short = i3.PositiveNumberProperty(default=18, doc="spacing between bars of shorter vernier scale") vern_spacing_long = i3.PositiveNumberProperty(default=18.5, doc="spacing between bars of longer vernier scale") vern_number_of_bar = i3.IntProperty(default=13, doc="the number of vernier bars") # Detailed properties of Vernier scales vern_bar_length = i3.PositiveNumberProperty(default=30, doc="length of the shortest bars on the scale") vern_bar_extra_length = i3.PositiveNumberProperty(default=10, doc="extra length of the central bar") vern_bar_width = i3.PositiveNumberProperty(default=5, doc="width of a single bar") # Separation between Vernier scales and Crosses section vern_cross_spacing = i3.PositiveNumberProperty(default=30, doc="Distance between cross box and closest edge of scales") # Separation between 2 scales of 2 layers vern_layer_gap = i3.NonNegativeNumberProperty(default=0.0, doc="gap between 2 scales of 2 layers on alignment") def _default_verniers(self): vern_1 = self.cell.verniers[0].Layout(spacing=self.vern_spacing_long, number_of_bars=self.vern_number_of_bar, bar_length=self.vern_bar_length, bar_extra_length=self.vern_bar_extra_length, bar_width=self.vern_bar_width)#, #process=self.process1) vern_2 = self.cell.verniers[1].Layout(spacing=self.vern_spacing_short, number_of_bars=self.vern_number_of_bar, bar_length=self.vern_bar_length, bar_extra_length=self.vern_bar_extra_length, bar_width=self.vern_bar_width)#, #process=self.process2) return [vern_1, vern_2] def _default_cross_marks(self): # Dark Cross on layer 1 dark_cross = self.cell.cross_marks[0].Layout(inversion=False, cross_bar_width=self.dark_cross_bar_width, cross_boundary_width=self.cross_boundary_width)#, #process=self.process1) open_cross = self.cell.cross_marks[1].Layout(inversion=True, cross_bar_width=self.open_cross_bar_width, cross_boundary_width=self.cross_boundary_width)#, #process=self.process2) return [dark_cross, open_cross] def _generate_instances(self, insts): insts += i3.SRef(reference=self.cross_marks[0]) insts += i3.SRef(reference=self.cross_marks[1]) vern_1_horz_trans = i3.VMirror() + \ i3.Translation((0, -self.cross_boundary_width * 0.5 - self.vern_cross_spacing - (self.vern_bar_length + self.vern_bar_extra_length) - self.vern_layer_gap)) insts += i3.SRef(reference=self.verniers[0], transformation=vern_1_horz_trans) vern_2_horz_trans = i3.Translation((0, -self.cross_boundary_width * 0.5 - self.vern_cross_spacing - (self.vern_bar_length + self.vern_bar_extra_length))) insts += i3.SRef(reference=self.verniers[1], transformation=vern_2_horz_trans) vern_1_vert_trans = i3.Rotation(rotation=90) + \ i3.Translation((-self.cross_boundary_width*0.5 - self.vern_cross_spacing - (self.vern_bar_length + self.vern_bar_extra_length) - self.vern_layer_gap, 0)) insts += i3.SRef(reference=self.verniers[0], transformation=vern_1_vert_trans) vern_2_vert_trans = i3.Rotation(rotation=270) + \ i3.Translation((-self.cross_boundary_width*0.5 - (self.vern_bar_length + self.vern_bar_extra_length) - self.vern_cross_spacing, 0)) insts += i3.SRef(reference=self.verniers[1], transformation=vern_2_vert_trans) return insts
class Spirals_w(PlaceComponents): Spirals_w_list = i3.ChildCellListProperty( doc="List containing the different routed masks") width_vec = i3.ListProperty(default=[10000.0, 20000.0]) s_length_vec = i3.ListProperty(default=[50000.0]) n = i3.PositiveNumberProperty(default=1, doc="Radius of curvature") tipo = i3.PositiveNumberProperty(default=1, doc="Radius of curvature") def _default_n(self): for counter, cell in enumerate(self.width_vec): numero = counter + 1 #print 'number of legths: ', self.n return numero def _default_Spirals_w_list(self): Spirals_w_list = [] for w, width in enumerate(self.width_vec): print 'The core width is: ', width wg_t = WireWaveguideTemplate() wg_t.Layout( core_width=width, cladding_width=width, ) Spirals_w_list.append( Spirals(s_length_vec=self.s_length_vec, waveguide_template=wg_t, tipo=self.tipo, width=w + 1, n=self.n, name='Spirals_w_' + str(width)) #.Layout(local_mbend_radius = radius) ) return Spirals_w_list def _default_child_cells(self): child_cells = {} for counter, width in enumerate(self.Spirals_w_list): child_cells['Spirals{}'.format(counter)] = width print 'child_cells:', child_cells return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): d = {} for counter, child in enumerate(self.child_cells): # We get the layoutview of the childcell spiral = self.child_cells[child].get_default_view(self) isz_0 = spiral.instances['Spiral0'].reference.inner_size sx = isz_0[1] + 200 print 'sx = ', sx #print("inner_size = {}".format(isz_0, isz_1)) number = self.n if self.tipo == 1: d['Spirals' + str(counter)] = i3.Translation( translation=(0.0, (counter) * sx)) #+i3.HMirror()+i3.VMirror() if self.tipo == 2: d['Spirals' + str(counter)] = i3.Translation(translation=( 0.0, -(counter) * sx)) + i3.HMirror() + i3.VMirror() return d
class 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 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 CircuitOfBlocks(microfluidics.PlaceAndAutoRoute): """Parametric cell with several traps, which are stacked vertically (Parallel) or horizontally (Series) """ #_name_prefix = "circuitOfTraps" type = i3.NumberProperty(default=0) # 0 Paralell 1 Series block_distance = i3.NumberProperty(default=400.) #distance betwn traps block_with_tee = i3.ChildCellListProperty( ) # Generating traps with Tee from Child Cell List Property trace_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate()) n_blocks_x = i3.PositiveIntProperty(default=30) n_blocks_y = i3.PositiveIntProperty(default=30) x_footprint = i3.PositiveIntProperty(default=1000) y_footprint = i3.PositiveIntProperty(default=1000) def _default_child_cells(self): return { "blk_w_tee{}".format(cnt): self.block_with_tee[cnt] for cnt in range(self.n_blocks_x * self.n_blocks_y) } def _default_links(self): links = [] bx = self.n_blocks_x ######################## ############# PARALLEL if self.type == 0: for cntx in range(0, self.n_blocks_x): # self connection at the top -bypass top = self.n_blocks_y * self.n_blocks_x - self.n_blocks_x + cntx links.append(("blk_w_tee{}:in2".format(top), "blk_w_tee{}:out2".format(top))) # connecting bottom to top for cnty in range(0, self.n_blocks_y - 1): links.append( ("blk_w_tee{}:in2".format(cnty * bx + cntx), "blk_w_tee{}:in1".format((cnty + 1) * bx + cntx))) links.append( ("blk_w_tee{}:out2".format(cnty * bx + cntx), "blk_w_tee{}:out1".format((cnty + 1) * bx + cntx))) #interconnecting horizontally if self.n_blocks_x > 1: for cntd in range(0, self.n_blocks_x - 1): links.append(("blk_w_tee{}:out1".format(cntd), "blk_w_tee{}:in1".format(cntd + 1))) ######## END PARALLEL ################# ######################## ############# SERIES if self.type == 1: # series #all by-pass, each object for cnt in range(0, self.n_blocks_y * self.n_blocks_x): #all bypass links.append(("blk_w_tee{}:in2".format(cnt), "blk_w_tee{}:out2".format(cnt))) #all interconnecting horizontally if self.n_blocks_x > 1: for cnty in range(0, self.n_blocks_y): for cntd in range(0, (self.n_blocks_x - 1)): links.append( ("blk_w_tee{}:out1".format(cnty * bx + cntd), "blk_w_tee{}:in1".format(cnty * bx + cntd + 1))) #left connections for cntd in range(1, (self.n_blocks_y - 1), 2): #links.append(("blk_w_tee{}:in1".format(cntd * bx), "blk_w_tee{}:in1".format((cntd+1) * bx))) links.append(("blk_w_tee{}:in1".format( (cntd + 1) * bx), "blk_w_tee{}:in1".format(cntd * bx))) #right connections for cntd in range(1, (self.n_blocks_y), 2): links.append(("blk_w_tee{}:out1".format(cntd * bx - 1), "blk_w_tee{}:out1".format((cntd + 1) * bx - 1))) ######## END SERIES ################# return links def _default_block_with_tee( self): # Generating traps from Child Cell List Property tee1 = TeeSimple() tee1.Layout(tee_length=(200.0)) my_block = CellTrapSimple() my_block.Layout(cell_trap_length=300.0) return [ TrapWithTees( name="blk_w_tee_{}".format(cnt), trap=my_block, tee=tee1, ) for cnt in range(self.n_blocks_x * self.n_blocks_y) ] class Layout(microfluidics.PlaceAndAutoRoute.Layout): def _default_child_transformations(self): # generate grid x = np.linspace(0, self.cell.x_footprint, self.cell.n_blocks_x) y = np.linspace(0, self.cell.y_footprint, self.cell.n_blocks_y) # generate positions from functions.position_coordinates import generate_positions coords = generate_positions(x, y, self.type) return { "blk_w_tee{}".format(cnt): i3.Translation(coords[cnt]) for cnt in range(self.n_blocks_x * self.n_blocks_y) } def _generate_ports(self, ports): # Add ports if self.type == 0: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:out1'.format(self.n_blocks_x - 1): 'out1' }) if self.type == 1: if self.n_blocks_y % 2 == 0: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:in1'.format(self.n_blocks_x * self.n_blocks_y - self.n_blocks_x): 'out1' # last left }) else: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:out1'.format(self.n_blocks_x * self.n_blocks_y - 1): 'out1' # last right }) return ports
class my_dc(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) # gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") gap_inc_vec2 = i3.ListProperty(default=[], doc="length of 12mmi") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) cleave = i3.PositiveNumberProperty(doc="tolerance", default=150) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}_{}".format(str(self.width), str(self.cleave)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (self.cleave, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}_{}".format( str(self.width), str(self.cleave)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] # cell = MMI2x2Tapered(mmi_trace_template=self.mmi_trace_template, # input_trace_template=self.mmi_access_template, # output_trace_template=self.mmi_access_template, # trace_template=self.trace_template, # ) # # cell.Layout(name="MMI22_l_430", transition_length=200.0, # length=430, trace_spacing=11.0 # ) # # MMI22_list.append(cell) # # print 'cell name ' + str(cell.name) # print '__________________________' for l, dl in enumerate(self.gap_inc_vec2): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2112() cell.Layout(name="MMI2112_l_{}".format(str(self.gap_inc_vec2[l])), length=self.gap_inc_vec2[l]) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 11, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ # ("taper0:out", "ring0:in2"), # ("taper1:out", "ring0:in1"), # ("taper2:out", "ring0:out2"), # ("taper3:out", "ring0:out1"), ("taper0:out", "ring0:narrow_in"), ("taper1:out", "ring0:MMI1a_out1"), ("taper2:out", "ring0:MMI1a_out2"), ("taper3:out", "ring1:narrow_in"), ("taper4:out", "ring1:MMI1a_out1"), ("taper5:out", "ring1:MMI1a_out2"), ("taper6:out", "ring2:narrow_in"), ("taper7:out", "ring2:MMI1a_out1"), ("taper8:out", "ring2:MMI1a_out2"), ("taper9:out", "taper10:out") ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 6000 trans['ring0'] = (600, 0) trans['ring1'] = (600, 1 * column) trans['ring2'] = (600, 2 * column) # trans['ring3'] = (1300, 8000 + 2 * column ) trans["taper0"] = (0, 0) trans["taper1"] = i3.HMirror(0) + i3.Translation((2500, -1500)) trans["taper2"] = i3.HMirror(0) + i3.Translation((2500, 1500)) trans["taper3"] = (0, 1 * column) trans["taper4"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 1 * column)) trans["taper5"] = i3.HMirror(0) + i3.Translation( (2500, 1500 + 1 * column)) trans["taper6"] = (0, 2 * column) trans["taper7"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 2 * column)) trans["taper8"] = i3.HMirror(0) + i3.Translation( (2500, 1500 + 2 * column)) trans["taper9"] = (0, 3800 + 2 * column) trans["taper10"] = i3.HMirror(0) + i3.Translation( (2500, -1500 + 3 * column)) # trans["taper11"] = i3.HMirror(0) + i3.Translation((3000, 6500+ 2 * column)) # trans["taper12"] = i3.HMirror(0) + i3.Translation((3000, 9500+ 2 * column)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(name, self.cell.wg_t1.name), # coordinate=(1300.0, 100.0), alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), font=2, height=30.0, transformation=i3.Translation((600, 100 + 6000 * counter))) for i in range(1, 8, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}".format(i), coordinate=(400, -4400 + 3000 * i), font=2, height=200.0, ) for j in range(-1, 2, 1): for i in range(0, 4, 1): elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 + 100 + 6000 * i), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 - 100 + 6000 * i), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100 + j * 6000, -3000 - 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -3000 - 100), box_size=(100, 100)) return elems
class my_dc3(PlaceAndAutoRoute): DC_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") mmi_trace_template = i3.WaveguideTemplateProperty() mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port_{}".format(str(self.width))) wg_t1.Layout(core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t1 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(0.0, 0.0), (150.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts( name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.trace_template) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port def _default_mmi_trace_template(self): mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width return mmi_trace_template def _default_mmi_access_template(self): mmi_access_template = WireWaveguideTemplate(name="MMI_at") mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) return mmi_access_template def _default_DC_list(self): print '____________ MMI 2x2 ______________' MMI22_list = [] for l, dl in enumerate(self.gap_inc_vec): print 'length number ' + str(l) print 'dl ' + str(dl) cell = MMI2x2Tapered(mmi_trace_template=self.mmi_trace_template, input_trace_template=self.mmi_access_template, output_trace_template=self.mmi_access_template, trace_template=self.trace_template, ) cell.Layout(name="MMI22_l_{}".format(str(self.gap_inc_vec[l])), transition_length=200.0, length=self.gap_inc_vec[l], trace_spacing=11.0 ) MMI22_list.append(cell) print 'cell name ' + str(cell.name) print '__________________________' return MMI22_list def _default_child_cells(self): child_cells = dict() for counter in range(0, 4, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taper' + str(counter)] = self.WG2 for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['ring' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells def _default_links(self): links = [ ("taper0:out", "ring0:in2"), ("taper1:out", "ring0:in1"), ("taper2:out", "ring0:out2"), ("taper3:out", "ring0:out1"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 10000 # trans["dircoup1"] = (1650, 0) # trans["dircoup2"] = (4950, 0) # trans['mzi_22_22_0'] = (0, 0) trans['ring0'] = (1500, 0) # trans['ring1'] = (2500, 0 + column) # trans['ring2'] = (2500, 0 + 2 * column) # trans['ring3'] = (1500, 0 + 3 * column) trans["taper0"] = (0, 2500) trans["taper1"] = (0, -2500) trans["taper2"] = i3.Rotation(rotation=-90) + i3.Translation((2500, 5000)) trans["taper3"] = i3.HMirror(0) + i3.Translation((4000, -5.5)) return trans def _default_bend_radius(self): bend_radius = 300 return bend_radius def _generate_elements(self, elems): for counter, child in enumerate(self.DC_list): name = child.name # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text="{}_{}".format(name, self.cell.wg_t1.name), # # coordinate=(1300.0, 100.0), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=20.0, # transformation=i3.Translation((1500, 100 + 10000 * counter)) # ) # elems += i3.PolygonText(layer=i3.TECH.PPLAYER.WG.TEXT, # text="{} {}".format(name, self.cell.wg_t1.name), # # coordinate=(-2000, -150), # alignment=(i3.TEXT_ALIGN_LEFT, i3.TEXT_ALIGN_LEFT), # font=2, # height=200.0, # transformation=i3.Rotation((0.0, 0.0), 90.0) # + i3.Translation((450+2900, -2000 + 10000 * counter)) # ) # for j in range (-1,2,1): # for i in range(0,4,1): # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000+100+10000*i),box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 - 100 + 10000 * i), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 + 100 + 6000 * 3+3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 100+j*6000, -3000 - 100 + 6000 * 3+3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 300, -3000 + 100 + 6000 * 3 + 3000), box_size=(100, 100)) # elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=( # 300, -3000 - 100 ), box_size=(100, 100)) return elems
class my_exe2(PlaceComponents): DC_list = i3.ChildCellListProperty(default=[]) def _default_DC_list(self): MMI22_list = [] dc_10 = my_dc(gap_inc_vec2=[110.0, 110.0, 110], name="ring1") # dc_10_layout = dc_10.Layout() # dc_10_layout.visualize(annotate=True) # dc_10_layout.write_gdsii("DC_V4.gds") # dc_15 = my_dc(gap_inc_vec2=[110.0, 110.0, 110], name="ring2") MMI22_list.append(dc_10) MMI22_list.append(dc_15) recess0 = NP(width=338, pocket=True, tilt=True) recess1 = NP(pillar=True) recess2 = NP_mmi12(width=330, pillar=True, pocket=False, tilt=False) recess3 = NP_mmi12(width=330, pillar=True, pocket=False, tilt=False) recess4 = NP_mmi12(width=330, pillar=True, pocket=True, tilt=False) recess5 = NP_mmi12(width=330, pillar=True, pocket=True, tilt=False) recess6 = NP_mmi12(width=330, pillar=True, pocket=True, tilt=True) recess7 = NP_mmi12(width=330, pillar=True, pocket=True, tilt=True) recess8 = NP(width=338, pillar=True, pocket=False, tilt=False) recess9 = NP(width=338, pillar=True, pocket=True, tilt=False) recess10 = NP_mmi12(width=338, pillar=True, pocket=False, tilt=False) recess11 = NP_mmi12(width=338, pillar=True, pocket=False, tilt=False) recess12 = NP_mmi12(width=338, pillar=True, pocket=True, tilt=False) recess13 = NP_mmi12(width=338, pillar=True, pocket=True, tilt=False) recess14 = NP_mmi12(width=338, pillar=True, pocket=True, tilt=True) recess15 = NP_mmi12(width=338, pillar=True, pocket=True, tilt=True) for i in range(0, 16, 1): print(i) _inst = locals()['recess{}'.format(i)] MMI22_list.append(_inst) # # # Al0 = AL_NP(width=338) # Al1 = AL_NP(width=338) # Al2 = AL_NP(width=338) # Al3 = AL_NP(pillar=True) # Al4 = AL_NP(pillar=True) # Al5 = AL_NP(pillar=True) # Al6 = AL_NP() # Al7 = AL_NP() # Al8 = AL_NP(width=338, pillar=True) # Al9 = AL_NP(width=338, pillar=True) # Al10 = AL_PI() # Al11 = AL_PI() # # for i in range(0, 12, 1): # print(i) # _inst = locals()['Al{}'.format(i)] # MMI22_list.append(_inst) # SiN0 = SiN_NP(width=338) # SiN1 = SiN_NP(width=338) # SiN2 = SiN_NP(width=338, tilt_0=True) # SiN3 = SiN_NP(pillar=True) # SiN4 = SiN_NP(pillar=True) # SiN5 = SiN_NP(pillar=True, tilt_0=True) # SiN6 = SiN_NP() # SiN7 = SiN_NP() # SiN8 = SiN_NP(width=338, pillar=True) # SiN9 = SiN_NP(width=338, pillar=True) # SiN10 = SiN_PI() # SiN11 = SiN_PI() # for i in range(0, 12, 1): # print(i) # _inst = locals()['SiN{}'.format(i)] # MMI22_list.append(_inst) return MMI22_list def _default_child_cells(self): child_cells = dict() for counter, child in enumerate(self.DC_list): print 'child number' + str(counter) child_cells['CHILD' + str(counter)] = child print 'child name ' + str(child.name) print child return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): trans = dict() row = 3000 trans["CHILD0"] = (0, 0) trans["CHILD1"] = i3.HMirror(2500) - i3.Translation((5000, 0)) trans['CHILD2'] = (-15000, -5000) trans['CHILD3'] = (-15000, 0) trans['CHILD4'] = (-15000, 2000 + row * 1) trans['CHILD5'] = (-15000, 2000 + row * 2) trans['CHILD6'] = (-15000, 2000 + row * 3) trans['CHILD7'] = (-15000, 2000 + row * 4) trans['CHILD8'] = (-15000, 2000 + row * 5) trans['CHILD9'] = (-15000, 2000 + row * 6) trans['CHILD10'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 0)) trans['CHILD11'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000)) trans['CHILD12'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 1)) trans['CHILD13'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 2)) trans['CHILD14'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 3)) trans['CHILD15'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 4)) trans['CHILD16'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 5)) trans['CHILD17'] = i3.Rotation(rotation=180) + i3.Translation( (15000, 5000 + row * 6)) # trans['CHILD14'] = (-15000, 0 + row * -1) # trans['CHILD15'] = (-15000, 0 + row * 0) # trans['CHILD16'] = (-15000, 0 + row * 1) # trans['CHILD17'] = (-15000, 0 + row * 2) # trans['CHILD18'] = (-15000, 0 + row * 3) # trans['CHILD19'] = (-15000, 0 + row * 4) # trans['CHILD20'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 0)) # trans['CHILD21'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 1)) # trans['CHILD22'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 2)) # trans['CHILD23'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 3)) # trans['CHILD24'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 4)) # trans['CHILD25'] = i3.Rotation(rotation=180) + i3.Translation((15000, 0 + row * 5)) return trans def _generate_elements(self, elems): elems += i3.Rectangle( layer=i3.TECH.PPLAYER.NONE.DOC, center=(0, 9000), # change box_size=(200, 28000)) # generated1 = i3.TECH.PPLAYER.HFW - i3.TECH.PPLAYER.NONE.DOC # mapping = {generated1: i3.TECH.PPLAYER.HFW} # elems = i3.get_elements_for_generated_layers(elems, mapping) return elems
class Lspiral(PlaceAndAutoRoute): rectV_list = i3.ChildCellListProperty(default=[]) rectH_list = i3.ChildCellListProperty(default=[]) gap_inc_vec = i3.ListProperty(default=[], doc="Length of MMI") gap_inc_vec2 = i3.ListProperty(default=[], doc="length of 12mmi") WG1 = i3.ChildCellProperty(doc="", locked=True) WG2 = i3.ChildCellProperty() wg_t1 = i3.WaveguideTemplateProperty(doc="board WG") wg_t2 = i3.WaveguideTemplateProperty(doc="change WG") # mmi_trace_template = i3.WaveguideTemplateProperty() # mmi_access_template = i3.WaveguideTemplateProperty() width = i3.PositiveNumberProperty(doc="width of ports", default=15) # cleave = i3.PositiveNumberProperty(doc="tolerance", default=150) offset = i3.NumberProperty(doc="count", default=0) def _default_wg_t1(self): wg_t1 = WireWaveguideTemplate(name="port20") wg_t1.Layout( core_width=20, cladding_width=20 + 2 * 12.0, ) return wg_t1 def _default_wg_t2(self): wg_t2 = WireWaveguideTemplate( name="port_{}_{}".format(str(self.width), str(self.offset))) wg_t2.Layout( core_width=self.width, cladding_width=self.width + 2 * 12.0, ) return wg_t2 def _default_trace_template(self): wg_sm = WireWaveguideTemplate(name="sm_template") wg_sm.Layout(core_width=3.8, cladding_width=3.8 + 2 * 12.0) return wg_sm def _default_WG1(self): WG1 = i3.Waveguide(name="straight{}".format(str(self.width)), trace_template=self.wg_t1) WG1.Layout(shape=[(-200.0, 0.0), (600.0, 0.0)]) return WG1 def _default_WG2(self): Port = AutoTransitionPorts(name="ports{}".format(str(self.width)), contents=self.WG1, port_labels=["out"], trace_template=self.wg_t2) Port.Layout(transition_length=300) # .visualize(annotate=True) return Port # def _default_mmi_trace_template(self): # mmi_trace_template = WireWaveguideTemplate(name="MMI_tt") # mmi_trace_template.Layout(core_width=20.0, cladding_width=20.0 + 2 * 12) # MMI_width # return mmi_trace_template # # def _default_mmi_access_template(self): # mmi_access_template = WireWaveguideTemplate(name="MMI_at") # mmi_access_template.Layout(core_width=9.0, cladding_width=9.0 + 2 * 12) # return mmi_access_template def _default_rectH_list(self): MMI22_list = [] for l in range(0, 5, 1): cell = i3.Waveguide(name="rectH{}_{}".format( str(l), str(self.offset)), trace_template=self.wg_t2) cell.Layout(shape=[(0.0, 0.0), (17000 - 4000 * l, 0.0)]) # cell = i3.Waveguide(name="rectV{}".format(str(l)), # trace_template=self.wg_t2) # cell.Layout(shape=[(18000 - 4000 * l, 0.0), (0.0, 0.0)]) MMI22_list.append(cell) return MMI22_list def _default_rectV_list(self): print '____________ MMI 2x2 ______________' MMI22_list2 = [] for l in range(0, 5, 1): # cell = i3.Waveguide(name="rectH{}".format(str(l)), # trace_template=self.wg_t2) # cell.Layout(shape=[(0.0, 0.0), (18000-4000*l, 0.0)]) cell = i3.Waveguide(name="rectV{}_{}".format( str(l), str(self.offset)), trace_template=self.wg_t2) cell.Layout(shape=[(0.0, 0.0), (0.0, -1000 - 4000 * l)]) MMI22_list2.append(cell) return MMI22_list2 def _default_child_cells(self): child_cells = dict() for counter in range(0, 5, 1): print counter # child_cells['straight' + str(counter)] = self.WG1 child_cells['taperH' + str(counter)] = self.WG2 child_cells['taperV' + str(counter)] = self.WG2 for counter, child in enumerate(self.rectH_list): print 'child number' + str(counter) child_cells['recH' + str(counter)] = child print 'child name ' + str(child.name) for counter, child in enumerate(self.rectV_list): print 'child number' + str(counter) child_cells['recV' + str(counter)] = child print 'child name ' + str(child.name) return child_cells def _default_links(self): links = [ ("recH0:out", "recV4:out"), ("recH1:out", "recV3:out"), ("recH2:out", "recV2:out"), ("recH3:out", "recV1:out"), ("recH4:out", "recV0:out"), ] return links class Layout(PlaceAndAutoRoute.Layout): def _default_child_transformations(self): trans = dict() column = 4000 # trans['ring0'] = (600, 0) # trans['ring1'] = (600, 1 * column) # trans['ring2'] = (600, 2 * column) # # trans['ring3'] = (1300, 8000 + 2 * column ) for i in range(0, 5, 1): trans["taperH{}".format(i)] = (0, column * i + 100 * self.offset) trans["taperV{}".format(i)] = i3.Rotation( rotation=-90) + i3.Translation( (4000 + column * i - 100 * self.offset, 20000)) trans["recH{}".format(i)] = (900, column * i + 100 * self.offset) trans["recV{}".format(i)] = (4000 + column * i - 100 * self.offset, 20000 - 900) # trans["taper0"] = (0, 0) # trans["taper1"] = i3.HMirror(0) + i3.Translation((2500, -1500)) # trans["taper2"] = i3.HMirror(0) + i3.Translation((2500, 1500)) # # trans["taper3"] = (0, 1 * column) # trans["taper4"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 1 * column)) # # trans["taper5"] = i3.HMirror(0) + i3.Translation((2500, 1500 + 1 * column)) # # trans["taper6"] = (0, 2 * column) # trans["taper7"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 2 * column)) # trans["taper8"] = i3.HMirror(0) + i3.Translation((2500, 1500 + 2 * column)) # # trans["taper9"] = (0, 3800 + 2 * column) # # trans["taper10"] = i3.HMirror(0) + i3.Translation((2500, -1500 + 3 * column)) # # trans["taper11"] = i3.HMirror(0) + i3.Translation((3000, 6500+ 2 * column)) # # trans["taper12"] = i3.HMirror(0) + i3.Translation((3000, 9500+ 2 * column)) return trans def _default_bend_radius(self): bend_radius = 500 return bend_radius def _generate_elements(self, elems): for i in range(0, 5, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="WITDH={}_length={}*2_R=500".format( str(self.width), 17000 - 4000 * i), coordinate=(900, 55 + 4000 * i + 100 * self.offset), font=2, height=20.0, ) for j in range(0, 13, 1): elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(str(i), str(j)), coordinate=(550, 63 + 4000 * i + 100 * j), font=2, height=30.0, ) elems += i3.PolygonText( layer=i3.TECH.PPLAYER.WG.TEXT, text="{}_{}".format(str(i), str(j)), # coordinate=(), font=2, height=30.0, transformation=i3.Rotation(rotation=-90) + i3.Translation( (20000 - 4000 * i - 100 * j + 63, 20000 - 550)), ) for i in range(0, 6, 1): elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 4000 * i - 1000 + 700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, 4000 * i - 1000 + 700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(4000 * i + 300, 19700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(4000 * i + 300, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(-100, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(500, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 19500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, 20100), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(-100, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(100, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(300, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(500, -500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19500), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19700), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 19900), box_size=(100, 100)) elems += i3.Rectangle(layer=i3.TECH.PPLAYER.WG.TEXT, center=(20500, 20100), box_size=(100, 100)) return elems