def test_2_Trans(self): a = pya.Trans() b = pya.Trans(pya.Trans.M135, pya.Point(17, 5)) ma = pya.CplxTrans(a, 0.5) mb = pya.CplxTrans(b, 2.0) u = pya.CplxTrans(a) self.assertEqual(str(ma), "r0 *0.5 0,0") self.assertEqual(str(mb), "m135 *2 17,5") self.assertEqual(ma == mb, False) self.assertEqual(ma == ma, True) self.assertEqual(ma != mb, True) self.assertEqual(ma != ma, False) self.assertEqual(str(mb.inverted()), "m135 *0.5 2.5,8.5") i = mb.dup() i.invert() self.assertEqual(str(i), "m135 *0.5 2.5,8.5") self.assertEqual(i * mb == u, True) self.assertEqual(mb * i == u, True) self.assertEqual(str(mb.trans(pya.Point(1, 0))), "17,3") self.assertEqual(str(mb.ctrans(2)), "4.0") self.assertEqual(str(i.ctrans(2)), "1.0")
def Start(mod="guiopen"): if mod == "gds": IO.layout = pya.Layout() elif mod == "guinew": IO.main_window = pya.Application.instance().main_window() IO.layout = IO.main_window.create_layout(1).layout() IO.layout_view = IO.main_window.current_view() IO.layout_view.rename_cellview("pythonout", 0) elif mod == "guiopen": IO.main_window = pya.Application.instance().main_window() IO.layout_view = IO.main_window.current_view() try: IO.layout = IO.layout_view.cellview( IO.layout_view.active_cellview_index()).layout() except AttributeError as _: return IO.Start("guinew") if len(IO.layout.top_cells()) > 0: IO.top = IO.layout.top_cells()[0] else: IO.top = IO.layout.create_cell("TOP") # IO.auxiliary = IO.layout.create_cell("auxiliary") IO.top.insert(pya.CellInstArray(IO.auxiliary.cell_index(), pya.Trans())) # IO.link = IO.layout.create_cell("link") IO.auxiliary.insert( pya.CellInstArray(IO.link.cell_index(), pya.Trans())) # IO.layer = IO.layout.layer(0, 0) for li1, li2 in [(0, 1), (0, 2)]: IO.layout.layer(li1, li2) return IO.layout, IO.top
def transformation_from_shape_impl(self): w = self.shape.bbox().width() h = self.shape.bbox().height() if w > h: return pya.Trans(3, False, pya.Point(self.shape.bbox().center().x+0.1*w, self.shape.bbox().center().y)) else: return pya.Trans(pya.Point(self.shape.bbox().center().x, self.shape.bbox().center().y+0.1*h))
def test_1a(self): # instantiate and register the library tl = PCellTestLib2() ly = pya.Layout(True) ly.dbu = 0.01 li1 = find_layer(ly, "1/0") self.assertEqual(li1 == None, True) ci1 = ly.add_cell("c1") c1 = ly.cell(ci1) lib = pya.Library.library_by_name("PCellTestLib2") self.assertEqual(lib != None, True) pcell_decl = lib.layout().pcell_declaration("Box2") param = [ pya.LayerInfo(1, 0) ] # rest is filled with defaults pcell_var_id = ly.add_pcell_variant(lib, pcell_decl.id(), param) pcell_var = ly.cell(pcell_var_id) pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans())) self.assertEqual(pcell_var.basic_name(), "Box2") self.assertEqual(pcell_var.pcell_parameters().__repr__(), "[<1/0>, 1.0, 1.0]") self.assertEqual(pcell_var.display_title(), "PCellTestLib2.Box2(L=1/0,W=1.000,H=1.000)") self.assertEqual(nh(pcell_var.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}") self.assertEqual(pcell_var.pcell_parameter("height").__repr__(), "1.0") self.assertEqual(c1.pcell_parameters(pcell_inst).__repr__(), "[<1/0>, 1.0, 1.0]") self.assertEqual(nh(c1.pcell_parameters_by_name(pcell_inst)), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}") self.assertEqual(c1.pcell_parameter(pcell_inst, "height").__repr__(), "1.0") self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'height': 1.0, 'layer': <1/0>, 'width': 1.0}") self.assertEqual(pcell_inst["height"].__repr__(), "1.0") self.assertEqual(pcell_inst.pcell_parameter("height").__repr__(), "1.0") self.assertEqual(pcell_var.pcell_declaration().__repr__(), pcell_decl.__repr__()) self.assertEqual(c1.pcell_declaration(pcell_inst).__repr__(), pcell_decl.__repr__()) self.assertEqual(pcell_inst.pcell_declaration().__repr__(), pcell_decl.__repr__()) li1 = find_layer(ly, "1/0") self.assertEqual(li1 == None, False) pcell_inst.change_pcell_parameter("height", 2.0) self.assertEqual(nh(pcell_inst.pcell_parameters_by_name()), "{'height': 2.0, 'layer': <1/0>, 'width': 1.0}") self.assertEqual(ly.begin_shapes(c1.cell_index(), li1).shape().__str__(), "box (-50,-100;50,100)") param = { "layer": pya.LayerInfo(2, 0), "width": 2, "height": 1 } li2 = ly.layer(2, 0) c1.change_pcell_parameters(pcell_inst, param) self.assertEqual(ly.begin_shapes(c1.cell_index(), li2).shape().__str__(), "box (-100,-50;100,50)") l10 = ly.layer(10, 0) c1.shapes(l10).insert(pya.Box(0, 10, 100, 210)) l11 = ly.layer(11, 0) c1.shapes(l11).insert(pya.Text("hello", pya.Trans())) self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l11).shape(), l10), False) self.assertEqual(pcell_decl.can_create_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10), True) self.assertEqual(repr(pcell_decl.parameters_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "[<10/0>, 1.0, 2.0]") self.assertEqual(str(pcell_decl.transformation_from_shape(ly, ly.begin_shapes(c1.cell_index(), l10).shape(), l10)), "r0 50,110")
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)
def setup_top(): top_name = 'top' print('INFO: Creating new top cell: ' + top_name) design_top = main_layout.top_cell() top = main_layout.create_cell('top') fill_top_cell = main_layout.create_cell('fill') top.insert(pya.CellInstArray(design_top.cell_index(), pya.Trans())) top.insert(pya.CellInstArray(fill_top_cell.cell_index(), pya.Trans())) return fill_top_cell, design_top
def setup_top(): top_name = 'top' print('INFO: Creating new top cell: ' + top_name) design_top = main_layout.top_cell() top = main_layout.create_cell('top') fill_top_cell = main_layout.create_cell('fill') top.insert(pya.CellInstArray(design_top.cell_index(), pya.Trans())) top.insert(pya.CellInstArray(fill_top_cell.cell_index(), pya.Trans())) print('INFO: Flattening top cell') top.move_tree(fill_top_cell) fill_top_cell.copy_tree(design_top) fill_top_cell.flatten(True) return fill_top_cell
def _boxes_move_and_copy(inregion, radius, number): xys = [(radius * cos(2 * pi * ii / number), radius * sin(2 * pi * ii / number)) for ii in range(number)] regions = [] for x, y in xys: regions.append(inregion.transformed(pya.Trans(int(x), int(y)))) return regions
def test_13(self): n = 100 w = 10000 ly = pya.Layout() l1 = ly.layer(1, 0) top = ly.create_cell("TOP") ix = 0 while ix < n: sys.stdout.write(str(ix) + "/" + str(n) + "\n") sys.stdout.flush() iy = 0 while iy < n: x = ix * w y = iy * w cell = ly.create_cell("X" + str(ix) + "Y" + str(iy)) cell.shapes(l1).insert(pya.Box(0, 0, w, w)) top.insert( pya.CellInstArray(cell.cell_index(), pya.Trans(pya.Point(ix * w, iy * w)))) iy += 1 ix += 1 ly._destroy()
def place_cell(parent_cell, cell, placement_origin, params=None, relative_to=None): """ Places a cell and return ports Args: parent_cell: cell to place into cell: cell to be placed placement_origin: pya.Point object to be used as origin relative_to: port name Returns: ports(dict): key:port.name, value: geometry.Port with positions relative to parent_cell's origin """ layout = parent_cell.layout() pcell, ports = cell.pcell(layout, params=params) if relative_to is not None: offset = next((port.position for port in ports if port.name == relative_to), None) placement_origin = placement_origin - offset parent_cell.insert( pya.CellInstArray( pcell.cell_index(), pya.Trans(pya.Trans.R0, placement_origin.to_itype(layout.dbu)))) for port in ports: port.position += placement_origin return {port.name: port for port in ports}
def test_2(self): # instantiate and register the library tl = PCellTestLib() ly = pya.Layout(True) ly.dbu = 0.01 ci1 = ly.add_cell("c1") c1 = ly.cell(ci1) lib = pya.Library.library_by_name("PCellTestLib") pcell_decl_id = lib.layout().pcell_id("Box") param = [ pya.LayerInfo(1, 0), 10.0, 2.0 ] pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) pcell_var = ly.cell(pcell_var_id) pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans())) li1 = find_layer(ly, "1/0") self.assertEqual(li1 != None, True) self.assertEqual(ly.is_valid_layer(li1), True) self.assertEqual(str(ly.get_info(li1)), "1/0") self.assertEqual(pcell_inst.is_pcell(), True) self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)") pcell_inst.convert_to_static() self.assertEqual(pcell_inst.is_pcell(), False) self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)") pcell_inst.convert_to_static() self.assertEqual(pcell_inst.is_pcell(), False) self.assertEqual(ly.begin_shapes(pcell_inst.cell_index, li1).shape().__str__(), "box (-500,-100;500,100)")
def layout_pgtext(cell, layer, x, y, text, mag, inv=False): pcell = cell.layout().create_cell("TEXT", "Basic", {"text": text, "layer": layer, "mag": mag, "inverse": inv}) dbu = cell.layout().dbu cell.insert(pya.CellInstArray(pcell.cell_index(), pya.Trans(pya.Trans.R0, x / dbu, y / dbu)))
def next_level(self): self.level += 1 print("Drawing Hilbert Level %g" % self.level) newcell = self.layout.create_cell(self.cell_prefix + "level_" + str(self.level)) transll = pya.Trans(0, 0) translr = pya.Trans(self.box_size + self.length, 0) transul = pya.Trans(1, False, self.box_size + self.cd, self.box_size + self.length) transur = pya.Trans(3, False, self.box_size + self.length, self.box_size * 2 + self.length + self.cd) print(" Placing Cells...") ll_inst = pya.CellInstArray(self.cell.cell_index(), transll) lr_inst = pya.CellInstArray(self.cell.cell_index(), translr) ul_inst = pya.CellInstArray(self.cell.cell_index(), transul) ur_inst = pya.CellInstArray(self.cell.cell_index(), transur) newcell.insert(ll_inst) newcell.insert(lr_inst) newcell.insert(ur_inst) newcell.insert(ul_inst) print(" Connecting Quadrants...") p11 = pya.Point(self.box_size + self.cd / 2, self.box_size + self.cd / 2) p12 = pya.Point(self.box_size + self.cd / 2 + self.length, self.box_size + self.cd / 2) p21 = pya.Point(self.cd / 2, self.cd / 2 + self.box_size) p22 = pya.Point(self.cd / 2, self.cd / 2 + self.box_size + self.length) p31 = pya.Point(self.box_size * 2 + self.length + self.cd / 2, self.cd / 2 + self.box_size) p32 = pya.Point(self.box_size * 2 + self.length + self.cd / 2, self.cd / 2 + self.box_size + self.length) path1 = pya.Path([p11, p12], self.cd, self.cd / 2, self.cd / 2).polygon() path2 = pya.Path([p21, p22], self.cd, self.cd / 2, self.cd / 2).polygon() path3 = pya.Path([p31, p32], self.cd, self.cd / 2, self.cd / 2).polygon() newcell.shapes(self.layer).insert(path1) newcell.shapes(self.layer).insert(path2) newcell.shapes(self.layer).insert(path3) print(" Updating Box Size...") self.box_size = self.box_size * 2 + self.length self.cell = newcell print("Done!")
def DrawMark(self, cell, pts, newcellname="Mark"): IO.layout.read(self.filename) for i in IO.layout.top_cells(): if (i.name == self.insertcellname): i.name = newcellname for pt in pts: tr = pya.Trans(pt.x, pt.y) new_instance = pya.CellInstArray(i.cell_index(), tr) cell.insert(new_instance)
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)
def _merge_and_draw(outregion, inregion, tr_to=None, cutbool=True): #region=outregion-inregion if cutbool: region = outregion - inregion else: region = outregion - ( outregion - inregion ) #outregion-inregion#outregion-(outregion-inregion)# if type(tr_to) == type(None): center = outregion.bbox().center() region.transform(pya.Trans(-center.x, -center.y)) tr = pya.Trans(center.x, center.y) else: tr = tr_to cut = IO.layout.create_cell("cut") IO.auxiliary.insert(pya.CellInstArray(cut.cell_index(), tr)) BasicPainter.Draw(cut, IO.layer, region) return region, cut
def test_1_Trans(self): a = pya.Trans() b = pya.Trans( pya.Trans.M135, pya.Point( 17, 5 )) c = pya.Trans( 3, True, pya.Point( 17, 5 )) d = pya.Trans( pya.Point( 17, 5 )) e = pya.Trans( pya.Trans.M135 ) e2 = pya.Trans.from_dtrans( pya.DTrans.M135 ) f = pya.Trans( pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 )) ) self.assertEqual( str(a), "r0 0,0" ) self.assertEqual( str(pya.Trans.from_s(str(a))), str(a) ) self.assertEqual( str(b), "m135 17,5" ) self.assertEqual( str(c), "m135 17,5" ) self.assertEqual( str(d), "r0 17,5" ) self.assertEqual( str(e), "m135 0,0" ) self.assertEqual( str(e2), "m135 0,0" ) self.assertEqual( str(f), "m135 17,5" ) self.assertEqual( str(pya.Trans.from_s(str(f))), str(f) ) self.assertEqual( str(b.trans( pya.Point( 1, 0 ))), "17,4" ) self.assertEqual( a == b, False ) self.assertEqual( a == a, True ) self.assertEqual( a != b, True ) self.assertEqual( a != a, False ) self.assertEqual( (d * e) == b, True ) self.assertEqual( (e * d) == b, False ) i = c.inverted() self.assertEqual( str(i), "m135 5,17" ) self.assertEqual( (i * b) == a, True ) self.assertEqual( (b * i) == a, True ) c = pya.Trans( 3, True, pya.Point( 17, 5 )) self.assertEqual( str(c), "m135 17,5" ) c.disp = pya.Point(1, 7) self.assertEqual( str(c), "m135 1,7" ) c.angle = 1 self.assertEqual( str(c), "m45 1,7" ) c.rot = 3 self.assertEqual( str(c), "r270 1,7" ) c.mirror = True self.assertEqual( str(c), "m135 1,7" ) self.assertEqual( str(e.trans( pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(( e * pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(e.trans( pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(( e * pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" ) self.assertEqual( str(e.trans( pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" ) self.assertEqual( str(( e * pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" ) self.assertEqual( str(e.trans( pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" ) self.assertEqual( str(( e * pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" ) self.assertEqual( str(e.trans( pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" ) self.assertEqual( str(( e * pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
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")
def test_4_Trans(self): a = pya.Trans() m = pya.CplxTrans(a, 1.1) da = pya.DTrans() dm = pya.DCplxTrans(da, 1.1) self.assertEqual(str(m), "r0 *1.1 0,0") self.assertEqual(str(pya.DCplxTrans.from_s(str(m))), str(m)) self.assertEqual(str(m.trans(pya.Point(5, -7))), "5.5,-7.7") im = pya.ICplxTrans(a, 0.5) im_old = im.dup() self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(pya.ICplxTrans.from_s(str(im))), str(im)) self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") im = pya.ICplxTrans(m) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im = pya.ICplxTrans(dm) self.assertEqual(str(im), "r0 *1.1 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "6,-8") im.assign(im_old) self.assertEqual(str(im), "r0 *0.5 0,0") self.assertEqual(str(im.trans(pya.Point(5, -7))), "3,-4") self.assertEqual(str(pya.ICplxTrans(5, -7)), "r0 *1 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, 5, -7)), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Point(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.Vector(5, -7))), "r180 *1.5 5,-7") self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5, pya.DVector(5, -7))), "r180 *1.5 5,-7") self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans.R180, 1.5)), "r180 *1.5 0,0") c = pya.ICplxTrans.from_dtrans(pya.DCplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0") c = pya.ICplxTrans.from_trans(pya.CplxTrans.M135) self.assertEqual(str(c), "m135 *1 0,0")
def test_6_Layout_props2(self): ly = pya.Layout(True) pv = [[17, "a"], ["b", [1, 5, 7]]] pid = ly.properties_id(pv) # does not work? @@@ # pv = { 17: "a", "b": [ 1, 5, 7 ] } # pid2 = ly.properties_id( pv ) # self.assertEqual( pid, pid2 ) ci1 = ly.add_cell("c1") ci2 = ly.add_cell("c2") linfo = pya.LayerInfo() linfo.layer = 16 linfo.datatype = 1 lindex = ly.insert_layer(linfo) c1 = ly.cell(ci1) c2 = ly.cell(ci2) tr = pya.Trans() inst = c2.insert(pya.CellInstArray(c1.cell_index(), tr)) self.assertEqual(inst.parent_cell.name, c2.name) self.assertEqual(inst.cell.name, c1.name) self.assertEqual(repr(inst.layout()), repr(ly)) s1 = c1.shapes(lindex).insert(pya.Box(10, -10, 50, 40), pid) s2 = c1.shapes(lindex).insert(pya.Box(10, -10, 50, 40)) self.assertEqual(repr(s1.property(17)), "\'a\'") s1.set_property(5, 23) s1.delete_property(17) self.assertEqual(repr(s1.property(17)), "None") self.assertEqual(str(s1.property(5)), "23") self.assertEqual(repr(s2.property(17)), "None") self.assertEqual(repr(inst.property("a")), "None") inst.set_property("a", 33) self.assertEqual(str(inst.property("a")), "33") inst.delete_property("a") self.assertEqual(repr(inst.property("a")), "None") # cell properties self.assertEqual(repr(c1.property(17)), "None") c1.prop_id = pid self.assertEqual(c1.prop_id, pid) self.assertEqual(repr(c1.property(17)), "\'a\'") c1.set_property(5, 23) c1.delete_property(17) self.assertEqual(repr(c1.property(17)), "None") self.assertEqual(str(c1.property(5)), "23")
def DrawMark(self, cell, pts, newcellname="Mark"): IO.layout.read(self.filename) for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.name = newcellname break for pt in pts: tr = pya.Trans(int(pt.x), int(pt.y)) new_instance = pya.CellInstArray(icell.cell_index(), tr) cell.insert(new_instance) for icell in IO.layout.top_cells(): if (icell.name == self.insertcellname): icell.flatten(True) icell.delete()
def create(w, p, dc1, dc2, len1, len2, n1, ps=0, ending=True): """Create a square grating with alternating duty cycle. w: length in x-direction p: period of grating dc1: duty cycle 1 dc2: duty cycle 2 len1: length of each dc1 section len2: length of each dc2 section n1: number of dc1 & dc2 section pairs ps: phase shift between sections of different duty cycle (0 to 1) ending: the grating ends with a dc1 section """ dcc = pya.Region() for i in range(n1): dcc.insert(sg.create((w//p+0.5)*p, len1, 0, p, dc1).transform( pya.Trans(0, False, 0, i*(len1+len2)))) dcc.insert(sg.create((w//p+0.5)*p, len2, 0, p, dc2).transform( pya.Trans(0, False, ps*p, (i+0.5)*(len1+len2)))) if ending == True: dcc.insert(sg.create((w//p+0.5)*p, len1, 0, p, dc1).transform( pya.Trans(0, False, 0, n1*(len1+len2)))) dcc.transform(pya.Trans(0, False, 0, -dcc.bbox().center().y)) return dcc
def scanBoxes(cellList=None, layerList=None, layermod='in', position='leftdown'): if cellList == None: cellList = [IO.top] if layerList == None: layerList = [(0, 1)] _layerlist = [] for ii in layerList: if type(ii) == str: if IO.layout.find_layer(ii) != None: _layerlist.append(IO.layout.find_layer(ii)) else: if IO.layout.find_layer(ii[0], ii[1]) != None: _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 ] region = pya.Region() for cell in cellList: for layer in layers: s = cell.begin_shapes_rec(layer) region.insert(s) region.merge() pts = [] for polygon in region.each(): print(polygon) try: polygon = polygon.bbox() finally: pass print(polygon) pt = polygon.p1 if position == 'leftdown' else polygon.center() pts.append(pt) output = [] layer = IO.layout.layer(0, 2) cell = IO.layout.create_cell("boxMarks") IO.auxiliary.insert(pya.CellInstArray(cell.cell_index(), pya.Trans())) painter = PcellPainter() for index, pt in enumerate(pts, 1): name = "M" + str(index) painter.DrawText(cell, layer, name, pya.DCplxTrans(100, 0, False, pt.x, pt.y)) output.append([name, {"x": pt.x, "y": pt.y}]) return output
def create(ly, li, text, mag, bias=0, flatten=False): """Add text. ly: Layout object li: layer index text: text content mag: magnification flatten: False: return CellInstArray object (default) True: return Region object """ # finding the PCell declaration object ... lib = pya.Library.library_by_name("Basic") if lib == None: raise Exception("Unknown lib 'Basic'") pcell_decl = lib.layout().pcell_declaration("TEXT") if pcell_decl == None: raise Exception("Unknown PCell 'TEXT'") # translating named parameters into an ordered sequence ... # named parameters param = { "text": text, "layer": ly.get_info(li), # target layer of the text "mag": mag, "bias": bias } # translate to array (to pv) pv = [] for p in pcell_decl.get_parameters(): if p.name in param: pv.append(param[p.name]) else: pv.append(p.default) # create the PCell variant cell pcell_var = ly.add_pcell_variant(lib, pcell_decl.id(), pv) if not flatten: # transformation t = pya.Trans() # insert into "top_cell" (must be provided by the caller) return pya.CellInstArray(pcell_var, t) else: # collect shapes reg = pya.Region(ly.cell(pcell_var).begin_shapes_rec(li)) return reg
def make_layer_cells(): #Load View app = pya.Application.instance() mw = app.main_window() lv = mw.current_view() ly = lv.active_cellview().layout() dbu = ly.dbu if lv == None: raise Exception("No view selected") cv = lv.cellview(lv.active_cellview_index()) #Loop through layers for layer in [1, 2, 3]: new_cell = ly.create_cell(cv.cell.display_title() + "L" + str(layer)) # Loop through instances for inst in cv.cell.each_inst(): #Calculate location of instances itrans = pya.ICplxTrans.from_trans(pya.CplxTrans()) box = inst.bbox().transformed(itrans) x = box.center().x y = box.center().y #Create new cell to represent given layer new_subcell = ly.create_cell(inst.cell.display_title() + "L" + str(layer)) #Map Bounding box and shape layers to new layer lm = pya.LayerMapping() lm.map(ly.layer(1, 3), ly.layer(1, 3)) lm.map(ly.layer(layer, 0), ly.layer(layer, 0)) lm.map(ly.layer(layer, 1), ly.layer(layer, 0)) #Create Instance Array to place into cell array = pya.CellInstArray() #Copy shapes, place, and insert array.cell_index = new_subcell.cell_index() new_subcell.copy_shapes(inst.cell, lm) array.trans = pya.Trans(pya.Point(x, y)) new_cell.insert(array)
def port_to_pin_helper(ports_list, cell, layerPinRec): # Create the pins, as short paths: from siepic_tools.config import PIN_LENGTH dbu = cell.layout().dbu for port in ports_list: if port.name.startswith("el"): pin_length = port.width else: pin_length = PIN_LENGTH * dbu port_position_i = port.position.to_itype(dbu) cell.shapes(layerPinRec).insert( pya.DPath([port.position - 0.5 * pin_length * port.direction, port.position + 0.5 * pin_length * port.direction], port.width).to_itype(dbu)) cell.shapes(layerPinRec).insert(pya.Text(port.name, pya.Trans( pya.Trans.R0, port_position_i.x, port_position_i.y))).text_size = 2 / dbu
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)
def test_3(self): # instantiate and register the library tl = PCellTestLib() ly = pya.Layout(True) ly.dbu = 0.01 c1 = ly.create_cell("c1") lib = pya.Library.library_by_name("PCellTestLib") pcell_decl_id = lib.layout().pcell_id("Box") param = { "w": 4.0, "h": 8.0, "l": pya.LayerInfo(1, 0) } pcell_var_id = ly.add_pcell_variant(lib, pcell_decl_id, param) pcell_var = ly.cell(pcell_var_id) pcell_inst = c1.insert(pya.CellInstArray(pcell_var_id, pya.Trans())) self.assertEqual(ly.begin_shapes(c1.cell_index(), ly.layer(1, 0)).shape().__str__(), "box (-200,-400;200,400)")
def DrawBoxes(cell, layer, dlength, dgap, radius, number, layerlist=None, layermod='not in', box=None, cutbool=True, dx=0, dy=0, filterfunc=None): ''' filterfunc=lambda pp:pp.area()>=20000 则只保留面积大于20000的部分, filterfunc为None时不检查 ''' fillCell = IO.layout.create_cell("fill") IO.auxiliary.insert( pya.CellInstArray(fillCell.cell_index(), pya.Trans())) fillRegion = SpecialPainter.DrawFillRegion(cell=fillCell, layer=IO.layer, radius=radius, number=number, layerlist=layerlist, layermod=layermod, box=box, cutbool=cutbool) boxesRegion = SpecialPainter.DrawBoxesInRegion(cell=cell, layer=layer, region=fillRegion, dlength=dlength, dgap=dgap, dx=dx, dy=dy, filterfunc=filterfunc) return fillCell, fillRegion, boxesRegion
def main(): # [1] Create TOP layout (LAYOUT_TOP, where layouts A,B,... would be merged) import pya LAYOUT_TOP = pya.Layout() CELL_TOP = LAYOUT_TOP.create_cell("CELL_TOP") # Create layer #'s import layer_numbers as lm l_TP_outline = LAYOUT_TOP.layer(lm.layer_num_TP_outline, 0) # One touch pixel Outline # Insert box outline for unit touch pixel dimensions CELL_TOP.shapes(l_TP_outline).insert(pya.Box(0, 0, p * 14, p * 14)) for ind, (k, v) in enumerate(gds_files_d.items()): print("\nProcessing ... : ", ind, k, v) # 0 | 2_unit_1_7.gds | [1, 7] # [2] Loop over each GDS, create separate layouts (LAYOUT_A, LAYOUT_B, ...), and read each GDS files LAYOUT_A = pya.Layout() LAYOUT_A.read(k) # From GDS name, get # of repeats in x-y dir [nx, ny] = get_nx_ny(k) #[nx, ny] = [1, 1] # [3] In TOP layout, create (empty) target cells (ta, tb, ...) CELL_TA = LAYOUT_TOP.create_cell("CELL_" + str(v[0]) + "_" + str(v[1])) # CELL_2_7, CELL_14_5, ... CELL_TOP.insert( pya.CellInstArray( CELL_TA.cell_index(), pya.Trans(pya.Point(p * (v[1] - 1), p * (v[0] - 1))), pya.Vector(p, 0), pya.Vector(0, p), nx, ny)) # v : value (e.g. [1, 7]) --> x = v[1], y = v[0] # [4] From [3], copy over the layouts from A to TA, using ta.move_tree(layout_A.top_cell() ) CELL_TA.move_tree(LAYOUT_A.top_cell()) # Export GDS LAYOUT_TOP.write("3_PANEL_wip.gds")