def via_layer(self): width = self.con1[1][0] via_count = int((width - 2 * EN_VIA + SP_VIA) / (W_VIA + SP_VIA)) via_offset = (width - W_VIA - (SP_VIA + W_VIA) * (via_count - 1)) / 2 delta = 0.5 * (SP_VIA + W_VIA) for via in self.via: via_cell = gdspy.Cell("VIA", True) via_layer = layer['VIA' + str(via)] via_shape = gdspy.Rectangle( (0, self.VIA_OFF), (W_VIA, self.VIA_OFF + W_VIA), via_layer) via_cell.add(via_shape) if (via - self.m_bot) % 2 == 0: via_array1 = gdspy.CellArray(via_cell, via_count, 1, [SP_VIA + W_VIA, 0], (via_offset, 0)) via_array2 = gdspy.CellArray(via_cell, via_count, 1, [SP_VIA + W_VIA, 0], (via_offset, self.con2[0][1])) else: via_array1 = gdspy.CellArray(via_cell, via_count - 1, 1, [SP_VIA + W_VIA, 0], (via_offset + delta, 0)) via_array2 = gdspy.CellArray( via_cell, via_count - 1, 1, [SP_VIA + W_VIA, 0], (via_offset + delta, self.con2[0][1])) self.cell.add(via_array1) self.cell.add(via_array2)
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 finger_core(self): # MOMCAP Finger CORE # Define CAP finger shapes # This should be legal by default if f_tip=170n, sp=70n, w=70n self.W_CON = (basic.legal_len(2 * W_CON + 2 * self.f_tip + self.l) - 2 * self.f_tip - self.l) * 0.5 self.VIA_OFF = int((self.W_CON - W_VIA) * 100) / 200.0 self.finger_y1 = self.W_CON + self.f_tip self.finger_y2 = self.finger_y1 + self.l self.finger_sp = self.sp + self.w con_len = basic.legal_len(self.finger_sp * (self.nf - 1) + self.w) self.con1 = [[0, 0], [con_len, self.W_CON]] self.con2 = [[0, self.finger_y2 + self.f_tip], [ self.con1[1][0], self.con1[1][1] + self.finger_y2 + self.f_tip ]] self.origin = [0, 0] for metal in self.metal: # Cap core finger cell finger_cell = gdspy.Cell("FINGER", True) finger_shape = gdspy.Rectangle( (0, self.finger_y1), (self.w, self.finger_y2), layer[metal]) finger_cell.add(finger_shape) finger_array = gdspy.CellArray(finger_cell, self.nf, 1, [self.finger_sp, 0]) self.cell.add(finger_array) # Finger extension ext_cell = gdspy.Cell("EXT", True) ext_shape = gdspy.Rectangle((0, self.W_CON), (self.w, self.finger_y1), layer[metal]) ext_cell.add(ext_shape) bot_ext = gdspy.CellArray(ext_cell, self.nf / 2, 1, [2 * self.finger_sp, 0]) bot_cell = gdspy.Cell("BOT_EXT", True) bot_cell.add(bot_ext) top_ext = gdspy.CellReference( bot_cell, (self.finger_sp, self.finger_y2 - self.W_CON)) self.cell.add([bot_ext, top_ext]) # Finger connection metal con_bot_shape = gdspy.Rectangle(self.con1[0], self.con1[1], layer[metal]) con_top_shape = gdspy.Rectangle(self.con2[0], self.con2[1], layer[metal]) self.cell.add([con_bot_shape, con_top_shape]) # Adding Pins self.plus.add_shape(metal, [self.con1[0], self.con1[1]]) self.minus.add_shape(metal, [self.con2[0], self.con2[1]]) #self.plus.add_shape(metal, [self.con1[0],[self.con1[1][0],self.con1[0][1]+min_w['M1']]]) #self.minus.add_shape(metal, [[self.con2[0][0],self.con2[1][1]-min_w['M1']],self.con2[1]]) # MOMDMY Layer momdmy_shape = gdspy.Rectangle( (-GRID, self.W_CON), (self.con2[1][0] + GRID, self.con2[0][1]), layer['MOMDMY'], datatype=int(metal[1])) self.cell.add(momdmy_shape)
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 MZM_DC(lib, cell_Heater, cell_DC, cellName='MZM_DC', w_wg=0.5, N=2, w_etch_DC=3 ): bc = cell_DC.get_bounding_box() l_DC = bc[1][0] - bc[0][0] S_Port_DC = bc[1][1] - bc[0][1] - 2*w_etch_DC - w_wg bc = cell_Heater.get_bounding_box() l_Heater = bc[1][0] - bc[0][0] cell = lib.new_cell(cellName) cell.add(gdspy.CellArray(cell_DC, N+1, 1, (l_Heater+l_DC, 0))) cell.add(gdspy.CellArray(cell_Heater, N, 1, (l_Heater+l_DC, 0), (l_DC, 0))) for i in range(N): wg = wg_line(w_wg, w_etch_DC, ((l_DC+l_Heater)*i+l_DC, -S_Port_DC), l_Heater) cell.add(wg) return cell
def rect_array(self, pos, size, columns, rows, spacing, origin=(0, 0), **kwargs): pos, size = parse_entry(pos, size) name = kwargs['name'] layer = kwargs['layer'] points = [(pos[0], pos[1]), (pos[0] + size[0], pos[1] + 0), (pos[0] + size[0], pos[1] + size[1]), (pos[0], pos[1] + size[1])] poly1 = gdspy.Polygon(points, layer) self.gds_object_instances[name] = poly1 cell_to_copy = gdspy.Cell('cell_to_copy') self.gds_cells['cell_to_copy'] = cell_to_copy cell_to_copy.add(poly1) spacing = parse_entry(spacing) cell_array = gdspy.CellArray(cell_to_copy, columns, rows, spacing, origin) polygon_list = cell_array.get_polygons() poly2 = gdspy.PolygonSet(polygon_list, layer) self.cell.add(poly2) self.gds_object_instances[name] = poly2
def CreateMarks(nx = 2, #number of columns ny = 2, #number of rows dx = 3000, #horizontal distance dy = 3000, #vertical distance PhotoLayer=2, eBeamLayer=5): """ Create cross lithography marks on the chip. """ # Mark for EB crmk = gds.Cell('cross', exclude_from_current=True) crmk.add(gds.Rectangle((-100,-10),(-10, 10),layer=eBeamLayer)) crmk.add(gds.Rectangle((-120, -30),(10, 30),layer=PhotoLayer)) crmk.add(gds.Rectangle((100,-10),(10,10),layer=eBeamLayer)) crmk.add(gds.Rectangle((120,-30),(-10,30),layer=PhotoLayer)) crmk.add(gds.Rectangle((-10,-100),(10,-10),layer=eBeamLayer)) crmk.add(gds.Rectangle((-30,-120),(30, 10),layer=PhotoLayer)) crmk.add(gds.Rectangle((-10,100),(10,10),layer=eBeamLayer)) crmk.add(gds.Rectangle((-30,120),(30,-10),layer=PhotoLayer)) crmk.add(gds.Rectangle((-4,0),(0,1),layer=eBeamLayer)) crmk.add(gds.Rectangle((-1,1),(0,4),layer=eBeamLayer)) crmk.add(gds.Rectangle((4,0),(0,-1),layer=eBeamLayer)) crmk.add(gds.Rectangle((1,-1),(0,-4),layer=eBeamLayer)) # Make array mkar = gds.CellArray(crmk, nx, ny, (dx,dy), origin=(-(nx-1)*dx/2, -(ny-1)*dy/2)) return crmk, mkar
def test_offset(): gdspy.current_library = gdspy.GdsLibrary() r = gdspy.Rectangle((0, 0), (1, 2)) result = gdspy.Rectangle((-1, -1), (2, 3)) assert equals(gdspy.offset(r, 1), result) c = gdspy.Cell("OFFSET").add(r) ca = gdspy.CellArray(c, 2, 1, (1, 0)) result = gdspy.Rectangle((0.2, 0.2), (1.8, 1.8)) assert equals(gdspy.offset([ca], -0.2, join_first=True), result) v = [gdspy.Rectangle((-1, -1), (1, 1)), [(0, 0), (1, 0), (1, 1), (0, 1)]] x = 1 + 0.1 * numpy.tan(numpy.pi / 8) result = gdspy.Polygon( [ (-1.1, -x), (-1.1, x), (-x, 1.1), (x, 1.1), (1.1, x), (1.1, -x), (x, -1.1), (-x, -1.1), ], layer=8, ) assert equals(gdspy.offset(v, 0.1, join="bevel", layer=12), result)
def power_strip(w, h, offset=[0,0], lay=[5,6]): power_cell = gdspy.Cell("POWER", True) contact_num_w = int((w-2*basic.EN_VIA+basic.SP_VIA)/(basic.W_VIA+basic.SP_VIA)) contact_num_h = int((h-2*basic.EN_VIA+basic.SP_VIA)/(basic.W_VIA+basic.SP_VIA)) contact_space_w = (w-basic.EN_VIA-contact_num_w*basic.W_VIA)/(contact_num_w-1)+basic.W_VIA contact_space_h = (h-basic.EN_VIA-contact_num_h*basic.W_VIA)/(contact_num_h-1)+basic.W_VIA if contact_space_w < basic.SP_VIA + basic.W_VIA: contact_num_w = contact_num_w - 1 contact_space_w = (h-2*basic.EN_VIA-contact_num_w*basic.W_VIA)/(contact_num_w-1)+basic.W_VIA if contact_space_h < basic.SP_VIA + basic.W_VIA: contact_num_h = contact_num_h - 1 contact_space_h = (h-2*basic.EN_VIA-contact_num_h*basic.W_VIA)/(contact_num_h-1)+basic.W_VIA contact_space_h = int(contact_space_h/basic.GRID)*basic.GRID contact_space_w = int(contact_space_w/basic.GRID)*basic.GRID x_offset = (w-basic.W_VIA-contact_space_w*(contact_num_w-1))/2 + offset[0] y_offset = (h-basic.W_VIA-contact_space_h*(contact_num_h-1))/2 + offset[1] x_offset = int(x_offset/basic.GRID)*basic.GRID y_offset = int(y_offset/basic.GRID)*basic.GRID for i in lay: met_layer = 'M' + str(i) m1_shape = gdspy.Rectangle((offset[0],offset[1]),(offset[0]+w,offset[1]+h),basic.layer[met_layer], basic.datatype[met_layer]) power_cell.add(m1_shape) if i != lay[-1]: contact_cell = basic.contact(i) contact_array = gdspy.CellArray(contact_cell, contact_num_w, contact_num_h, [contact_space_w, contact_space_h], [x_offset, y_offset]) power_cell.add(contact_array) power_cell.flatten() return power_cell
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 get_gdspy_cell(self, executor=None): import gdspy if self.cell_gdspy is None: self.cell_gdspy = gdspy.Cell(self.name) for sub_cell in self.cells: angle = np.rad2deg(sub_cell['angle']) if sub_cell['angle'] is not None else None if sub_cell['columns'] == 1 and sub_cell['rows'] == 1 and not sub_cell['spacing']: self.cell_gdspy.add( gdspy.CellReference(sub_cell['cell'].get_gdspy_cell(executor), origin=sub_cell['origin'], rotation=angle, magnification=sub_cell['magnification'], x_reflection=sub_cell['x_reflection'])) else: self.cell_gdspy.add( gdspy.CellArray(sub_cell['cell'].get_gdspy_cell(executor), origin=sub_cell['origin'], rotation=angle, magnification=sub_cell['magnification'], x_reflection=sub_cell['x_reflection'], columns=sub_cell['columns'], rows=sub_cell['rows'], spacing=sub_cell['spacing'])) for layer, geometries in self.layer_dict.items(): for geometry in geometries: if executor: executor.submit(convert_to_layout_objs, geometry, layer, library='gdspy') \ .add_done_callback(lambda future: self.cell_gdspy.add(future.result())) else: self.cell_gdspy.add(convert_to_layout_objs(geometry, layer, library='gdspy')) return self.cell_gdspy
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)
def test_notempty(): name = "ca_notempty" c = gdspy.Cell(name) ref = gdspy.CellArray(name, 2, 3, (3, 2), (1, -1), 90, 2, True) ref.translate(-1, 1) c.add(gdspy.Rectangle((0, 0), (1, 2), 2, 3)) assert ref.area() == 48 assert ref.area(True) == {(2, 3): 48} err = numpy.array(((0, 0), (8, 5))) - ref.get_bounding_box() assert numpy.max(numpy.abs(err)) < 1e-15 assert ref.origin[0] == ref.origin[1] == 0 r = gdspy.boolean( [gdspy.Rectangle((0, 0), (8, 2)), gdspy.Rectangle((0, 3), (8, 5))], ref.get_polygons(), "xor", 1e-6, 0, ) assert r is None d = ref.get_polygons(True) assert len(d.keys()) == 1 r = gdspy.boolean( [gdspy.Rectangle((0, 0), (8, 2)), gdspy.Rectangle((0, 3), (8, 5))], d[(2, 3)], "xor", 1e-6, 0, ) assert r is None
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 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_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 GeneratePixelArray(pixelcellname='PIXEL', edgecell='EDGE', nX=256, nY=256, pitchX=55, pitchY=55, topcellname='TOP'): mpx_cell = gdspy.Cell(topcellname) mpx_cell.add( gdspy.CellArray(pixelcellname, nX, nY, (pitchX, pitchY), (pitchX / 2., pitchY / 2.))) mpx_cell.add( gdspy.CellArray(edgecell, 1, 1, (0, 0), (nX * pitchX / 2., nY * pitchY / 2.))) mpx_cell.add( gdspy.CellArray('GR', 1, 1, (0, 0), (nX * pitchX / 2., nY * pitchY / 2.)))
def bench_gdspy(output=None): p = gdspy.Polygon([(0, 0), (1, 0), (0, 1)]) fp = gdspy.FlexPath([(-1, 0.5), (1, 0), (0.5, -0.5)], [0.1, 0.1], 0.3, ends="round") rp = gdspy.RobustPath((0, 0), [0.1, 0.1], 0.3).smooth( [(2, 0.5), (2, 1), (-1, 4)] ) c1 = gdspy.Cell("REF", exclude_from_current=True) c1.add([p, fp, rp]) r1 = gdspy.CellArray(c1, columns=3, rows=2, spacing=(2, 2), rotation=30) r2 = gdspy.CellArray(c1, origin=(8, 0), columns=5, rows=4, spacing=(2, 2)) r3 = gdspy.CellArray(c1, origin=(9, 1), columns=4, rows=3, spacing=(2, 2)) c2 = gdspy.Cell("MAIN", exclude_from_current=True) c2.add([r1, r2, r3]) bb = c2.get_bounding_box() if output: c2.add(gdspy.Rectangle(*bb, layer=1)) c2.write_svg(output, 100)
def test_missing_ca(tmpdir): lib = gdspy.GdsLibrary() c1 = gdspy.Cell("cell1") c1.add(gdspy.CellArray("missing", 2, 3, (1, 4), (-1, -2), 180, 0.5, True, ignore_missing=True)) lib.add(c1) out = str(tmpdir.join("test.gds")) now = datetime.datetime.today() lib.write_gds(out, timestamp=now)
def test_empty(): name = "ca_empty" c = gdspy.Cell(name) ref = gdspy.CellArray(name, 2, 3, (3, 2), (1, -1), 90, 2, True) ref.translate(-1, 1) assert ref.area() == 0 assert ref.area(True) == dict() assert ref.get_bounding_box() is None assert ref.get_polygons() == [] assert ref.get_polygons(True) == dict() assert ref.origin[0] == ref.origin[1] == 0
def bench_gdspy(output=None): poly = gdspy.Round((0, 0), 1.5, number_of_points=6, layer=1) orig = gdspy.Cell("OFF", exclude_from_current=True) orig.add(poly) ref = gdspy.CellArray(orig, 4, 1, (2, 0), origin=(-3, 5)) off = gdspy.offset([poly, ref], 0.2, "round", layer=0) boo = gdspy.boolean(off, [poly, ref], "not", layer=2) if output: cell = gdspy.Cell("MAIN", exclude_from_current=True) cell.add([ref, poly, off, boo]) cell.write_svg(output, 50)
def test_noreference(): name = "ca_noreference" with pytest.warns(UserWarning): ref = gdspy.CellArray(name, 2, 3, (3, 2), (1, -1), 90, 2, True) ref.translate(-1, 1) assert ref.ref_cell == name assert ref.area() == 0 assert ref.area(True) == dict() assert ref.get_bounding_box() is None assert ref.get_polygons() == [] assert ref.get_polygons(True) == dict() assert ref.origin[0] == ref.origin[1] == 0
def bench_gdspy(output=None): p = gdspy.Polygon([(0, 0), (1, 0), (0, 1)]) fp = gdspy.FlexPath([(0, 0), (1, 0), (0.5, -0.5)], 0.1, ends="round") c1 = gdspy.Cell("REF", exclude_from_current=True) c1.add([p, fp]) r = gdspy.CellArray(c1, columns=3, rows=2, spacing=(2, 2), rotation=30) c2 = gdspy.Cell("MAIN", exclude_from_current=True) c2.add(r) bb = c2.get_bounding_box() if output: c2.add(gdspy.Rectangle(*bb, layer=1)) c2.write_svg(output, 100)
def lattice(cell, repeat, spacing): #============================ # Generate a crystal lattice \\ #========================================================================= # Arguments: cell : unit cell as gdspy Cell object || # repeat : (n_x, n_y) vector with amount of cells || # spacing : sapce between unit cells || #========================================================================= array = gd.CellArray(cell, repeat[0], repeat[1], spacing) ends = {'A': (0, spacing[1] * repeat[1] / 2), 'B': (spacing[0] * (repeat[0] - 1) / 2, spacing[1] * (repeat[1] - 1/2))} epsz = {'A': 0, 'B': 0} return gtools.classes.GDStructure(array, ends, epsz)
def test_bounding_box2(): cell0 = gdspy.Cell("0") cell0.add(gdspy.Rectangle((0, 0), (0.5, 0.25))) cell1 = gdspy.Cell("1") cell1.add(gdspy.CellArray(cell0, 2, 4, (0.5, 0.25))) # Cell1: plain 1x1 um square, with bottom-left corner at 0,0 assert_bb(cell1.get_bounding_box(), ((0, 0), (1, 1))) # Cell2: place and rotate Cell1 45deg about origin cell2 = gdspy.Cell("2") cell2.add(gdspy.CellReference(cell1, rotation=45)) assert_bb(cell2.get_bounding_box(), ((-(0.5 ** 0.5), 0), (0.5 ** 0.5, 2 ** 0.5))) # Cell3: place and rotate Cell2 an additional 45deg about origin (Cell1 is now rotated total 90deg) cell3 = gdspy.Cell("3") cell3.add(gdspy.CellReference(cell2, rotation=45)) assert_bb(cell3.get_bounding_box(), ((-1, 0), (0, 1))) # Cell4: nest Cell2 one level deeper with no transform (geometric equivalent to Cell2) cell4 = gdspy.Cell("4") cell4.add(gdspy.CellArray(cell2, 1, 1, (1, 1))) assert_bb(cell4.get_bounding_box(), ((-(0.5 ** 0.5), 0), (0.5 ** 0.5, 2 ** 0.5))) # Cell5: rotate Cell4 an addition 45 degrees (geometric equivalent to Cell3) cell5 = gdspy.Cell("5") cell5.add(gdspy.CellArray(cell4, 1, 1, (1, 1), rotation=45)) assert_bb(cell5.get_bounding_box(), ((-1, 0), (0, 1))) # Cell6: translate Cell1 by 2um east cell6 = gdspy.Cell("6") cell6.add(gdspy.CellArray(cell1, 1, 1, (1, 1), origin=(2, 0))) assert_bb(cell6.get_bounding_box(), ((2, 0), (3, 1)))
def library(): lib = gdspy.GdsLibrary() c1 = gdspy.Cell("cell1") c1.add(gdspy.Rectangle((0, -1), (1, 2), 2, 4)) c1.add(gdspy.Label("label", (1, -1), "w", 45, 1.5, True, 5, 6)) c2 = gdspy.Cell("cell2") c2.add(gdspy.Round((0, 0), 1, number_of_points=32, max_points=20)) c3 = gdspy.Cell("cell3") c3.add(gdspy.CellReference(c1, (0, 1), -90, 2, True)) c4 = gdspy.Cell("cell04") c4.add(gdspy.CellArray(c2, 2, 3, (1, 4), (-1, -2), 180, 0.5, True)) lib.add([c1, c2, c3, c4]) return lib
def init_array(self, bit=8, col_bit=4, ref=True, x_overlap=True): # Generate array of self.row * self.column # Currently ref column only True works # Implement Cell Array self.col_bit = col_bit self.row_bit = bit - col_bit self.column = 2**col_bit self.row = 2**(bit - col_bit) - 1 # Minus 1 because of column_cell if ref: self.row = self.row + 1 self.row_bit = self.row_bit + 1 bound = self.array_cell.cell.get_bounding_box() self.x_dist = bound[1][0] - bound[0][0] self.y_dist = bound[1][1] - bound[0][1] if x_overlap: self.overlap_offset = 2 * (self.array_cell.sub_x1 - self. array_cell.od25_p1[0]) + min_w['M1'] self.x_dist = self.x_dist - self.overlap_offset self.dist = [self.x_dist, self.y_dist] self.array = gdspy.CellArray(self.array_cell.cell, self.row, self.column, self.dist) self.col = gdspy.CellArray(self.column_cell.cell, 1, self.column, self.dist, [self.x_dist * self.row, 0]) self.dummy_hori_1 = gdspy.CellArray(self.dummy_cell_t.cell, self.row, 1, self.dist, [0, -self.y_dist]) self.dummy_hori_2 = gdspy.CellArray(self.dummy_cell_b.cell, self.row + 1, 1, self.dist, [0, self.y_dist * self.column]) self.dummy_hori_3 = gdspy.CellReference( self.dummy_cell.cell, (self.x_dist * self.row, -self.y_dist)) self.dummy_vert_1 = gdspy.CellArray(self.dummy_cell.cell, 1, self.column + 2, self.dist, [-self.x_dist, -self.y_dist]) self.dummy_vert_2 = gdspy.CellArray( self.dummy_cell.cell, 1, self.column + 2, self.dist, [self.x_dist * (self.row + 1), -self.y_dist]) self.cell.add(self.array) self.cell.add(self.col) self.cell.add(self.dummy_vert_1) self.cell.add(self.dummy_vert_2) self.cell.add(self.dummy_hori_1) self.cell.add(self.dummy_hori_2) self.cell.add(self.dummy_hori_3) # Calculate crutial coordinates self.sub_x = [] self.top_x = [] self.top_y = [] self.bot_x = [] for i in range(self.column): self.top_y.append(self.array_cell.con2[0][1] + i * self.y_dist) for i in range(-1, self.row + 3): self.sub_x.append(self.array_cell.sub_x1 + i * self.x_dist) for i in range(self.row): self.top_x.append(self.array_cell.topx + i * self.x_dist) for i in range(self.row + 1): self.bot_x.append(self.array_cell.botx + i * self.x_dist) self.cell.flatten() self.bound = self.cell.get_bounding_box()
def metal_hori(w, h, lay=1): #usually h set to basic.min_w['M1'] met_layer = 'M' + str(lay) m1_cell = gdspy.Cell('M1_HORI', True) m1_shape = gdspy.Rectangle((0,0), (w,h), basic.layer[met_layer], basic.datatype[met_layer]) m1_cell.add(m1_shape) contact_cell = basic.contact(lay-1) if lay == 1: contact_num = int((w-2*basic.en['M1']['CO']+basic.sp['CO']['CO'])/(basic.min_w['CO']+basic.sp['CO']['CO'])) else: contact_num = int((w-2*basic.EN_VIA+basic.SP_VIA)/(basic.W_VIA+basic.SP_VIA)) if contact_num == 1: if lay == 1: contact_space = basic.sp['CO']['CO'] else: contact_space = basic.SP_VIA else: if lay == 1: contact_space = (w-2*basic.en['M1']['CO']-contact_num*basic.min_w['CO'])/(contact_num-1)+basic.min_w['CO'] if contact_space < basic.sp['CO']['CO'] + basic.min_w['CO']: contact_num = contact_num - 1 contact_space = (w-2*basic.en['M1']['CO']-contact_num*basic.min_w['CO'])/(contact_num-1)+basic.min_w['CO'] else: contact_space = (w-basic.EN_VIA-contact_num*basic.W_VIA)/(contact_num-1)+basic.W_VIA if contact_space < basic.SP_VIA + basic.W_VIA: contact_num = contact_num - 1 contact_space = (w-2*basic.EN_VIA-contact_num*basic.W_VIA)/(contact_num-1)+basic.W_VIA contact_space = int(contact_space/basic.GRID)*basic.GRID # to satisify manufactor grid #contact_num = int((w-2*en['M1']['CO']+sp['CO']['CO'])/(basic.min_w['CO']+sp['CO']['CO'])) #if contact_num ==1: # contact_space = sp['CO']['CO'] #else: # contact_space = (w-2*en['M1']['CO']-contact_num*basic.min_w['CO'])/(contact_num-1)+basic.min_w['CO'] # if contact_space < sp['CO']['CO'] + basic.min_w['CO']: # contact_num = contact_num - 1 # contact_space = (w-2*en['M1']['CO']-contact_num*basic.min_w['CO'])/(contact_num-1)+basic.min_w['CO'] #contact_space = int(contact_space/basic.GRID)*basic.GRID # to satisify manufactor grid # Offset Center if lay == 1: x_offset = (w - basic.min_w['CO'] - contact_space*(contact_num-1))/2 y_offset = (h-basic.min_w['CO'])/2 else: x_offset = (w - basic.W_VIA - contact_space*(contact_num-1))/2 y_offset = (h-basic.W_VIA)/2 x_offset = int(x_offset/basic.GRID)*basic.GRID y_offset = int(y_offset/basic.GRID)*basic.GRID contact_array = gdspy.CellArray(contact_cell, contact_num, 1, [contact_space, contact_space], [x_offset, y_offset]) m1_cell.add(contact_array) m1_cell.flatten() return m1_cell
def tree(): p1 = gdspy.Polygon(((0, 0), (0, 1), (1, 0)), 0, 0) p2 = gdspy.Polygon(((2, 0), (2, 1), (1, 0)), 1, 1) l1 = gdspy.Label("label1", (0, 0), layer=11) l2 = gdspy.Label("label2", (2, 1), layer=12) c1 = gdspy.Cell("tree_" + unique()) c1.add(p1) c1.add(l1) c2 = gdspy.Cell("tree_" + unique()) c2.add(l2) c2.add(p2) c2.add(gdspy.CellReference(c1)) c3 = gdspy.Cell("tree_" + unique()) c3.add(gdspy.CellArray(c2, 3, 2, (3, 3))) return c3, c2, c1
def bench_gdspy(output=None): c1 = gdspy.Cell("REF", exclude_from_current=True) c1.add(gdspy.Rectangle((0, 0), (10, 10))) c1.add( gdspy.FlexPath([(0, 0), (10, 0), (10, 10), (0, 10)], [0.1, 0.1], 0.3, layer=1)) c1.add(gdspy.Label("Label", (5, 5), anchor='o')) c2 = gdspy.Cell("MAIN", exclude_from_current=True) c2.add(gdspy.CellArray(c1, columns=3, rows=2, spacing=(20, 20))) c2.flatten() c1.remove_polygons(lambda *_: True) c1.remove_paths(lambda *_: True) c1.remove_labels(lambda *_: True) if output: c2.write_svg(output, 10)