diff --git a/src/db/unit_tests/dbDeepRegionTests.cc b/src/db/unit_tests/dbDeepRegionTests.cc index e6d3b7dc3..a9f2c84dd 100644 --- a/src/db/unit_tests/dbDeepRegionTests.cc +++ b/src/db/unit_tests/dbDeepRegionTests.cc @@ -1452,6 +1452,44 @@ TEST(25_Pull) } } +TEST(26_BreakoutCells) +{ + db::Layout ly; + { + std::string fn (tl::testsrc ()); + fn += "/testdata/algo/deep_region_l26.gds"; + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly); + } + + db::cell_index_type top_cell_index = *ly.begin_top_down (); + db::Cell &top_cell = ly.cell (top_cell_index); + + db::DeepShapeStore dss; + + unsigned int l1 = ly.get_layer (db::LayerProperties (1, 0)); + unsigned int l2 = ly.get_layer (db::LayerProperties (2, 0)); + + db::Region r1 (db::RecursiveShapeIterator (ly, top_cell, l1), dss); + db::Region r2 (db::RecursiveShapeIterator (ly, top_cell, l2), dss); + + dss.add_breakout_cell (0, ly.cell_by_name ("CHILD").second); + + db::Region r12 = r1 & r2; + db::Region r1m2 = r1 - r2; + db::Region r21 = r2 & r1; + db::Region r2m1 = r2 - r1; + + ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (100, 0)), r12); + ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (101, 0)), r1m2); + ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (102, 0)), r21); + ly.insert (top_cell.cell_index (), ly.get_layer (db::LayerProperties (103, 0)), r2m1); + + CHECKPOINT(); + db::compare_layouts (_this, ly, tl::testsrc () + "/testdata/algo/deep_region_au26.gds"); +} + TEST(100_Integration) { db::Layout ly; diff --git a/src/db/unit_tests/dbDeepShapeStoreTests.cc b/src/db/unit_tests/dbDeepShapeStoreTests.cc index f2f8eaf91..9aadfa660 100644 --- a/src/db/unit_tests/dbDeepShapeStoreTests.cc +++ b/src/db/unit_tests/dbDeepShapeStoreTests.cc @@ -210,14 +210,58 @@ TEST(4_FlatAndEmptyInput) TEST(5_State) { - db::DeepShapeStore store; + db::DeepShapeStore store ("TOP", 0.01); + EXPECT_EQ (store.layout ().dbu (), 0.01); store.set_threads (4); EXPECT_EQ (store.threads (), 4); - store.push_state (); - store.set_threads (2); - EXPECT_EQ (store.threads (), 2); - store.pop_state (); - EXPECT_EQ (store.threads (), 4); -} + store.set_max_area_ratio (2.5); + EXPECT_EQ (store.max_area_ratio (), 2.5); + store.set_max_vertex_count (100); + EXPECT_EQ (store.max_vertex_count (), size_t (100)); + store.set_text_enlargement (5); + EXPECT_EQ (store.text_enlargement (), 5); + store.set_text_property_name (tl::Variant ("x")); + EXPECT_EQ (store.text_property_name ().to_string (), "x"); + EXPECT_EQ (store.breakout_cells (0) == 0, true); + { + std::set boc; + boc.insert (5); + store.set_breakout_cells (0, boc); + EXPECT_EQ (store.breakout_cells (0) == 0, false); + EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true); + EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), false); + store.add_breakout_cell (0, 3); + EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true); + EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), true); + } + + store.push_state (); + + store.set_threads (2); + store.set_max_area_ratio (1); + store.set_max_vertex_count (10); + store.set_text_enlargement (1); + store.set_text_property_name (tl::Variant ("y")); + EXPECT_EQ (store.threads (), 2); + EXPECT_EQ (store.max_area_ratio (), 1.0); + EXPECT_EQ (store.max_vertex_count (), size_t (10)); + EXPECT_EQ (store.text_enlargement (), 1); + EXPECT_EQ (store.text_property_name ().to_string (), "y"); + + store.clear_breakout_cells (0); + EXPECT_EQ (store.breakout_cells (0) == 0, true); + + store.pop_state (); + + EXPECT_EQ (store.threads (), 4); + EXPECT_EQ (store.max_area_ratio (), 2.5); + EXPECT_EQ (store.max_vertex_count (), size_t (100)); + EXPECT_EQ (store.text_enlargement (), 5); + EXPECT_EQ (store.text_property_name ().to_string (), "x"); + + EXPECT_EQ (store.breakout_cells (0) == 0, false); + EXPECT_EQ (store.breakout_cells (0)->find (5) != store.breakout_cells (0)->end (), true); + EXPECT_EQ (store.breakout_cells (0)->find (3) != store.breakout_cells (0)->end (), true); +} diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 932334032..e04637320 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -2108,3 +2108,198 @@ TEST(9_StrictDeviceExtraction) db::compare_layouts (_this, ly, au); } + +TEST(10_DeviceExtractionWithBreakoutCells) +{ + db::Layout ly; + db::LayerMap lmap; + + unsigned int nwell = define_layer (ly, lmap, 1); + unsigned int active = define_layer (ly, lmap, 2); + unsigned int poly = define_layer (ly, lmap, 3); + unsigned int poly_lbl = define_layer (ly, lmap, 3, 1); + unsigned int diff_cont = define_layer (ly, lmap, 4); + unsigned int poly_cont = define_layer (ly, lmap, 5); + unsigned int metal1 = define_layer (ly, lmap, 6); + unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1); + unsigned int via1 = define_layer (ly, lmap, 7); + unsigned int metal2 = define_layer (ly, lmap, 8); + unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1); + + { + db::LoadLayoutOptions options; + options.get_options ().layer_map = lmap; + options.get_options ().create_other_layers = false; + + std::string fn (tl::testsrc ()); + fn = tl::combine_path (fn, "testdata"); + fn = tl::combine_path (fn, "algo"); + fn = tl::combine_path (fn, "device_extract_l10.gds"); + + tl::InputStream stream (fn); + db::Reader reader (stream); + reader.read (ly, options); + } + + db::Cell &tc = ly.cell (*ly.begin_top_down ()); + + db::DeepShapeStore dss; + dss.set_text_enlargement (1); + dss.set_text_property_name (tl::Variant ("LABEL")); + + // original layers + db::Region rnwell (db::RecursiveShapeIterator (ly, tc, nwell), dss); + db::Region ractive (db::RecursiveShapeIterator (ly, tc, active), dss); + db::Region rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss); + db::Region rpoly_lbl (db::RecursiveShapeIterator (ly, tc, poly_lbl), dss); + db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss); + db::Region rpoly_cont (db::RecursiveShapeIterator (ly, tc, poly_cont), dss); + db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss); + db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss); + db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss); + db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss); + db::Region rmetal2_lbl (db::RecursiveShapeIterator (ly, tc, metal2_lbl), dss); + + // derived regions + + db::Region rpactive = ractive & rnwell; + db::Region rpgate = rpactive & rpoly; + db::Region rpsd = rpactive - rpgate; + + db::Region rnactive = ractive - rnwell; + db::Region rngate = rnactive & rpoly; + db::Region rnsd = rnactive - rngate; + + // return the computed layers into the original layout and write it for debugging purposes + + unsigned int lpgate = ly.insert_layer (db::LayerProperties (20, 0)); // 20/0 -> P Gate + unsigned int lngate = ly.insert_layer (db::LayerProperties (21, 0)); // 21/0 -> N Gate + unsigned int lpdiff = ly.insert_layer (db::LayerProperties (22, 0)); // 22/0 -> P Diffusion + unsigned int lndiff = ly.insert_layer (db::LayerProperties (23, 0)); // 23/0 -> N Diffusion + + rpgate.insert_into (&ly, tc.cell_index (), lpgate); + rngate.insert_into (&ly, tc.cell_index (), lngate); + rpsd.insert_into (&ly, tc.cell_index (), lpdiff); + rnsd.insert_into (&ly, tc.cell_index (), lndiff); + + // perform the extraction + + db::Netlist nl; + db::hier_clusters cl; + + db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS"); + db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS"); + + db::NetlistDeviceExtractor::input_layers dl; + + dss.push_state (); + std::set boc; + boc.insert (dss.layout (0).cell_by_name ("INV").second); + dss.set_breakout_cells (0, boc); + + dl["SD"] = &rpsd; + dl["G"] = &rpgate; + dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes + pmos_ex.extract (dss, 0, dl, nl, cl); + + dl["SD"] = &rnsd; + dl["G"] = &rngate; + dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes + nmos_ex.extract (dss, 0, dl, nl, cl); + + dss.pop_state (); + + // perform the net extraction + + db::NetlistExtractor net_ex; + + db::Connectivity conn; + // Intra-layer + conn.connect (rpsd); + conn.connect (rnsd); + conn.connect (rpoly); + conn.connect (rdiff_cont); + conn.connect (rpoly_cont); + conn.connect (rmetal1); + conn.connect (rvia1); + conn.connect (rmetal2); + // Inter-layer + conn.connect (rpsd, rdiff_cont); + conn.connect (rnsd, rdiff_cont); + conn.connect (rpoly, rpoly_cont); + conn.connect (rpoly_cont, rmetal1); + conn.connect (rdiff_cont, rmetal1); + conn.connect (rmetal1, rvia1); + conn.connect (rvia1, rmetal2); + conn.connect (rpoly, rpoly_lbl); // attaches labels + conn.connect (rmetal1, rmetal1_lbl); // attaches labels + conn.connect (rmetal2, rmetal2_lbl); // attaches labels + + // extract the nets + + net_ex.extract_nets (dss, 0, conn, nl, cl); + + // debug layers produced for nets + // 202/0 -> Active + // 203/0 -> Poly + // 204/0 -> Diffusion contacts + // 205/0 -> Poly contacts + // 206/0 -> Metal1 + // 207/0 -> Via1 + // 208/0 -> Metal2 + // 210/0 -> N source/drain + // 211/0 -> P source/drain + std::map dump_map; + dump_map [layer_of (rpsd) ] = ly.insert_layer (db::LayerProperties (210, 0)); + dump_map [layer_of (rnsd) ] = ly.insert_layer (db::LayerProperties (211, 0)); + dump_map [layer_of (rpoly) ] = ly.insert_layer (db::LayerProperties (203, 0)); + dump_map [layer_of (rdiff_cont)] = ly.insert_layer (db::LayerProperties (204, 0)); + dump_map [layer_of (rpoly_cont)] = ly.insert_layer (db::LayerProperties (205, 0)); + dump_map [layer_of (rmetal1) ] = ly.insert_layer (db::LayerProperties (206, 0)); + dump_map [layer_of (rvia1) ] = ly.insert_layer (db::LayerProperties (207, 0)); + dump_map [layer_of (rmetal2) ] = ly.insert_layer (db::LayerProperties (208, 0)); + + // write nets to layout + db::CellMapping cm = dss.cell_mapping_to_original (0, &ly, tc.cell_index ()); + dump_nets_to_layout (nl, cl, ly, dump_map, cm); + + std::string nl_au_string = + "circuit INVCHAIN ();" + " subcircuit INV3 $1 ($1=$9,$2=$7,$3=$8,$4=IN,$5=$9,$6=$6,$7=$2,$8=$6,$9=$4,$10=$3,$11=VDD,$12=VSS);" + " subcircuit INV2 $2 ($1=$8,$2=$11,$3=$9,$4=$10,$5=$8,$6=$11,$7=$3,$8=OUT,$9=$3,$10=OUT,$11=$6,$12=$5,$13=VDD,$14=VSS);" + " subcircuit INV $3 ($1=VSS,$2=VDD,$3=$11,$4=OUT,$5=$5,$6=$5,$7=$10,$8=$10);" + "end;" + "circuit INV2 ($1=$I16,$2=$I15,$3=$I14,$4=$I13,$5=$I12,$6=$I11,$7=$I10,$8=$I9,$9=$I8,$10=$I7,$11=$I6,$12=$I5,$13=$I4,$14=$I2);" + " subcircuit INV $1 ($1=$I2,$2=$I4,$3=$I14,$4=$I6,$5=$I8,$6=$I10,$7=$I16,$8=$I12);" + " subcircuit INV $2 ($1=$I2,$2=$I4,$3=$I13,$4=$I5,$5=$I7,$6=$I9,$7=$I15,$8=$I11);" + "end;" + "circuit INV ($1=$1,$2=$2,$3=$3,$4=$4,$5=$5,$6=$9,$7=$I8,$8=$I7);" + " device PMOS $1 (S=$4,G=$3,D=$2) (L=0.25,W=0.95,AS=0.79325,AD=0.26125,PS=3.57,PD=1.5);" + " device PMOS $2 (S=$2,G=$I8,D=$5) (L=0.25,W=0.95,AS=0.26125,AD=0.03325,PS=1.5,PD=1.97);" + " device NMOS $3 (S=$4,G=$3,D=$1) (L=0.25,W=0.95,AS=0.79325,AD=0.26125,PS=3.57,PD=1.5);" + " device NMOS $4 (S=$1,G=$I7,D=$9) (L=0.25,W=0.95,AS=0.26125,AD=0.03325,PS=1.5,PD=1.97);" + " subcircuit TRANS $1 ($1=$4,$2=$1,$3=$3);" + " subcircuit TRANS $2 ($1=$4,$2=$2,$3=$3);" + "end;" + "circuit TRANS ($1=$1,$2=$2,$3=$3);" + "end;" + "circuit INV3 ($1=$I17,$2=$I16,$3=$I15,$4=$I14,$5=$I12,$6=$I11,$7=$I9,$8=$I8,$9=$I7,$10=$I5,$11=$I4,$12=$I2);" + " subcircuit INV $1 ($1=$I2,$2=$I4,$3=$I15,$4=$I5,$5=$I8,$6=$I11,$7=$I17,$8=$I12);" + " subcircuit INV $2 ($1=$I2,$2=$I4,$3=$I14,$4=$I9,$5=$I7,$6=$I7,$7=$I16,$8=$I16);" + " subcircuit INV $3 ($1=$I2,$2=$I4,$3=$I16,$4=$I7,$5=$I9,$6=$I9,$7=$I14,$8=$I14);" + "end;" + ; + + // compare netlist as string + CHECKPOINT (); + db::compare_netlist (_this, nl, nl_au_string); + + // compare the collected test data + + std::string au = tl::testsrc (); + au = tl::combine_path (au, "testdata"); + au = tl::combine_path (au, "algo"); + au = tl::combine_path (au, "device_extract_au10.gds"); + + db::compare_layouts (_this, ly, au); +} diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index 3df15643e..278369787 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -160,3 +160,8 @@ TEST(17_layout_variants) run_test (_this, "ringo_layout_var", "ringo_layout_var.gds"); } +TEST(18_cheats) +{ + run_test (_this, "invchain_cheat", "invchain_for_cheat.gds"); +} + diff --git a/testdata/algo/deep_region_au26.gds b/testdata/algo/deep_region_au26.gds new file mode 100644 index 000000000..48204b202 Binary files /dev/null and b/testdata/algo/deep_region_au26.gds differ diff --git a/testdata/algo/deep_region_l26.gds b/testdata/algo/deep_region_l26.gds new file mode 100644 index 000000000..cc4063959 Binary files /dev/null and b/testdata/algo/deep_region_l26.gds differ diff --git a/testdata/algo/device_extract_au10.gds b/testdata/algo/device_extract_au10.gds new file mode 100644 index 000000000..613e8b0ca Binary files /dev/null and b/testdata/algo/device_extract_au10.gds differ diff --git a/testdata/algo/device_extract_l10.gds b/testdata/algo/device_extract_l10.gds new file mode 100644 index 000000000..43446a79f Binary files /dev/null and b/testdata/algo/device_extract_l10.gds differ diff --git a/testdata/lvs/invchain_cheat.lvs b/testdata/lvs/invchain_cheat.lvs new file mode 100644 index 000000000..34ff10e5c --- /dev/null +++ b/testdata/lvs/invchain_cheat.lvs @@ -0,0 +1,73 @@ + +source($lvs_test_source) + +report_lvs($lvs_test_target_lvsdb) + +writer = write_spice(true, false) +target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout") + +schematic("invchain_for_cheat.cir") + +deep + +# Drawing layers + +nwell = input(1, 0) +active = input(2, 0) +poly = input(3, 0) +diff_cont = input(4, 0) +poly_cont = input(5, 0) +metal1 = input(6, 0) +via1 = input(7, 0) +metal2 = input(8, 0) + +# Bulk layer for terminal provisioning + +bulk = polygon_layer + +# Computed layers + +active_in_nwell = active & nwell +pactive = active_in_nwell +pgate = pactive & poly +psd = pactive - pgate + +active_outside_nwell = active - nwell +nactive = active_outside_nwell +ngate = nactive & poly +nsd = nactive - ngate + +# Device extraction + +cheat("INV") do + + # PMOS transistor device extraction + extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate, + "tS" => psd, "tD" => psd, "tG" => poly }) + + # NMOS transistor device extraction + extract_devices(mos3("NMOS"), { "SD" => nsd, "G" => ngate, + "tS" => nsd, "tD" => nsd, "tG" => poly }) + +end + +# Define connectivity for netlist extraction + +# Inter-layer +connect(psd, diff_cont) +connect(nsd, diff_cont) +connect(poly, poly_cont) +connect(diff_cont, metal1) +connect(poly_cont, metal1) +connect(metal1, via1) +connect(via1, metal2) + +# Global +connect_global(bulk, "SUBSTRATE") + +# Compare section + +netlist.simplify + +compare + diff --git a/testdata/lvs/invchain_cheat.lvsdb b/testdata/lvs/invchain_cheat.lvsdb new file mode 100644 index 000000000..7e0338182 --- /dev/null +++ b/testdata/lvs/invchain_cheat.lvsdb @@ -0,0 +1,757 @@ +#%lvsdb-klayout +J( + W(INVCHAIN) + U(0.001) + L(l3 '3/0') + L(l6 '4/0') + L(l7 '2/0') + L(l8 '6/0') + L(l9 '7/0') + L(l10 '8/0') + L(l11) + L(l2) + L(l5) + C(l3 l3 l7) + C(l6 l6 l8 l2 l5) + C(l7 l3 l7 l8) + C(l8 l6 l7 l8 l9) + C(l9 l8 l9 l10) + C(l10 l9 l10) + C(l11 l11) + C(l2 l6 l2) + C(l5 l6 l5) + G(l11 SUBSTRATE) + D(D$PMOS PMOS + T(S + R(l2 (-960 -475) (835 950)) + ) + T(G + R(l3 (-125 -475) (250 950)) + ) + T(D + R(l2 (125 -475) (550 950)) + ) + ) + D(D$PMOS$1 PMOS + T(S + R(l2 (-675 -475) (550 950)) + ) + T(G + R(l3 (-125 -475) (250 950)) + ) + T(D + R(l2 (125 -475) (35 950)) + ) + ) + D(D$NMOS NMOS + T(S + R(l5 (-960 -475) (835 950)) + ) + T(G + R(l3 (-125 -475) (250 950)) + ) + T(D + R(l5 (125 -475) (550 950)) + ) + ) + D(D$NMOS$1 NMOS + T(S + R(l5 (-675 -475) (550 950)) + ) + T(G + R(l3 (-125 -475) (250 950)) + ) + T(D + R(l5 (125 -475) (35 950)) + ) + ) + X(INV + R((-1500 -800) (3000 4600)) + N(1 + R(l6 (290 -310) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-290 -690) (360 760)) + R(l9 (-305 -705) (250 250)) + R(l9 (-250 150) (250 250)) + R(l10 (-2025 -775) (3000 900)) + R(l5 (-1375 -925) (550 950)) + ) + N(2 + R(l6 (290 2490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-290 -690) (360 760)) + R(l9 (-305 -705) (250 250)) + R(l9 (-250 150) (250 250)) + R(l10 (-2025 -775) (3000 900)) + R(l2 (-1375 -925) (550 950)) + ) + N(3 + R(l3 (-125 -250) (250 2500)) + R(l3 (-250 -3050) (250 1600)) + R(l3 (-250 1200) (250 1600)) + ) + N(4 + R(l6 (-510 -310) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-290 -3530) (360 2840)) + R(l8 (-360 -2800) (360 760)) + R(l8 (-360 2040) (360 760)) + R(l2 (-740 -855) (835 950)) + R(l5 (-835 -3750) (835 950)) + ) + N(5 + R(l2 (925 2325) (35 950)) + ) + N(6 + R(l5 (925 -475) (35 950)) + ) + N(7) + N(8) + P(1) + P(2) + P(3) + P(4) + P(5) + P(6) + P(7) + P(8) + D(1 D$PMOS + Y(0 2800) + E(L 0.25) + E(W 0.95) + E(AS 0.79325) + E(AD 0.26125) + E(PS 3.57) + E(PD 1.5) + T(S 4) + T(G 3) + T(D 2) + ) + D(2 D$PMOS$1 + Y(800 2800) + E(L 0.25) + E(W 0.95) + E(AS 0.26125) + E(AD 0.03325) + E(PS 1.5) + E(PD 1.97) + T(S 2) + T(G 7) + T(D 5) + ) + D(3 D$NMOS + Y(0 0) + E(L 0.25) + E(W 0.95) + E(AS 0.79325) + E(AD 0.26125) + E(PS 3.57) + E(PD 1.5) + T(S 4) + T(G 3) + T(D 1) + ) + D(4 D$NMOS$1 + Y(800 0) + E(L 0.25) + E(W 0.95) + E(AS 0.26125) + E(AD 0.03325) + E(PS 1.5) + E(PD 1.97) + T(S 1) + T(G 8) + T(D 6) + ) + ) + X(INV2 + R((0 0) (5500 4600)) + N(1) + N(2) + N(3) + N(4) + N(5) + N(6) + N(7) + N(8) + N(9) + N(10) + N(11 + R(l6 (1790 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(12 + R(l6 (3490 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(13 + R(l6 (990 3290) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-3590 -690) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + N(14 + R(l6 (990 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-3590 -690) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + P(1) + P(2) + P(3) + P(4) + P(5) + P(6) + P(7) + P(8) + P(9) + P(10) + P(11) + P(12) + P(13) + P(14) + X(1 INV M O(180) Y(1500 800) + P(0 14) + P(1 13) + P(2 3) + P(3 11) + P(4 9) + P(5 7) + P(6 1) + P(7 5) + ) + X(2 INV Y(4000 800) + P(0 14) + P(1 13) + P(2 4) + P(3 12) + P(4 10) + P(5 8) + P(6 2) + P(7 6) + ) + ) + X(INV3 + R((0 0) (6300 4600)) + N(1) + N(2) + N(3) + N(4) + N(5) + N(6) + N(7 + R(l6 (990 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(8) + N(9 + R(l6 (2590 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(10 + R(l6 (4290 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(11 + R(l6 (1790 3290) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-3590 -690) (360 760)) + R(l8 (-360 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + N(12 + R(l6 (1790 490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-3590 -690) (360 760)) + R(l8 (-360 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + P(1) + P(2) + P(3) + P(4) + P(5) + P(6) + P(7) + P(8) + P(9) + P(10) + P(11) + P(12) + X(1 INV Y(4800 800) + P(0 12) + P(1 11) + P(2 3) + P(3 10) + P(4 8) + P(5 6) + P(6 1) + P(7 5) + ) + X(2 INV Y(1500 800) + P(0 12) + P(1 11) + P(2 4) + P(3 7) + P(4 9) + P(5 9) + P(6 2) + P(7 2) + ) + X(3 INV M O(180) Y(2300 800) + P(0 12) + P(1 11) + P(2 2) + P(3 9) + P(4 7) + P(5 7) + P(6 4) + P(7 4) + ) + ) + X(INVCHAIN + R((-1500 -800) (10400 4600)) + N(1 + R(l6 (490 990) (220 220)) + R(l6 (-1220 -1520) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-65 -2185) (1105 350)) + ) + N(2 + R(l6 (3790 990) (220 220)) + R(l6 (-1220 -1520) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-65 -2185) (1105 350)) + ) + N(3 + R(l6 (1405 990) (220 220)) + R(l6 (-535 -1520) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (20 -2270) (440 520)) + ) + N(4 + R(l6 (7090 990) (220 220)) + R(l6 (-1220 -1520) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (-65 -2185) (1105 350)) + ) + N(5 + R(l6 (4705 990) (220 220)) + R(l6 (-535 -1520) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (20 -2270) (440 520)) + ) + N(6 + R(l3 (-1295 925) (1235 350)) + ) + N(7 + R(l3 (445 805) (480 550)) + ) + N(8 + R(l3 (1345 925) (1945 350)) + ) + N(9 + R(l3 (3745 805) (480 550)) + ) + N(10 + R(l3 (4645 925) (1945 350)) + ) + N(11 + R(l3 (7045 805) (480 550)) + ) + N(12 + R(l6 (7690 -310) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + ) + N(13 + R(l6 (6890 2490) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-3520 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-6820 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (3010 -690) (360 760)) + R(l8 (-3660 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + R(l8 (-6960 -760) (360 760)) + R(l8 (-360 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + N(14 + R(l6 (6890 -310) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-3520 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-6820 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (3080 -620) (220 220)) + R(l6 (-220 180) (220 220)) + R(l8 (3010 -690) (360 760)) + R(l8 (-3660 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + R(l8 (-6960 -760) (360 760)) + R(l8 (-360 -760) (360 760)) + R(l8 (2940 -760) (360 760)) + ) + X(1 INV3 Y(-1500 -800) + P(0 9) + P(1 7) + P(2 8) + P(3 6) + P(4 9) + P(5 5) + P(6 1) + P(7 5) + P(8 3) + P(9 2) + P(10 13) + P(11 14) + ) + X(2 INV2 Y(2600 -800) + P(0 8) + P(1 11) + P(2 9) + P(3 10) + P(4 8) + P(5 11) + P(6 2) + P(7 12) + P(8 2) + P(9 12) + P(10 5) + P(11 4) + P(12 13) + P(13 14) + ) + X(3 INV M O(180) Y(7400 0) + P(0 14) + P(1 13) + P(2 11) + P(3 12) + P(4 4) + P(5 4) + P(6 10) + P(7 10) + ) + ) +) +H( + X(TRANS + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + P(1 I('1')) + P(2 I('2')) + P(3 I('3')) + ) + X(INV + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + N(4 I('4')) + N(5 I('5')) + N(6 I('6')) + N(7 I('7')) + N(8 I('8')) + P(1 I('1')) + P(2 I('2')) + P(3 I('3')) + P(4 I('4')) + P(5 I('5')) + P(6 I('6')) + P(7 I('7')) + P(8 I('8')) + D(1 PMOS + I($1) + E(L 0.25) + E(W 0.95) + E(AS 0.79325) + E(AD 0.26125) + E(PS 3.57) + E(PD 1.5) + T(S 4) + T(G 3) + T(D 2) + T(B 4) + ) + D(2 PMOS + I($2) + E(L 0.25) + E(W 0.95) + E(AS 0.26125) + E(AD 0.03325) + E(PS 1.5) + E(PD 1.97) + T(S 2) + T(G 7) + T(D 5) + T(B 2) + ) + D(3 NMOS + I($3) + E(L 0.25) + E(W 0.95) + E(AS 0.79325) + E(AD 0.26125) + E(PS 3.57) + E(PD 1.5) + T(S 4) + T(G 3) + T(D 1) + T(B 4) + ) + D(4 NMOS + I($4) + E(L 0.25) + E(W 0.95) + E(AS 0.26125) + E(AD 0.03325) + E(PS 1.5) + E(PD 1.97) + T(S 1) + T(G 8) + T(D 6) + T(B 1) + ) + X(1 TRANS I($1) + P(0 4) + P(1 1) + P(2 3) + ) + X(2 TRANS I($2) + P(0 4) + P(1 2) + P(2 3) + ) + ) + X(INV3 + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + N(4 I('4')) + N(5 I('5')) + N(6 I('6')) + N(7 I('7')) + N(8 I('8')) + N(9 I('9')) + N(10 I('10')) + N(11 I('11')) + N(12 I('12')) + P(1 I('1')) + P(2 I('2')) + P(3 I('3')) + P(4 I('4')) + P(5 I('5')) + P(6 I('6')) + P(7 I('7')) + P(8 I('8')) + P(9 I('9')) + P(10 I('10')) + P(11 I('11')) + P(12 I('12')) + X(1 INV I($1) + P(0 12) + P(1 11) + P(2 3) + P(3 10) + P(4 8) + P(5 6) + P(6 1) + P(7 5) + ) + X(2 INV I($2) + P(0 12) + P(1 11) + P(2 4) + P(3 7) + P(4 9) + P(5 9) + P(6 2) + P(7 2) + ) + X(3 INV I($3) + P(0 12) + P(1 11) + P(2 2) + P(3 9) + P(4 7) + P(5 7) + P(6 4) + P(7 4) + ) + ) + X(INV2 + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + N(4 I('4')) + N(5 I('5')) + N(6 I('6')) + N(7 I('7')) + N(8 I('8')) + N(9 I('9')) + N(10 I('10')) + N(11 I('11')) + N(12 I('12')) + N(13 I('13')) + N(14 I('14')) + P(1 I('1')) + P(2 I('2')) + P(3 I('3')) + P(4 I('4')) + P(5 I('5')) + P(6 I('6')) + P(7 I('7')) + P(8 I('8')) + P(9 I('9')) + P(10 I('10')) + P(11 I('11')) + P(12 I('12')) + P(13 I('13')) + P(14 I('14')) + X(1 INV I($1) + P(0 14) + P(1 13) + P(2 3) + P(3 11) + P(4 9) + P(5 7) + P(6 1) + P(7 5) + ) + X(2 INV I($2) + P(0 14) + P(1 13) + P(2 4) + P(3 12) + P(4 10) + P(5 8) + P(6 2) + P(7 6) + ) + ) + X(INVCHAIN + N(1 I('9')) + N(2 I('7')) + N(3 I('8')) + N(4 I('6')) + N(5 I('5')) + N(6 I('1')) + N(7 I('3')) + N(8 I('2')) + N(9 I('13')) + N(10 I('14')) + N(11 I('11')) + N(12 I('10')) + N(13 I('12')) + N(14 I('4')) + X(1 INV3 I($1) + P(0 1) + P(1 2) + P(2 3) + P(3 4) + P(4 1) + P(5 5) + P(6 6) + P(7 5) + P(8 7) + P(9 8) + P(10 9) + P(11 10) + ) + X(2 INV2 I($2) + P(0 3) + P(1 11) + P(2 1) + P(3 12) + P(4 3) + P(5 11) + P(6 8) + P(7 13) + P(8 8) + P(9 13) + P(10 5) + P(11 14) + P(12 9) + P(13 10) + ) + X(3 INV I($3) + P(0 10) + P(1 9) + P(2 11) + P(3 13) + P(4 14) + P(5 14) + P(6 12) + P(7 12) + ) + ) +) +Z( + X(() TRANS 0 + Z( + ) + ) + X(INV INV S + Z( + ) + ) + X(INV2 INV2 S + Z( + ) + ) + X(INV3 INV3 S + Z( + ) + ) + X(INVCHAIN INVCHAIN S + Z( + ) + ) +) diff --git a/testdata/lvs/invchain_for_cheat.cir b/testdata/lvs/invchain_for_cheat.cir new file mode 100644 index 000000000..1aae680d3 --- /dev/null +++ b/testdata/lvs/invchain_for_cheat.cir @@ -0,0 +1,85 @@ + +* cell INVCHAIN +.SUBCKT INVCHAIN +* cell instance $1 r0 *1 -1.5,-0.8 +X$1 9 7 8 6 9 5 1 5 3 2 13 14 INV3 +* cell instance $2 r0 *1 2.6,-0.8 +X$2 8 11 9 10 8 11 2 12 2 12 5 4 13 14 INV2 +* cell instance $3 m90 *1 7.4,0 +X$3 14 13 11 12 4 4 10 10 INV +.ENDS INVCHAIN + +* cell INV3 +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +.SUBCKT INV3 1 2 3 4 5 6 7 8 9 10 11 12 +* cell instance $1 r0 *1 4.8,0.8 +X$1 12 11 3 10 8 6 1 5 INV +* cell instance $2 r0 *1 1.5,0.8 +X$2 12 11 4 7 9 9 2 2 INV +* cell instance $3 m90 *1 2.3,0.8 +X$3 12 11 2 9 7 7 4 4 INV +.ENDS INV3 + +* cell INV2 +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +.SUBCKT INV2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 +* cell instance $1 m90 *1 1.5,0.8 +X$1 14 13 3 11 9 7 1 5 INV +* cell instance $2 r0 *1 4,0.8 +X$2 14 13 4 12 10 8 2 6 INV +.ENDS INV2 + +* cell INV +* pin +* pin +* pin +* pin +* pin +* pin +* pin +* pin +.SUBCKT INV 1 2 3 4 5 6 7 8 +* cell instance $1 r0 *1 0,0 +X$1 4 1 3 TRANS +* cell instance $2 r0 *1 0,2.8 +X$2 4 2 3 TRANS +* device instance $1 r0 *1 0,2.8 PMOS +M$1 4 3 2 4 PMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U +* device instance $2 r0 *1 0.8,2.8 PMOS +M$2 2 7 5 2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U +* device instance $3 r0 *1 0,0 NMOS +M$3 4 3 1 4 NMOS L=0.25U W=0.95U AS=0.79325P AD=0.26125P PS=3.57U PD=1.5U +* device instance $4 r0 *1 0.8,0 NMOS +M$4 1 8 6 1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U PD=1.97U +.ENDS INV + +* cell TRANS +* pin +* pin +* pin +.SUBCKT TRANS 1 2 3 +.ENDS TRANS diff --git a/testdata/lvs/invchain_for_cheat.gds b/testdata/lvs/invchain_for_cheat.gds new file mode 100644 index 000000000..43446a79f Binary files /dev/null and b/testdata/lvs/invchain_for_cheat.gds differ