Exemplo n.º 1
0
 def init_regions( self ):
     self.P0 = DPoint( 0,0 )
     self.P1 = self.P0 + DPoint( self.Z1.gap,0 )
     self.P2 = self.P1 + DPoint( self.Z1.width,0 )
     self.P3 = self.P2 + DPoint( 0,self.Z1.gap )
     self.P4 = self.P2 + DPoint( self.Z1.gap, self.Z2.gap )
     self.P5 = self.P4 + DPoint( 0,self.Z2.width )
     self.P6 = DPoint( 0, self.Z1.gap + self.Z1.width )
     self.P7 = DPoint( 0, self.Z1.gap )
     self.P8 = self.P7 + DPoint( self.Z1.gap,0 )
     self.P9 = self.P2 + DPoint( self.Z1.gap,0 )
     self.P10 = self.P5 + DPoint( 0, self.Z2.gap )
     self.P11 = self.P10 - DPoint( 2*self.Z1.gap + self.Z1.width, 0 )
     self.P12 = self.P6 + DPoint( 0, self.Z1.gap )
     
     self.connections = [(self.P6 + self.P7)*0.5,(self.P1 + self.P2)*0.5,(self.P5 + self.P4)*0.5]
     self.angle_connections = [0,3/2*pi,0]
             
     self.metal_polygon = DPolygon( [self.P1,self.P2,self.P3,self.P4,self.P5,self.P6,self.P7,self.P8] )
     self.empty1_polygon = DPolygon( [self.P0,self.P1,self.P8,self.P7] )
     self.empty2_polygon = DPolygon( [self.P2,self.P9,self.P4,self.P3]  )
     self.empty3_polygon = DPolygon( [self.P5,self.P10,self.P12,self.P6] )
     self.gnd_polygon = DPolygon( [self.P10,self.P11,self.P12] )
     self.metal_region = pya.Region( list(map(pya.Polygon().from_dpoly,[self.metal_polygon,self.gnd_polygon])) )
     self.empty_region = pya.Region( list(map(pya.Polygon().from_dpoly ,[self.empty1_polygon,self.empty2_polygon,self.empty3_polygon])) )
Exemplo n.º 2
0
def sub(layout, cell, slayers, dlayers, ex_amount, layers, out_cell=None):
    """Analogous to :func:`~kppc.photonics.dataprep.add`

    Instead of perfoming a combination with the destination layers, this function will substract the input region.
    """
    if out_cell:
        o_cell = out_cell
    else:
        o_cell = cell

    am = ex_amount / layout.dbu

    srclayers = [slayers, ] if isinstance(slayers, str) else slayers
    dstlayers = [dlayers, ] if isinstance(dlayers, str) else dlayers

    in_layers = [layout.layer(layers[m][0], layers[m][1]) for m in srclayers]
    region = pya.Region()
    for layer in in_layers:
        if layer != -1:
            shapeit = layout.begin_shapes(cell, layer)
            region.insert(shapeit)
    region.merge()
    if ex_amount != 0:
        region.size(am)
        region.merge()
    for layer in dstlayers:
        sub_region = pya.Region()
        layer_n, layer_d = layers[layer]
        l = layout.layer(layer_n, layer_d)
        shapeit = o_cell.begin_shapes_rec(l)
        sub_region.insert(shapeit)
        sub_region.merge()
        o_cell.shapes(l).clear()
        o_cell.shapes(l).insert(sub_region - region)
Exemplo n.º 3
0
 def DrawBoxesInRegion(cell,
                       layer,
                       region,
                       dlength,
                       dgap,
                       dx=0,
                       dy=0,
                       filterfunc=None):
     d = dlength + dgap
     area = region.bbox()
     dx = dx % d
     dy = dy % d
     left = floor((area.left - dx) / d)
     bottom = floor((area.bottom - dy) / d)
     right = ceil((area.right - dx) / d)
     top = ceil((area.top - dy) / d)
     x0 = left * d + dx
     y0 = bottom * d + dy
     boxesregion = pya.Region()
     for ii in range(right - left):
         for jj in range(top - bottom):
             x1 = x0 + ii * d
             y1 = y0 + jj * d
             box = pya.Box(x1, y1, x1 + dlength, y1 + dlength)
             boxesregion.insert(box)
     andRegion = boxesregion & region
     if filterfunc:
         andRegion_ = pya.Region()
         for pp in andRegion.each():
             if filterfunc(pp):
                 andRegion_.insert(pp)
         andRegion = andRegion_
     BasicPainter.Draw(cell, layer, andRegion)
     return andRegion
Exemplo n.º 4
0
def do_fill():
    cfg = read_cfg()
    setup_cfg(cfg)

    # Map outline from GDS to layer index
    outline = cfg['outline']
    outline_index = main_layout.find_layer(outline['layer'],
                                           outline['datatype'])

    for layer, layer_cfg in cfg['layers'].items():
        print('INFO: Performing fill for {} [gds={}:{} klayout={}]'.format(
            layer, layer_cfg['layer'], layer_cfg['datatype'],
            layer_cfg['klayout']))

        outline_area = pya.Region(fill_top_cell.bbox_per_layer(outline_index))
        outline_area.size(-layer_cfg['space_to_outline'])

        shapes_area = pya.Region(fill_top_cell.shapes(layer_cfg['klayout']))

        do_non_opc_fill(fill_top_cell, layer, layer_cfg, outline_area,
                        shapes_area)
        do_opc_fill(fill_top_cell, layer, layer_cfg, outline_area, shapes_area)

    # Discards the flatten shapes from the design but keeps the fill instances
    fill_top_cell.clear_shapes()

    print('INFO: Writing gds: ' + out_gds)
    main_layout.write(out_gds)

    print('INFO: Fill finished')
    print('\t time taken: %.2f seconds ' % (time.time() - start_time))
Exemplo n.º 5
0
  def produce_impl(self):
  
    # fetch the parameters
    dbu = self.layout.dbu
    ly = self.layout

    LayerSi = self.layer
    LayerSiN = ly.layer(self.layer)
    LayerPinRecN = ly.layer(self.pinrec)
    LayerDevRecN = ly.layer(self.devrec)
    LayerTextN = ly.layer(self.textl)
    LayerEtch = ly.layer(self.etch)
    TextLayerN = ly.layer(self.textl)

    # Fetch all the parameters:
    a = self.a/dbu
    r = self.r/dbu
    n_vertices = self.n_vertices
    n = int(math.ceil(self.n/2))
    #print(n)
    n_sweep = self.n_sweep
    n_x = n
    n_y = n
  

    # Define Si slab and hole region for future subtraction
    Si_slab = pya.Region()
    hole = pya.Region()
    ruler = pya.Region()
    #hole_r = [r+50,r}
    '''
def main():
    # Loop each cut map, & export each GDS as unique name
    for key in cut_d:
        filename = "2_" + key  # Add prefix to the filename
        print("\nfilename : ", filename)

        # Get 1_UNIT (no cuts as a reference) & create SINGLE instance
        for i in gdsFiles:
            layout.read(i)

            for cell in layout.top_cells():
                # we don't want to insert the topcell itself
                if (cell.name != "1_UNIT_CUTS"):
                    print("Adding : " + cell.name)
                    cell_index = cell.cell_index()
                    new_instance = pya.CellInstArray(
                        cell_index, pya.Trans(pya.Point(0, 0)))
                    UNIT.insert(new_instance)

        # Define imported metal as a region (for boolean)
        region_metal = pya.Region(layout.top_cell().begin_shapes_rec(l_metal))

        # Define cut area & make as region
        for ind, each_cut in enumerate(cut_d[key]):
            cut_box_coord = get_cut_coord(each_cut, d)
            UNIT.shapes(l_cut_box).insert(cut_box_coord)
            region_cut_box = pya.Region(cut_box_coord)
            # Do boolean (XOR)
            # For more than 1 cuts, need to loop and take XOR of previous XOR results
            if ind == 0:
                region_xor = region_metal ^ region_cut_box
            else:
                region_xor = region_xor ^ region_cut_box

        # Remove existings metal layer + cut boxes
        # (!!! SKIP THIS TO CHECK CUT BOXES IN GDS !!!)
        layout.clear_layer(l_metal)
        layout.clear_layer(l_cut_box)

        # INSERT BOOLEAN RESULT AS ORIGINAL METAL LAYER
        UNIT.shapes(l_metal).insert(region_xor)

        # Check if filename gds exists -> If so skip "write"
        if os.path.isfile(root + "/" + filename + ".gds"):
            print("**** GDS name by : " + filename + ".gds already exists!")
            print("**** SKIPPING GDS WRITE!!!")
        else:
            # Export GDS
            layout.write(filename + ".gds")

            # Check if this cell can be used as another at different coordinate
            dup_l = get_dup_names(filename + ".gds")
            if dup_l[0] != '':
                for each in dup_l:
                    print("Create copy as : ", each,
                          "  <-----------------------------------------")
                    layout.write(each)
Exemplo n.º 7
0
    def pieceHolderCassette(self, dbu=1):
        '''
      pieceHolderCassette()
      
      Generates the shape of the Jeol JBX-5500FS piece holder cassette
      
      Parameters
      ---------
      dbu : double
            The database unit
            
      Returns
      ------
      region : [pya.Region]
           A region containing the piece holder cassette shape
           
      Description
      ------
      The center of this piece holder shape (0,0) is at stage position (62.5mm, 37.5mm)
      
      Jeol Stage Y axis is reverse of KLayout Y axis
      '''
        # Create the quarter circle
        r = 36100 / dbu
        rx = 62500 / dbu
        ry = -37500 / dbu
        polygon = pya.Polygon([
            pya.Point(-r, -r),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, -r)
        ])
        polygon = polygon.round_corners(0, r, 128)
        rectangle = pya.Polygon([
            pya.Point(-r, 0),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, 0)
        ])
        tt = pya.ICplxTrans(1, 90, False, 0, 0)
        qCircle = pya.Region(polygon) - pya.Region(rectangle) - pya.Region(
            rectangle.transform(tt))

        # Create the trapezoid
        trapezoid = pya.Polygon([
            pya.Point(49500 / dbu, -70500 / dbu),
            pya.Point(40500 / dbu, -20500 / dbu),
            pya.Point(60500 / dbu, -20500 / dbu),
            pya.Point(51500 / dbu, -70500 / dbu)
        ])
        tt = pya.ICplxTrans(-rx, -ry)

        cassette = qCircle + pya.Region(trapezoid.transform(tt))

        return cassette
Exemplo n.º 8
0
    def ring(self, outerDiameter, innerDiameter, vertices=128, fracture=True):
        '''
      circle(outerDiameter, innerDiameter, vertices)
      
      Generates a circle shape
      
      Parameters
      ---------
      outerDiameter : integer
            The outer diameter of the ring
      innerDiameter : integer
            The inner diameter of the ring
      vertices : integer (128)
            Number of vertices in the circle (coerce to multiples of 4)
      fracture : boolean (True)
            Create the inner polygon with vertices that is optimal for fracturing horizontally
      
      Returns
      ------
      region : [pya.Region]
           A region containing the circle shape
      '''
        ro = int(outerDiameter / 2)
        ri = int(innerDiameter / 2)
        vertices = int(vertices / 4) * 4

        # Create a circle
        polygon = pya.Polygon([
            pya.Point(-ro, -ro),
            pya.Point(-ro, ro),
            pya.Point(ro, ro),
            pya.Point(ro, -ro)
        ])
        polygonOuter = polygon.round_corners(0, ro, vertices)
        polygon = pya.Polygon([
            pya.Point(-ri, -ri),
            pya.Point(-ri, ri),
            pya.Point(ri, ri),
            pya.Point(ri, -ri)
        ])

        if fracture:
            points = polygonOuter.each_point_hull()
            polygonInnerPoints = []
            r2 = np.power(ri, 2)
            for point in points:
                if (ri > np.absolute(point.y)):
                    x = np.sqrt(r2 - np.power(point.y, 2))
                    polygonInnerPoints.append(
                        pya.Point(np.sign(point.x) * x, point.y))
            polygonInner = pya.Polygon(polygonInnerPoints)
        else:
            polygonInner = polygon.round_corners(0, ri, vertices)

        return pya.Region(polygonOuter) - pya.Region(polygonInner)
Exemplo n.º 9
0
  def siWafer(self, diameter, primaryFlat, secondaryFlat, angle, vertices = 128):
      '''
      siWafer(diameter, secondaryFlatAngle)
      
      Generates a Silicon Wafer shape
      
      Parameters
      ---------
      diameter : integer
            The diameter of a standard silicon wafer
      primaryFlat : integer
            The length of the primary flat
      secondaryFlat : integer
            The length of the secondary flat
      angle : double
            The location of the secondary flat relative (counterclockwise) to primary flat
      vertices : integer (coerce to even number)
            The number of vertices used to generate the circle
      
      Returns
      ------
      region : [pya.Region]
           A region containing the Si Wafer shape
      
      Description
      ---------
      SEMI Wafer Flat M1-0302 Specification
      Wafer Size  = [2", 3", 100mm, 125mm, 150mm, 200mm, 300mm]
      Diameter [mm] = [50.8, 76.2, 100, 125, 150, 200, 300]
      Thickness [um] = [279, 381, 525 or 625, 625, 675 or 625, 725, 775]
      Primary Flat Length = [15.88, 22.22, 32.5, 42.5, 57.5, Notch, Notch]
      Secondary Flat Length = [8, 11.18, 18, 27.5, 37.5, NA, NA]
      '''
      dList = [50800, 76200, 10000, 12500, 15000]
      pFlatLengthList = [15.88, 22.22, 32.5, 42.5, 57.5]
      sFlatLengthList = [8, 11.18, 18, 27.5, 37.5]
      
      r = int(diameter/2)
      
      #Height of arc position (https://mathworld.wolfram.com/CircularSegment.html)
      pH = r- int(np.sqrt(4*np.power(r,2)-np.power(primaryFlat,2))/2)
      sH = r - int(np.sqrt(4*np.power(r,2)-np.power(secondaryFlat,2))/2)
      
      # Create a circle
      polygon = pya.Polygon([pya.Point(-r,-r), pya.Point(-r,r), pya.Point(r,r), pya.Point(r,-r)])
      polygon = polygon.round_corners(0,r,vertices)
      
      #Create a rectangle to produce the primary flat
      pRectangle = pya.Polygon([pya.Point(-r,r-pH), pya.Point(-r,r+pH), pya.Point(r,r+pH), pya.Point(r,r-pH)])
      
      #Create a rectangle to produce the secondary flat
      sRectangle = pya.Polygon([pya.Point(-r,r-sH), pya.Point(-r,r+sH), pya.Point(r,r+sH), pya.Point(r,r-sH)])
      tt = pya.ICplxTrans(1, angle, False, 0, 0)

      return pya.Region(polygon)-pya.Region(pRectangle)-pya.Region(sRectangle.transform(tt))
Exemplo n.º 10
0
 def Output_Region(self):
     polygonsout=[]
     for x in self.regionlistout:
         if isinstance(x,pya.DPolygon):
             polygonsout.append(pya.Polygon.from_dpoly(x))
     self.regionlistout=[]
     polygonsin=[]
     for x in self.regionlistin:
         if isinstance(x,pya.DPolygon):
             polygonsin.append(pya.Polygon.from_dpoly(x))
     self.regionlistin=[]
     return pya.Region(polygonsout)-pya.Region(polygonsin)
Exemplo n.º 11
0
def main():

    # Loop each cut locations, & assign GDS name from key
    for key in cut_loc:
        filename = key
        print("\nfilename : ", filename)

        # Read 1_UNIT (no cuts as a reference) & create SINGLE instance
        for each_gds in gds_files:
            KLAYOUT.read(each_gds)

            # Read Top Cell for each GDS file
            for top_cell_read in KLAYOUT.top_cells():
                if (top_cell_read.name != "1_UNIT_CUTS"
                    ):  # Don't insert TOP_CELL("1_UNIT_CUTS") on itself
                    # print ( "Adding " + top_cell_read.name )
                    cell_index = top_cell_read.cell_index()
                    new_instance = pya.CellInstArray(
                        cell_index, pya.Trans(pya.Point(0, 0)))
                    # pya.Trans(pya.Point(0,0)) --> defines the LOCATION at which instance should be placed
                    TOP_CELL.insert(new_instance)

        # Define imported metal as a region (for boolean)
        region_metal = pya.Region(KLAYOUT.top_cell().begin_shapes_rec(l_metal))

        # Define cut area & make as region
        for ind, each_cut in enumerate(cut_loc[key]):
            cut_box_coord = get_cut_coord(each_cut, dim)
            TOP_CELL.shapes(l_cut_box).insert(cut_box_coord)
            region_cut_box = pya.Region(cut_box_coord)
            # Do boolean (XOR)
            # For more than 1 cuts, need to loop and take XOR of previous XOR results
            if ind == 0:
                region_xor = region_metal ^ region_cut_box
            else:
                region_xor = region_xor ^ region_cut_box

        # Remove existings metal layer + cut boxes
        # (!!! SKIP THIS TO CHECK CUT BOXES IN GDS !!!)
        KLAYOUT.clear_layer(l_metal)
        KLAYOUT.clear_layer(l_cut_box)

        # INSERT BOOLEAN RESULT AS ORIGINAL METAL LAYER
        TOP_CELL.shapes(l_metal).insert(region_xor)

        # Check if filename gds exists -> If so skip "write"
        if os.path.isfile(root + "/" + filename + ".gds"):
            print("**** GDS name by : " + filename + ".gds already exists!")
            print("**** SKIPPING GDS WRITE!!!")
        else:
            # Export GDS
            KLAYOUT.write(filename + ".gds")
Exemplo n.º 12
0
 def getShapesFromCellAndLayer(cellList,
                               box,
                               layerList=None,
                               layermod='not in'):
     layers = Collision.getLayers(layerList=layerList, layermod=layermod)
     outregion = pya.Region(box)
     inregion = pya.Region()
     for cell in cellList:
         for layer in layers:
             s = cell.begin_shapes_rec_touching(layer, box)
             inregion.insert(s)
     inregion.merge()
     return [outregion, inregion]
Exemplo n.º 13
0
def do_opc_fill(fill_top_cell, layer, layer_cfg, outline_area, shapes_area):
    has_opc = 'opc' in layer_cfg
    if not has_opc:
        return
    opc_cfg = layer_cfg['opc']
    sp_non = opc_cfg['space_to_non_fill']
    sp_fill = opc_cfg['space_to_fill']
    halo = opc_cfg['halo']

    non_opc_cfg = layer_cfg['non-opc']
    sp_fill_non_opc = non_opc_cfg['space_to_fill'] - half(sp_fill)

    non_opc_fill = pya.Region(
        fill_top_cell.begin_shapes_rec(non_opc_cfg['klayout']))
    if 'klayout2' in non_opc_cfg:
        non_opc_fill |= pya.Region(
            fill_top_cell.begin_shapes_rec(non_opc_cfg['klayout2']))

    fill_base_area = outline_area & (
        shapes_area.sized(halo) - shapes_area.sized(sp_non - half(sp_fill)) -
        non_opc_fill.sized(sp_fill_non_opc))

    is_h = layer_cfg['dir'] == 'H'
    for w, h in zip(opc_cfg['width'], opc_cfg['height']):
        w_space = h_space = half(sp_fill)
        le = opc_cfg.get('space_line_end', 0)
        if is_h:
            w, h = (max(w, h), min(w, h))
            w_space += half(le)
        else:
            w, h = (min(w, h), max(w, h))
            h_space += half(le)

        opc_fill = pya.Region(
            fill_top_cell.begin_shapes_rec(opc_cfg['klayout']))
        if 'klayout2' in opc_cfg:
            opc_fill |= pya.Region(
                fill_top_cell.begin_shapes_rec(opc_cfg['klayout2']))

        fill_area = fill_base_area - opc_fill.sized(w_space, h_space, 2)
        small_cell, fill_cell_bbox = create_fill_cell(layer + '_opc', opc_cfg,
                                                      w, h)
        while not fill_area.is_empty():
            fill_top_cell.fill_region(fill_area, small_cell.cell_index(),
                                      fill_cell_bbox, None, fill_area,
                                      pya.Point(0, 0), None)
        if 'datatype2' in opc_cfg:
            e2_cell, _ = create_fill_cell(layer + '_opc_e2', opc_cfg, w, h,
                                          True)
            double_pattern(fill_top_cell, small_cell, e2_cell)
Exemplo n.º 14
0
    def circle(self, diameter, vertices=128):
        '''
      circle(diameter, vertices)
      
      Generates a circle shape
      
      Parameters
      ---------
      diameter : integer
            The diameter of a circle
      vertices : integer (128)
            Number of vertices in the circle (coerce to multiple of 4)
      
      Returns
      ------
      region : [pya.Region]
           A region containing the circle shape
      
      Description
      ------
      The number of vertices is coerced to even numbers to ensure good fracturing
      '''
        r = int(diameter / 2)
        vertices = int(vertices / 4) * 4

        # Create a circle
        polygon = pya.Polygon([
            pya.Point(-r, -r),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, -r)
        ])
        polygon = polygon.round_corners(0, r, vertices)

        return pya.Region(polygon)
Exemplo n.º 15
0
 def getRegionFromLayers(layerList=None, layermod='in'):
     layers = Collision.getLayers(layerList=layerList, layermod=layermod)
     region = pya.Region()
     for layer in layers:
         region.insert(IO.top.begin_shapes_rec(layer))
     region.merge()
     return region
Exemplo n.º 16
0
  def test_1_Region(self):

    r = pya.Region()
    self.assertEqual(str(r), "")

    r.insert(pya.Box(0, 100, 200, 300))
    self.assertEqual(str(r), "(0,100;0,300;200,300;200,100)")

    r2 = pya.Region(pya.Box(50, 150, 250, 350))
    self.assertEqual(str(r2), "(50,150;50,350;250,350;250,150)")

    r += r2
    self.assertEqual(str(r), "(0,100;0,300;200,300;200,100);(50,150;50,350;250,350;250,150)")

    r.merge()
    self.assertEqual(str(r), "(0,100;0,300;50,300;50,350;250,350;250,150;200,150;200,100)")
Exemplo n.º 17
0
def do_non_opc_fill(fill_top_cell, layer, layer_cfg, outline_area,
                    shapes_area):
    non_opc_cfg = layer_cfg['non-opc']
    sp_non = non_opc_cfg['space_to_non_fill']
    sp_fill = non_opc_cfg['space_to_fill']
    # Constant across iterations
    fill_base_area = outline_area - shapes_area.sized(sp_non - half(sp_fill))

    for w, h in zip(non_opc_cfg['width'], non_opc_cfg['height']):
        # Orient the fill in the preferred direction
        if layer_cfg['dir'] == 'H':
            w, h = (max(w, h), min(w, h))
        else:
            w, h = (min(w, h), max(w, h))

        # The set of non-OPC fill shapes may expand on each iteration so we
        # recompute it
        non_opc_fill = pya.Region(
            fill_top_cell.begin_shapes_rec(non_opc_cfg['klayout']))
        fill_area = fill_base_area - non_opc_fill.sized(half(sp_fill))

        small_cell, fill_cell_bbox = create_fill_cell(layer + '_non_opc',
                                                      non_opc_cfg, w, h)
        while not fill_area.is_empty():
            fill_top_cell.fill_region(fill_area, small_cell.cell_index(),
                                      fill_cell_bbox, None, fill_area,
                                      pya.Point(0, 0), None)

        if 'datatype2' in non_opc_cfg:
            e2_cell, _ = create_fill_cell(layer + '_non_opc_e2', non_opc_cfg,
                                          w, h, True)
            double_pattern(fill_top_cell, small_cell, e2_cell)
Exemplo n.º 18
0
 def Output_Region(self):
     polygons=[]
     for x in self.outputlist:
         if isinstance(x,pya.DPolygon):
             polygons.append(pya.Polygon.from_dpoly(x))
     self.outputlist=[]
     return pya.Region(polygons)
Exemplo n.º 19
0
    def get_polygons(self, include_pins=True):
        from .utils import get_layout_variables
        TECHNOLOGY, lv, ly, cell = get_layout_variables()

        r = pya.Region()

        s = self.cell.begin_shapes_rec(ly.layer(TECHNOLOGY['Waveguide']))
        while not (s.at_end()):
            if s.shape().is_polygon() or s.shape().is_box() or s.shape(
            ).is_path():
                r.insert(s.shape().polygon.transformed(s.itrans()))
            s.next()

        if include_pins:
            s = self.cell.begin_shapes_rec(ly.layer(TECHNOLOGY['PinRec']))
            import math
            from .utils import angle_vector
            while not (s.at_end()):
                if s.shape().is_path():
                    p = s.shape().path.transformed(s.itrans())
                    # extend the pin path by 1 micron for FDTD simulations
                    pts = [pt for pt in p.each_point()]
                    # direction / angle of the optical pin
                    rotation = angle_vector(pts[0] - pts[1]) * math.pi / 180
                    pts[1] = (
                        pts[1] -
                        pya.Point(int(math.cos(rotation) * 1000),
                                  int(math.sin(rotation) * 1000))).to_p()
                    r.insert(pya.Path(pts, p.width).polygon())
                s.next()

        r.merge()
        polygons = [p for p in r.each_merged()]

        return polygons
Exemplo n.º 20
0
 def conflict(self, other):
     if isinstance(other, Collision):
         return self.region.interacting(other.region)
     if isinstance(other, pya.DPoint):
         region = pya.Region(
             pya.DPolygon(
                 BasicPainter.arc(other, self.pointRadius, 8, 0, 360)))
         return self.region.interacting(region)
     raise TypeError('Invalid input')
Exemplo n.º 21
0
def convfunc(cell,layer,layerList,distanceList,numberList,box):
    layers = Collision.getLayers(layerList=layerList, layermod='in')
    outregion = pya.Region(box)
    inregions = []
    region = pya.Region()

    for layeri,radius,number in zip(layers,distanceList,numberList):
        inregion = pya.Region()
        s = IO.top.begin_shapes_rec_touching(layeri, box)
        inregion.insert(s)
        inregion.merge()
        xys = [(radius*cos(2*pi*ii/number), radius*sin(2*pi*ii/number)) for ii in range(number)]
        for x, y in xys:
            region += inregion.transformed(pya.Trans(int(x), int(y)))
            region.merge()
        region += inregion
        region.merge()
    region &= outregion 

    fregion = pya.Region()

    for polygon in region.each():
        
        pts=list(polygon.each_point_hull())
        npts=[]
        for ii,pt in enumerate(pts):
            if ii%2==0 or ii==len(pts)-1:
                npts.append(pt)
                continue
            if pt.distance(pts[ii+1])>10000 or pt.distance(pts[ii-1])>10000:
                npts.append(pt)
                continue
        fregion.insert(pya.Polygon(npts))
        # xx=[]
        # yy=[]
        # for pt in polygon.to_simple_polygon().each_point():
        #     xx.append(str(pt.x))
        #     yy.append(str(pt.y))
        # pushln('xx_=['+','.join(xx)+'];')
        # pushln('yy_=['+','.join(yy)+'];')
        # pushln(vname+'{end+1}={xx_,yy_};')


    BasicPainter.Draw(cell, layer, fregion)
Exemplo n.º 22
0
 def vernier(self, width, length, pitch):
   '''
   vernier(width, length, pitch)
   
   Generates a vernier scale
   
   Parameters
   ---------
   width : integer
         The width of each tick marker
   length : integer
         The length of the central tick mark
         The major tick marks are 3/4 this length
         The minor tick marks are half this length
   pitch : integer
         The distance between each tick mark
   
   Returns
   ------
   region : [pya.Region]
        A region containing the vernier scale
   
   Description
   ---------
   A pair of vernier scale can be used to measure misalignment by eye.
   
   In photolithography the wafer will contain one vernier pattern (width = 4, length = 40, pitch = 8, units = micron)
   and the mask will contain a second vernier pattern (pitch = 8.2) providing an alignment measurement resolution of 0.2 micron.
   '''
   scaleM = 0.75
   scaleS = 0.5
   
   # Create the large tick mark
   polygons = []
   #tick = pya.Polygon([pya.Point(0,0), pya.Point(length,0), pya.Point(length,width), pya.Point(0,width)])
   tick = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length,width), pya.Point(length,0)])
   tc = pya.ICplxTrans(int(-length/2),int(-width/2))
   polygons.append(tc.trans(tick))
   
   # Create the medium tick mark
   #tickm = pya.Polygon([pya.Point(0,0), pya.Point(length*scaleM,0), pya.Point(length*scaleM,width), pya.Point(0,width)])
   tickm = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length*scaleM,width), pya.Point(length*scaleM,0)])
   pos = [-2, -1, 1, 2]
   for i in pos:
     tt = pya.ICplxTrans(0,int(i*pitch*5))
     polygons.append(tc.trans(tt.trans(tickm)))
   
   # Create the small tick mark
   #ticks = pya.Polygon([pya.Point(0,0), pya.Point(length*scaleS,0), pya.Point(length*scaleS,width), pya.Point(0,width)])
   ticks = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length*scaleS,width), pya.Point(length*scaleS,0)])
   pos = [-9, -8, -7, -6, -4, -3, -2, -1, 1, 2, 3, 4, 6, 7, 8, 9]
   for i in pos:
     tt = pya.ICplxTrans(0,int(i*pitch))
     polygons.append(tc.trans(tt.trans(ticks)))
     
   return pya.Region(polygons)
Exemplo n.º 23
0
 def DrawAirbridgeWithCollisionCheck(self, cell, centerlinelist, newcellname, boxY, boxWidth, boxHeight, push=10000, extend=5000):
     # get all shapes
     region = Collision.getRegionFromLayers(layerList=[], layermod='not in')
     # insert
     regionInsert = pya.Region()
     regionInsert.insert(
         pya.Box(-boxWidth/2, boxY-boxHeight/2, boxWidth/2, boxY+boxHeight/2))
     regionInsert.insert(
         pya.Box(-boxWidth/2, -boxY-boxHeight/2, boxWidth/2, -boxY+boxHeight/2))
     return self.DrawAirbridge(cell, centerlinelist, newcellname, collision={'region': region, 'regionInsert': regionInsert, 'push': push,'extend': extend})
Exemplo n.º 24
0
 def Border(leng=3050000,siz=3050000,wed=50000):
     polygons=[]        
     pts=[pya.Point(-siz,-siz),pya.Point(-siz+leng,-siz),pya.Point(-siz+leng,-siz+wed)]
     pts.extend([pya.Point(-siz+wed,-siz+wed),pya.Point(-siz+wed,-siz+leng),pya.Point(-siz,-siz+leng)])
     polygon1=pya.Polygon(pts)
     polygons.append(polygon1)
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R90)))
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R180)))
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R270)))
     return pya.Region(polygons)
Exemplo n.º 25
0
 def DPathPolygon(pts, width, start, end, giveupsomepoints=False):
     region1 = pya.Region([
         pya.Polygon.from_dpoly(
             pya.DPath(pts, width, start, end).polygon())
     ])
     region2 = pya.Region([
         pya.Polygon.from_dpoly(
             pya.DPath(pts, width + 2000, start, end).polygon())
     ])
     polygon = list((region1 & region2).each_merged())[0]
     if giveupsomepoints:
         pts = []
         sourcepts = list(polygon.each_point_hull())
         for i, pt in enumerate(sourcepts):
             if i == 0 or pt.distance(pts[-1]) >= min(
                     1000, max(100, rounded)):
                 pts.append(pt)
         return pya.DPolygon(pts)
     return polygon
Exemplo n.º 26
0
def add(layout, cell, slayers, dlayers, ex_amount, layers, out_cell=None):
    """Combines all slayers' shapes into a region and merges this region with each of dlayers' regions.

    :param layout: the layout on which the cells are located
    :param cell: the cell from which to copy the layers (source shapes)
    :param slayers: the layers to copy
    :param dlayers: the layers where to copy to
    :param ex_amount: the amount added around the source shapes
    :param layers: the layermapping
    :param out_cell: the cell where to put the shapes. If not specified, the input cell will be used.
    """
    # adjust amount from microns to database units
    am = ex_amount / layout.dbu

    if out_cell:
        o_cell = out_cell
    else:
        o_cell = cell

    srclayers = [slayers, ] if isinstance(slayers, str) else slayers
    dstlayers = [dlayers, ] if isinstance(dlayers, str) else dlayers

    in_layers = [layout.layer(layers[m][0], layers[m][1]) for m in srclayers]
    region = pya.Region()
    for layer in in_layers:
        if layer != -1:
            shapeit = cell.begin_shapes_rec(layer)
            region.insert(shapeit)
    region.merge()
    if ex_amount > 0:
        # increase the size of the region
        region.size(am)
        region.merge()
    for layer in dstlayers:
        layer_n, layer_d = layers[layer]
        l = layout.layer(layer_n, layer_d)
        shapeit = o_cell.begin_shapes_rec(l)
        add_region = pya.Region()
        add_region.insert(shapeit)
        add_region.merge()
        o_cell.shapes(l).clear()
        o_cell.shapes(l).insert(add_region + region)
Exemplo n.º 27
0
 def _candidatePoints(potentialPts, region, size):
     candidatePts = []
     for pt in potentialPts:
         x1 = pt.x
         y1 = pt.y
         check_box = pya.Box(x1 - size / 2, y1 - size / 2, x1 + size / 2,
                             y1 + size / 2)
         empty = (pya.Region(check_box) & region).is_empty()
         if empty:
             candidatePts.append(pt)
     return candidatePts
Exemplo n.º 28
0
 def Output_Region(self):
     region = super().Output_Region()
     polygonsex = []
     for x in self.regionlistex:
         if isinstance(x, pya.DPolygon):
             polygonsex.append(pya.Polygon.from_dpoly(x))
     self.regionlistex = []
     region2 = pya.Region(polygonsex)
     region2.merge()
     self.region = region2 + region
     return self.region
Exemplo n.º 29
0
    def test_deep1(self):

        ut_testsrc = os.getenv("TESTSRC")

        # construction/destruction magic ...
        self.assertEqual(pya.DeepShapeStore.instance_count(), 0)
        dss = pya.DeepShapeStore()
        dss._create()
        self.assertEqual(pya.DeepShapeStore.instance_count(), 1)
        dss = None
        self.assertEqual(pya.DeepShapeStore.instance_count(), 0)

        dss = pya.DeepShapeStore()
        ly = pya.Layout()
        ly.read(
            os.path.join(ut_testsrc, "testdata", "algo", "deep_region_l1.gds"))
        l1 = ly.layer(1, 0)
        r = pya.Region(ly.top_cell().begin_shapes_rec(l1), dss)
        rf = pya.Region(ly.top_cell().begin_shapes_rec(l1))

        self.assertEqual(r.area(), 53120000)
        self.assertEqual(rf.area(), 53120000)

        ly_new = pya.Layout()
        tc = ly_new.add_cell("TOP")
        l1 = ly_new.layer(1, 0)
        l2 = ly_new.layer(2, 0)
        ly_new.insert(tc, l1, r)
        ly_new.insert(tc, l2, rf)

        s1 = {}
        s2 = {}
        for cell in ly_new.each_cell():
            s1[cell.name] = cell.shapes(l1).size()
            s2[cell.name] = cell.shapes(l2).size()
        self.assertEqual(s1, {"INV2": 1, "TOP": 0, "TRANS": 0})
        self.assertEqual(s2, {"INV2": 0, "TOP": 10, "TRANS": 0})

        # force destroy, so the unit tests pass on the next iteration
        dss = None
        self.assertEqual(pya.DeepShapeStore.instance_count(), 0)
Exemplo n.º 30
0
    def cut(layerlist=None, layermod='not in', box=None, mergeanddraw=True):
        if layerlist == None: layerlist = [(0, 0)]
        if type(box) == type(None): box = Interactive._box_selected()
        if not box: return

        # celllist=[]
        # cells=[]
        # def buildcells(cell):
        #     if cell.name.split('$')[0] in celllist:return
        #     cells.append(cell)
        #     for ii in cell.each_child_cell():
        #         buildcells(layout.cell(ii))
        # buildcells(top)
        # cellnames=[c.name for c in cells]
        cells = [IO.top]

        _layerlist = []
        for ii in layerlist:
            if type(ii) == str:
                _layerlist.append(IO.layout.find_layer(ii))
            else:
                _layerlist.append(IO.layout.find_layer(ii[0], ii[1]))
        layers = [
            index for index in IO.layout.layer_indices() if index in _layerlist
        ] if layermod == 'in' else [
            index for index in IO.layout.layer_indices()
            if index not in _layerlist
        ]

        outregion = pya.Region(box)
        inregion = pya.Region()

        for cell in cells:
            for layer in layers:
                s = cell.begin_shapes_rec_touching(layer, box)
                inregion.insert(s)

        if not mergeanddraw:
            return outregion, inregion

        return Interactive._merge_and_draw(outregion, inregion)[0]