def test_extract(): c = [gdspy.Cell('tree_' + unique(), True) for _ in range(8)] gdspy.current_library = gdspy.GdsLibrary() lib = gdspy.GdsLibrary() lib.add(c) c[0].add(gdspy.CellReference(c[1])) c[0].add(gdspy.CellReference(c[3])) c[1].add(gdspy.CellReference(c[2])) c[1].add(gdspy.CellArray(c[2], 2, 1, (0, 0))) c[1].add(gdspy.CellArray(c[3], 2, 1, (0, 0))) c[4].add(gdspy.CellReference(c[3])) c[6].add(gdspy.CellArray(c[5], 2, 1, (0, 0))) assert len(gdspy.current_library.cell_dict) == 0 lib.extract(c[7]) assert gdspy.current_library.cell_dict == {c[7].name: c[7]} lib.extract(c[1]) assert gdspy.current_library.cell_dict == { c[7].name: c[7], c[1].name: c[1], c[2].name: c[2], c[3].name: c[3] } lib.extract(c[0]) assert gdspy.current_library.cell_dict == { c[7].name: c[7], c[0].name: c[0], c[1].name: c[1], c[2].name: c[2], c[3].name: c[3] }
def __init__(self, name, holecell, arrayaxes=((1, 0), (0, 1)), arrayperiods=(1, 1), excludepoly=None): self.Name = name self.Axes = arrayaxes self.Periods = arrayperiods self.holearray = gdspy.Cell(name) self.hole = holecell self.excludepoly = excludepoly if (len(numpy.array(holecell).shape) == 0): for i in range(self.Periods[0]): ax0pt = addtup((0, 0), scalartup(i, self.Axes[0])) for j in range(self.Periods[1]): ax1pt = addtup((0, 0), scalartup(j, self.Axes[1])) if (excludepoly == None) | (not gdspy.inside( [addtup(ax0pt, ax1pt)], excludepoly)[0]): refcell = gdspy.CellReference(holecell, addtup(ax0pt, ax1pt)) self.holearray.add(refcell) elif (numpy.array(holecell).shape == arrayperiods): for i in range(self.Periods[0]): ax0pt = addtup((0, 0), scalartup(i, self.Axes[0])) for j in range(self.Periods[1]): ax1pt = addtup((0, 0), scalartup(j, self.Axes[1])) if (excludepoly == None) | (not gdspy.inside( [addtup(ax0pt, ax1pt)], excludepoly)[0]): refcell = gdspy.CellReference(holecell[i, j], addtup(ax0pt, ax1pt)) self.holearray.add(refcell) else: raise ValueError( "Error in the holecell input! Not right dimention")
def YBranch(layerNumber=1): # X location of spline points taperLength = 2.0 x = numpy.linspace(0, taperLength, 13) # Width of waveguides waveguideWidth = 0.5 # Widths of each spline length as described in the paper w = numpy.array( [0.5, 0.5, 0.6, 0.7, 0.9, 1.26, 1.4, 1.4, 1.4, 1.4, 1.31, 1.2, 1.2]) # Top and bottom vectors for splines topY = w / taperLength # Spline measurements numSpline = 90 cs = CubicSpline(x, topY) xs = numpy.linspace(0, taperLength, numSpline) topSpline = cs(xs) bottomSpline = -topSpline[::-1] xx = numpy.concatenate([xs, xs[::-1]]) yy = numpy.concatenate([topSpline, bottomSpline]) vertices = numpy.stack([xx, yy], axis=1) # Create the taper polygon and cell yTaperCell = gdspy.Cell('yTaper') taperPoly = gdspy.Polygon(vertices, layerNumber) taperPoly.fracture() yTaperCell.add(taperPoly) # S Bends Zs = 13 Xs = 2 sBendCellTop = SBend(Zs, Xs, waveguideWidth, layerNumber) translationTop = [taperLength, topY[-1] - waveguideWidth / 2.0] translationBottom = [taperLength, -(topY[-1] - waveguideWidth / 2.0)] # Output branch (single waveguide) #L = 1.5 #outputBranchCell = gdspy.Cell('outputBranch') #outputBranchCell.add(gdspy.PolyPath([[0, 0],[L, 0]],waveguideWidth,layer=layerNumber)) # First we need a cell to add the polygons to. yBranchCell = gdspy.Cell('Ybranch') # Add all cells to master cell yBranchCell.add(gdspy.CellReference(yTaperCell, (0, 0), x_reflection=False)) yBranchCell.add( gdspy.CellReference(sBendCellTop, translationTop, x_reflection=False)) yBranchCell.add( gdspy.CellReference(sBendCellTop, translationBottom, x_reflection=True)) #yBranchCell.add(gdspy.CellReference(outputBranchCell, (-L,0), x_reflection=False)) return yBranchCell
def test_add_update2(): lib = gdspy.GdsLibrary() main = gdspy.Cell("MAIN") c1 = gdspy.Cell("C1") c2 = gdspy.Cell("C2") c3 = gdspy.Cell("C1") r1 = gdspy.CellReference(c1) main.add(r1) with pytest.warns(UserWarning): r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) main.add(r2) r3 = gdspy.CellReference(c2) main.add(r3) r4 = gdspy.CellReference(c3) c2.add(r4) with pytest.warns(UserWarning): r5 = gdspy.CellReference("C3") c1.add(r5) with pytest.warns(UserWarning): r6 = gdspy.CellReference("C2") main.add(r6) lib.add([main, c1, c2], include_dependencies=False) lib.add( c3, include_dependencies=False, overwrite_duplicate=True, update_references=False, ) assert r1.ref_cell is c1 assert r2.ref_cell == "C1" assert r3.ref_cell is c2 assert r4.ref_cell is c3 assert r5.ref_cell == "C3" assert r6.ref_cell == "C2"
def test_replace(): lib = gdspy.GdsLibrary() main = gdspy.Cell("MAIN") c1 = gdspy.Cell("C1") c2 = gdspy.Cell("C2") c3 = gdspy.Cell("C1") r1 = gdspy.CellReference(c1) main.add(r1) with pytest.warns(UserWarning): r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) main.add(r2) r3 = gdspy.CellReference(c2) main.add(r3) r4 = gdspy.CellReference(c3) c2.add(r4) with pytest.warns(UserWarning): r5 = gdspy.CellReference("C3") c1.add(r5) with pytest.warns(UserWarning): r6 = gdspy.CellReference("C2") main.add(r6) lib.add([main, c1, c2], include_dependencies=False) assert lib.replace_references(c2, c3) == 2 assert r3.ref_cell is c3 assert r6.ref_cell is c3 assert lib.replace_references("C3", "C1") == 1 assert r5.ref_cell is c1 assert lib.replace_references("C1", c2) == 6 assert r1.ref_cell is c2 assert r2.ref_cell is c2 assert r3.ref_cell is c2 assert r4.ref_cell is c2 assert r5.ref_cell is c2 assert r6.ref_cell is c2
def vernierChip(): # Initialize cells vernierChipCell = gdspy.Cell('vernierChip') vernier2DCell = vernier2D() boxOutlineCell = boxOutline() # Add border first vernierChipCell.add(gdspy.CellReference(boxOutlineCell, (0, 0))) chipDims = vernierChipCell.get_bounding_box() chipWidth = abs(chipDims[0, 0] - chipDims[1, 0]) # Now iterate through placing corners thetaPos = [45, 135, -135, -45] thetaRot = [0, 90, 180, -90] for k in range(0, 4): xPos = np.sign(np.cos(np.deg2rad( thetaPos[k]))) * (chipWidth / 2 - buffer / 2) yPos = np.sign(np.sin(np.deg2rad( thetaPos[k]))) * (chipWidth / 2 - buffer / 2) vernierChipCell.add( gdspy.CellReference(vernier2DCell, (xPos, yPos), rotation=thetaRot[k])) # return cell return vernierChipCell
def test_top_level_3(tree): lib, c = tree c[7].add(gdspy.CellReference(c[0])) c[3].add(gdspy.CellReference(c[4])) c[2].add(gdspy.CellReference(c[6])) c[1].add(gdspy.CellReference(c[7])) assert lib.top_level() == []
def DrawReflectionFeedline( FeedlineCellName = 'Feedline', MainlineLength = 3000, LineWidth = 10, #width of feedline SpaceWidth = 6, #space between feedline and ground plane BigWidth = 96, #maximum launcher-lines width LauncherWidth = 352, #total launcher width layer = 2): """ This function returns a feedline cell (in a list) that contains references to one curved mainline cell and one launcher cell, placed on one end of the main line. The cell origin is defined at the center of the mainline. """ '''launcher''' launcher = DrawLauncher( LauncherCellName = 'Launcher', LineWidth = LineWidth, #width of each parallel line SpaceWidth = SpaceWidth, #space between parallel lines BigWidth = 96, #maximum launcher-lines width LauncherWidth = 352, #total launcher width layer = 2) '''main line''' mainline = gds.Cell(FeedlineCellName+'Mainline', exclude_from_current=True) path = gds.FlexPath([(0,0),(MainlineLength,0)], [SpaceWidth, SpaceWidth], SpaceWidth + LineWidth , layer=layer) path.turn(LauncherWidth, 'r') path.segment((0,-MainlineLength/4), relative=True) mainline.add(path) #Adds cell references to main cell Feedline = gds.Cell(FeedlineCellName, exclude_from_current=True) Feedline.add(gds.CellReference(launcher, origin=(-MainlineLength/2, 0))) Feedline.add(gds.CellReference(mainline, origin=(-MainlineLength/2,0))) return [Feedline]
def vernier2D(): # Intialize 2D cell vernier2DCell = gdspy.Cell('vernier2D') # Initialize 1D cell vernierCell = vernier() # Get vernier dimensions vernierDims = vernierCell.get_bounding_box() vernierWidth = abs(vernierDims[0, 0] - vernierDims[1, 0]) vernierHeight = abs(vernierDims[0, 1] - vernierDims[1, 1]) # Place one Vernier pattern in the x direction xCell = gdspy.CellReference(vernierCell, rotation=-90) xCell.translate(-(vernierHeight / 2 + separationDistance), -vernierWidth / 2) vernier2DCell.add(xCell) # Place another Vernier pattern in the y direction yCell = gdspy.CellReference(vernierCell, rotation=180) yCell.translate(-vernierWidth / 2, -(vernierHeight / 2 + separationDistance)) vernier2DCell.add(yCell) # Return final cell return vernier2DCell
def DrawTransmissionFeedline( FeedlineCellName = 'Feedline', MainlineLength = 2000, LineWidth = 10, #width of transmission line SpaceWidth = 6, #space between transmission line and grounding plane BigWidth = 96, #maximum launcher-lines width LauncherWidth = 352, #total launcher width layer = 2): """ This function returns a symmetrical feedline cell (in a list) that contains references to one mainline cell and one launcher cell, placed on both sides of the main line. The cell origin is defined at the center of the mainline. """ '''launcher''' launcher = DrawLauncher( LauncherCellName = 'Launcher', LineWidth = 10, #width of feedline SpaceWidth = 6, #space between feedline and ground plane BigWidth = 96, #maximum launcher-lines width LauncherWidth = 352, #total launcher width layer = 2) '''main line''' mainline = gds.Cell(FeedlineCellName+'Mainline', exclude_from_current=True) mainline.add(gds.FlexPath([(0,0),(MainlineLength,0)], [SpaceWidth, SpaceWidth], SpaceWidth + LineWidth , layer=layer)) #Adds cell references to main cell Feedline = gds.Cell(FeedlineCellName, exclude_from_current=True) Feedline.add(gds.CellReference(launcher, origin=(-MainlineLength/2, 0))) Feedline.add(gds.CellReference(mainline, origin=(-MainlineLength/2,0))) Feedline.add(gds.CellReference(launcher, origin=(MainlineLength/2, 0), rotation=180 , x_reflection=True)) return [Feedline]
def add(self, element, origin=(0, 0), rotation=0.0, x_reflection=False): """ Add a reference to an element or list of elements to the cell associated with this component """ this_cell = CURRENT_CELLS[self.cell_hash] if self.first_cell == True: """ Only add elements if this is the first cell made. Otherwise, duplicate elements will be added """ if isinstance(element, Component): element_cell = CURRENT_CELLS[element.cell_hash] rot = self.__direction_to_rotation(element.direction) this_cell.add( gdspy.CellReference( element_cell, origin=element.port, rotation=rot, x_reflection=x_reflection, )) elif isinstance(element, gdspy.Cell): this_cell.add( gdspy.CellReference( element, origin=origin, rotation=rotation, x_reflection=x_reflection, )) else: this_cell.add(element)
def test_remove(): lib = gdspy.GdsLibrary() main = gdspy.Cell("MAIN") c1 = gdspy.Cell("C1") c2 = gdspy.Cell("C2") c3 = gdspy.Cell("C1") r1 = gdspy.CellReference(c1) main.add(r1) with pytest.warns(UserWarning): r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) main.add(r2) r3 = gdspy.CellReference(c2) main.add(r3) r4 = gdspy.CellReference(c3) c2.add(r4) with pytest.warns(UserWarning): r5 = gdspy.CellReference("C3") c1.add(r5) with pytest.warns(UserWarning): r6 = gdspy.CellReference("C2") main.add(r6) lib.add([main, c1, c2], include_dependencies=False) assert lib.remove("C3") == 1 assert len(c1.references) == 0 assert len(c2.references) == 1 assert c2.references[0] is r4 assert lib.remove(c1) == 3 assert "C1" not in lib.cells assert len(main.references) == 2 assert main.references[0] is r3 assert main.references[1] is r6 assert len(c2.references) == 0
def combine(w): DC = lib.new_cell('DC' + str(int(w * 1000))) DC.add(build_DC(w)) part1 = gdspy.CellReference(DC, origin=(0, -spacing_FA), rotation=0, x_reflection=True) part2 = gdspy.CellReference(DC) part = [part1, part2] return part
def DrawRFsquid( RFsquidCellName='RFsquid', RFsquidLength=155.5, RFsquidWidth=12, LineWidth=2, #width of the RFsquid line JJparameters={ 'FingerWidth': 0.36, #Dictionary with the Josephson junction parameters 'FingerLength': 1.36, # 'TaperWidth': 0.5, # 'BridgeWidth': 0.14 }, layer=2): """ This function returns an RFsquid cell (in a list) that contains references to a line cell and a Josephson junction cell. The cell origin is defined at the center of the RFsquid loop. """ '''Josephson Junctions''' RFsquidJJ = DrawJosephsonJunction( JosephsonJunctionCellName=RFsquidCellName + 'JosephsonJunction', LineWidth=LineWidth, #width of line connected to the junction FingerWidth=JJparameters['FingerWidth'], # FingerLength=JJparameters['FingerLength'], # TaperWidth=JJparameters['TaperWidth'], # BridgeWidth=JJparameters['BridgeWidth'], # layer=layer) '''line''' JosephsonJunctionTotalLength = JJparameters['FingerLength'] + JJparameters[ 'TaperWidth'] + JJparameters['BridgeWidth'] RFsquidLine = gds.Cell(RFsquidCellName + 'Line', exclude_from_current=True) RFsquidLineCoordinates = [ (0, (-RFsquidWidth + LineWidth) / 2), ((RFsquidLength - LineWidth) / 2, (-RFsquidWidth + LineWidth) / 2), ((RFsquidLength - LineWidth) / 2, (RFsquidWidth - LineWidth) / 2), ((-RFsquidLength + LineWidth) / 2, (RFsquidWidth - LineWidth) / 2), ((-RFsquidLength + LineWidth) / 2, (-RFsquidWidth + LineWidth) / 2), (-JosephsonJunctionTotalLength, (-RFsquidWidth + LineWidth) / 2) ] RFsquidLine.add( gds.FlexPath(RFsquidLineCoordinates, LineWidth, corners="circular bend", bend_radius=LineWidth, layer=layer)) #Adds cell references to main cell RFsquid = gds.Cell(RFsquidCellName, exclude_from_current=True) RFsquid.add(gds.CellReference(RFsquidLine, origin=(0, 0))) RFsquid.add( gds.CellReference(RFsquidJJ, origin=(-JosephsonJunctionTotalLength, (-RFsquidWidth + LineWidth) / 2))) return [RFsquid]
def tree(): c = [gdspy.Cell('tree_' + unique(), True) for _ in range(8)] lib = gdspy.GdsLibrary() lib.add(c) c[0].add(gdspy.CellReference(c[1])) c[0].add(gdspy.CellReference(c[3])) c[1].add(gdspy.CellReference(c[2])) c[1].add(gdspy.CellArray(c[2], 2, 1, (0, 0))) c[1].add(gdspy.CellArray(c[3], 2, 1, (0, 0))) c[4].add(gdspy.CellReference(c[3])) c[6].add(gdspy.CellArray(c[5], 2, 1, (0, 0))) return lib, c
def coulper_coupler(lib, grating, w_wg=0.5, w_etch=3, l_wg=100): GC = lib.new_cell("GC") # create the cell: waveguides wg = lib.new_cell('waveguides'+str(int(w_wg*1000))) points = [(0, w_wg/2), (l_wg, w_wg/2), (l_wg, w_wg/2+w_etch), (0, w_wg/2+w_etch)] poly = gdspy.Polygon(points, **ld_fulletch) wg.add(poly) poly = gdspy.Polygon(points, **ld_fulletch).mirror((0, 0), (1, 0)) wg.add(poly) GC.add(gdspy.CellReference(grating, origin=(0,0), rotation=180)) GC.add(gdspy.CellReference(wg, origin=(0,0), rotation=0)) GC.add(gdspy.CellReference(grating, origin=(l_wg,0), rotation=0))
def nwell_gr(self): if not self.nmos and NWELL_GR: nwell_gr, self.bulk = basic.nwell_GR(self.cell.get_bounding_box()[0], self.cell.get_bounding_box()[1],self.origin, (1 not in self.bulkCon)) #self.add_bulk_shape(nwell_gr.get_polygons(True)[(layer['M1'],0)]) nwell_gr_ref = gdspy.CellReference(nwell_gr) self.cell.add(nwell_gr_ref) #self.flatten() if self.nmos and SUB_GR: sub_gr, self.bulk = basic.sub_GR(self.cell.get_bounding_box()[0], self.cell.get_bounding_box()[1],self.origin, (1 not in self.bulkCon)) #self.add_bulk_shape(sub_gr.get_polygons(True)[(layer['M1'],0)]) sub_gr_ref = gdspy.CellReference(sub_gr) self.cell.add(sub_gr_ref)
def gc_line(cell, gc, origin=(0, 0), l=200): cell.add(gdspy.CellReference(gc, origin)) cell.add(gdspy.CellReference(gc, (l + origin[0], origin[1]), rotation=180)) path_connect = gdspy.Path(w_wg) path_connect.segment(l) path_connect2 = gdspy.Path(w_wg + 6) path_connect2.segment(l) path_connect_positive = gdspy.boolean(path_connect, path_connect2, 'xor', layer=1, datatype=1) cell.add(path_connect_positive) return cell
def test_add(): lib = gdspy.GdsLibrary() c1 = gdspy.Cell("gl_add_1") c2 = gdspy.Cell("gl_add_2") c3 = gdspy.Cell("gl_add_3") r1 = gdspy.CellReference(c1) with pytest.warns(UserWarning): r2 = gdspy.CellReference("gl_add_2") c3.add([r1, r2]) lib.add(c1) lib.add((c2, c3)) assert lib.cells == {"gl_add_1": c1, "gl_add_2": c2, "gl_add_3": c3} lib = gdspy.GdsLibrary() lib.add(c3) assert lib.cells == {"gl_add_1": c1, "gl_add_3": c3}
def test_gather(): def same_points(x, y): for px, py in zip(x, y): for ptx, pty in zip(px, py): for cx, cy in zip(ptx, pty): if cx != cy: return False return True pts = [(0, 0), (1, 1), (1, 0)] ps1 = gdspy.Round((10, 10), 1, inner_radius=0.2) ps2 = gdspy.Path(0.1, (-1, -1), 2, 1).segment(2, "-x") c = gdspy.Cell("C1").add(gdspy.Rectangle((-4, 3), (-5, 4))) cr = gdspy.CellReference(c, (10, -10)) ca = gdspy.CellArray(c, 2, 1, (2, 0)) assert gdspy.operation._gather_polys(None) == [] assert same_points(gdspy.operation._gather_polys([pts]), [pts]) assert same_points(gdspy.operation._gather_polys(ps1), ps1.polygons) assert same_points(gdspy.operation._gather_polys(ps2), ps2.polygons) assert same_points(gdspy.operation._gather_polys(cr), cr.get_polygons()) assert same_points(gdspy.operation._gather_polys(ca), ca.get_polygons()) result = [pts] result.extend(ps2.polygons) result.extend(cr.get_polygons()) assert same_points(gdspy.operation._gather_polys([pts, ps2, cr]), result)
def Scan_tooth(lib, Cell, para, cellname_prefix='GC_Apodized', step=0.005, n=(3, 4), origin=(0, 0), space=100): temp_complement = np.linspace(-step * n[0], step * n[1], n[0] + n[1] + 1) y_start = space para = np.array(para) temp_para = np.array(para) for complement in temp_complement: for index_para in range(len(para)): if index_para % 2 != 0: temp_para[index_para] = para[index_para] + complement temp_para = list(temp_para) cellname = cellname_prefix + '_Tooth' + str(round(complement * 1e3)) # create the rect grating for Air GC_rect_Apodized_Air = lib.new_cell(cellname) gc_rect(GC_rect_Apodized_Air, temp_para) GC_line = gc_line(lib.new_cell(cellname + "_Line"), GC_rect_Apodized_Air) Cell.add( gdspy.CellReference(GC_line, (origin[0] + 0, origin[1] + space - y_start))) space += -100 posi_end = (origin[0] + 0, origin[1] + space - 200) return posi_end
def Scan_D_Apod(lib, Cell, D, d, cellname_prefix='GC_PC_APodized', step=0.005, n=(3, 4), origin=(0, 0), space=100): temp_complement = np.linspace(-step * n[0], step * n[1], n[0] + n[1] + 1) y_start = space para = D # print(para) for complement in temp_complement: temp_para = para + complement # print(temp_para) cell = gc_PC_apodized( lib, cellname_prefix + '_D' + str(round(complement * 1e3)), temp_para, d) GC_line = gc_line(lib.new_cell(cell.name + "_Line"), cell, l=200) Cell.add( gdspy.CellReference(GC_line, (origin[0] + 0, origin[1] + space - y_start))) space += -100 posi_end = (origin[0] + 0, origin[1] + space - 200) return posi_end
def test_add_label_rotation_x_reflection(): # add a child cell with a label c1 = gdspy.Cell("child") label = gdspy.Label("label", (0, 0)) p = gdspy.Polygon(((0, 0), (1, 0), (0, 1))) c1.add(p) c1.add(label) # add parent with rotated cell rotation = 90 dx = 5 dy = 10 c2 = gdspy.Cell("parent") c1ref = gdspy.CellReference(ref_cell=c1, rotation=rotation, x_reflection=True) c1ref.translate(dx, dy) c2.add(c1ref) label2 = c2.get_labels(set_transform=True)[0] label_rotation = label2.rotation label_x_reflection = label2.x_reflection assert label_rotation == rotation, [label_rotation, rotation] assert label_x_reflection == True, label_x_reflection assert label2.position[0] == dx assert label2.position[1] == dy
def test_robustpath_transform(target): rp = gdspy.FlexPath([(0, 0)], [2, 1, 1], 5) rp.segment((15, 20)) rp.scale(0.7) rp.turn(10, "r") rp.transform((10, 0), -1.5, 1.5, x_reflection=True) rp.segment((10, -10), relative=True) rp.rotate(-0.7) rp.translate(50, 30) rp.segment((-10, 0)) assertsame(target["RobustPath4"], gdspy.Cell("FP5").add(rp)) rp = gdspy.RobustPath((0, 0), [2, 1, 1], 5) rp.segment((15, 20)) rp.turn(10, "r") rp.segment((10, -10), relative=True) poly = rp.to_polygonset() rp.rotate(-0.7) rp.scale(0.7) rp.translate(50, 30) rp.transform((10, 0), numpy.pi / 4, 1.5, True) poly.rotate(-0.7) poly.scale(0.7) poly.translate(50, 30) c0 = gdspy.Cell("POLY") c0.add(poly) ref = gdspy.CellReference(c0, (10, 0), 45, 1.5, True) assertsame(gdspy.Cell("RP").add(rp), gdspy.Cell("REF").add(ref), tolerance=1e-2)
def max_tracks(L, W, S, limit='XX'): ''' Determine the maximum number of tracks based on length given by 'limit' L : Overall length of the octagonal balun. W : Width of the metal track. S : Spacing between the metal tracks. limit : If None, the inner most track is 0 length. Usually a crossover is passed in and its length determines the minimum length of the inner most track. ''' if limit == None: length = 0 else: CO = gdspy.CellReference(limit) length = 2 * CO.get_bounding_box()[1][0] #preliminary calculations of some constants tanz = np.tan(np.pi / 8) ld2tanz = length / (2 * tanz) WpS = W + S tracks = -(ld2tanz + W - L / 2) / WpS + 1 return int(tracks)
def connect_top_2(self, width=0.2, con_l=0.6): # LSB bit on the right of array self.col_p1 = [self.bound[1][0] + width, self.top_y[0] - 2 * width] self.col_p1 = basic.legal_coord(self.col_p1, self.origin, 2) self.col_p2 = [self.col_p1[0] + width, self.bound[1][1]] col_shape = gdspy.Rectangle(self.col_p1, self.col_p2, layer['M' + str(self.array_cell.m_top)]) self.cell.add(col_shape) for i in range(1, self.col_bit + 1): col_shape = gdspy.Rectangle( [self.col_p1[0] + 2 * i * width, self.col_p1[1]], [self.col_p2[0] + 2 * i * width, self.col_p2[1]], layer['M' + str(self.array_cell.m_top)]) self.cell.add(col_shape) for y in self.top_y: con_shape = gdspy.Rectangle([self.bound[1][0], y], [ self.col_p2[0] + 2 * self.col_bit * width + 2 * width, y + self.array_cell.con2[1][1] - self.array_cell.con2[0][1] ], layer['M' + str(self.array_cell.m_top + 1)]) self.cell.add(con_shape) # Connect according to interdigitation col_coord = self.interdigitation_code(self.col_bit + 1) vert_cell = basic.metal_vert(width, con_l, self.array_cell.m_top + 1) bit = 0 diff = 0.5 * con_l - 0.5 * (self.array_cell.con2[1][1] - self.array_cell.con2[0][1]) for coord in col_coord: for y in coord: temp_con = gdspy.CellReference( vert_cell, (self.col_p1[0] + 2 * bit * width, self.top_y[y] - diff)) self.cell.add(temp_con) bit = bit + 1
def connect_top_1(self, width=0.2, con_l=0.6, lay=4): # MSB bit below the array self.row_p1 = [self.bound[0][0], self.bound[0][1] - 2 * width] self.row_p1 = basic.legal_coord(self.row_p1, self.origin, 3) self.row_p2 = [ self.top_x[-1] + self.route_width + 2 * width, self.row_p1[1] + width ] row_shape = gdspy.Rectangle(self.row_p1, self.row_p2, layer['M' + str(lay - 1)]) self.cell.add(row_shape) for i in range(1, self.row_bit): row_shape = gdspy.Rectangle( [self.row_p1[0], self.row_p1[1] - 2 * i * width], [self.row_p2[0], self.row_p2[1] - 2 * i * width], layer['M' + str(lay - 1)]) self.cell.add(row_shape) for x in self.top_x: con_shape = gdspy.Rectangle( [x, self.row_p1[1] - 2 * (self.row_bit - 1) * width - width], [x + self.route_width, self.bound[0][1]], layer['M' + str(lay)]) self.cell.add(con_shape) # Connect according to interdigitation row_coord = self.interdigitation_code(self.row_bit) hori_cell = basic.metal_hori(con_l, width, lay) bit = 0 diff = 0.5 * con_l - 0.5 * self.route_width for coord in row_coord: for x in coord: temp_con = gdspy.CellReference( hori_cell, (self.top_x[x] - diff, self.row_p1[1] - bit * 2 * width)) self.cell.add(temp_con) bit = bit + 1
def _get_all_holes(self) -> gdspy.library.Cell: """Return a cell with a grid of holes. The keepout has not been applied yet. Returns: gdspy.library.Cell: Cell containing all the holes. """ gather_holes_cell_name = f'Gather_holes_{self.chip_name}_{self.layer}' gather_holes_cell = self.lib.new_cell(gather_holes_cell_name, overwrite_duplicate=True) x_holes = np.arange(self.grid_minx, self.grid_maxx, self.delta_x, dtype=float).tolist() y_holes = np.arange(self.grid_miny, self.grid_maxy, self.delta_y, dtype=float).tolist() if self.one_hole_cell is not None: for x_loc in x_holes: for y_loc in y_holes: gather_holes_cell.add( gdspy.CellReference(self.one_hole_cell, origin=(x_loc, y_loc))) return gather_holes_cell
def test_inside(): polygons = [ gdspy.Round((0, 0), 10, inner_radius=5, number_of_points=180), gdspy.Rectangle((20, -10), (40, 10)).polygons[0], gdspy.CellReference( gdspy.Cell("X").add(gdspy.Rectangle((-10, 0), (10, 20)))), ] assert gdspy.inside([(0, 0)], polygons[0]) == (False, ) assert gdspy.inside([(0, 0)], polygons[2]) == (True, ) assert gdspy.inside([(0, 0)], polygons) == (True, ) assert gdspy.inside([(0, 0), (0, 30), (30, 0), (0, -1)], polygons) == ( True, False, True, False, ) assert gdspy.inside( [[(0, 0), (0, 30), (30, 0), (0, -1)], [(0, -1), (0, 30)], [(0, 0), (30, 0)]], polygons, "any", ) == (True, False, True) assert gdspy.inside( [[(0, 0), (0, 30), (30, 0), (0, -1)], [(0, -1), (0, 30)], [(0, 0), (30, 0)]], polygons, "all", ) == (False, False, True)
def test_copy(): p = gdspy.Rectangle((0, 0), (1, 1)) q = gdspy.copy(p, 1, -1) assert set(p.polygons[0][:, 0]) == {0, 1} assert set(p.polygons[0][:, 1]) == {0, 1} assert set(q.polygons[0][:, 0]) == {1, 2} assert set(q.polygons[0][:, 1]) == {-1, 0} p = gdspy.PolygonSet([[(0, 0), (1, 0), (0, 1)], [(2, 2), (3, 2), (2, 3)]]) q = gdspy.copy(p, 1, -1) assert set(p.polygons[0][:, 0]) == {0, 1} assert set(p.polygons[0][:, 1]) == {0, 1} assert set(q.polygons[0][:, 0]) == {1, 2} assert set(q.polygons[0][:, 1]) == {-1, 0} assert set(p.polygons[1][:, 0]) == {2, 3} assert set(p.polygons[1][:, 1]) == {2, 3} assert set(q.polygons[1][:, 0]) == {3, 4} assert set(q.polygons[1][:, 1]) == {1, 2} l = gdspy.Label("text", (0, 1)) m = gdspy.copy(l, -1, 1) assert l.position[0] == 0 and l.position[1] == 1 assert m.position[0] == -1 and m.position[1] == 2 c = gdspy.CellReference("empty", (0, 1), ignore_missing=True) d = gdspy.copy(c, -1, 1) assert c.origin == (0, 1) assert d.origin == (-1, 2) c = gdspy.CellArray("empty", 2, 3, (1, 0), (0, 1), ignore_missing=True) d = gdspy.copy(c, -1, 1) assert c.origin == (0, 1) assert d.origin == (-1, 2)