class Square(PlaceComponents): size=i3.PositiveNumberProperty(default=20.0, doc="simension of the square of aligning mark") separation=i3.PositiveNumberProperty(default=2.0, doc="simension of the square of aligning mark") square = i3.ChildCellProperty(doc="grating with pitch 1", locked=True) tt_square = i3.TraceTemplateProperty(doc="Wide trace template used ") layName = i3.StringProperty(default = 'new') props = i3.DictProperty() def _default_props(self): return AssignProcess(self.layName) def _default_tt_square(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=(self.size), cladding_width=(self.size), **self.props ) print 'ttw in Square is ', tt_w return tt_w def _default_square(self): rect=i3.Waveguide(trace_template=self.tt_square) layout_rect = rect.Layout(shape=[(0.0, self.size/2.0),(self.size,self.size/2.0)]) print 'The trace template of the hline of the cross ', rect.trace_template return rect def _default_child_cells(self): child_cells={"S1" : self.square, } return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): child_transformations={ "S1" : i3.Translation(translation=(-(self.size*0.5),(-self.size*0.5))), } return child_transformations
class Layout(i3.LayoutView): # Properties ------- # taper to draw taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \ 'Properties = "length", "width1", "width2", "width_etch" ' ) # number of rows n_rows = i3.IntProperty(default=3, doc='number of taper clip rows') # number of taper pairs per row n_taper_pairs_per_row = i3.IntProperty( default=2, doc='number of taper clip pairs per row') # spacing between rows row_spacing = i3.PositiveNumberProperty( default=0.0, doc='spacing between rows (midpoint to midpoint)') # Taper pair properties connect_length = i3.NumberProperty(default=0.0, doc='distance between tapers') pair_connect_length = i3.NumberProperty( default=0.0, doc='distance between taper pairs') # input/output connection length bot_gc_connect_length = i3.NumberProperty( default=0.0, doc='distance between grating and bottom taper') top_gc_connect_length = i3.NumberProperty( default=0.0, doc='distance between grating and top taper') # radius of each arc bend_radius = i3.PositiveNumberProperty( default=5.0, doc='spacing between rows (midpoint to midpoint)') # Methods ------- def _generate_instances(self, insts): # Generates taper clip # make my OWN custom waveguide trace template # wg_trace = f_MyIMECWaveguideTemplate(core_width=self.taper_prop_dict['width1'], # cladding_width=self.taper_prop_dict['width1'] + 2.0 * self.taper_prop_dict['width_etch']) # make waveguide wg = i3.Waveguide(trace_template=StripWgTemplate(), name=self.name + '_WG') wg_round = i3.RoundedWaveguide(trace_template=StripWgTemplate(), name=self.name + '_WG_ROUND') # how much to translate bends left/right # t_left = i3.Translation((self.bend_radius + (float(self.n_rows)/2.0) )) t_left = i3.Translation((-2.5 * self.bend_radius, 0.0)) t_right = i3.Translation((2.5 * self.bend_radius, 0.0)) # draw taper pair rows for ii in range(self.n_rows): # add rows tp_rows_layout = TaperPairRow(name=self.name + '_TProw' + str(ii)).get_default_view( i3.LayoutView) tp_rows_layout.set( taper_prop_dict=self.taper_prop_dict, connect_length=self.connect_length, pair_connect_length=self.pair_connect_length, n_pairs=self.n_taper_pairs_per_row) # set translation t = i3.Translation((0.0, float(ii) * self.row_spacing)) # place taper pair row tp_row_name = self.name + '_TP_ROW' + str(ii) insts += i3.SRef(name=tp_row_name, reference=tp_rows_layout, transformation=t) # draw connecting arcs if ii > 0: if (ii % 2) == 1: # bend on the right # make shape bend row_name = self.name + '_TP_ROW' + str(ii - 1) shape_bend = i3.ShapeBend(start_point=insts[row_name]. ports['right'].position, radius=self.bend_radius, start_angle=-90.05, end_angle=90.05, angle_step=0.1) # add 180 deg bend wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_arc_r' + str(ii)) arc_name = self.name + '_arc' + str(ii) insts += i3.SRef( name=arc_name, reference=wg_copy.Layout(shape=shape_bend), transformation=t_right) # connect bottom wgs # get coords in_port_coords = insts[arc_name].ports['in'].position out_port_coords = insts[row_name].ports[ 'right'].position # draw bezier curve bez = BezierCurve( N=100, P0=(in_port_coords[0] + 0.01, in_port_coords[1]), P1=(in_port_coords[0] - self.bend_radius / 2.0, in_port_coords[1]), P2=(out_port_coords[0] + self.bend_radius / 2.0, out_port_coords[1]), P3=(out_port_coords[0] - 0.01, out_port_coords[1]), R=(-self.bend_radius, +self.bend_radius), dy_dx=(0.0, -0.0)) bez_coords = bez.bezier_coords() # make ipkiss shape s = i3.Shape(bez_coords) # add bottom wg connector wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_arc_r_con' + str(ii)) insts += i3.SRef(name=self.name + '_con_wg_r_b_' + str(ii), reference=wg_copy.Layout(shape=s)) # connect top wgs next_row_name = self.name + '_TP_ROW' + str(ii) in_port_coords = insts[arc_name].ports['out'].position out_port_coords = insts[next_row_name].ports[ 'right'].position # draw bezier curve bez = BezierCurve( N=500, P0=(in_port_coords[0] + 0.01, in_port_coords[1]), P1=(in_port_coords[0] - self.bend_radius / 2.0, in_port_coords[1]), P2=(out_port_coords[0] + self.bend_radius / 2.0, out_port_coords[1]), P3=(out_port_coords[0] - 0.01, out_port_coords[1]), R=(self.bend_radius, -self.bend_radius), dy_dx=(0.0, -0.0)) bez_coords = bez.bezier_coords() # make ipkiss shape s = i3.Shape(bez_coords) # add wg bend wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_bez_r' + str(ii)) insts += i3.SRef(name=self.name + '_con_wg_r_t_' + str(ii), reference=wg_copy.Layout(shape=s)) else: # bend on the left # make shape bend row_name = self.name + '_TP_ROW' + str(ii - 1) shape_bend = i3.ShapeBend(start_point=( insts[row_name].ports['left'].position), radius=self.bend_radius, start_angle=90.05, end_angle=-90.05, angle_step=0.1, clockwise=False) # add 180 deg bend wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_arc_l' + str(ii)) arc_name = self.name + '_arc' + str(ii) insts += i3.SRef( name=arc_name, reference=wg_copy.Layout(shape=shape_bend), transformation=t_left) # connect bottom wgs # get coords in_port_coords = insts[arc_name].ports['out'].position out_port_coords = insts[row_name].ports[ 'left'].position # draw bezier curve bez = BezierCurve( N=100, P0=(in_port_coords[0] - 0.01, in_port_coords[1]), P1=(in_port_coords[0] + self.bend_radius / 2.0, in_port_coords[1]), P2=(out_port_coords[0] - self.bend_radius / 2.0, out_port_coords[1]), P3=(out_port_coords[0] + 0.01, out_port_coords[1]), R=(-self.bend_radius, +self.bend_radius), dy_dx=(0.0, -0.0)) bez_coords = bez.bezier_coords() # make ipkiss shape s = i3.Shape(bez_coords) # add bottom wg connector wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_arc_l_con' + str(ii)) insts += i3.SRef(name=self.name + '_con_wg_l_b_' + str(ii), reference=wg_copy.Layout(shape=s)) # connect top wgs next_row_name = self.name + '_TP_ROW' + str(ii) in_port_coords = insts[arc_name].ports['in'].position out_port_coords = insts[next_row_name].ports[ 'left'].position # draw bezier curve bez = BezierCurve( N=500, P0=(in_port_coords[0] - 0.01, in_port_coords[1]), P1=(in_port_coords[0] + self.bend_radius / 2.0, in_port_coords[1]), P2=(out_port_coords[0] - self.bend_radius / 2.0, out_port_coords[1]), P3=(out_port_coords[0] + 0.01, out_port_coords[1]), R=(-self.bend_radius, +self.bend_radius), dy_dx=(0.0, -0.0)) bez_coords = bez.bezier_coords() # make ipkiss shape s = i3.Shape(bez_coords) # add wg bend wg_copy = i3.Waveguide( trace_template=StripWgTemplate(), name=self.name + '_bez_l' + str(ii)) insts += i3.SRef(name=self.name + '_con_wg_l_t_' + str(ii), reference=wg_copy.Layout(shape=s)) # end if bend # end drawing connecting arcs # end for ii in range(self.rows) # # connect the input grating # # pick grating layout to return # grating_layout = { # 'FGCCTE_FC1DC_625_313': FGCCTE_FC1DC_625_313().Layout(), # 'FGCCTE_FCWFC1DC_630_378': FGCCTE_FCWFC1DC_630_378().Layout(), # 'FGCCTM_FC1DC_984_492': FGCCTM_FC1DC_984_492().Layout(), # }[self.grating_name] # # # # # place bottom grating # # always assuming bottom grating starts on the left # bot_grating_name = self.name+'_bot_grating' # t = i3.vector_match_transform( grating_layout.ports['waveguide'], # insts[self.name + '_TP_ROW0'].ports['left'] ) + \ # i3.Translation( ( -self.bot_gc_connect_length, 0.0 ) ) # # insts += i3.SRef( name = bot_grating_name, # reference = grating_layout, # transformation = t ) # # # connect bottom grating to taper # route_wg_bot = i3.RouteManhattan( input_port = insts[bot_grating_name].ports['waveguide'], # output_port = insts[self.name + '_TP_ROW0'].ports['left'] ) # # # add wg # wg_bot = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_BOT') # insts += i3.SRef(name=self.name + '_connect_wg_bot', reference=wg_bot.Layout(shape=route_wg_bot)) # # # # # place top grating # top_grating_name = self.name + '_top_grating' # if (self.n_rows % 2) == 1: # # even # of rows, output is to the right # t = i3.vector_match_transform( grating_layout.ports['waveguide'], # insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right'], # mirrored = True ) + \ # i3.Translation((self.top_gc_connect_length, 0.0)) # # insts += i3.SRef( name = top_grating_name, # reference = grating_layout, # transformation = t) # # # connect top grating to taper # route_wg_top = i3.RouteManhattan( input_port = insts[top_grating_name].ports['waveguide'], # output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['right']) # # # add wg # wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP') # insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top)) # # else: # # odd # of rows, output is to the left # t = i3.vector_match_transform( grating_layout.ports['waveguide'], # insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left'], # mirrored = False ) + \ # i3.Translation((-self.top_gc_connect_length, 0.0)) # # insts += i3.SRef( name = top_grating_name, # reference = grating_layout, # transformation = t) # # # connect top grating to taper # route_wg_top = i3.RouteManhattan( input_port = insts[top_grating_name].ports['waveguide'], # output_port = insts[self.name + '_TP_ROW' + str(self.n_rows-1)].ports['left']) # # # add wg # wg_top = i3.Waveguide( trace_template = StripWgTemplate(), name = self.name + '_WG_TOP') # insts += i3.SRef(name=self.name + '_connect_wg_top', reference=wg_top.Layout(shape=route_wg_top)) return insts
class Layout(i3.LayoutView): # Properties ------- # taper to draw taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \ 'Properties = "length", "width1", "width2", "width_etch" ' ) # connecting length between tapers connect_length = i3.NumberProperty(default=0.0, doc='distance between tapers') # connecting length between taper PAIRS pair_connect_length = i3.NumberProperty( default=0.0, doc='distance between taper pairs') # number of taper pairs n_pairs = i3.IntProperty(default=1, doc='number of taper pairs') # Methods ------- def _generate_instances(self, insts): # Generates taper pairs tp_name_list = [] for ii in range(self.n_pairs): # for each pair # draw taper pair layout tp_lay = TaperPair(name=self.name + '_tp' + str(ii)).get_default_view(i3.LayoutView) tp_lay.set(taper_prop_dict=self.taper_prop_dict, connect_length=self.connect_length) # set name tp_name = 'tp' + str(ii) tp_name_list.append(tp_name) # set transformation if ii > 0: # set transform t = i3.vector_match_transform( tp_lay.ports['left'], insts[ tp_name_list[ii - 1] ].ports['right']) \ + i3.Translation( ( self.pair_connect_length, 0.0 ) ) # print t # draw next taper pair insts += i3.SRef(name=tp_name, reference=tp_lay, transformation=t) # route wg route_wg = i3.RouteManhattan( input_port=insts[tp_name_list[ii - 1]].ports['right'], output_port=insts[tp_name_list[ii]].ports['left']) # # make my OWN custom waveguide trace template # wg_trace = f_MyIMECWaveguideTemplate( core_width = self.taper_prop_dict['width1'], # cladding_width = self.taper_prop_dict['width1'] + 2.0*self.taper_prop_dict['width_etch'] ) # make waveguide wg = i3.Waveguide(trace_template=StripWgTemplate(), name=self.name + '_WG' + str(ii)) # add wg insts += i3.SRef(name=self.name + 'connect_wg' + str(ii), reference=wg.Layout(shape=route_wg)) else: # draw first taper pair insts += i3.SRef(name=tp_name, reference=tp_lay) # DEBUG # print insts # end if else return insts # end _generate_instances() def _generate_ports(self, ports): # add ports 'left' and 'right' # left port ports += i3.OpticalPort( name='left', position=self.instances['tp0'].ports['left'].position, angle=180.0) # right port ports += i3.OpticalPort( name='right', position=self.instances['tp' + str(self.n_pairs - 1)].ports['right'].position, angle=0.0) return ports
class Layout(i3.LayoutView): # Properties ------- taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \ 'Properties = "length", "width1", "width2", "width_etch" ' ) # Methods ------- def _generate_instances(self, insts): # Generates taper clip # taper clip defaults n_rows = 3 n_taper_pairs_per_row = [1, 3, 5] row_spacing = 15.0 grating_name = 'FGCCTE_FCWFC1DC_630_378' connect_length = 5.0 pair_connect_length = 5.0 bot_gc_connect_length = 15.0 top_gc_connect_length = 15.0 bend_radius = 10.0 # taper properties # taper_prop_dict = { # 'length': 100.0, # 'width1': 0.450, # 'width2': 11.0, # 'width_etch': 2.0 # } # add first taper clip tc1_name = self.name + '_tc1' taper_clip_layout = TaperClip(tc1_name).get_default_view( i3.LayoutView) taper_clip_layout.set( n_rows=n_rows, n_taper_pairs_per_row=n_taper_pairs_per_row[0], row_spacing=row_spacing, grating_name=grating_name, connect_length=connect_length, pair_connect_length=pair_connect_length, bot_gc_connect_length=bot_gc_connect_length, top_gc_connect_length=top_gc_connect_length, bend_radius=bend_radius, taper_prop_dict=self.taper_prop_dict) # plop it down insts += i3.SRef(name=tc1_name, reference=taper_clip_layout) # add second taper clip tc2_name = self.name + '_tc2' taper_clip_layout = TaperClip(tc2_name).get_default_view( i3.LayoutView) taper_clip_layout.set( n_rows=n_rows, n_taper_pairs_per_row=n_taper_pairs_per_row[1], row_spacing=row_spacing, grating_name=grating_name, connect_length=connect_length, pair_connect_length=pair_connect_length, bot_gc_connect_length=bot_gc_connect_length, top_gc_connect_length=top_gc_connect_length, bend_radius=bend_radius, taper_prop_dict=self.taper_prop_dict) # plop it down tc1_size_info = insts[tc1_name].size_info() tc2_size_info = taper_clip_layout.size_info() t = i3.vector_match_transform( i3.OpticalPort(name='temp1', position=(tc2_size_info.west, 0.0), angle=180.0), i3.OpticalPort(name='temp2', position=(tc1_size_info.east, 0.0), angle=0.0)) t += i3.Translation((-25.0, 0.0)) insts += i3.SRef(name=tc2_name, reference=taper_clip_layout, transformation=t) # add third taper clip tc3_name = self.name + '_tc3' taper_clip_layout = TaperClip(tc3_name).get_default_view( i3.LayoutView) taper_clip_layout.set( n_rows=n_rows, n_taper_pairs_per_row=n_taper_pairs_per_row[2], row_spacing=row_spacing, grating_name=grating_name, connect_length=connect_length, pair_connect_length=pair_connect_length, bot_gc_connect_length=bot_gc_connect_length, top_gc_connect_length=top_gc_connect_length, bend_radius=bend_radius, taper_prop_dict=taper_prop_dict) # plop it down tc2_size_info = insts[tc2_name].size_info() tc3_size_info = taper_clip_layout.size_info() pos = (0.0, 60.0) insts += i3.SRef(name=tc3_name, reference=taper_clip_layout, position=pos) # t = i3.vector_match_transform( # i3.OpticalPort(name='temp1', position=(tc3_size_info.west, 0.0), angle=180.0), # i3.OpticalPort(name='temp2', position=(tc2_size_info.east, 0.0), angle=0.0) ) # t += i3.Translation( (-25.0, 0.0) ) # insts += i3.SRef( name = tc3_name, # reference = taper_clip_layout, # transformation = t ) return insts
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 AligningMarks(PlaceComponents): tt_cross = i3.TraceTemplateProperty(doc="Wide trace template used for the contact pads") hline = i3.ChildCellProperty(doc="Horizontal line", locked=True) vline = i3.ChildCellProperty(doc="Vertical", locked=True) square = i3.ChildCellProperty(doc="Vertical", locked=True) size=i3.PositiveNumberProperty(default=250.0, doc="bigger dimension of aligning mark") width=i3.PositiveNumberProperty(default=20.0, doc="smaller dimension of aligning mark") #Pitch1=i3.PositiveNumberProperty(default=2.0, doc="pitch grating 1") separation=i3.NumberProperty(default=100.0, doc="separation between cross and gratings") #dc=i3.PositiveNumberProperty(default=0.47, doc="duty cycle") layName = i3.StringProperty(default = 'metal2') props = i3.DictProperty() def _default_props(self): return AssignProcess(self.layName) def _default_tt_cross(self): tt_w = WireWaveguideTemplate() tt_w.Layout(core_width=(self.width), cladding_width=(self.width), **self.props ) return tt_w def _default_hline(self): rect=i3.Waveguide(trace_template=self.tt_cross) layout_rect = rect.Layout(shape=[(0.0, self.size/2.0),(self.size,self.size/2.0)]) print 'The trace template of the hline of the cross ', rect.trace_template return rect def _default_vline(self): rect=i3.Waveguide(trace_template=self.tt_cross) layout_rect = rect.Layout(shape=[(self.size/2.0, 0.0),(self.size/2.0,self.size)]) print 'The trace template of the vline of the cross ', rect.trace_template return rect def _default_square(self): #square=Square(size=self.width, layName=self.layName) square=Square(size=self.width, layName='metal') #square.Layout().visualize() return square def _default_child_cells(self): child_cells={"S1" : self.square, "S2" : self.square, "S3" : self.square, "S4" : self.square, "V" : self.vline, "H" : self.hline } return child_cells class Layout(PlaceComponents.Layout): def _default_child_transformations(self): child_transformations={"S1" : i3.Translation(translation=(-(self.width+5.0),(self.width+5.0))), "S2" : i3.Translation(translation=((self.width+5.0),(self.width+5.0))), "S3" : i3.Translation(translation=(-(self.width+5.0),-(self.width+5.0))), "S4" : i3.Translation(translation=((self.width+5.0),-(self.width+5.0))), "V" : i3.Translation(translation=(0.0, 0.0))+ i3.Translation(translation=(-(self.size)/2.0,-(self.size)/2.0)), "H" : i3.Translation(translation=(0.0, 0.0))+ i3.Translation(translation=(-(self.size)/2.0,-(self.size)/2.0)) } return child_transformations
class APAC(AutoPlaceAndConnect): connectors = i3.ListProperty( doc= "list of tuples that need to be replaced by connectors. Format is [('inst1:term1','inst2:term2', connector_func=None, connector_kwargs, ...]", restriction=i3.RestrictTypeList(allowed_types=[collections.Sequence])) connector_function = i3.CallableProperty( doc="Connector function used by default if nothing is specified") connector_kwargs = i3.DictProperty( doc="Routing kwargs passed if nothing is specified") electrical_links = i3.ListProperty(default=[], doc="List of electrical links") propagated_electrical_ports = i3.ListProperty( default=[], doc= "List of electrical ports that are propagated to the next level. By default None are propagated" ) def connector_less_apac(self): """ generete a connectorless apac to get the location of all the instances. """ lv = self.get_default_view(i3.LayoutView) temp_apac = APAC(name="{}_connectorless".format(self.name), child_cells=self.child_cells, links=self.links) temp_apac_lv = temp_apac.Layout( child_transformations=lv.child_transformations, mirror_children=lv.mirror_children) return temp_apac_lv @i3.cache() def get_child_instances(self): return self.connector_less_apac().instances def _default_connector_function(self): return manhattan def _default_connector_kwargs(self): return {} def _default__connector_cells(self): connector_cells = [] if len(self.connectors) > 0: clv = self.connector_less_apac() for cnt, c in enumerate(self.connectors): connector_function = self.connector_function connector_kwargs = self.connector_kwargs start_port = get_port_from_interface(port_id=c[0], lv=clv) end_port = get_port_from_interface(port_id=c[1], lv=clv) if len(c) > 2: if c[2] is not None: connector_function = c[2] if len(c) == 4: if c[3] is not None: connector_kwargs = c[3] name = self.name + "_connector_{}".format(cnt) cell = connector_function(start_port=start_port, end_port=end_port, name=name, connector_kwargs=connector_kwargs) connector_cells.append(cell) return connector_cells class Layout(AutoPlaceAndConnect.Layout): metal1_layer = i3.LayerProperty( doc="layer used for the electrical links") metal1_width = i3.PositiveNumberProperty( default=5, doc="Width of the metal1 paths") electrical_routes = i3.ListProperty( doc= "routes used for the electical connections. Is has the same length as electical links. None will use Routemanhatan" ) def _default_metal1_layer(self): return i3.TECH.PPLAYER.M1.LINE def _default_electrical_routes(self): return [None] * len(self.electrical_links) @i3.cache() def _get_final_electrical_routes(self): final_routes = [] for c, r in zip(self.electrical_links, self.electrical_routes): if r is None: inst1, port1 = self._resolve_inst_port(c[0]) inst2, port2 = self._resolve_inst_port(c[1]) route = i3.RouteManhattan(input_port=port1, output_port=port2, angle_out=0.0, angle_in=0.0, rounding_algorithm=None) final_routes.append(route) else: final_routes.append(r) return final_routes @i3.cache() def _get_electrical_route_elements(self): els = [] for r in self._get_final_electrical_routes(): els += i3.Path(layer=self.metal1_layer, shape=r, line_width=self.metal1_width) return els def _generate_elements(self, elems): elems = super(APAC.Layout, self)._generate_elements(elems) elems.extend(self._get_electrical_route_elements()) return elems def _generate_ports(self, ports): connected_links = [p[0].replace(':', '_') for p in self.links] + [ p[1].replace(':', '_') for p in self.links ] connected_links.extend( [p[0].replace(':', '_') for p in self.connectors] + [p[1].replace(':', '_') for p in self.connectors]) for key, val in self._get_child_cell_instances().iteritems(): if key in self.child_cells.keys(): for p in val.ports: name = "{}_{}".format(key, p.name) if name not in connected_links: ext_key = '{}:{}'.format(key, p.name) if ext_key in self.cell.external_port_names: name = self.cell.external_port_names[ext_key] if p.domain is i3.ElectricalDomain and name not in self.propagated_electrical_ports: pass else: ports.append(p.modified_copy(name=name)) return ports class Netlist(AutoPlaceAndConnect.Netlist): def _generate_terms(self, terms): from ipkiss3.pcell.netlist.term import TermDict terms = super(AutoPlaceAndConnect.Netlist, self)._generate_terms(terms) new_terms = TermDict() for key, val in terms.iteritems(): if val.domain is i3.ElectricalDomain and val.name not in self.propagated_electrical_ports: pass else: new_terms[key] = val return new_terms
class Layout(i3.LayoutView): # Properties ------- # taper to draw # taper_layout = i3.ViewProperty( default='', doc='taper cell to draw and stuff' ) # connecting length between tapers connect_length = i3.NumberProperty(default=0.0, doc='distance between tapers') # taper cell # taper_cell = i3.PCellProperty( default=i3.PCell(), doc='taper cell to draw') taper_prop_dict = i3.DictProperty( default = {}, doc = 'Dictionary of taper cell properties.' + \ 'Properties = "length", "width1", "width2", "width_etch" ' ) # this is terrible... # actually f**k it hard code in the taper # Methods ------- def _generate_instances(self, insts): # generates taper pair # generate left taper cell taper_layout_left = ParabolicTaper( name=self.name + '_TAPER_L').get_default_view(i3.LayoutView) taper_layout_left.set( length=self.taper_prop_dict['length'], width1=self.taper_prop_dict['width1'], width2=self.taper_prop_dict['width2'], width_etch=self.taper_prop_dict['width_etch']) # generate right taper cell taper_layout_right = ParabolicTaper( name=self.name + '_TAPER_R').get_default_view(i3.LayoutView) taper_layout_right.set( length=self.taper_prop_dict['length'], width1=self.taper_prop_dict['width1'], width2=self.taper_prop_dict['width2'], width_etch=self.taper_prop_dict['width_etch']) # draw taper pairs insts += i3.SRef(name=self.name + '_taper1', reference=taper_layout_left) t = i3.vector_match_transform(taper_layout_left.ports['right'], taper_layout_right.ports['right'], mirrored=True) + i3.Translation( (self.connect_length, 0.0)) insts += i3.SRef(name=self.name + '_taper2', reference=taper_layout_right, transformation=t) # route between tapers if self.connect_length > 0.0: route_tapers = i3.RouteManhattan( input_port=insts[self.name + '_taper1'].ports['right'], output_port=insts[self.name + '_taper2'].ports['right']) # # make my OWN custom waveguide trace template # wg_trace = f_MyIMECWaveguideTemplate( core_width = taper_layout_left.width2, # cladding_width = taper_layout_right.width2 + 2.0*taper_layout_right.width_etch ) # wg_lay = i3.Waveguide(trace_template=StripWgTemplate(), name=wg_name).get_default_view(i3.LayoutView) # make waveguide wg = i3.Waveguide(trace_template=StripWgTemplate(), name=self.name + '_WG') # add wg insts += i3.SRef(name=self.name + 'connect_wg', reference=wg.Layout(shape=route_tapers)) # end if self.connect_length > 0.0 return insts # end _generate_instances() def _generate_ports(self, ports): # add ports 'left' and 'right' # left port ports += i3.OpticalPort( name='left', position=self.instances[self.name + '_taper1'].ports['left'].position, angle=180.0) # right port ports += i3.OpticalPort( name='right', position=self.instances[self.name + '_taper2'].ports['left'].position, angle=0.0) return ports