예제 #1
0
    def init_regions(self):
        self.connections = [DPoint(0, 0), self.dr]
        self.start = DPoint(0, 0)
        self.end = self.start + self.dr
        alpha = atan2(self.dr.y, self.dr.x)
        self.angle_connections = [alpha, alpha]
        alpha_trans = ICplxTrans().from_dtrans(
            DCplxTrans(1, alpha * 180 / pi, False, self.start))

        metal_poly = DSimplePolygon([
            DPoint(0, -self.width / 2),
            DPoint(self.dr.abs(), -self.width / 2),
            DPoint(self.dr.abs(), self.width / 2),
            DPoint(0, self.width / 2)
        ])
        self.connection_edges = [3, 1]
        self.metal_region.insert(pya.SimplePolygon().from_dpoly(metal_poly))
        if (self.gap != 0):
            self.empty_region.insert(
                pya.Box(
                    Point().from_dpoint(DPoint(0, self.width / 2)),
                    Point().from_dpoint(
                        DPoint(self.dr.abs(), self.width / 2 + self.gap))))
            self.empty_region.insert(
                pya.Box(
                    Point().from_dpoint(DPoint(0, -self.width / 2 - self.gap)),
                    Point().from_dpoint(DPoint(self.dr.abs(),
                                               -self.width / 2))))
        self.metal_region.transform(alpha_trans)
        self.empty_region.transform(alpha_trans)
예제 #2
0
    def draw_pinning_holes(self):
        selection_region = Region(
            pya.Box(Point(100e3, 100e3), Point(101e3, 101e3)))
        tmp_ph = self.region_ph.dup()
        other_regs = tmp_ph.select_not_interacting(selection_region)
        reg_to_fill = self.region_ph.select_interacting(selection_region)
        filled_reg = fill_holes(reg_to_fill)

        self.region_ph = filled_reg + other_regs
예제 #3
0
 def _prepare_wall(self):
     self.wall = []
     for Z0 in self.objects:
         if (isinstance(Z0, CPW) and Z0.dr.abs() != 0):
             for ny in range(0, self.Ny):
                 for nx in range(0, self.Nx):
                     x = nx * self.width
                     y = ny * self.height
                     w = Z0.width
                     drLeft = DPoint(-Z0.dr.y, Z0.dr.x) * (1 / Z0.dr.abs())
                     box = pya.DBox(DPoint(x, y),
                                    DPoint(x + self.width, y + self.height))
                     if ((box.left - abs(drLeft.x) * 2 * Z0.b / 2) >
                             Z0.end.x
                             or (box.right + abs(drLeft.x) * 2 * Z0.b / 2) <
                             Z0.start.x):
                         continue
                     if ((box.bottom - abs(drLeft.y) * 2 * Z0.b / 2) >
                             Z0.end.y
                             or (box.top + abs(drLeft.y) * 2 * Z0.b / 2) <
                             Z0.start.y):
                         continue
                     self.wall.append(Point(nx, ny))
     for pt in self.wall:
         self.field[pt.x, pt.y] = -2
예제 #4
0
def pin(w,pin_text, trans, LayerPinRecN, dbu, cell):
  """
  w: Waveguide Width, e.g., 500 (in dbu)
  pin_text: Pin Text, e.g., "pin1"
  trans: e.g., trans =  Trans(0, False, 0, 0)  - first number is 0, 1, 2, or 3.
  pinrec: PinRec Layer, e.g., layout.layer(TECHNOLOGY['PinRec']))
  devrec: DevRec Layer, e.g., layout.layer(TECHNOLOGY['DevRec']))
  """
  
  # Create the pin, as short paths:
  from SiEPIC._globals import PIN_LENGTH

  pin = trans*Path([Point(-PIN_LENGTH/2, 0), Point(PIN_LENGTH/2, 0)], w)
  cell.shapes(LayerPinRecN).insert(pin)
  text = Text (pin_text, trans)
  shape = cell.shapes(LayerPinRecN).insert(text)
  shape.text_size = w*0.8

  print("Done drawing the layout for - pin" )
예제 #5
0
    def init_regions(self):

        self.metal_regions["photo"] = Region()
        self.empty_regions["photo"] = Region()

        self.connections = [DPoint(0, 0), self.dr]
        self.start = DPoint(0, 0)
        self.end = self.start + self.dr
        alpha = atan2(self.dr.y, self.dr.x)
        self.angle_connections = [alpha, alpha]
        alpha_trans = ICplxTrans().from_dtrans(
            DCplxTrans(1, alpha * 180 / pi, False, self.start))
        self.metal_regions['photo'].insert(
            pya.Box(Point().from_dpoint(DPoint(0, -self.width / 2)),
                    Point().from_dpoint(DPoint(self.dr.abs(),
                                               self.width / 2))))
        self.empty_regions['photo'].insert(
            pya.Box(
                Point().from_dpoint(DPoint(0, self.width / 2)),
                Point().from_dpoint(
                    DPoint(self.dr.abs(), self.width / 2 + self.gap))))
        self.empty_regions['photo'].insert(
            pya.Box(
                Point().from_dpoint(DPoint(0, -self.width / 2 - self.gap)),
                Point().from_dpoint(DPoint(self.dr.abs(), -self.width / 2))))
        self.metal_regions['photo'].transform(alpha_trans)
        self.empty_regions['photo'].transform(alpha_trans)
        self.metal_region = self.metal_regions['photo']
        self.empty_region = self.empty_regions['photo']
예제 #6
0
    def init_regions(self):

        self.metal_regions["photo"] = Region()
        self.empty_regions["photo"] = Region()

        self.metal_regions["bridges"] = Region()
        self.empty_regions["bridges"] = Region()

        self.metal_regions["bridge_patches"] = Region()
        self.empty_regions["bridge_patches"] = Region()

        self.connections = [DPoint(0, 0), self.dr]
        self.start = DPoint(0, 0)
        self.end = self.start + self.dr
        alpha = atan2(self.dr.y, self.dr.x)
        self.angle_connections = [alpha, alpha]
        alpha_trans = ICplxTrans().from_dtrans(
            DCplxTrans(1, alpha * 180 / pi, False, self.start))
        self.metal_regions["photo"].insert(
            pya.Box(Point().from_dpoint(DPoint(0, -self.width / 2)),
                    Point().from_dpoint(DPoint(self.dr.abs(),
                                               self.width / 2))))
        self.empty_regions["photo"].insert(
            pya.Box(
                Point().from_dpoint(DPoint(0, self.width / 2)),
                Point().from_dpoint(
                    DPoint(self.dr.abs(), self.width / 2 + self.gap))))
        self.empty_regions["photo"].insert(
            pya.Box(
                Point().from_dpoint(DPoint(0, -self.width / 2 - self.gap)),
                Point().from_dpoint(DPoint(self.dr.abs(), -self.width / 2))))
        self.metal_regions["photo"].transform(alpha_trans)
        self.empty_regions["photo"].transform(alpha_trans)

        if self.dr.x == 0:
            N_bridges = int((self.dr.y - self._bridge_interval) //
                            self._bridge_interval + 1)
            for i in range(N_bridges):
                ab = Airbridge(self.start + DPoint(
                    0,
                    (self._bridge_interval / 2 + i * self._bridge_interval) *
                    sign(self.dr.y)),
                               trans_in=DTrans.R90)
                self.metal_regions["bridges"] += ab.metal_regions["bridges"]
                self.metal_regions["bridges"] += ab.metal_regions[
                    "bridge_patches"]
        elif self.dr.y == 0:
            N_bridges = int((self.dr.x - self._bridge_interval) //
                            self._bridge_interval + 1)
            print("N_bridges", N_bridges)
            for i in range(N_bridges):
                bridge_pos = self.start + DPoint(
                    (self._bridge_interval / 2 + i * self._bridge_interval) *
                    sign(self.dr.x), 0)
                ab = Airbridge(bridge_pos, trans_in=None)
                self.metal_regions["bridges"] += ab.metal_regions["bridges"]
                self.metal_regions["bridge_patches"] += ab.metal_regions[
                    "bridge_patches"]
 def find_path_mur( self, start, end, Nx=15, Ny=15 ):
     self.start_last = start
     self.end_last = end
     self.Nx = Nx
     self.Ny = Ny
     self.width = self.bbox.width()/Nx
     self.height = self.bbox.height()/Ny
     self.field = np.full( (self.Nx,self.Ny), -1, dtype=np.int32 )
     field_start = Point( int(start.x/self.width), int(start.y/self.height) )
     field_end = Point( int(end.x/self.width), int(end.y/self.height) )
     
     self._prepare_wall()
     
     in_propogation = True
     self.field[ field_start.x,field_start.y ] = 0
     field_back_buffer = np.copy( self.field )
     print( self.field, "\n\n" )
     
     while( self.field[ field_end.x, field_end.y] == -1 and in_propogation):
         for x in range( 0,Nx ):
             for y in range( 0,Ny ):
                 if( self.field[x,y] >= 0 ):
                     for dx in [-1,0,1]:
                         for dy in [-1,0,1]:
                             if( (x + dx) >= Nx or (x + dx < 0) or (y + dy) >= Ny or (y + dy < 0) ):
                                 continue
                             if( dy == 0 and dx == 0 ):
                                 continue
                             elif( self.field[x + dx,y + dy] == -1 ):
                                 field_back_buffer[x+dx,y+dy] = self.field[x,y] + 1
         if( np.array_equal( self.field, field_back_buffer ) ):
             in_propogation = False
         np.copyto( self.field, field_back_buffer )
         print( self.field, "\n\n" )    
         
     path = []
     if( self.field[ field_end.x, field_end.y ] > 0 ):
         current = Point( field_end.x, field_end.y )
         while( True ):
             for dx in [-1,0,1]:
                 isNext = False
                 for dy in [-1,0,1]:
                     if( (current.x + dx) >= Nx or (current.x + dx < 0) or (current.y + dy) >= Ny or (current.y + dy < 0) ):
                         continue
                     elif( current == Point(0,0) ):
                         return path
                     else:
                         if( self.field[ current.x + dx, current.y + dy ] == (self.field[current.x,current.y] - 1) ):
                             path.append(current.dup())
                             current.x += dx
                             current.y += dy
                             isNext = True
                             break
                 if( isNext ):
                     break
     else:
         print( "No path is founded" )
         return None
예제 #8
0
    origin = DPoint(0, 0)
    width = 20e3
    gap = 25e3

    Z0 = CPW(width, gap, origin + DPoint(0.5e6, 0.5e6),
             origin + DPoint(1e6, 0.5e6))
    Z0.place(cell, layer_i)
    start = DPoint(0, 0)
    end = DPoint(1e6, 1e6)
    ## pathfinding START ##

    pf = Path_finder(Z0, bbox=CHIP.box)

    path = pf.find_path_mur(start, end, 100, 100)
    ## pathfinding END ##

    ### DRAW SECTION START ###
    for y in range(0, pf.Ny):
        for x in range(0, pf.Nx):
            if (pf.field[x, y] == -2):
                cell.shapes(layer_j).insert(pya.Box().from_dbox(
                    pya.DBox(DPoint(x * pf.width, y * pf.height),
                             DPoint((x + 1) * pf.width, (y + 1) * pf.height))))
            if (Point(x, y) not in path):
                cell.shapes(layer_i).insert(pya.Box().from_dbox(
                    pya.DBox(DPoint(x * pf.width, y * pf.height),
                             DPoint((x + 1) * pf.width, (y + 1) * pf.height))))

    ### DRAW SECTION END ###
    lv.zoom_fit()
### MAIN FUNCTION END ###
info = pya.LayerInfo(1, 0)
info2 = pya.LayerInfo(2, 0)
layer_photo = layout.layer(info)
layer_el = layout.layer(info2)

# clear this cell and layer
cell.clear()

# setting layout view
#lv.select_cell(cell.cell_index(), 0)
lv.add_missing_layers()

#Constants

ground = pya.Box(Point(-CHIP.dx / 2, -CHIP.dy / 2),
                 Point(CHIP.dx / 2, CHIP.dy / 2))
canvas = Region(ground)

ebeam = Region()

#Transmon parameters

xmon_cpw_params = CPWParameters(20e3, 10e3)

arms_vert_len = 144.3e3
arms_hor_len = 200e3
JJ_site_span = 8e3
h_JJ = 278
w_JJ = 150
asymmetry = 0.5
예제 #10
0
	layer_info_photo = pya.LayerInfo(10,0)
	layer_info_el = pya.LayerInfo(1,0)
	layer_photo = layout.layer( layer_info_photo )
	layer_el = layout.layer( layer_info_el )

	# clear this cell and layer
	cell.clear()

	# setting layout view
	if lv:
		lv.select_cell(cell.cell_index(), 0)
		lv.add_missing_layers()


	## DRAWING SECTION START ##
	cell.shapes( layer_photo ).insert( pya.Box( Point(0,0), Point( CHIP.dx, CHIP.dy ) ) )
	origin = DPoint( 0,0 )

	contact_L = 1e6

	# main drive line coplanar
	width = 24.1e3
	gap = 12.95e3
	p1 = DPoint( 0 + contact_L, CHIP.dy/2 )
	p2 = DPoint( CHIP.dx - contact_L, CHIP.dy/2 )
	Z0 = CPW( width, gap, p1, p2 )
	Z0.place( cell, layer_photo )

	# left contact pad
	width1 = CHIP.width*2
	gap1 = CHIP.gap*2
예제 #11
0
    layer_info_photo = pya.LayerInfo(10,0)
    layer_info_el = pya.LayerInfo(1,0)    
    layer_photo = layout.layer( layer_info_photo )
    layer_el = layout.layer( layer_info_el )

    # clear this cell and layer
    cell.clear()

    # setting layout view  
    lv.select_cell(cell.cell_index(), 0)
    lv.add_missing_layers()
    

    
    ## DRAWING SECTION START ##
    cell.shapes( layer_photo ).insert( pya.Box( Point(0,0), Point( CHIP.dx, CHIP.dy ) ) )
    origin = DPoint( 0,0 )
    
    contact_L = 1e6
    
    # main drive line coplanar
    width = 24.1e3
    gap = 12.95e3
    y = 0.2*CHIP.dy
    p1 = DPoint( 0, y )
    p2 = DPoint( CHIP.dx, y )
    Z0 = CPW( width, gap, p1, p2 )
    Z0.place( cell, layer_photo )
    
    
    # resonator
예제 #12
0
info = pya.LayerInfo(1, 0)
info2 = pya.LayerInfo(2, 0)
layer_photo = layout.layer(info)
layer_el = layout.layer(info2)

# clear this cell and layer
cell.clear()

# setting layout view
#lv.select_cell(cell.cell_index(), 0)
lv.add_missing_layers()

#Constants

ground = pya.Box(Point(-(CHIP.dx + 100e3), -(CHIP.dy + 100e3) * 2),
                 Point(CHIP.dx + 100e3, (CHIP.dy + 100e3) * 2))

canvas = Region(ground)

ebeam = Region()

#Transmon parameters

xmon_cpw_params = CPWParameters(20e3, 10e3)

arms_vert_len = 144.3e3
arms_hor_len = 200e3
JJ_site_span = 8e3
h_JJ = 238
w_JJ = 150
    layer_info_photo = pya.LayerInfo(10, 0)
    layer_info_el = pya.LayerInfo(1, 0)
    layer_photo = layout.layer(layer_info_photo)
    layer_el = layout.layer(layer_info_el)

    # clear this cell and layer
    cell.clear()

    # setting layout view
    lv.select_cell(cell.cell_index(), 0)
    lv.add_missing_layers()

    ## DRAWING SECTION START ##
    cell.shapes(layer_photo).insert(
        pya.Box(Point(0, 0), Point(CHIP.dx, CHIP.dy)))
    origin = DPoint(0, 0)

    contact_L = 1e6

    # main drive line coplanar
    width = 24.1e3
    gap = 12.95e3
    p1 = DPoint(0 + contact_L, CHIP.dy / 2)
    p2 = DPoint(CHIP.dx - contact_L, CHIP.dy / 2)
    Z0 = CPW(width, gap, p1, p2)
    Z0.place(cell, layer_photo)

    # left contact pad
    width1 = CHIP.width * 2
    gap1 = CHIP.gap * 2
예제 #14
0
info = pya.LayerInfo(1, 0)
info2 = pya.LayerInfo(2, 0)
layer_photo = layout.layer(info)
layer_el = layout.layer(info2)

# clear this cell and layer
cell.clear()

# setting layout view
#lv.select_cell(cell.cell_index(), 0)
lv.add_missing_layers()

#Constants

ground = pya.Box(Point(-CHIP.dx / 2, -CHIP.dy / 2),
                 Point(CHIP.dx / 2, CHIP.dy / 2))
canvas = Region(ground)

ebeam = Region()

feed_cpw_params = CPWParameters(20e3, 10e3)
md_cpw_params = CPWParameters(7e3, 4e3)
fc_cpw_params = CPWParameters(7e3, 4e3)

### DRAW SECTION START ###

cp1 = Contact_Pad(origin=DPoint(-CHIP.dx / 2, -CHIP.dy / 4),
                  feedline_cpw_params=md_cpw_params)
cp1.place(canvas)
예제 #15
0
    cross_lens = [125e3]
    cross_gnd_gaps = [20e3]
    xmon_dX = 2 * cross_lens[0] + cross_widths[0] + 2 * cross_gnd_gaps[0]
    xmon_distances = [1e3 * x for x in range(393, 394, 10)]
    from itertools import product

    pars = product(cross_widths, cross_lens, cross_gnd_gaps, xmon_distances)
    for cross_width, cross_len, cross_gnd_gap, xmon_distance in pars:
        # clear this cell and layer
        cell.clear()
        xmon_dX = 2 * cross_len + cross_width + 2 * cross_gnd_gap
        CHIP.dx = 5 * xmon_dX + xmon_distance
        CHIP.dy = 5 * xmon_dX + xmon_distance
        CHIP.center = DPoint(CHIP.dx / 2, CHIP.dy / 2)

        chip_box = pya.Box(Point(0, 0), Point(CHIP.dx, CHIP.dy))
        cell.shapes(layer_photo).insert(chip_box)

        xmon_cross1 = Xmon_cross(CHIP.center + DPoint(-xmon_distance / 2, 0),
                                 cross_width, cross_len, cross_gnd_gap)
        xmon_cross1.place(cell, layer_photo)

        xmon_cross2 = Xmon_cross(CHIP.center + DPoint(xmon_distance / 2, 0),
                                 cross_width, cross_len, cross_gnd_gap)
        xmon_cross2.place(cell, layer_photo)

        ## DRAWING SECTION END ##
        # lv.zoom_fit()

        ### MATLAB COMMANDER SECTION START ###
        ml_terminal = SonnetLab()
예제 #16
0
def layout_waveguide4(cell, dpath, waveguide_type, debug=True):

    if debug:
        print('SiEPIC.utils.layout.layout_waveguide4: ')
        print(' - waveguide_type: %s' % (waveguide_type))

    # get the path and clean it up
    layout = cell.layout()
    dbu = layout.dbu
    dpath = dpath.to_itype(dbu)
    dpath.unique_points()
    pts = dpath.get_points()
    dpts = dpath.get_dpoints()

    # Load the technology and all waveguide types
    from SiEPIC.utils import load_Waveguides_by_Tech
    technology_name = layout.technology_name
    waveguide_types = load_Waveguides_by_Tech(technology_name)
    if debug:
        print(' - technology_name: %s' % (technology_name))
        print(' - waveguide_types: %s' % (waveguide_types))

    # Load parameters for the chosen waveguide type
    params = [t for t in waveguide_types if t['name'] == waveguide_type]
    if type(params) == type([]) and len(params) > 0:
        params = params[0]
    else:
        print('error: waveguide type not found in PDK waveguides')
        raise Exception(
            'error: waveguide type (%s) not found in PDK waveguides' %
            waveguide_type)

    # compound waveguide types:
    if 'compound_waveguide' in params:
        # find the singlemode and multimode waveguides:
        if 'singlemode' in params['compound_waveguide']:
            singlemode = params['compound_waveguide']['singlemode']
        else:
            raise Exception(
                'error: waveguide type (%s) does not have singlemode defined' %
                waveguide_type)
        if 'multimode' in params['compound_waveguide']:
            multimode = params['compound_waveguide']['multimode']
        else:
            raise Exception(
                'error: waveguide type (%s) does not have multimode defined' %
                waveguide_type)
        params_singlemode = [
            t for t in waveguide_types if t['name'] == singlemode
        ]
        params_multimode = [
            t for t in waveguide_types if t['name'] == multimode
        ]
        if type(params_singlemode) == type([]) and len(params_singlemode) > 0:
            params_singlemode = params_singlemode[0]
        else:
            raise Exception(
                'error: waveguide type (%s) not found in PDK waveguides' %
                singlemode)
        if type(params_multimode) == type([]) and len(params_multimode) > 0:
            params_multimode = params_multimode[0]
        else:
            raise Exception(
                'error: waveguide type (%s) not found in PDK waveguides' %
                multimode)
        # find the taper
        if 'taper_library' in params[
                'compound_waveguide'] and 'taper_cell' in params[
                    'compound_waveguide']:
            taper = layout.create_cell(
                params['compound_waveguide']['taper_cell'],
                params['compound_waveguide']['taper_library'])
            if not taper:
                raise Exception(
                    'Cannot import cell %s : %s' %
                    (params['compound_waveguide']['taper_cell'],
                     params['compound_waveguide']['taper_library']))
        else:
            raise Exception(
                'error: waveguide type (%s) does not have taper cell and library defined'
                % waveguide_type)
        from pya import Trans, CellInstArray
        '''
        find sections of waveguides that are larger than (2 x radius + 2 x taper_length)
         - insert two tapers
         - insert multimode straight section
         - insert singlemode waveguides (including bends) before
        '''
        import math
        from SiEPIC.extend import to_itype
        from pya import Point
        radius = to_itype(params_singlemode['radius'], dbu)
        taper_length = taper.find_pins()[0].center.distance(
            taper.find_pins()[1].center)
        min_length = 2 * radius + 2 * taper_length
        offset = radius
        wg_sm_segment_pts = []
        wg_last = 0
        waveguide_length = 0
        for ii in range(1, len(dpts)):
            start_point = dpts[ii - 1]
            end_point = dpts[ii]
            distance_points = end_point.distance(start_point)
            if distance_points < min_length:
                # single mode segment, keep track
                if ii == 1:
                    wg_sm_segment_pts.append(pts[ii - 1])
                wg_sm_segment_pts.append(pts[ii])
                if ii == len(pts) - 1:
                    subcell = layout.create_cell("Waveguide_sm_%s" % ii)
                    cell.insert(CellInstArray(subcell.cell_index(), Trans()))
                    waveguide_length += layout_waveguide3(subcell,
                                                          wg_sm_segment_pts,
                                                          params_singlemode,
                                                          debug=True)
            else:
                # insert two tapers and multimode waveguide
                angle = math.atan2(
                    (end_point.y - start_point.y),
                    (end_point.x - start_point.x)) / math.pi * 180
                if ii == 1:
                    wg_first = offset
                else:
                    wg_first = 0
                if ii == len(pts) - 1:
                    wg_last = offset
                if round(angle) % 360 == 270.0:
                    t = Trans(Trans.R270, start_point.x,
                              start_point.y - offset + wg_first)
                    t2 = Trans(Trans.R90, end_point.x,
                               end_point.y + offset - wg_last)
                    wg_start_pt = Point(
                        start_point.x,
                        start_point.y - offset - taper_length + wg_first)
                    wg_end_pt = Point(
                        end_point.x,
                        end_point.y + offset + taper_length - wg_last)
                if round(angle) % 360 == 90.0:
                    t = Trans(Trans.R90, start_point.x,
                              start_point.y + offset - wg_first)
                    t2 = Trans(Trans.R270, end_point.x,
                               end_point.y - offset + wg_last)
                    wg_start_pt = Point(
                        start_point.x,
                        start_point.y + offset + taper_length - wg_first)
                    wg_end_pt = Point(
                        end_point.x,
                        end_point.y - offset - taper_length + wg_last)
                if round(angle) % 360 == 180.0:
                    t = Trans(Trans.R180, start_point.x - offset + wg_first,
                              start_point.y)
                    t2 = Trans(Trans.R0, end_point.x + offset - wg_last,
                               end_point.y)
                    wg_start_pt = Point(
                        start_point.x - offset - taper_length + wg_first,
                        start_point.y)
                    wg_end_pt = Point(
                        end_point.x + offset + taper_length - wg_last,
                        end_point.y)
                if round(angle) % 360 == 0.0:
                    t = Trans(Trans.R0, start_point.x + offset - wg_first,
                              start_point.y)
                    t2 = Trans(Trans.R180, end_point.x - offset + wg_last,
                               end_point.y)
                    wg_start_pt = Point(
                        start_point.x + offset + taper_length - wg_first,
                        start_point.y)
                    wg_end_pt = Point(
                        end_point.x - offset - taper_length + wg_last,
                        end_point.y)
                inst_taper = cell.insert(CellInstArray(taper.cell_index(), t))
                inst_taper = cell.insert(CellInstArray(taper.cell_index(), t2))
                waveguide_length += taper_length * 2
                subcell = layout.create_cell("Waveguide_mm_%s" % ii)
                cell.insert(CellInstArray(subcell.cell_index(), Trans()))
                waveguide_length += layout_waveguide3(subcell,
                                                      [wg_start_pt, wg_end_pt],
                                                      params_multimode,
                                                      debug=True)
                # compound segment
                if ii > 1:
                    wg_sm_segment_pts.append(t.disp.to_p())
                    subcell = layout.create_cell("Waveguide_sm_%s" % ii)
                    cell.insert(CellInstArray(subcell.cell_index(), Trans()))
                    waveguide_length += layout_waveguide3(subcell,
                                                          wg_sm_segment_pts,
                                                          params_singlemode,
                                                          debug=True)
                    wg_sm_segment_pts = [t2.disp.to_p(), pts[ii]]
                else:
                    wg_sm_segment_pts = [t2.disp.to_p(), pts[ii]]

    else:
        # primitive waveguide type
        waveguide_length = layout_waveguide3(cell, pts, params, debug=True)

    return waveguide_length
예제 #17
0
def layout_waveguide3(cell, pts, params, debug=True):

    if debug:
        print('SiEPIC.utils.layout.layout_waveguide3: ')

    layout = cell.layout()
    dbu = layout.dbu
    technology_name = layout.technology_name
    from SiEPIC.utils import get_technology_by_name
    TECHNOLOGY = get_technology_by_name(technology_name)

    from SiEPIC.extend import to_itype
    wg_width = to_itype(params['width'], dbu)
    radius = float(params['radius'])
    model = params['model']
    cellName = 'Waveguide2'
    CML = params['CML']

    if debug:
        print(' - waveguide params: %s' % (params))

    if 'compound_waveguide' in params:
        print('error: this function cannot handle compound waveguides')
        raise Exception(
            'error: this function cannot handle compound waveguides (%s)' %
            waveguide_type)

    # draw the waveguide
    waveguide_length = layout_waveguide2(
        TECHNOLOGY, layout, cell, [wg['layer'] for wg in params['component']],
        [wg['width'] for wg in params['component']],
        [wg['offset'] for wg in params['component']], pts, radius,
        params['adiabatic'], params['bezier'])

    # Draw the marking layers
    from SiEPIC.utils import angle_vector
    LayerPinRecN = layout.layer(TECHNOLOGY['PinRec'])

    make_pin(cell, 'opt1', pts[0], wg_width, LayerPinRecN,
             angle_vector(pts[0] - pts[1]) % 360)
    make_pin(cell, 'opt2', pts[-1], wg_width, LayerPinRecN,
             angle_vector(pts[-1] - pts[-2]) % 360)

    from pya import Trans, Text, Path, Point
    '''
    t1 = Trans(angle_vector(pts[0]-pts[1])/90, False, pts[0])
    cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t1))
    cell.shapes(LayerPinRecN).insert(Text("opt1", t1, 0.3/dbu, -1))
    
    t = Trans(angle_vector(pts[-1]-pts[-2])/90, False, pts[-1])
    cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t))
    cell.shapes(LayerPinRecN).insert(Text("opt2", t, 0.3/dbu, -1))
    '''

    LayerDevRecN = layout.layer(TECHNOLOGY['DevRec'])

    # Compact model information
    angle_vec = angle_vector(pts[0] - pts[1]) / 90
    halign = 0  # left
    angle = 0
    dpt = Point(0, 0)
    if angle_vec == 0:  # horizontal
        halign = 2  # right
        angle = 0
        dpt = Point(0, 0.2 * wg_width)
    if angle_vec == 2:  # horizontal
        halign = 0  # left
        angle = 0
        dpt = Point(0, 0.2 * wg_width)
    if angle_vec == 1:  # vertical
        halign = 2  # right
        angle = 1
        dpt = Point(0.2 * wg_width, 0)
    if angle_vec == -1:  # vertical
        halign = 0  # left
        angle = 1
        dpt = Point(0.2 * wg_width, 0)
    pt2 = pts[0] + dpt
    pt3 = pts[0] - dpt
    pt4 = pts[0] - 6 * dpt
    pt5 = pts[0] + 2 * dpt

    t = Trans(angle, False, pt3)
    text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % CML, t,
                0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt2)
    text = Text('Component=%s' % model, t, 0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt5)
    text = Text('cellName=%s' % cellName, t, 0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pts[0])
    pts_txt = str([[round(p.to_dtype(dbu).x, 3),
                    round(p.to_dtype(dbu).y, 3)]
                   for p in pts]).replace(', ', ',')
    text = Text(
        'Spice_param:wg_length=%.9f wg_width=%.3g points="%s" radius=%.3g' %
        (waveguide_length * 1e-6, wg_width * 1e-9, pts_txt, radius * 1e-6), t,
        0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt4)
    text = Text('Length=%.3f (microns)' % (waveguide_length), t,
                0.5 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)

    return waveguide_length
예제 #18
0
def make_pin(cell, name, center, w, layer, direction, debug=False):
    '''
    Makes a pin that SiEPIC-Tools will recognize
    cell: which cell to draw it in
    name: text label for the pin
    center: location, int [x,y]
    w: pin width
    layer: layout.layer() type
    direction = 
        0: right
        90: up
        180: left
        270: down

    Units: intput can be float for microns, or int for nm
    '''

    from SiEPIC.extend import to_itype
    from pya import Point, DPoint
    import numpy
    dbu = cell.layout().dbu
    if type(w) == type(float()):
        w = to_itype(w, dbu)
        if debug:
            print('SiEPIC.utils.layout.make_pin: w converted to %s' % w)
    else:
        if debug:
            print('SiEPIC.utils.layout.make_pin: w %s' % w)


#    print(type(center[0]))
    if type(center) == type(Point()) or type(center) == type(DPoint()):
        center = [center.x, center.y]
    if type(center[0]) == type(float()) or type(center[0]) == type(
            numpy.float64()):
        center[0] = to_itype(center[0], dbu)
        center[1] = to_itype(center[1], dbu)
        if debug:
            print('SiEPIC.utils.layout.make_pin: center converted to %s' %
                  (center))
    else:
        if debug:
            print('SiEPIC.utils.layout.make_pin: center %s' % (center))

    from SiEPIC._globals import PIN_LENGTH as pin_length

    direction = direction % 360
    if direction not in [0, 90, 180, 270]:
        raise ('error in make_pin: direction must be one of [0, 90, 180, 270]')

    # text label
    t = pya.Trans(pya.Trans.R0, center[0], center[1])
    text = pya.Text(name, t)
    shape = cell.shapes(layer).insert(text)
    shape.text_dsize = float(w * dbu / 2)
    shape.text_valign = 1

    if direction == 0:
        p1 = pya.Point(center[0] - pin_length / 2, center[1])
        p2 = pya.Point(center[0] + pin_length / 2, center[1])
        shape.text_halign = 2
    if direction == 90:
        p1 = pya.Point(center[0], center[1] - pin_length / 2)
        p2 = pya.Point(center[0], center[1] + pin_length / 2)
        shape.text_halign = 2
        shape.text_rot = 1
    if direction == 180:
        p1 = pya.Point(center[0] + pin_length / 2, center[1])
        p2 = pya.Point(center[0] - pin_length / 2, center[1])
        shape.text_halign = 3
    if direction == 270:
        p1 = pya.Point(center[0], center[1] + pin_length / 2)
        p2 = pya.Point(center[0], center[1] - pin_length / 2)
        shape.text_halign = 3
        shape.text_rot = 1

    pin = pya.Path([p1, p2], w)
    cell.shapes(layer).insert(pin)
    layer_info_photo = pya.LayerInfo(10, 0)
    layer_info_el = pya.LayerInfo(1, 0)
    layer_photo = layout.layer(layer_info_photo)
    layer_el = layout.layer(layer_info_el)

    # clear this cell and layer
    cell.clear()

    # setting layout view
    lv.select_cell(cell.cell_index(), 0)
    lv.add_missing_layers()

    ## DRAWING SECTION START ##
    cell.shapes(layer_photo).insert(
        pya.Box(Point(0, 0), Point(CHIP.dx, CHIP.dy)))
    origin = DPoint(0, 0)

    contact_L = 1e6

    # main drive line coplanar
    width = 24.1e3
    gap = 12.95e3
    p1 = DPoint(0 + contact_L, CHIP.dy / 2)
    p2 = DPoint(CHIP.dx - contact_L, CHIP.dy / 2)
    Z0 = CPW(width, gap, p1, p2)
    Z0.place(cell, layer_photo)

    # left contact pad
    width1 = CHIP.width * 2
    gap1 = CHIP.gap * 2
예제 #20
0
fpLayerN = cell_top.layout().layer(lib[layer_floorplan])
TextLayerN = cell_top.layout().layer(lib[layer_text])
# Draw the floor plan
ly_height = 350
ly_width = 600
cell_top.shapes(fpLayerN).insert(Box(0, 0, ly_width / dbu, ly_height / dbu))

#%%Import Grating couplers
GC_imported = ly.create_cell("Grating_Coupler_13deg_TE_1550_Oxide",
                             pdk).cell_index()
GC_pitch = 127
t = Trans(Trans.R0, 0.5 * ly_width / dbu,
          (0.5 * ly_height - GC_pitch / 2) / dbu)
cell_top.insert(
    CellInstArray(GC_imported, t,
                  DPoint(0, GC_pitch).to_itype(dbu), Point(0, 0), 2, 1))

#%%draw waveguide connecting grating couplers
path = [[0.5 * ly_width, 0.5 * ly_height - GC_pitch / 2]]  # start point
path.append([0.5 * ly_width + 50, 0.5 * ly_height - GC_pitch / 2])
path.append([0.5 * ly_width + 50, 0.5 * ly_height + GC_pitch / 2])
path.append([0.5 * ly_width, 0.5 * ly_height + GC_pitch / 2])  # end point
path = DPath([DPoint(each[0], each[1]) for each in path], 0.5)
path = path.to_itype(dbu)
pts = path.get_points()

widths = [0.5]
layers = ['Waveguide']
offset = [0]
radius = 15