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)
def test_20_Antenna(self): ut_testsrc = os.getenv("TESTSRC") # --- simple antenna check input = os.path.join(ut_testsrc, "testdata", "algo", "antenna_l1.gds") ly = pya.Layout() ly.read(input) au = os.path.join(ut_testsrc, "testdata", "algo", "antenna_au1.gds") ly_au = pya.Layout() ly_au.read(au) dss = pya.DeepShapeStore() self.assertEqual(dss.is_singular(), False) rdiode = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(1, 0)), dss) rpoly = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(6, 0)), dss) rcont = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(8, 0)), dss) rmetal1 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(9, 0)), dss) rvia1 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(11, 0)), dss) rmetal2 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(12, 0)), dss) self.assertEqual(dss.is_singular(), True) l2n = pya.LayoutToNetlist(dss) l2n.register(rdiode, "diode") l2n.register(rpoly, "poly") l2n.register(rcont, "cont") l2n.register(rmetal1, "metal1") l2n.register(rvia1, "via1") l2n.register(rmetal2, "metal2") l2n.connect(rpoly) l2n.connect(rcont) l2n.connect(rmetal1) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.extract_netlist() a1_3 = l2n.antenna_check(rpoly, rmetal1, 3) a1_10 = l2n.antenna_check(rpoly, rmetal1, 10) a1_30 = l2n.antenna_check(rpoly, rmetal1, 30) # Note: flatten.merged performs some normalization self.assertEqual( str(a1_3.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(100, 0)))), "") self.assertEqual( str(a1_10.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(101, 0)))), "") self.assertEqual( str(a1_30.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(102, 0)))), "") # --- same with flat l2n._destroy() input = os.path.join(ut_testsrc, "testdata", "algo", "antenna_l1.gds") ly = pya.Layout() ly.read(input) au = os.path.join(ut_testsrc, "testdata", "algo", "antenna_au1.gds") ly_au = pya.Layout() ly_au.read(au) rfdiode = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(1, 0))) rfpoly = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(6, 0))) rfcont = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(8, 0))) rfmetal1 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(9, 0))) rfvia1 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(11, 0))) rfmetal2 = pya.Region(ly.top_cell().begin_shapes_rec(ly.layer(12, 0))) self.assertEqual(rfdiode.is_deep(), False) self.assertEqual(rfpoly.is_deep(), False) self.assertEqual(rfmetal1.is_deep(), False) self.assertEqual(rfvia1.is_deep(), False) self.assertEqual(rfmetal2.is_deep(), False) l2n = pya.LayoutToNetlist(ly.top_cell().name, ly.dbu) l2n.register(rfdiode, "diode") l2n.register(rfpoly, "poly") l2n.register(rfcont, "cont") l2n.register(rfmetal1, "metal1") l2n.register(rfvia1, "via1") l2n.register(rfmetal2, "metal2") l2n.connect(rfpoly) l2n.connect(rfcont) l2n.connect(rfmetal1) l2n.connect(rfpoly, rfcont) l2n.connect(rfcont, rfmetal1) l2n.extract_netlist() a1_3 = l2n.antenna_check(rfpoly, rfmetal1, 3) a1_10 = l2n.antenna_check(rfpoly, rfmetal1, 10) a1_30 = l2n.antenna_check(rfpoly, rfmetal1, 30) # Note: flatten.merged performs some normalization self.assertEqual( str(a1_3.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(100, 0)))), "") self.assertEqual( str(a1_10.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(101, 0)))), "") self.assertEqual( str(a1_30.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(102, 0)))), "") # --- simple antenna check with metal2 l2n._destroy() l2n = pya.LayoutToNetlist(dss) l2n.register(rdiode, "diode") l2n.register(rpoly, "poly") l2n.register(rcont, "cont") l2n.register(rmetal1, "metal1") l2n.register(rvia1, "via1") l2n.register(rmetal2, "metal2") l2n.connect(rpoly) l2n.connect(rcont) l2n.connect(rmetal1) l2n.connect(rmetal2) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.extract_netlist() a2_5 = l2n.antenna_check(rpoly, rmetal2, 5) a2_10 = l2n.antenna_check(rpoly, rmetal2, 10) a2_17 = l2n.antenna_check(rpoly, rmetal2, 17) # Note: flatten.merged performs some normalization self.assertEqual( str(a2_5.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(200, 0)))), "") self.assertEqual( str(a2_10.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(201, 0)))), "") self.assertEqual( str(a2_17.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(202, 0)))), "") # --- antenna check with diodes and antenna effect reduction l2n._destroy() l2n = pya.LayoutToNetlist(dss) l2n.register(rdiode, "diode") l2n.register(rpoly, "poly") l2n.register(rcont, "cont") l2n.register(rmetal1, "metal1") l2n.register(rvia1, "via1") l2n.register(rmetal2, "metal2") l2n.connect(rdiode) l2n.connect(rpoly) l2n.connect(rcont) l2n.connect(rmetal1) l2n.connect(rdiode, rcont) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.extract_netlist() a3_3 = l2n.antenna_check(rpoly, rmetal1, 3, [[rdiode, 8.0]]) a3_10 = l2n.antenna_check(rpoly, rmetal1, 10, [[rdiode, 8.0]]) a3_30 = l2n.antenna_check(rpoly, rmetal1, 30, [[rdiode, 8.0]]) # Note: flatten.merged performs some normalization self.assertEqual( str(a3_3.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(300, 0)))), "") self.assertEqual( str(a3_10.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(301, 0)))), "") self.assertEqual( str(a3_30.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(302, 0)))), "") # --- antenna check with diodes l2n._destroy() l2n = pya.LayoutToNetlist(dss) l2n.register(rdiode, "diode") l2n.register(rpoly, "poly") l2n.register(rcont, "cont") l2n.register(rmetal1, "metal1") l2n.register(rvia1, "via1") l2n.register(rmetal2, "metal2") l2n.connect(rdiode) l2n.connect(rpoly) l2n.connect(rcont) l2n.connect(rmetal1) l2n.connect(rdiode, rcont) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.extract_netlist() a4_3 = l2n.antenna_check(rpoly, rmetal1, 3, [rdiode]) a4_10 = l2n.antenna_check(rpoly, rmetal1, 10, [rdiode]) a4_30 = l2n.antenna_check(rpoly, rmetal1, 30, [rdiode]) # Note: flatten.merged performs some normalization self.assertEqual( str(a4_3.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(400, 0)))), "") self.assertEqual( str(a4_10.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(401, 0)))), "") self.assertEqual( str(a4_30.flatten() ^ pya.Region(ly_au.top_cell().begin_shapes_rec( ly_au.layer(402, 0)))), "")