From d5506a176a0591084884bbb5768e3512c6ca4f08 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Nov 2019 01:20:22 +0100 Subject: [PATCH 01/10] WIP: first implementation - needs testing. --- src/db/db/dbCircuit.cc | 64 ++++++++- src/db/db/dbCircuit.h | 8 +- src/db/db/dbNetlist.cc | 2 +- src/db/db/gsiDeclDbNetlist.cc | 5 + src/db/unit_tests/dbNetlistExtractorTests.cc | 131 +++++++++++++++++++ src/db/unit_tests/dbNetlistTests.cc | 11 ++ testdata/lvs/invchain_for_cheat.cir | 56 -------- testdata/ruby/dbNetlist.rb | 15 +++ 8 files changed, 227 insertions(+), 65 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 1ca2d79c7..735f6116b 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -105,6 +105,14 @@ Circuit &Circuit::operator= (const Circuit &other) m_cell_index = other.m_cell_index; m_pins = other.m_pins; + m_pin_by_id.clear (); + for (pin_list::iterator p = m_pins.begin (); p != m_pins.end (); ++p) { + if (m_pin_by_id.size () <= p->id ()) { + m_pin_by_id.resize (p->id () + 1, pin_list::iterator ()); + } + m_pin_by_id [p->id ()] = p; + } + std::map device_table; for (const_device_iterator i = other.begin_devices (); i != other.end_devices (); ++i) { Device *d = new Device (*i); @@ -157,17 +165,22 @@ void Circuit::set_netlist (Netlist *netlist) const Pin *Circuit::pin_by_id (size_t id) const { - if (id >= m_pins.size ()) { + if (id >= m_pin_by_id.size ()) { return 0; } else { - return &m_pins [id]; + pin_list::iterator pi = m_pin_by_id [id]; + if (pi == pin_list::iterator ()) { + return 0; + } else { + return pi.operator-> (); + } } } void Circuit::rename_pin (size_t id, const std::string &name) { - if (id < m_pins.size ()) { - m_pins [id].set_name (name); + if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) { + m_pin_by_id [id]->set_name (name); } } @@ -207,6 +220,7 @@ void Circuit::clear () { m_name.clear (); m_pins.clear (); + m_pin_by_id.clear (); m_devices.clear (); m_nets.clear (); m_subcircuits.clear (); @@ -290,22 +304,33 @@ Circuit::const_child_circuit_iterator Circuit::end_parents () const void Circuit::clear_pins () { m_pins.clear (); + m_pin_by_id.clear (); } const Pin &Circuit::add_pin (const Pin &pin) { m_pins.push_back (pin); - m_pins.back ().set_id (m_pins.size () - 1); + m_pins.back ().set_id (m_pin_by_id.size ()); + m_pin_by_id.push_back (--m_pins.end ()); return m_pins.back (); } const Pin &Circuit::add_pin (const std::string &name) { m_pins.push_back (Pin (name)); - m_pins.back ().set_id (m_pins.size () - 1); + m_pins.back ().set_id (m_pin_by_id.size ()); + m_pin_by_id.push_back (--m_pins.end ()); return m_pins.back (); } +void Circuit::remove_pin (size_t id) +{ + if (id < m_pin_by_id.size () && m_pin_by_id [id] != pin_list::iterator ()) { + m_pins.erase (m_pin_by_id [id]); + m_pin_by_id [id] = pin_list::iterator (); + } +} + void Circuit::add_net (Net *net) { m_nets.push_back (net); @@ -554,13 +579,38 @@ void Circuit::purge_nets () { std::vector nets_to_be_purged; for (net_iterator n = begin_nets (); n != end_nets (); ++n) { - if (n->is_floating ()) { + if (n->is_passive ()) { nets_to_be_purged.push_back (n.operator-> ()); } } + + std::set pins_to_delete; + for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { + for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) { + pins_to_delete.insert (p->pin_id ()); + } delete *n; } + + // remove the pin references of the pins we're going to delete + for (refs_iterator r = begin_refs (); r != end_refs (); ++r) { + db::SubCircuit *subcircuit = r.operator-> (); + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + db::Net *net = subcircuit->net_for_pin (*p); + for (db::Net::subcircuit_pin_iterator sp = net->begin_subcircuit_pins (); sp != net->end_subcircuit_pins (); ++sp) { + if (sp->pin_id () == *p && sp->subcircuit () == subcircuit) { + net->erase_subcircuit_pin (sp); + break; + } + } + } + } + + // and actually remove those pins + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + remove_pin (*p); + } } /** diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h index c8bcac695..5fa298ea0 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -89,7 +89,7 @@ class DB_PUBLIC Circuit : public db::NetlistObject, public gsi::ObjectBase { public: - typedef tl::vector pin_list; + typedef std::list pin_list; typedef pin_list::const_iterator const_pin_iterator; typedef pin_list::iterator pin_iterator; typedef tl::shared_collection device_list; @@ -330,6 +330,11 @@ public: */ const Pin &add_pin (const Pin &pin); + /** + * @brief Removes the pin with the given ID + */ + void remove_pin (size_t id); + /** * @brief Begin iterator for the pins of the circuit (non-const version) */ @@ -751,6 +756,7 @@ private: db::cell_index_type m_cell_index; net_list m_nets; pin_list m_pins; + std::vector m_pin_by_id; device_list m_devices; subcircuit_list m_subcircuits; Netlist *mp_netlist; diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 62056542c..1f7ab2fe8 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -472,7 +472,7 @@ void Netlist::remove_device_abstract (DeviceAbstract *device_abstract) void Netlist::purge_nets () { - for (circuit_iterator c = begin_circuits (); c != end_circuits (); ++c) { + for (bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up (); ++c) { c->purge_nets (); } } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 6d2ca28cd..f6dd51ce8 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1131,6 +1131,11 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", "to the outside through such a pin. The pin is added after all existing " "pins. For more details see the \\Pin class." ) + + gsi::method ("remove_pin", &db::Circuit::remove_pin, gsi::arg ("id"), + "@brief Removes the pin with the given ID from the circuit\n" + "\n" + "This method has been introduced in version 0.26.2.\n" + ) + gsi::iterator ("each_child", (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_children, (db::Circuit::child_circuit_iterator (db::Circuit::*) ()) &db::Circuit::end_children, "@brief Iterates over the child circuits of this circuit\n" "Child circuits are the ones that are referenced from this circuit via subcircuits." diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index fd64adaa0..d1bad5e47 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -2573,3 +2573,134 @@ TEST(12_FloatingSubcircuitExtraction) ); } +TEST(13_RemoveDummyPins) +{ + 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, "issue-425.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; + + // 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; + + 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); + + // perform the net extraction + + 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 + + db::NetlistExtractor net_ex; + net_ex.set_include_floating_subcircuits (true); + net_ex.extract_nets (dss, 0, conn, nl, cl); + + nl.simplify (); + + // compare netlist as string + CHECKPOINT (); + db::compare_netlist (_this, nl, + "circuit RINGO (FB=FB,VSS=VSS,VDD=VDD);\n" + " subcircuit INV2 $1 (IN=FB,OUT=$I25,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $2 (IN=$I25,OUT=$I1,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $3 (IN=$I1,OUT=$I2,$3=VSS,$4=VDD);\n" + " subcircuit INV2 $4 (IN=$I2,OUT=$I3,$3=VSS,$4=VDD);\n" + "end;\n" + "circuit INV2 (IN=IN,OUT=OUT,$3=$4,$4=$5);\n" + " device PMOS $1 (S=$2,G=IN,D=$5) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$2,G=IN,D=$4) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n" + ); +} + diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index c3056e4aa..06e1eea1b 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -360,6 +360,17 @@ TEST(3_CircuitBasic) EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); EXPECT_EQ (c2.pin_by_id (1)->name (), "p2"); EXPECT_EQ (c2.pin_by_id (2), 0); + + c2.remove_pin (1); + EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); + EXPECT_EQ (c2.pin_by_id (1), 0); + EXPECT_EQ (c2.pin_by_id (2), 0); + + db::Pin p3 = c2.add_pin ("p3"); + EXPECT_EQ (c2.pin_by_id (0)->name (), "p1"); + EXPECT_EQ (c2.pin_by_id (1), 0); + EXPECT_EQ (c2.pin_by_id (2)->name (), "p3"); + EXPECT_EQ (c2.pin_by_id (3), 0); } TEST(4_CircuitDevices) diff --git a/testdata/lvs/invchain_for_cheat.cir b/testdata/lvs/invchain_for_cheat.cir index 1aae680d3..50e75dba1 100644 --- a/testdata/lvs/invchain_for_cheat.cir +++ b/testdata/lvs/invchain_for_cheat.cir @@ -1,85 +1,29 @@ * 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/ruby/dbNetlist.rb b/testdata/ruby/dbNetlist.rb index 695eb4e38..879939444 100644 --- a/testdata/ruby/dbNetlist.rb +++ b/testdata/ruby/dbNetlist.rb @@ -170,6 +170,21 @@ class DBNetlist_TestClass < TestBase c.each_pin { |p| names << p.name } assert_equal(names, [ "A", "B" ]) + assert_equal(c.pin_by_id(0) == nil, false) + assert_equal(c.pin_by_id(1) == nil, false) + assert_equal(c.pin_by_id(0).name, "A") + assert_equal(c.pin_by_id(1).name, "B") + + c.remove_pin(0) + + names = [] + c.each_pin { |p| names << p.name } + assert_equal(names, [ "B" ]) + + assert_equal(c.pin_by_id(0) == nil, true) + assert_equal(c.pin_by_id(1) == nil, false) + assert_equal(c.pin_by_id(1).name, "B") + end def test_4_Device From 18b80489ed5bc69623bf9d2613ba0e754e285fbe Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Nov 2019 01:20:59 +0100 Subject: [PATCH 02/10] Added test data. --- testdata/algo/issue-425.gds | Bin 0 -> 2578 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 testdata/algo/issue-425.gds diff --git a/testdata/algo/issue-425.gds b/testdata/algo/issue-425.gds new file mode 100644 index 0000000000000000000000000000000000000000..e2e675e8f7eed6603c7d01303e21a9d712228cf1 GIT binary patch literal 2578 zcma)-O-NKx6vxl|y7Oin&CCkL!lcNB7=#%i2#S4(F^Zam2(=MfwvdRZ2x?(L5EN}{ zAwdSYi697c6%pa8Wl)6FIuKkr<=p<~-FJNNO}?iCGr!^7`@iSjbIv`N6xsGgYO(Cx zFRG!vw4V-;6aP=XtTDwFsCTs9xTbaG2$RVAMr1z_ik(UB?nv*(^%WcA%lLwN9{dqe?3Lv#J$5q5 zdid>TeMGU-WSSmx+n`xC)bn74{Tqrs-9PKtzoFI5I($Qly~@9epMPTs{_i1vOVHhf z@54f|GZXud>EZi(Fb=W~@gES1J<{h*{+!UiI>cG@cRBbiQ)4}owEnxoByw7f*BoWm zhp*INY2rA!1)@TO)Jlk8Lva4MqDD8|cJIb;rnjnk4aKa&=3M5hDinqm^=XOOoiLa{S5^egbyWuojpH~A8Z z-RUy=?epce6V=rdF>_ybrqa6nl~sm2RT&=~C9gf$eUR1dc4&M!t;|S;aC0A#Iy8M` z4YjWj&oz`J_k-U;u`?5KjpT56uwkvG>!gk0^E;%GT!>jK1*F=!Ig>FJ$X$dW^n! z!svx!ujw)R;^zI?XOqR9QtLl>gWR8_n$V3Cv(O7=)@GOUo7C`yaR~TT-lo6f{U04H zogKzZbZNiAbo-z?W0(91R;eB&ZUnXT#d%UdnVmH=o8iVto#vmg8RnY$vs;? zhk4DYGthfYbo5O`vAfOYOrifoovc5Gej0kvy9B=vBZ}RfPGkW0Jjwu{&gAJ#fA%a) cM4l$b#vtH4g<1b^HN1U1ZvYR! Date: Sat, 23 Nov 2019 19:24:59 +0100 Subject: [PATCH 03/10] Updates for 'cheats' testcase which was entirely broken. --- testdata/lvs/invchain_cheat.cir.1 | 37 +- testdata/lvs/invchain_cheat.cir.2 | 30 -- testdata/lvs/invchain_cheat.cir.3 | 30 -- testdata/lvs/invchain_cheat.cir.4 | 30 -- testdata/lvs/invchain_cheat.lvs | 85 +++- testdata/lvs/invchain_cheat.lvsdb | 701 +++++++++++----------------- testdata/lvs/invchain_for_cheat.cir | 28 +- testdata/lvs/invchain_for_cheat.gds | Bin 3078 -> 3450 bytes 8 files changed, 368 insertions(+), 573 deletions(-) delete mode 100644 testdata/lvs/invchain_cheat.cir.2 delete mode 100644 testdata/lvs/invchain_cheat.cir.3 delete mode 100644 testdata/lvs/invchain_cheat.cir.4 diff --git a/testdata/lvs/invchain_cheat.cir.1 b/testdata/lvs/invchain_cheat.cir.1 index ebb1e0e31..f4bef3947 100644 --- a/testdata/lvs/invchain_cheat.cir.1 +++ b/testdata/lvs/invchain_cheat.cir.1 @@ -1,30 +1,25 @@ * Extracted by KLayout -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV +.SUBCKT INVCHAIN IN OUT VSS VDD +X$1 IN \$2 \$3 \$2 \$3 \$4 VDD VSS INV3 +X$2 \$5 \$6 \$4 \$5 VDD VSS INV2 +X$3 VSS VDD \$6 OUT INV .ENDS INVCHAIN -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV +.SUBCKT INV3 3 5 7 4 6 8 \$I4 \$I2 +X$1 \$I2 \$I4 3 4 INV +X$2 \$I2 \$I4 5 6 INV +X$3 \$I2 \$I4 7 8 INV .ENDS INV3 -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV +.SUBCKT INV2 \$I8 \$I7 \$I6 \$I5 \$I4 \$I2 +X$1 \$I2 \$I4 \$I6 \$I8 INV +X$2 \$I2 \$I4 \$I5 \$I7 INV .ENDS INV2 -.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$9 \$I8 \$I7 -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 -M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -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 -M$4 \$1 \$I7 \$9 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U +.SUBCKT INV \$1 \$2 \$3 \$4 +M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U ++ PD=3.45U +M$2 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U ++ PD=3.45U .ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.2 b/testdata/lvs/invchain_cheat.cir.2 deleted file mode 100644 index 559a90f2a..000000000 --- a/testdata/lvs/invchain_cheat.cir.2 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$5 \$8 \$I8 \$I7 -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 -M$2 \$2 \$I8 \$5 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -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 -M$4 \$1 \$I7 \$8 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.3 b/testdata/lvs/invchain_cheat.cir.3 deleted file mode 100644 index be921871d..000000000 --- a/testdata/lvs/invchain_cheat.cir.3 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$7 \$10 \$I8 \$I7 -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 -M$2 \$2 \$I8 \$7 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -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 -M$4 \$1 \$I7 \$10 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.cir.4 b/testdata/lvs/invchain_cheat.cir.4 deleted file mode 100644 index f6fcce0cb..000000000 --- a/testdata/lvs/invchain_cheat.cir.4 +++ /dev/null @@ -1,30 +0,0 @@ -* Extracted by KLayout - -.SUBCKT INVCHAIN -X$1 \$7 \$1 \$9 \$8 \$6 \$9 \$5 \$5 \$3 \$2 \$I2 \$I1 INV3 -X$2 \$8 \$11 \$9 \$10 \$8 \$11 \$2 \$I3 \$2 \$I3 \$5 \$4 \$I2 \$I1 INV2 -X$3 \$I1 \$I2 \$11 \$I3 \$4 \$4 \$10 \$10 INV -.ENDS INVCHAIN - -.SUBCKT INV3 \$I18 \$I17 \$I15 \$I14 \$I13 \$I11 \$I10 \$I8 \$I7 \$I5 \$I4 \$I2 -X$1 \$I2 \$I4 \$I13 \$I17 \$I7 \$I7 \$I18 \$I18 INV -X$2 \$I2 \$I4 \$I18 \$I7 \$I17 \$I17 \$I13 \$I13 INV -X$3 \$I2 \$I4 \$I14 \$I5 \$I8 \$I10 \$I15 \$I11 INV -.ENDS INV3 - -.SUBCKT INV2 \$I16 \$I15 \$I14 \$I13 \$I12 \$I11 \$I10 \$I9 \$I8 \$I7 \$I6 \$I5 -+ \$I4 \$I2 -X$1 \$I2 \$I4 \$I14 \$I6 \$I8 \$I10 \$I16 \$I12 INV -X$2 \$I2 \$I4 \$I13 \$I5 \$I7 \$I9 \$I15 \$I11 INV -.ENDS INV2 - -.SUBCKT INV \$1 \$2 \$3 \$4 \$6 \$9 \$I8 \$I7 -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 -M$2 \$2 \$I8 \$6 \$2 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -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 -M$4 \$1 \$I7 \$9 \$1 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.03325P PS=1.5U -+ PD=1.97U -.ENDS INV diff --git a/testdata/lvs/invchain_cheat.lvs b/testdata/lvs/invchain_cheat.lvs index 34ff10e5c..d0fd20237 100644 --- a/testdata/lvs/invchain_cheat.lvs +++ b/testdata/lvs/invchain_cheat.lvs @@ -6,7 +6,52 @@ 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") +# needs this delegate because we use MOS3 which is not available in Spice +class SpiceReaderDelegate < RBA::NetlistSpiceReaderDelegate + + # says we want to catch these subcircuits as devices + def wants_subcircuit(name) + name == "HVNMOS" || name == "HVPMOS" + end + + # translate the element + def element(circuit, el, name, model, value, nets, params) + + if el != "M" + # all other elements are left to the standard implementation + return super + end + + if nets.size != 4 + error("Device #{model} needs four nodes") + end + + # provide a device class + cls = circuit.netlist.device_class_by_name(model) + if ! cls + cls = RBA::DeviceClassMOS3Transistor::new + cls.name = model + circuit.netlist.add(cls) + end + + # create a device + device = circuit.create_device(cls, name) + + # and configure the device + [ "S", "G", "D" ].each_with_index do |t,index| + device.connect_terminal(t, nets[index]) + end + device.set_parameter("W", params["W"] * 1e6) + device.set_parameter("L", params["L"] * 1e6) + + device + + end + +end + +reader = RBA::NetlistSpiceReader::new(SpiceReaderDelegate::new) +schematic("invchain_for_cheat.cir", reader) deep @@ -15,32 +60,38 @@ deep nwell = input(1, 0) active = input(2, 0) poly = input(3, 0) +poly_lbl = input(3, 1) diff_cont = input(4, 0) poly_cont = input(5, 0) metal1 = input(6, 0) +metal1_lbl = input(6, 1) via1 = input(7, 0) metal2 = input(8, 0) +metal2_lbl = input(8, 1) # 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 +psd = nil +nsd = nil cheat("INV") do + # 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 + # PMOS transistor device extraction extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate, "tS" => psd, "tD" => psd, "tG" => poly }) @@ -62,12 +113,18 @@ connect(poly_cont, metal1) connect(metal1, via1) connect(via1, metal2) +# attach labels +connect(poly, poly_lbl) +connect(metal1, metal1_lbl) +connect(metal2, metal2_lbl) + # Global connect_global(bulk, "SUBSTRATE") # Compare section netlist.simplify +align compare diff --git a/testdata/lvs/invchain_cheat.lvsdb b/testdata/lvs/invchain_cheat.lvsdb index 7f128c691..5b854ca93 100644 --- a/testdata/lvs/invchain_cheat.lvsdb +++ b/testdata/lvs/invchain_cheat.lvsdb @@ -3,66 +3,50 @@ J( W(INVCHAIN) U(0.001) L(l3 '3/0') + L(l11 '3/1') L(l6 '4/0') - L(l7 '2/0') + L(l7 '5/0') L(l8 '6/0') + L(l12 '6/1') L(l9 '7/0') L(l10 '8/0') - L(l11) + L(l13 '8/1') + L(l14) L(l2) L(l5) - C(l3 l3 l7) + C(l3 l3 l11 l7) + C(l11 l3 l11) C(l6 l6 l8 l2 l5) C(l7 l3 l7 l8) - C(l8 l6 l7 l8 l9) + C(l8 l6 l7 l8 l12 l9) + C(l12 l8 l12) C(l9 l8 l9 l10) - C(l10 l9 l10) - C(l11 l11) + C(l10 l9 l10 l13) + C(l13 l10 l13) + C(l14 l14) C(l2 l6 l2) C(l5 l6 l5) - G(l11 SUBSTRATE) + G(l14 SUBSTRATE) D(D$PMOS PMOS T(S - R(l2 (-960 -475) (835 950)) + R(l2 (-900 -475) (775 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)) + R(l2 (125 -475) (775 950)) ) ) D(D$NMOS NMOS T(S - R(l5 (-960 -475) (835 950)) + R(l5 (-900 -475) (775 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)) + R(l5 (125 -475) (775 950)) ) ) X(INV @@ -74,7 +58,7 @@ J( R(l9 (-305 -705) (250 250)) R(l9 (-250 150) (250 250)) R(l10 (-2025 -775) (3000 900)) - R(l5 (-1375 -925) (550 950)) + R(l5 (-1375 -925) (775 950)) ) N(2 R(l6 (290 2490) (220 220)) @@ -83,7 +67,7 @@ J( R(l9 (-305 -705) (250 250)) R(l9 (-250 150) (250 250)) R(l10 (-2025 -775) (3000 900)) - R(l2 (-1375 -925) (550 950)) + R(l2 (-1375 -925) (775 950)) ) N(3 R(l3 (-125 -250) (250 2500)) @@ -98,99 +82,55 @@ J( 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)) + R(l2 (-680 -855) (775 950)) + R(l5 (-775 -3750) (775 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) + E(AS 0.73625) + E(AD 0.73625) + E(PS 3.45) + E(PD 3.45) 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 + D(2 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) + E(AS 0.73625) + E(AD 0.73625) + E(PS 3.45) + E(PD 3.45) 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 + N(1 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 + N(2 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 + N(3) + N(4) + N(5 R(l6 (990 3290) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (3080 -620) (220 220)) @@ -198,7 +138,7 @@ J( R(l8 (-3590 -690) (360 760)) R(l8 (2940 -760) (360 760)) ) - N(14 + N(6 R(l6 (990 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (3080 -620) (220 220)) @@ -212,63 +152,52 @@ J( 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(0 6) + P(1 5) P(2 3) - P(3 11) - P(4 9) - P(5 7) - P(6 1) - P(7 5) + P(3 1) ) X(2 INV Y(4000 800) - P(0 14) - P(1 13) + P(0 6) + P(1 5) P(2 4) - P(3 12) - P(4 10) - P(5 8) - P(6 2) - P(7 6) + P(3 2) ) ) X(INV3 R((0 0) (6300 4600)) - N(1) - N(2 + N(1 I('3') + R(l11 (1509 1929) (2 2)) + ) + N(2 I('5') + R(l11 (2319 1909) (2 2)) + ) + N(3 I('7') + R(l11 (4829 1889) (2 2)) + ) + N(4 I('4') R(l6 (990 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-121 -1941) (2 2)) ) - N(3) - N(4) - N(5) - N(6) - N(7) - N(8) - N(9 + N(5 I('6') R(l6 (2590 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-131 -1971) (2 2)) ) - N(10 + N(6 I('8') R(l6 (4290 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-101 -1991) (2 2)) ) - N(11 + N(7 R(l6 (1790 3290) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 -620) (220 220)) @@ -279,7 +208,7 @@ J( R(l8 (-360 -760) (360 760)) R(l8 (2940 -760) (360 760)) ) - N(12 + N(8 R(l6 (1790 490) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 -620) (220 220)) @@ -290,136 +219,92 @@ J( 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(1 I('3')) + P(2 I('5')) + P(3 I('7')) + P(4 I('4')) + P(5 I('6')) + P(6 I('8')) P(7) P(8) - P(9) - P(10) - P(11) - P(12) X(1 INV Y(1500 800) - P(0 12) - P(1 11) - P(2 5) - P(3 2) - P(4 9) - P(5 9) - P(6 1) - P(7 1) + P(0 8) + P(1 7) + P(2 1) + P(3 4) ) X(2 INV M O(180) Y(2300 800) - P(0 12) - P(1 11) - P(2 1) - P(3 9) - P(4 2) - P(5 2) - P(6 5) - P(7 5) + P(0 8) + P(1 7) + P(2 2) + P(3 5) ) X(3 INV Y(4800 800) - P(0 12) - P(1 11) - P(2 4) - P(3 10) - P(4 8) - P(5 7) - P(6 3) - P(7 6) + P(0 8) + P(1 7) + P(2 3) + P(3 6) ) ) 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(1 I(IN) + R(l3 (-1295 925) (1235 350)) + R(l11 (-911 -151) (2 2)) ) N(2 - R(l6 (3790 990) (220 220)) - R(l6 (-1220 -1520) (220 220)) + R(l3 (445 805) (480 550)) + R(l6 (-1435 -1665) (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)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) N(3 - R(l6 (1405 990) (220 220)) - R(l6 (-535 -1520) (220 220)) + R(l3 (1345 925) (1945 350)) + R(l6 (-2200 -1585) (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)) + R(l7 (95 -2120) (220 220)) + R(l8 (-295 -370) (440 520)) ) N(4 - R(l6 (7090 990) (220 220)) - R(l6 (-1220 -1520) (220 220)) + R(l3 (3745 805) (480 550)) + R(l6 (-1435 -1665) (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)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) N(5 - R(l6 (4705 990) (220 220)) - R(l6 (-535 -1520) (220 220)) + R(l3 (4645 925) (1945 350)) + R(l6 (-2200 -1585) (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)) + R(l7 (95 -2120) (220 220)) + R(l8 (-295 -370) (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)) + R(l6 (-1435 -1665) (220 220)) + R(l6 (-220 180) (220 220)) + R(l6 (-220 2180) (220 220)) + R(l6 (-220 180) (220 220)) + R(l7 (780 -2120) (220 220)) + R(l8 (-1065 -285) (1105 350)) ) - N(12 + N(7 I(OUT) R(l6 (7690 -310) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-220 2180) (220 220)) R(l6 (-220 180) (220 220)) + R(l12 (-121 -2011) (2 2)) ) - 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 + N(8 I(VSS) R(l6 (6890 -310) (220 220)) R(l6 (-220 180) (220 220)) R(l6 (-3520 -620) (220 220)) @@ -438,136 +323,96 @@ J( R(l8 (-6960 -760) (360 760)) R(l8 (-360 -760) (360 760)) R(l8 (2940 -760) (360 760)) + R(l13 (2719 -381) (2 2)) + R(l13 (-3302 -2) (2 2)) + R(l13 (-3302 -2) (2 2)) ) + N(9 I(VDD) + 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)) + R(l13 (-581 -381) (2 2)) + R(l13 (3298 -2) (2 2)) + R(l13 (-6602 -2) (2 2)) + ) + P(1 I(IN)) + P(7 I(OUT)) + P(8 I(VSS)) + P(9 I(VDD)) X(1 INV3 Y(-1500 -800) - P(0 7) - P(1 1) - P(2 9) - P(3 8) - P(4 6) - P(5 9) - P(6 5) - P(7 5) - P(8 3) - P(9 2) - P(10 13) - P(11 14) + P(0 1) + P(1 2) + P(2 3) + P(3 2) + P(4 3) + P(5 4) + P(6 9) + P(7 8) ) 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) + P(0 5) + P(1 6) + P(2 4) + P(3 5) + P(4 9) + P(5 8) ) 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) + P(0 8) + P(1 9) + P(2 6) + P(3 7) ) ) ) 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) + E(AS 0) + E(AD 0) + E(PS 0) + E(PD 0) + T(S 1) T(G 3) - T(D 2) - T(B 4) + T(D 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 + D(2 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) + E(AS 0) + E(AD 0) + E(PS 0) + E(PD 0) + T(S 2) 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) + T(D 4) ) ) X(INV3 @@ -579,10 +424,6 @@ H( 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')) @@ -591,39 +432,23 @@ H( 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(0 1) + P(1 2) P(2 3) - P(3 10) - P(4 8) - P(5 6) - P(6 1) - P(7 5) + P(3 4) ) 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) + P(0 1) + P(1 2) + P(2 5) + P(3 6) ) 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) + P(0 1) + P(1 2) + P(2 7) + P(3 8) ) ) X(INV2 @@ -633,125 +458,135 @@ H( 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(0 1) + P(1 2) P(2 3) - P(3 11) - P(4 9) - P(5 7) - P(6 1) - P(7 5) + P(3 4) ) 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) + P(0 1) + P(1 2) + P(2 5) + P(3 6) ) ) X(INVCHAIN - N(1 I('9')) - N(2 I('7')) - N(3 I('8')) - N(4 I('6')) + N(1 I('1')) + N(2 I('2')) + N(3 I('3')) + N(4 I('4')) 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')) + N(6 I('6')) + N(7 I('7')) + N(8 I('8')) + N(9 I('9')) X(1 INV3 I($1) P(0 1) P(1 2) P(2 3) P(3 4) - P(4 1) + P(4 4) P(5 5) - P(6 6) - P(7 5) - P(8 7) - P(9 8) - P(10 9) - P(11 10) + P(6 5) + P(7 6) ) 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) + P(0 1) + P(1 2) + P(2 6) + P(3 7) + P(4 7) + P(5 8) ) 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) + P(0 1) + P(1 2) + P(2 8) + P(3 9) ) ) ) Z( - X(() TRANS 0 + X(INV INV 1 Z( + N(2 1 1) + N(1 2 1) + N(3 3 1) + N(4 4 1) + P(1 0 1) + P(0 1 1) + P(2 2 1) + P(3 3 1) + D(2 2 1) + D(1 1 1) ) ) - X(INV INV S + X(INV2 INV2 1 Z( + N(5 1 1) + N(6 2 1) + N(3 3 1) + N(1 4 W) + N(4 5 1) + N(2 6 W) + P(4 0 1) + P(5 1 1) + P(2 2 1) + P(0 3 1) + P(3 4 1) + P(1 5 1) + X(1 1 1) + X(2 2 1) ) ) - X(INV2 INV2 S + X(INV3 INV3 1 Z( + N(7 1 1) + N(8 2 1) + N(1 3 1) + N(4 4 W) + N(2 5 1) + N(5 6 W) + N(3 7 1) + N(6 8 W) + P(6 0 1) + P(7 1 1) + P(0 2 1) + P(3 3 1) + P(1 4 1) + P(4 5 1) + P(2 6 1) + P(5 7 1) + X(1 1 1) + X(2 2 1) + X(3 3 1) ) ) - X(INV3 INV3 S - Z( - ) - ) - X(INVCHAIN INVCHAIN S + X(INVCHAIN INVCHAIN 1 Z( + N(2 4 1) + N(3 5 1) + N(4 6 1) + N(5 7 1) + N(6 8 1) + N(1 3 1) + N(7 9 1) + N(9 1 1) + N(8 2 1) + P(0 () 1) + P(1 () 1) + P(3 () 1) + P(2 () 1) + X(3 3 1) + X(2 2 1) + X(1 1 1) ) ) ) diff --git a/testdata/lvs/invchain_for_cheat.cir b/testdata/lvs/invchain_for_cheat.cir index 50e75dba1..d37bd4cee 100644 --- a/testdata/lvs/invchain_for_cheat.cir +++ b/testdata/lvs/invchain_for_cheat.cir @@ -1,29 +1,27 @@ * cell INVCHAIN .SUBCKT INVCHAIN -X$1 9 7 8 6 9 5 1 5 3 2 13 14 INV3 -X$2 8 11 9 10 8 11 2 12 2 12 5 4 13 14 INV2 -X$3 14 13 11 12 4 4 10 10 INV +X$1 1 2 3 4 4 5 5 6 INV3 +X$2 1 2 6 7 7 8 INV2 +X$3 1 2 8 9 INV .ENDS INVCHAIN * cell INV3 -.SUBCKT INV3 1 2 3 4 5 6 7 8 9 10 11 12 -X$1 12 11 3 10 8 6 1 5 INV -X$2 12 11 4 7 9 9 2 2 INV -X$3 12 11 2 9 7 7 4 4 INV +.SUBCKT INV3 1 2 3 4 5 6 7 8 +X$1 1 2 3 4 INV +X$2 1 2 5 6 INV +X$3 1 2 7 8 INV .ENDS INV3 * cell INV2 -.SUBCKT INV2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -X$1 14 13 3 11 9 7 1 5 INV -X$2 14 13 4 12 10 8 2 6 INV +.SUBCKT INV2 1 2 3 4 5 6 +X$1 1 2 3 4 INV +X$2 1 2 5 6 INV .ENDS INV2 * cell INV -.SUBCKT INV 1 2 3 4 5 6 7 8 -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 -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 -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 -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 +.SUBCKT INV 1 2 3 4 +M$1 1 3 4 1 PMOS L=0.25U W=0.95U +M$3 2 3 4 2 NMOS L=0.25U W=0.95U .ENDS INV diff --git a/testdata/lvs/invchain_for_cheat.gds b/testdata/lvs/invchain_for_cheat.gds index 43446a79f5d1373fbe0489d6d0c11e2abbef03d5..5856c8f19ae818e6b74931229ef3cb44e85bb9c8 100644 GIT binary patch delta 463 zcmZpZ_$8&pz{bGD6u}_F$i)7bftx{`L6|{^K^d7nQAt@8yF`?tV$J{m|5X3~|5L-j zz<8U1fw=`n!^AhvImw7!`{pX9ekSZvlP9niOrFFgC*`QX00BG#%nS^y&lnikyBOFc z*^C(`_i(A8NplJSrOQClrr4x~?g6EfK+@(6lTTsjW^n>aZvsi1V3X#m07_2*Nt=PC z?NFU2Xa$sR07+XgFt7*$F*^f;3@gq+oh-*1i^K17Y}J$3GV*SI#xBLe!NI`5#>>RO fI(ZhGJtOPnTVPU(9mI|Tle5?@*nn2CurL4s4!uY< delta 271 zcmew*)h40Dz{bGD6u}_F$i)7bfs28cL6kv_K^B=kQAt@8yF`?tqQn3H|5X3~|Kq^G zz<8U1f%yQ8hKX;SbCMCe_RUpH{Y==UCM&SV;*gPJEs$epV31+O>E6kc*sCY&GV)FK k Date: Sat, 23 Nov 2019 22:04:25 +0100 Subject: [PATCH 04/10] Unit tests fixed and a bugfix in the netlist compare One unit test was failing because the netlist compare did not properly consider dropped pins: * A severe bug ("g1" should be "g2") * Incomplete detection of dropped pins upwards in the hierarchy The general pin and net mapping scheme has been enhanced so that net mapping to "0" is valid (this will happen in case of dropped pins) and this condition is used to detect pins without match requirement. --- src/db/db/dbNetlistCompare.cc | 113 +++++-- src/db/db/dbNetlistCompare.h | 2 +- src/db/unit_tests/dbNetlistCompareTests.cc | 361 ++++++++++++++++++++- src/db/unit_tests/dbNetlistTests.cc | 2 +- 4 files changed, 444 insertions(+), 34 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index a95f6fba2..55f6091de 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -2951,14 +2951,34 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // Report missing net assignment for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (i->net (), 0); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (i->net (), 0); + } else { + mp_logger->net_mismatch (i->net (), 0); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g1.identify (g1.node_index_for_net (i->net ()), 0); + } } } for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { - if (! i->has_other () && mp_logger) { - mp_logger->net_mismatch (0, i->net ()); + if (! i->has_other ()) { + if (mp_logger) { + if (good) { + mp_logger->match_nets (0, i->net ()); + } else { + mp_logger->net_mismatch (0, i->net ()); + } + } + if (good) { + // in the "good" case, match the nets against 0 + g2.identify (g2.node_index_for_net (i->net ()), 0); + } } } @@ -2969,22 +2989,33 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, return good; } -void -NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *pin2, bool &good, bool &pin_mismatch) const +bool +NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const db::NetGraph &g2, const db::Circuit *c2, const db::Pin *pin2) const { const db::Circuit *c = pin1 ? c1 : c2; const db::Pin *pin = pin1 ? pin1 : pin2; + const db::NetGraph *graph = pin1 ? &g1 : &g2; + const db::Net *net = c->net_for_pin (pin->id ()); - // If the pin isn't connected internally inside the circuit we can ignore it - if (c->net_for_pin (pin->id ()) && c->net_for_pin (pin->id ())->is_passive ()) { - if (mp_logger) { - mp_logger->match_pins (pin1, pin2); + // Nets which are paired with "null" trigger this condition: + if (net) { + const db::NetGraphNode &n = graph->node (graph->node_index_for_net (net)); + if (n.has_other ()) { + if (mp_logger) { + mp_logger->match_pins (pin1, pin2); + } + return true; } - return; } // Determine whether the pin in question is used - only in this case we will report an error. // Otherwise, the report will be "match" against 0. + // "used" follows a heuristic criterion derived from the subcircuits which make use of this circuit: + // if one of these connects the pin to a net with either connections upwards, other subcircuits or + // devices, the pin is regarded "used". + // TODO: it would be better probably to have a global concept of "used pins" which considers all + // devices and propagates their presence as "used" property upwards, then downwards to the subcircuit + // pins. bool is_not_connected = true; for (db::Circuit::const_refs_iterator r = c->begin_refs (); r != c->end_refs () && is_not_connected; ++r) { @@ -2999,12 +3030,12 @@ NetlistComparer::handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1 if (mp_logger) { mp_logger->match_pins (pin1, pin2); } + return true; } else { if (mp_logger) { mp_logger->pin_mismatch (pin1, pin2); } - good = false; - pin_mismatch = true; + return false; } } @@ -3042,18 +3073,21 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } } - std::vector abstract_pins; - std::multimap net2pin; + std::vector abstract_pins2; + std::multimap net2pin2; for (db::Circuit::const_pin_iterator p = c2->begin_pins (); p != c2->end_pins (); ++p) { const db::Net *net = c2->net_for_pin (p->id ()); if (net) { - net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); + net2pin2.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); } else if (abstract_pin_name_mapping.find (p.operator-> ()) == abstract_pin_name_mapping.end ()) { - abstract_pins.push_back (p.operator-> ()); + abstract_pins2.push_back (p.operator-> ()); } } - std::vector::iterator next_abstract = abstract_pins.begin (); + // collect missing assignment for circuit 1 + std::multimap net2pin1; + + std::vector::iterator next_abstract = abstract_pins2.begin (); CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1]; c12_pin_mapping.set_other (c2); @@ -3078,7 +3112,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g c12_pin_mapping.map_pin (p->id (), fp->second->id ()); c22_pin_mapping.map_pin (fp->second->id (), p->id ()); - } else if (next_abstract != abstract_pins.end ()) { + } else if (next_abstract != abstract_pins2.end ()) { // assign an abstract pin - this is a dummy assignment which is mitigated // by declaring the pins equivalent in derive_pin_equivalence @@ -3093,7 +3127,10 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } else { // otherwise this is an error for subcircuits or worth a report for top-level circuits - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + if (! handle_pin_mismatch (g1, c1, p.operator-> (), g2, c2, 0)) { + good = false; + pin_mismatch = true; + } } @@ -3104,14 +3141,15 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net)); if (! n.has_other ()) { - handle_pin_mismatch (c1, p.operator-> (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); continue; } - std::multimap::iterator np = net2pin.find (n.other_net_index ()); + std::multimap::iterator np = net2pin2.find (n.other_net_index ()); for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { - if (np != net2pin.end () && np->first == n.other_net_index ()) { + if (np != net2pin2.end () && np->first == n.other_net_index ()) { if (mp_logger) { mp_logger->match_pins (pi->pin (), np->second); @@ -3122,11 +3160,12 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g std::multimap::iterator np_delete = np; ++np; - net2pin.erase (np_delete); + net2pin2.erase (np_delete); } else { - handle_pin_mismatch (c1, pi->pin (), c2, 0, good, pin_mismatch); + // remember and handle later when we know which pins are not mapped + net2pin1.insert (std::make_pair (g1.node_index_for_net (net), p.operator-> ())); } @@ -3134,16 +3173,28 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } - for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { - handle_pin_mismatch (c1, 0, c2, np->second, good, pin_mismatch); + for (std::multimap::iterator np = net2pin1.begin (); np != net2pin1.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, np->second, g2, c2, 0)) { + good = false; + pin_mismatch = true; + } + } + + for (std::multimap::iterator np = net2pin2.begin (); np != net2pin2.end (); ++np) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, np->second)) { + good = false; + pin_mismatch = true; + } } // abstract pins must match. - while (next_abstract != abstract_pins.end ()) { - handle_pin_mismatch (c1, 0, c2, *next_abstract, good, pin_mismatch); + while (next_abstract != abstract_pins2.end ()) { + if (! handle_pin_mismatch (g1, c1, 0, g2, c2, *next_abstract)) { + good = false; + pin_mismatch = true; + } ++next_abstract; } - } void @@ -3384,7 +3435,7 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g1.begin () [i->second].has_other ()) { + if (! g2.begin () [i->second].has_other ()) { mapped = false; } else { i->second = g2.begin () [i->second].other_net_index (); diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index bcb6b9f56..f1a7b2ff6 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -314,7 +314,7 @@ protected: void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const; void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, bool &good) const; void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &good) const; - void handle_pin_mismatch (const db::Circuit *c1, const db::Pin *pin1, const db::Circuit *c2, const db::Pin *p2, bool &good, bool &pin_mismatch) const; + bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const; mutable NetlistCompareLogger *mp_logger; std::map, std::vector > > m_same_nets; diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 820b61b1f..2a4ae00d5 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2055,11 +2055,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "net_mismatch INT IN1\n" "net_mismatch IN1 INT\n" "net_mismatch IN2 IN2\n" - "match_pins $0 (null)\n" "match_pins $1 $1\n" "match_pins $2 $2\n" "match_pins $3 $3\n" "match_pins $4 $4\n" + "match_pins $0 (null)\n" "match_pins (null) $0\n" "match_subcircuits $2 $1\n" "subcircuit_mismatch $1 $2\n" @@ -3366,3 +3366,362 @@ TEST(21_BusLikeAmbiguousConnections) EXPECT_EQ (good, true); } +TEST(22_NodesRemoved) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) $1\n" + "match_nets (null) BULK\n" + "match_pins IN IN\n" + "match_pins $1 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) $0\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets (null) BULK\n" + "match_nets (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, true); +} + +TEST(23_NodesRemovedWithError) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + // NOTE: $1 pin should not be connected to different nets, although it's not functional + " subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets $1 $1\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) BULK\n" + "match_pins $0 $0\n" + "match_pins IN IN\n" + "match_pins $2 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "net_mismatch $3 $I1\n" + "match_nets $I8 $I8\n" + "net_mismatch $6 BULK\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "subcircuit_mismatch $2 $2\n" + "end_circuit INV2PAIR INV2PAIR NOMATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, false); +} + +TEST(24_NodesRemovedButConnectedInOther) +{ + const char *nls1 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 ($2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC);\n" + " subcircuit INV2PAIR $2 ($2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I21);\n" + " subcircuit INV2PAIR $3 ($2=$I23,$3=VDD,$4=VSS,$5=$I21,$6=$I5);\n" + " subcircuit INV2PAIR $4 ($2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6);\n" + " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" + "end;\n" + "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" + " subcircuit INV2 $1 (IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" + " subcircuit INV2 $2 (IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" + "end;\n" + "circuit INV2 (IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + const char *nls2 = + "circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS);\n" + " subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD);\n" + "end;\n" + // rewired here: BULK->VSS (pin $4), $1->$I3/$I4 (both rewired pins are deleted in the first netlist) + // This proves that we can basically do everything with the dropped pins. + "circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1);\n" + " subcircuit INV2 $1 ($1=$I3,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=$I5);\n" + " subcircuit INV2 $2 ($1=$I4,IN=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=$I5);\n" + "end;\n" + "circuit INV2 ($1=$1,IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=BULK);\n" + " device PMOS $1 (S=$3,G=IN,D=VDD) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS $3 (S=$3,G=IN,D=VSS) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=VSS,G=$3,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + std::string txt = logger.text (); + + EXPECT_EQ (txt, + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_nets (null) $1\n" + "match_nets (null) BULK\n" + "match_pins IN IN\n" + "match_pins $1 $2\n" + "match_pins OUT OUT\n" + "match_pins VSS VSS\n" + "match_pins VDD VDD\n" + "match_pins (null) $0\n" + "match_pins (null) BULK\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit INV2 INV2 MATCH\n" + "begin_circuit INV2PAIR INV2PAIR\n" + "match_nets $I2 $I2\n" + "match_nets $I5 $I6\n" + "match_nets $I4 $I5\n" + "match_nets $I6 $I4\n" + "match_nets $I3 $I3\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_nets (null) BULK\n" + "match_nets (null) $I1\n" + "match_pins $0 $1\n" + "match_pins $1 $2\n" + "match_pins $2 $3\n" + "match_pins $3 $4\n" + "match_pins $4 $5\n" + "match_pins (null) BULK\n" + "match_pins (null) $6\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets $I7 $I7\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I21 $I13\n" + "match_nets FB FB\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets $I22 $I22\n" + "match_nets $I23 $I23\n" + "match_nets $I24 $I24\n" + "match_nets $I25 $I25\n" + "match_pins FB FB\n" + "match_pins OSC OSC\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $4 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + EXPECT_EQ (good, true); +} diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 06e1eea1b..c6bc770cf 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1404,7 +1404,7 @@ TEST(22_BlankCircuit) nl2.purge (); EXPECT_EQ (nl2.to_string (), - "circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n" + "circuit RINGO (OSC=OSC,VSS=VSS,VDD=VDD);\n" " subcircuit INV2 INV2_SC1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n" " subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n" "end;\n" From ed00503d410e3db4918bc74f757da70e696de77e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Nov 2019 23:36:52 +0100 Subject: [PATCH 05/10] Fixed Spice reader: must not use Netlist::purge_nets to remove dummy nets. Updated golden test data. --- src/db/db/dbCircuit.cc | 46 ++++++++++++++++++++---------- src/db/db/dbCircuit.h | 12 +++++++- src/db/db/dbNetlistSpiceReader.cc | 26 +++++++++++++++-- src/db/db/gsiDeclDbNetlist.cc | 12 ++++++-- testdata/algo/lvs_test2_au.lvsdb.1 | 27 ++++++------------ 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 735f6116b..04c456a2a 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -575,7 +575,17 @@ void Circuit::connect_pin (size_t pin_id, Net *net) } } +void Circuit::purge_nets_keep_pins () +{ + do_purge_nets (true); +} + void Circuit::purge_nets () +{ + do_purge_nets (false); +} + +void Circuit::do_purge_nets (bool keep_pins) { std::vector nets_to_be_purged; for (net_iterator n = begin_nets (); n != end_nets (); ++n) { @@ -587,29 +597,35 @@ void Circuit::purge_nets () std::set pins_to_delete; for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { - for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) { - pins_to_delete.insert (p->pin_id ()); + if (! keep_pins) { + for (db::Net::pin_iterator p = (*n)->begin_pins (); p != (*n)->end_pins (); ++p) { + pins_to_delete.insert (p->pin_id ()); + } } delete *n; } - // remove the pin references of the pins we're going to delete - for (refs_iterator r = begin_refs (); r != end_refs (); ++r) { - db::SubCircuit *subcircuit = r.operator-> (); - for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { - db::Net *net = subcircuit->net_for_pin (*p); - for (db::Net::subcircuit_pin_iterator sp = net->begin_subcircuit_pins (); sp != net->end_subcircuit_pins (); ++sp) { - if (sp->pin_id () == *p && sp->subcircuit () == subcircuit) { - net->erase_subcircuit_pin (sp); - break; + if (! pins_to_delete.empty ()) { + + // remove the pin references of the pins we're going to delete + for (refs_iterator r = begin_refs (); r != end_refs (); ++r) { + db::SubCircuit *subcircuit = r.operator-> (); + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + db::Net *net = subcircuit->net_for_pin (*p); + for (db::Net::subcircuit_pin_iterator sp = net->begin_subcircuit_pins (); sp != net->end_subcircuit_pins (); ++sp) { + if (sp->pin_id () == *p && sp->subcircuit () == subcircuit) { + net->erase_subcircuit_pin (sp); + break; + } } } } - } - // and actually remove those pins - for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { - remove_pin (*p); + // and actually remove those pins + for (std::set::const_iterator p = pins_to_delete.begin (); p != pins_to_delete.end (); ++p) { + remove_pin (*p); + } + } } diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h index 5fa298ea0..199aa8a8f 100644 --- a/src/db/db/dbCircuit.h +++ b/src/db/db/dbCircuit.h @@ -713,10 +713,19 @@ public: /** * @brief Purge unused nets * - * This method will purge all nets which return "floating". + * This method will purge all nets which return "is_passive". + * Pins on these nets will also be removed. */ void purge_nets (); + /** + * @brief Purge unused nets but + * + * This method will purge all nets which return "is_passive". + * Pins on these nets will be kept but their net will be 0. + */ + void purge_nets_keep_pins (); + /** * @brief Combine devices * @@ -786,6 +795,7 @@ private: void set_netlist (Netlist *netlist); bool combine_parallel_devices (const db::DeviceClass &cls); bool combine_serial_devices (const db::DeviceClass &cls); + void do_purge_nets (bool keep_pins); void devices_changed (); void subcircuits_changed (); diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 9234570c7..855b39546 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -282,15 +282,37 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) } } +/** + * @brief Removes dummy nets which are just there to define a pin for a subcircuit + */ +static void +remove_dummy_nets (db::Circuit &circuit) +{ + std::vector nets_to_be_purged; + for (db::Circuit::net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) { + if (n->subcircuit_pin_count () == 1 && (n->terminal_count () + n->pin_count ()) == 0) { + nets_to_be_purged.push_back (n.operator-> ()); + } + } + + for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { + delete *n; + } +} + void NetlistSpiceReader::finish () { while (! m_streams.empty ()) { pop_stream (); } - // purge nets with single connections (this way unconnected pins can be realized) if (mp_netlist) { - mp_netlist->purge_nets (); + // purge nets with single connections (this way unconnected pins can be realized) + // NOTE: we don't use Netlist::purge_nets as this method has too many side effects + db::NetlistLocker locker (mp_netlist); + for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) { + remove_dummy_nets (*c); + } } mp_stream.reset (0); diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index f6dd51ce8..59c5fa5e7 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1316,8 +1316,16 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", ) + gsi::method ("purge_nets", &db::Circuit::purge_nets, "@brief Purges floating nets.\n" - "Floating nets can be created as effect of reconnections of devices or pins. " - "This method will eliminate all nets that make less than two connections." + "Floating nets are nets with no device or subcircuit attached to. Such floating " + "nets are removed in this step. If these nets are connected outward to a circuit pin, this " + "circuit pin is also removed." + ) + + gsi::method ("purge_nets_keep_pins", &db::Circuit::purge_nets_keep_pins, + "@brief Purges floating nets but keep pins.\n" + "This method will remove floating nets like \\purge_nets, but if these nets are attached " + "to a pin, the pin will be left disconnected from any net.\n" + "\n" + "This method has been introduced in version 0.26.2.\n" ), "@brief Circuits are the basic building blocks of the netlist\n" "A circuit has pins by which it can connect to the outside. Pins are " diff --git a/testdata/algo/lvs_test2_au.lvsdb.1 b/testdata/algo/lvs_test2_au.lvsdb.1 index 40eb31bb7..eb5e0dbce 100644 --- a/testdata/algo/lvs_test2_au.lvsdb.1 +++ b/testdata/algo/lvs_test2_au.lvsdb.1 @@ -951,11 +951,8 @@ reference( net(4 name('4')) net(5 name('6')) net(6 name('5')) - net(7 name('101')) - net(8 name('8')) - net(9 name('102')) - net(10 name('7')) - net(11 name('103')) + net(7 name('8')) + net(8 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) @@ -986,26 +983,23 @@ reference( pin(0 4) pin(1 3) pin(2 4) - pin(3 7) pin(4 6) - pin(5 8) + pin(5 7) pin(6 3) ) circuit(4 INV2PAIR name($4) pin(0 4) pin(1 3) pin(2 4) - pin(3 9) - pin(4 8) - pin(5 10) + pin(4 7) + pin(5 8) pin(6 3) ) circuit(5 INV2PAIR name($5) pin(0 4) pin(1 3) pin(2 4) - pin(3 11) - pin(4 10) + pin(4 8) pin(5 5) pin(6 3) ) @@ -1090,11 +1084,8 @@ xref( ) circuit(RINGO RINGO nomatch xref( - net(() 7 mismatch) - net(() 9 mismatch) - net(() 11 mismatch) net(() 6 mismatch) - net(() 8 mismatch) + net(() 7 mismatch) net(5 () mismatch) net(6 () mismatch) net(7 () mismatch) @@ -1102,7 +1093,7 @@ xref( net(11 () mismatch) net(12 () mismatch) net(10 1 mismatch) - net(8 10 mismatch) + net(8 8 mismatch) net(1 5 mismatch) net(2 2 match) net(3 3 match) @@ -1120,7 +1111,7 @@ xref( circuit(3 () mismatch) circuit(4 () mismatch) circuit(5 () mismatch) - circuit(1 1 mismatch) + circuit(1 1 match) ) ) ) From 1a92bae3a80033b498f554092694481062f60fe3 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Nov 2019 23:38:38 +0100 Subject: [PATCH 06/10] Another update of golden data. --- testdata/algo/lvs_test2b_au.lvsdb.1 | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/testdata/algo/lvs_test2b_au.lvsdb.1 b/testdata/algo/lvs_test2b_au.lvsdb.1 index 2b3360370..078bd5afc 100644 --- a/testdata/algo/lvs_test2b_au.lvsdb.1 +++ b/testdata/algo/lvs_test2b_au.lvsdb.1 @@ -951,11 +951,8 @@ reference( net(4 name('4')) net(5 name('6')) net(6 name('5')) - net(7 name('101')) - net(8 name('8')) - net(9 name('102')) - net(10 name('7')) - net(11 name('103')) + net(7 name('8')) + net(8 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) @@ -986,26 +983,23 @@ reference( pin(0 4) pin(1 3) pin(2 4) - pin(3 7) pin(4 6) - pin(5 8) + pin(5 7) pin(6 3) ) circuit(4 INV2PAIR name($4) pin(0 4) pin(1 3) pin(2 4) - pin(3 9) - pin(4 8) - pin(5 10) + pin(4 7) + pin(5 8) pin(6 3) ) circuit(5 INV2PAIR name($5) pin(0 4) pin(1 3) pin(2 4) - pin(3 11) - pin(4 10) + pin(4 8) pin(5 5) pin(6 3) ) @@ -1090,11 +1084,8 @@ xref( ) circuit(RINGO RINGO nomatch xref( - net(() 7 mismatch) - net(() 9 mismatch) - net(() 11 mismatch) net(() 6 mismatch) - net(() 8 mismatch) + net(() 7 mismatch) net(5 () mismatch) net(6 () mismatch) net(7 () mismatch) @@ -1102,7 +1093,7 @@ xref( net(11 () mismatch) net(12 () mismatch) net(10 1 mismatch) - net(8 10 mismatch) + net(8 8 mismatch) net(1 5 mismatch) net(2 2 match) net(3 3 match) @@ -1120,7 +1111,7 @@ xref( circuit(3 () mismatch) circuit(4 () mismatch) circuit(5 () mismatch) - circuit(1 1 mismatch) + circuit(1 1 match) ) ) ) From 64bb01d80d05392a35b3ceb4427e50c395946c4c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 24 Nov 2019 00:23:19 +0100 Subject: [PATCH 07/10] Dropped attempt to remove dummy nodes from spice reader netlist as this wasn't effective anyway. --- src/db/db/dbNetlistSpiceReader.cc | 27 --------------------------- testdata/algo/lvs_test2_au.lvsdb.1 | 25 +++++++++++++++++-------- testdata/algo/lvs_test2b_au.lvsdb.1 | 25 +++++++++++++++++-------- 3 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 855b39546..c54a7e352 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -282,39 +282,12 @@ void NetlistSpiceReader::read (tl::InputStream &stream, db::Netlist &netlist) } } -/** - * @brief Removes dummy nets which are just there to define a pin for a subcircuit - */ -static void -remove_dummy_nets (db::Circuit &circuit) -{ - std::vector nets_to_be_purged; - for (db::Circuit::net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) { - if (n->subcircuit_pin_count () == 1 && (n->terminal_count () + n->pin_count ()) == 0) { - nets_to_be_purged.push_back (n.operator-> ()); - } - } - - for (std::vector::const_iterator n = nets_to_be_purged.begin (); n != nets_to_be_purged.end (); ++n) { - delete *n; - } -} - void NetlistSpiceReader::finish () { while (! m_streams.empty ()) { pop_stream (); } - if (mp_netlist) { - // purge nets with single connections (this way unconnected pins can be realized) - // NOTE: we don't use Netlist::purge_nets as this method has too many side effects - db::NetlistLocker locker (mp_netlist); - for (db::Netlist::bottom_up_circuit_iterator c = mp_netlist->begin_bottom_up (); c != mp_netlist->end_bottom_up (); ++c) { - remove_dummy_nets (*c); - } - } - mp_stream.reset (0); mp_netlist = 0; mp_circuit = 0; diff --git a/testdata/algo/lvs_test2_au.lvsdb.1 b/testdata/algo/lvs_test2_au.lvsdb.1 index eb5e0dbce..b78d22e71 100644 --- a/testdata/algo/lvs_test2_au.lvsdb.1 +++ b/testdata/algo/lvs_test2_au.lvsdb.1 @@ -951,8 +951,11 @@ reference( net(4 name('4')) net(5 name('6')) net(6 name('5')) - net(7 name('8')) - net(8 name('7')) + net(7 name('101')) + net(8 name('8')) + net(9 name('102')) + net(10 name('7')) + net(11 name('103')) # Outgoing pins and their connections to nets pin(1 name('1')) @@ -983,23 +986,26 @@ reference( pin(0 4) pin(1 3) pin(2 4) + pin(3 7) pin(4 6) - pin(5 7) + pin(5 8) pin(6 3) ) circuit(4 INV2PAIR name($4) pin(0 4) pin(1 3) pin(2 4) - pin(4 7) - pin(5 8) + pin(3 9) + pin(4 8) + pin(5 10) pin(6 3) ) circuit(5 INV2PAIR name($5) pin(0 4) pin(1 3) pin(2 4) - pin(4 8) + pin(3 11) + pin(4 10) pin(5 5) pin(6 3) ) @@ -1084,8 +1090,11 @@ xref( ) circuit(RINGO RINGO nomatch xref( - net(() 6 mismatch) net(() 7 mismatch) + net(() 9 mismatch) + net(() 11 mismatch) + net(() 6 mismatch) + net(() 8 mismatch) net(5 () mismatch) net(6 () mismatch) net(7 () mismatch) @@ -1093,7 +1102,7 @@ xref( net(11 () mismatch) net(12 () mismatch) net(10 1 mismatch) - net(8 8 mismatch) + net(8 10 mismatch) net(1 5 mismatch) net(2 2 match) net(3 3 match) diff --git a/testdata/algo/lvs_test2b_au.lvsdb.1 b/testdata/algo/lvs_test2b_au.lvsdb.1 index 078bd5afc..74daf3f76 100644 --- a/testdata/algo/lvs_test2b_au.lvsdb.1 +++ b/testdata/algo/lvs_test2b_au.lvsdb.1 @@ -951,8 +951,11 @@ reference( net(4 name('4')) net(5 name('6')) net(6 name('5')) - net(7 name('8')) - net(8 name('7')) + net(7 name('101')) + net(8 name('8')) + net(9 name('102')) + net(10 name('7')) + net(11 name('103')) # Outgoing pins and their connections to nets pin(1 name('1')) @@ -983,23 +986,26 @@ reference( pin(0 4) pin(1 3) pin(2 4) + pin(3 7) pin(4 6) - pin(5 7) + pin(5 8) pin(6 3) ) circuit(4 INV2PAIR name($4) pin(0 4) pin(1 3) pin(2 4) - pin(4 7) - pin(5 8) + pin(3 9) + pin(4 8) + pin(5 10) pin(6 3) ) circuit(5 INV2PAIR name($5) pin(0 4) pin(1 3) pin(2 4) - pin(4 8) + pin(3 11) + pin(4 10) pin(5 5) pin(6 3) ) @@ -1084,8 +1090,11 @@ xref( ) circuit(RINGO RINGO nomatch xref( - net(() 6 mismatch) net(() 7 mismatch) + net(() 9 mismatch) + net(() 11 mismatch) + net(() 6 mismatch) + net(() 8 mismatch) net(5 () mismatch) net(6 () mismatch) net(7 () mismatch) @@ -1093,7 +1102,7 @@ xref( net(11 () mismatch) net(12 () mismatch) net(10 1 mismatch) - net(8 8 mismatch) + net(8 10 mismatch) net(1 5 mismatch) net(2 2 match) net(3 3 match) From afacf7c0b5792230a0b9b3d0ee2ae8fde95c4e92 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 24 Nov 2019 01:28:07 +0100 Subject: [PATCH 08/10] WIP: fixed a segfault in the netlist browser. --- src/db/db/dbNetlistCrossReference.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/db/db/dbNetlistCrossReference.cc b/src/db/db/dbNetlistCrossReference.cc index 344969908..4ef99f9bf 100644 --- a/src/db/db/dbNetlistCrossReference.cc +++ b/src/db/db/dbNetlistCrossReference.cc @@ -508,8 +508,7 @@ NetlistCrossReference::build_pin_refs (const std::pair::const_iterator ipb = m_other_pin.find (pa); if (ipb != m_other_pin.end () && ipb->second) { - const db::Pin *pb = ipb->second; - std::map::iterator b = p2r_b.find (pb); + std::map::iterator b = p2r_b.find (ipb->second); if (b != p2r_b.end ()) { prb = b->second; // remove the entry so we won't find it again @@ -558,7 +557,7 @@ NetlistCrossReference::build_subcircuit_pin_refs (const std::paircircuit_ref ()->pin_by_id (a->first.second); std::map::const_iterator ipb = m_other_pin.find (pa); - if (ipb != m_other_pin.end ()) { + if (ipb != m_other_pin.end () && ipb->second) { std::map, const db::NetSubcircuitPinRef *>::iterator b = s2t_b.find (std::make_pair (sb, ipb->second->id ())); if (b != s2t_b.end ()) { From 0f1dc1d1913b7f29a8b3a543a4ab2c5c2e72ad43 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 24 Nov 2019 16:40:45 +0100 Subject: [PATCH 09/10] Refine pin mismatch handling so that only 'not used' nets will make a pin match against null. --- src/db/db/dbNetlistCompare.cc | 5 ++-- src/db/unit_tests/dbNetlistCompareTests.cc | 28 +++------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 55f6091de..5dad8cd22 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -2997,10 +2997,11 @@ NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit const db::NetGraph *graph = pin1 ? &g1 : &g2; const db::Net *net = c->net_for_pin (pin->id ()); - // Nets which are paired with "null" trigger this condition: + // Nets which are paired with "null" are "safely to be ignored" and + // pin matching against "null" is valid. if (net) { const db::NetGraphNode &n = graph->node (graph->node_index_for_net (net)); - if (n.has_other ()) { + if (n.has_other () && n.other_net_index () == 0) { if (mp_logger) { mp_logger->match_pins (pin1, pin2); } diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 2a4ae00d5..2e32cd4a2 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -3573,34 +3573,12 @@ TEST(23_NodesRemovedWithError) "match_pins $2 $3\n" "match_pins $3 $4\n" "match_pins $4 $5\n" - "match_pins (null) BULK\n" - "match_pins (null) $6\n" + "pin_mismatch (null) BULK\n" + "pin_mismatch (null) $6\n" "match_subcircuits $1 $1\n" "subcircuit_mismatch $2 $2\n" "end_circuit INV2PAIR INV2PAIR NOMATCH\n" - "begin_circuit RINGO RINGO\n" - "match_nets OSC OSC\n" - "match_nets $I7 $I7\n" - "match_nets $I6 $I6\n" - "match_nets $I5 $I5\n" - "match_nets $I21 $I13\n" - "match_nets FB FB\n" - "match_nets VSS VSS\n" - "match_nets VDD VDD\n" - "match_nets $I22 $I22\n" - "match_nets $I23 $I23\n" - "match_nets $I24 $I24\n" - "match_nets $I25 $I25\n" - "match_pins FB FB\n" - "match_pins OSC OSC\n" - "match_pins VDD VDD\n" - "match_pins VSS VSS\n" - "match_subcircuits $1 $1\n" - "match_subcircuits $2 $2\n" - "match_subcircuits $3 $3\n" - "match_subcircuits $4 $4\n" - "match_subcircuits $5 $5\n" - "end_circuit RINGO RINGO MATCH" + "circuit_skipped RINGO RINGO" ); EXPECT_EQ (good, false); } From a8cace399e25ec03b1332e25a57a79f2f4724a5e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 24 Nov 2019 18:25:56 +0100 Subject: [PATCH 10/10] Added some private tests to LVS tests for better coverage. --- src/lvs/unit_tests/lvsTests.cc | 68 +++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/src/lvs/unit_tests/lvsTests.cc b/src/lvs/unit_tests/lvsTests.cc index d4fc23a89..02d6f5280 100644 --- a/src/lvs/unit_tests/lvsTests.cc +++ b/src/lvs/unit_tests/lvsTests.cc @@ -30,22 +30,14 @@ #include "lymMacro.h" #include "tlFileUtils.h" -void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &suffix, const std::string &layout) +void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &au_netlist, const std::string &layout, bool priv = false) { - std::string rs = tl::testsrc (); - rs += "/testdata/lvs/" + lvs_rs; + std::string testsrc = priv ? tl::testsrc_private () : tl::testsrc (); + testsrc = tl::combine_path (tl::combine_path (testsrc, "testdata"), "lvs"); - std::string src = tl::testsrc (); - src += "/testdata/lvs/" + layout; - - std::string au_lvsdb = tl::testsrc (); - au_lvsdb += "/testdata/lvs/" + suffix + ".lvsdb.gz"; - - std::string au_cir = tl::testsrc (); - au_cir += "/testdata/lvs/" + suffix + ".cir.gz"; - - std::string au_l2n = tl::testsrc (); - au_l2n += "/testdata/lvs/" + suffix + ".l2n.gz"; + std::string rs = tl::combine_path (testsrc, lvs_rs); + std::string ly = tl::combine_path (testsrc, layout); + std::string au_cir = tl::combine_path (testsrc, au_netlist); std::string output_lvsdb = _this->tmp_file ("tmp.lvsdb"); std::string output_cir = _this->tmp_file ("tmp.cir"); @@ -59,7 +51,7 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string "$lvs_test_target_lvsdb = '%s'\n" "$lvs_test_target_cir = '%s'\n" "$lvs_test_target_l2n = '%s'\n" - , src, output_lvsdb, output_cir, output_l2n) + , ly, output_lvsdb, output_cir, output_l2n) ); config.set_interpreter (lym::Macro::Ruby); EXPECT_EQ (config.run (), 0); @@ -101,11 +93,53 @@ void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string TEST(1_full) { test_is_long_runner (); - run_test (_this, "vexriscv.lvs", "vexriscv", "vexriscv.oas.gz"); + run_test (_this, "vexriscv.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz"); } TEST(2_fullWithAlign) { test_is_long_runner (); - run_test (_this, "vexriscv_align.lvs", "vexriscv", "vexriscv.oas.gz"); + run_test (_this, "vexriscv_align.lvs", "vexriscv.cir.gz", "vexriscv.oas.gz"); +} + +TEST(10_private) +{ + // test_is_long_runner (); + run_test (_this, "test_10.lvs", "test_10.cir.gz", "test_10.gds.gz", true); +} + +TEST(11_private) +{ + // test_is_long_runner (); + run_test (_this, "test_11.lvs", "test_11.cir.gz", "test_11.gds.gz", true); +} + +TEST(12_private) +{ + // test_is_long_runner (); + run_test (_this, "test_12.lvs", "test_12.cir.gz", "test_12.gds.gz", true); +} + +TEST(13_private) +{ + // test_is_long_runner (); + run_test (_this, "test_13.lvs", "test_13.cir.gz", "test_13.gds.gz", true); +} + +TEST(14_private) +{ + test_is_long_runner (); + run_test (_this, "test_14.lvs", "test_14.cir.gz", "test_14.gds.gz", true); +} + +TEST(15_private) +{ + // test_is_long_runner (); + run_test (_this, "test_15.lvs", "test_15.cir.gz", "test_15.gds.gz", true); +} + +TEST(16_private) +{ + // test_is_long_runner (); + run_test (_this, "test_16.lvs", "test_16.cir.gz", "test_16.gds.gz", true); }