# encoding: UTF-8 # KLayout Layout Viewer # Copyright (C) 2006-2024 Matthias Koefferlein # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA if !$:.member?(File::dirname($0)) $:.push(File::dirname($0)) end load("test_prologue.rb") class DBLayoutToNetlist_TestClass < TestBase def test_1_Basic ly = RBA::Layout::new ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1.gds")) l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, [])) l2n.threads = 17 l2n.max_vertex_count = 42 l2n.area_ratio = 7.5 assert_equal(l2n.threads, 17) assert_equal(l2n.max_vertex_count, 42) assert_equal(l2n.area_ratio, 7.5) r = l2n.make_layer(ly.layer(6, 0)) assert_not_equal(l2n.internal_layout.object_id, ly.object_id) assert_equal(l2n.internal_layout.top_cell.name, ly.top_cell.name) assert_equal(l2n.internal_top_cell.name, ly.top_cell.name) assert_not_equal(l2n.layer_of(r), ly.layer(6, 0)) # would be a strange coincidence ... cm = l2n.const_cell_mapping_into(ly, ly.top_cell) (0 .. l2n.internal_layout.cells - 1).each do |ci| assert_equal(l2n.internal_layout.cell(ci).name, ly.cell(cm.cell_mapping(ci)).name) end ly2 = RBA::Layout::new ly2.create_cell(ly.top_cell.name) cm = l2n.cell_mapping_into(ly2, ly2.top_cell) assert_equal(ly2.cells, ly.cells) (0 .. l2n.internal_layout.cells - 1).each do |ci| assert_equal(l2n.internal_layout.cell(ci).name, ly2.cell(cm.cell_mapping(ci)).name) end rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" ) bulk_id = l2n.connect_global(rmetal1, "BULK") assert_equal(l2n.global_net_name(bulk_id), "BULK") # cell mapping with nets l2n = RBA::LayoutToNetlist::new l2n.read(File.join($ut_testsrc, "testdata", "algo", "l2n_reader_in.txt")) nets = [ l2n.netlist.circuit_by_name("RINGO").net_by_name("VSS"), l2n.netlist.circuit_by_name("RINGO").net_by_name("VDD") ] ly2 = RBA::Layout::new ly2.create_cell("TOP") cm = l2n.cell_mapping_into(ly2, ly2.top_cell, nets) map = (0 .. l2n.internal_layout.cells - 1).collect do |ci| cm.has_mapping?(ci) && (l2n.internal_layout.cell(ci).name + "=>" + ly2.cell(cm.cell_mapping(ci)).name) end assert_equal(map.select { |i| i }.join(","), "RINGO=>TOP") nets = [ l2n.netlist.circuit_by_name("INV2").net_by_name("IN"), ] ly2 = RBA::Layout::new ly2.create_cell("TOP") cm = l2n.cell_mapping_into(ly2, ly2.top_cell, nets) map = (0 .. l2n.internal_layout.cells - 1).collect do |ci| cm.has_mapping?(ci) && (l2n.internal_layout.cell(ci).name + "=>" + ly2.cell(cm.cell_mapping(ci)).name) end assert_equal(map.select { |i| i }.join(","), "RINGO=>TOP,INV2=>INV2") # extended attributes for extract_netlist l2n = RBA::LayoutToNetlist::new l2n.include_floating_subcircuits = true assert_equal(l2n.include_floating_subcircuits, true) l2n.include_floating_subcircuits = false assert_equal(l2n.include_floating_subcircuits, false) assert_equal(l2n.dump_joined_nets, "") l2n.join_nets([ "VDD", "NWELL" ]) l2n.join_nets([ "VSS", "BULK" ]) assert_equal(l2n.dump_joined_nets, "NWELL+VDD,BULK+VSS") l2n.clear_join_nets assert_equal(l2n.dump_joined_nets, "") assert_equal(l2n.dump_joined_nets_per_cell, "") l2n.join_nets("INV*", [ "VDD", "NWELL" ]) l2n.join_nets("ND2*", [ "VSS", "BULK" ]) assert_equal(l2n.dump_joined_nets_per_cell, "INV*:NWELL+VDD,ND2*:BULK+VSS") l2n.clear_join_nets assert_equal(l2n.dump_joined_nets, "") assert_equal(l2n.dump_joined_nets_per_cell, "") assert_equal(l2n.dump_joined_net_names, "") l2n.join_net_names("VDD") l2n.join_net_names("VSS") assert_equal(l2n.dump_joined_net_names, "VDD,VSS") l2n.clear_join_net_names assert_equal(l2n.dump_joined_net_names, "") assert_equal(l2n.dump_joined_net_names_per_cell, "") l2n.join_net_names("INV*", "VDD") l2n.join_net_names("ND2*", "VSS") assert_equal(l2n.dump_joined_net_names_per_cell, "INV*:VDD,ND2*:VSS") l2n.clear_join_net_names assert_equal(l2n.dump_joined_net_names, "") assert_equal(l2n.dump_joined_net_names_per_cell, "") end def test_2_ShapesFromNet ly = RBA::Layout::new ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds")) l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, [])) # only plain backend connectivity rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0), "metal1" ) rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1), "metal1_lbl" ) rvia1 = l2n.make_polygon_layer( ly.layer(7, 0), "via1" ) rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0), "metal2" ) rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1), "metal2_lbl" ) # Intra-layer l2n.connect(rmetal1) l2n.connect(rvia1) l2n.connect(rmetal2) # Inter-layer l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels # Perform netlist extraction l2n.extract_netlist nl_string = l2n.netlist.to_s assert_equal(nl_string, < rpsd, "G" => rpgate, "P" => rpoly }) # NMOS transistor device extraction nmos_ex = RBA::DeviceExtractorMOS3Transistor::new("NMOS") l2n.extract_devices(nmos_ex, { "SD" => rnsd, "G" => rngate, "P" => rpoly }) # Define connectivity for netlist extraction l2n.register(rpsd, "psd") l2n.register(rnsd, "nsd") # Intra-layer l2n.connect(rpsd) l2n.connect(rnsd) l2n.connect(rpoly) l2n.connect(rdiff_cont) l2n.connect(rpoly_cont) l2n.connect(rmetal1) l2n.connect(rvia1) l2n.connect(rmetal2) # Inter-layer l2n.connect(rpsd, rdiff_cont) l2n.connect(rnsd, rdiff_cont) l2n.connect(rpoly, rpoly_cont) l2n.connect(rpoly_cont, rmetal1) l2n.connect(rdiff_cont, rmetal1) l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.connect(rpoly, rpoly_lbl) # attaches labels l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels # Perform netlist extraction l2n.extract_netlist assert_equal(l2n.netlist.to_s, < rpsd, "G" => rpgate, "P" => rpoly, "W" => rnwell }) # NMOS transistor device extraction nmos_ex = RBA::DeviceExtractorMOS4Transistor::new("NMOS") l2n.extract_devices(nmos_ex, { "SD" => rnsd, "G" => rngate, "P" => rpoly, "W" => rbulk }) # Define connectivity for netlist extraction l2n.register(rpsd, "psd") l2n.register(rnsd, "nsd") l2n.register(rptie, "ptie") l2n.register(rntie, "ntie") # Intra-layer l2n.connect(rpsd) l2n.connect(rnsd) l2n.connect(rnwell) l2n.connect(rpoly) l2n.connect(rdiff_cont) l2n.connect(rpoly_cont) l2n.connect(rmetal1) l2n.connect(rvia1) l2n.connect(rmetal2) l2n.connect(rptie) l2n.connect(rntie) # Inter-layer l2n.connect(rpsd, rdiff_cont) l2n.connect(rnsd, rdiff_cont) l2n.connect(rpoly, rpoly_cont) l2n.connect(rpoly_cont, rmetal1) l2n.connect(rdiff_cont, rmetal1) l2n.connect(rdiff_cont, rntie) l2n.connect(rdiff_cont, rptie) l2n.connect(rnwell, rntie) l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.connect(rpoly, rpoly_lbl) # attaches labels l2n.connect(rmetal1, rmetal1_lbl) # attaches labels l2n.connect(rmetal2, rmetal2_lbl) # attaches labels # Global connections l2n.connect_global(rptie, "BULK") l2n.connect_global(rbulk, "BULK") # Perform netlist extraction l2n.extract_netlist assert_equal(l2n.netlist.to_s, < l2n.layer_by_name("psd"), ly.insert_layer(RBA::LayerInfo::new(11, 0)) => l2n.layer_by_name("nsd"), ly.insert_layer(RBA::LayerInfo::new(3, 0)) => l2n.layer_by_name("poly"), ly.insert_layer(RBA::LayerInfo::new(4, 0)) => l2n.layer_by_name("diff_cont"), ly.insert_layer(RBA::LayerInfo::new(5, 0)) => l2n.layer_by_name("poly_cont"), ly.insert_layer(RBA::LayerInfo::new(6, 0)) => l2n.layer_by_name("metal1"), ly.insert_layer(RBA::LayerInfo::new(7, 0)) => l2n.layer_by_name("via1"), ly.insert_layer(RBA::LayerInfo::new(8, 0)) => l2n.layer_by_name("metal2") } l2n.build_all_nets(cm, ly, lmap, "NET_", nil, RBA::LayoutToNetlist::BNH_Disconnected, nil, "DEVICE_") ly_au = RBA::Layout::new au_file = File.join($ut_testsrc, "testdata", "algo", "l2n_reader_au_1.gds") ly_au.read(au_file) lmap.each do |li,v| li_au = ly_au.layer(ly.get_info(li)) ly_region = RBA::Region::new(ly.top_cell.begin_shapes_rec(li)) ly_au_region = RBA::Region::new(ly_au.top_cell.begin_shapes_rec(li_au)) info = ly.get_info(li).to_s + ":" assert_equal(info + (ly_region ^ ly_au_region).to_s, info) end # build_nets ly = RBA::Layout::new ly.create_cell("TOP") cm = l2n.cell_mapping_into(ly, ly.top_cell) lmap = { ly.insert_layer(RBA::LayerInfo::new(10, 0)) => l2n.layer_by_name("psd"), ly.insert_layer(RBA::LayerInfo::new(11, 0)) => l2n.layer_by_name("nsd"), ly.insert_layer(RBA::LayerInfo::new(3, 0)) => l2n.layer_by_name("poly"), ly.insert_layer(RBA::LayerInfo::new(4, 0)) => l2n.layer_by_name("diff_cont"), ly.insert_layer(RBA::LayerInfo::new(5, 0)) => l2n.layer_by_name("poly_cont"), ly.insert_layer(RBA::LayerInfo::new(6, 0)) => l2n.layer_by_name("metal1"), ly.insert_layer(RBA::LayerInfo::new(7, 0)) => l2n.layer_by_name("via1"), ly.insert_layer(RBA::LayerInfo::new(8, 0)) => l2n.layer_by_name("metal2") } nets = [ l2n.netlist.circuit_by_name("RINGO").net_by_name("VSS"), l2n.netlist.circuit_by_name("RINGO").net_by_name("VDD") ] l2n.build_nets(nets, cm, ly, lmap, "NET_", nil, RBA::LayoutToNetlist::BNH_SubcircuitCells, "CIRCUIT_", "DEVICE_") ly_au = RBA::Layout::new au_file = File.join($ut_testsrc, "testdata", "algo", "l2n_reader_au_1d.gds") ly_au.read(au_file) lmap.each do |li,v| li_au = ly_au.layer(ly.get_info(li)) ly_region = RBA::Region::new(ly.top_cell.begin_shapes_rec(li)) ly_au_region = RBA::Region::new(ly_au.top_cell.begin_shapes_rec(li_au)) info = ly.get_info(li).to_s + ":" assert_equal(info + (ly_region ^ ly_au_region).to_s, info) end end def test_15_BuildNetShapes l2n = RBA::LayoutToNetlist::new input = File.join($ut_testsrc, "testdata", "algo", "l2n_reader_in.txt") l2n.read(input) # build_all_nets using Region#net metal1 = l2n.layer_by_name("metal1") metal1_all = metal1.nets(l2n) metal1_vdd = metal1.nets(l2n, nil, l2n.netlist.nets_by_name("VDD")) metal1_all_wp = metal1.nets(l2n, 1) ly = RBA::Layout::new tc = ly.create_cell("TOP") metal1_all.insert_into(ly, tc.cell_index, ly.layer(1, 0)) metal1_vdd.insert_into(ly, tc.cell_index, ly.layer(2, 0)) metal1_all_wp.insert_into(ly, tc.cell_index, ly.layer(3, 0)) si = tc.begin_shapes_rec(ly.layer(1, 0)) assert_equal(si.each.count, 111) si = tc.begin_shapes_rec(ly.layer(1, 0)) si.each do |i| assert_equal(i.shape.prop_id, 0) end # VDD net is smaller si = tc.begin_shapes_rec(ly.layer(2, 0)) assert_equal(si.each.count, 20) assert_equal(tc.dbbox(ly.layer(2, 0)).to_s, "(-0.18,2.42;23.94,3.18)") si = tc.begin_shapes_rec(ly.layer(3, 0)) assert_equal(si.each.count, 111) # properties are net names + ID si = tc.begin_shapes_rec(ly.layer(3, 0)) net_names = [] si.each do |i| ly.properties(i.shape.prop_id).each do |k,v| if k == 1 net_names << v[0] end end end assert_equal(net_names.sort.uniq.join(";"), "$10;$11;$12;$13;$14;$15;$16;$17;$18;$19;$20;$21;$22;$5;$6;$7;$8;$9;FB;OSC;VDD;VSS") end def test_20_Antenna # --- simple antenna check input = File.join($ut_testsrc, "testdata", "algo", "antenna_l1.gds") ly = RBA::Layout::new ly.read(input) au = File.join($ut_testsrc, "testdata", "algo", "antenna_au1.gds") ly_au = RBA::Layout::new ly_au.read(au) dss = RBA::DeepShapeStore::new assert_equal(dss.is_singular?, false) rdiode = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(1, 0)), dss) rpoly = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(6, 0)), dss) rcont = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(8, 0)), dss) rmetal1 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(9, 0)), dss) rvia1 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(11, 0)), dss) rmetal2 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(12, 0)), dss) assert_equal(dss.is_singular?, true) l2n = RBA::LayoutToNetlist::new(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 assert_equal((a1_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(100, 0)))).to_s, "") assert_equal((a1_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(101, 0)))).to_s, "") assert_equal((a1_30.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(102, 0)))).to_s, "") # --- same with flat l2n._destroy input = File.join($ut_testsrc, "testdata", "algo", "antenna_l1.gds") ly = RBA::Layout::new ly.read(input) au = File.join($ut_testsrc, "testdata", "algo", "antenna_au1.gds") ly_au = RBA::Layout::new ly_au.read(au) rfdiode = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(1, 0))) rfpoly = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(6, 0))) rfcont = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(8, 0))) rfmetal1 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(9, 0))) rfvia1 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(11, 0))) rfmetal2 = RBA::Region::new(ly.top_cell.begin_shapes_rec(ly.layer(12, 0))) assert_equal(rfdiode.is_deep?, false) assert_equal(rfpoly.is_deep?, false) assert_equal(rfmetal1.is_deep?, false) assert_equal(rfvia1.is_deep?, false) assert_equal(rfmetal2.is_deep?, false) l2n = RBA::LayoutToNetlist::new(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 assert_equal((a1_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(100, 0)))).to_s, "") assert_equal((a1_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(101, 0)))).to_s, "") assert_equal((a1_30.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(102, 0)))).to_s, "") # --- simple antenna check with metal2 l2n._destroy l2n = RBA::LayoutToNetlist::new(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 assert_equal((a2_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(200, 0)))).to_s, "") assert_equal((a2_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(201, 0)))).to_s, "") assert_equal((a2_17.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(202, 0)))).to_s, "") # --- simple incremental antenna check with metal1 + metal2 l2n._destroy l2n = RBA::LayoutToNetlist::new(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) assert_equal(l2n.is_extracted?, false) l2n.extract_netlist assert_equal(l2n.is_extracted?, true) 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 assert_equal((a1_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(100, 0)))).to_s, "") assert_equal((a1_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(101, 0)))).to_s, "") assert_equal((a1_30.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(102, 0)))).to_s, "") l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) assert_equal(l2n.is_extracted?, false) l2n.extract_netlist assert_equal(l2n.is_extracted?, true) 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 assert_equal((a2_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(200, 0)))).to_s, "") assert_equal((a2_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(201, 0)))).to_s, "") assert_equal((a2_17.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(202, 0)))).to_s, "") # --- antenna check with diodes and antenna effect reduction l2n._destroy l2n = RBA::LayoutToNetlist::new(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 assert_equal((a3_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(300, 0)))).to_s, "") assert_equal((a3_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(301, 0)))).to_s, "") assert_equal((a3_30.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(302, 0)))).to_s, "") # --- antenna check with diodes l2n._destroy l2n = RBA::LayoutToNetlist::new(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 assert_equal((a4_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(400, 0)))).to_s, "") assert_equal((a4_10.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(401, 0)))).to_s, "") assert_equal((a4_30.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(402, 0)))).to_s, "") # --- antenna check metal perimeter included l2n._destroy l2n = RBA::LayoutToNetlist::new(dss) 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(rvia1) l2n.connect(rmetal2) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.extract_netlist a5_5 = l2n.antenna_check(rpoly, 0.0, rmetal2, 1.0, 5) a5_15 = l2n.antenna_check(rpoly, 0.0, rmetal2, 1.0, 15) a5_29 = l2n.antenna_check(rpoly, 0.0, rmetal2, 1.0, 29) # Note: flatten.merged performs some normalization assert_equal((a5_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(500, 0)))).to_s, "") assert_equal((a5_15.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(501, 0)))).to_s, "") assert_equal((a5_29.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(502, 0)))).to_s, "") b5_5 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 2.5) b5_15 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 7.5) b5_29 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 14.5) # Note: flatten.merged performs some normalization assert_equal((b5_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(500, 0)))).to_s, "") assert_equal((b5_15.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(501, 0)))).to_s, "") assert_equal((b5_29.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(502, 0)))).to_s, "") # --- antenna check gate perimeter included l2n._destroy l2n = RBA::LayoutToNetlist::new(dss) 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(rvia1) l2n.connect(rmetal2) l2n.connect(rpoly, rcont) l2n.connect(rcont, rmetal1) l2n.connect(rmetal1, rvia1) l2n.connect(rvia1, rmetal2) l2n.extract_netlist a6_3 = l2n.antenna_check(rpoly, 0.3, rmetal2, 0.0, 3) a6_5 = l2n.antenna_check(rpoly, 0.3, rmetal2, 0.0, 5) a6_9 = l2n.antenna_check(rpoly, 0.3, rmetal2, 0.0, 9) # Note: flatten.merged performs some normalization assert_equal((a6_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(600, 0)))).to_s, "") assert_equal((a6_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(601, 0)))).to_s, "") assert_equal((a6_9.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(602, 0)))).to_s, "") b6_3 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 6) b6_5 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 10) b6_9 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 18) # Note: flatten.merged performs some normalization assert_equal((b6_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(600, 0)))).to_s, "") assert_equal((b6_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(601, 0)))).to_s, "") assert_equal((b6_9.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(602, 0)))).to_s, "") end def test_21_LogAPI l2n = RBA::LayoutToNetlist::new l2n.read(File.join($ut_testsrc, "testdata", "algo", "l2n_reader_au_6.l2n")) le = l2n.each_log_entry.collect { |s| s.to_s } assert_equal(le.size, 4) assert_equal(le[0].to_s, "info") assert_equal(le[1].to_s, "[cat description] In cell cell_name: info, shape: (1,1;2,2;3,1)") assert_equal(le[2].to_s, "warning") assert_equal(le[3].to_s, "error") end end load("test_epilogue.rb")