From 506cfc1c6fd1600308d208a65861c4df40b44328 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 30 Sep 2019 20:58:55 +0200 Subject: [PATCH 1/5] WIP: attempt to retain nets which don't have active elements but pins. This is supposed to simplify debugging in case of fake pins. When removing those nets, the pin is very difficult to find. --- src/db/db/dbCircuit.cc | 2 +- src/db/db/dbNetlist.cc | 10 +++++++++- src/db/unit_tests/dbLayoutToNetlistTests.cc | 2 +- src/db/unit_tests/dbNetlistTests.cc | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index f608a9f77..35cd1ca6e 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -545,7 +545,7 @@ 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_floating () && n->pin_count () == 0) { nets_to_be_purged.push_back (n.operator-> ()); } } diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 429ea8b7d..56d4befdd 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -485,8 +485,16 @@ void Netlist::purge () Circuit *circuit = c.operator-> (); + // purge floating, disconnected nets circuit->purge_nets (); - if (circuit->begin_nets () == circuit->end_nets () && ! circuit->dont_purge ()) { + + // if only floating net - connected to a pin - are left, consider this circuit for purging + bool purge_candidate = ! circuit->dont_purge (); + for (db::Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets () && purge_candidate; ++n) { + purge_candidate = n->is_floating (); + } + + if (purge_candidate) { // No nets left: delete the subcircuits that refer to us and finally delete the circuit while (circuit->begin_refs () != circuit->end_refs ()) { diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index c4b7ca373..011322222 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -1096,7 +1096,7 @@ TEST(3_GlobalNetConnections) " 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=(null),IN=IN,$3=$3,OUT=OUT,VSS=VSS,VDD=VDD,BULK=(null));\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" diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 9de025763..38cb3d709 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -1380,7 +1380,7 @@ TEST(22_BlankCircuit) nl2.purge (); EXPECT_EQ (nl2.to_string (), - "circuit RINGO (IN=(null),OSC=OSC,VSS=VSS,VDD=VDD);\n" + "circuit RINGO (IN=IN,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 bdf5e3c12422b6d8ed4b59efedd1ab14d3424819 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 30 Sep 2019 21:58:13 +0200 Subject: [PATCH 2/5] WIP: fake pin debug issue with LVS Fake pins: pins that happen because something connects to a cell at an unexpected position. Such a pin is difficult to find. The solution is to keep those nets and nur purge them so these nets can be identified in the layout. Here: is_floating? will be true only if there are no pins. Hence nets with pins are not removed. is_passive is introduced for nets - passive nets are such that don't have elements, but a pin. Circuits are purged if they only have passive nets. --- src/db/db/dbCircuit.cc | 2 +- src/db/db/dbDeviceClass.cc | 4 +- src/db/db/dbNet.h | 10 +++- src/db/db/dbNetlist.cc | 4 +- src/db/db/dbNetlistCompare.cc | 4 +- src/db/db/gsiDeclDbNetlist.cc | 9 +++- src/db/unit_tests/dbNetlistTests.cc | 7 ++- testdata/algo/lvs_test2_au.lvsdb.1 | 75 ++++++++++++++++++++--------- testdata/algo/lvs_test2b_au.lvsdb.1 | 75 ++++++++++++++++++++--------- 9 files changed, 136 insertions(+), 54 deletions(-) diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc index 35cd1ca6e..f608a9f77 100644 --- a/src/db/db/dbCircuit.cc +++ b/src/db/db/dbCircuit.cc @@ -545,7 +545,7 @@ void Circuit::purge_nets () { std::vector nets_to_be_purged; for (net_iterator n = begin_nets (); n != end_nets (); ++n) { - if (n->is_floating () && n->pin_count () == 0) { + if (n->is_floating ()) { nets_to_be_purged.push_back (n.operator-> ()); } } diff --git a/src/db/db/dbDeviceClass.cc b/src/db/db/dbDeviceClass.cc index d16daf212..7ae697472 100644 --- a/src/db/db/dbDeviceClass.cc +++ b/src/db/db/dbDeviceClass.cc @@ -136,13 +136,13 @@ bool AllDeviceParametersAreEqual::equal (const db::Device &a, const db::Device & // DeviceClass class implementation DeviceClass::DeviceClass () - : mp_netlist (0), m_strict (false) + : m_strict (false), mp_netlist (0) { // .. nothing yet .. } DeviceClass::DeviceClass (const DeviceClass &other) - : gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), mp_netlist (0), m_strict (false) + : gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0) { operator= (other); } diff --git a/src/db/db/dbNet.h b/src/db/db/dbNet.h index dd476652a..25e19324f 100644 --- a/src/db/db/dbNet.h +++ b/src/db/db/dbNet.h @@ -603,9 +603,17 @@ public: } /** - * @brief Returns true, if the net is floating (there is no active element on the net) + * @brief Returns true, if the net is floating (there is no device, no subcircuit and no pin) */ bool is_floating () const + { + return (m_subcircuit_pins.size () + m_terminals.size () + m_pins.size ()) < 1; + } + + /** + * @brief Returns true, if the net is passive (there is no active element on the net) + */ + bool is_passive () const { return (m_subcircuit_pins.size () + m_terminals.size ()) < 1; } diff --git a/src/db/db/dbNetlist.cc b/src/db/db/dbNetlist.cc index 56d4befdd..98e8a089e 100644 --- a/src/db/db/dbNetlist.cc +++ b/src/db/db/dbNetlist.cc @@ -488,10 +488,10 @@ void Netlist::purge () // purge floating, disconnected nets circuit->purge_nets (); - // if only floating net - connected to a pin - are left, consider this circuit for purging + // if only passive nets are left, consider this circuit for purging bool purge_candidate = ! circuit->dont_purge (); for (db::Circuit::net_iterator n = circuit->begin_nets (); n != circuit->end_nets () && purge_candidate; ++n) { - purge_candidate = n->is_floating (); + purge_candidate = n->is_passive (); } if (purge_candidate) { diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 1124dae2d..7eedbe941 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -320,7 +320,7 @@ public: } else if (! ca) { same (cb, ca); } else if (! cb) { - // makeing a object same as null will make this device being ignored + // making a object same as null will make this device being ignored m_cat_by_ptr [ca] = 0; return; } @@ -2428,7 +2428,7 @@ std::vector collect_pins_with_empty_nets (const db::Circuit *c, CircuitP for (db::Circuit::const_pin_iterator p = c->begin_pins (); p != c->end_pins (); ++p) { const db::Net *net = c->net_for_pin (p->id ()); - if ((! net || net->is_floating ()) && ! circuit_pin_mapper->is_mapped (c, p->id ())) { + if ((! net || net->is_passive ()) && ! circuit_pin_mapper->is_mapped (c, p->id ())) { pins.push_back (p->id ()); } } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index 9e59ea3c2..899925c45 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -567,7 +567,14 @@ Class decl_dbNet ("db", "Net", ) + gsi::method ("is_floating?", &db::Net::is_floating, "@brief Returns true, if the net is floating.\n" - "Floating nets are those who don't have any or only a single connection (pin_count + terminal_count < 2)." + "Floating nets are those which don't have any device or subcircuit on it and are not connected through a pin." + ) + + gsi::method ("is_passive?", &db::Net::is_passive, + "@brief Returns true, if the net is passive.\n" + "Passive nets don't have devices or subcircuits on it. They can be exposed through a pin.\n" + "\\is_floating? implies \\is_passive?.\n" + "\n" + "This method has been introduced in version 0.26.1.\n" ) + gsi::method ("is_internal?", &db::Net::is_internal, "@brief Returns true, if the net is an internal net.\n" diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 38cb3d709..1dc2f196f 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -752,6 +752,7 @@ TEST(6_Net) EXPECT_EQ (n.pin_count (), size_t (0)); EXPECT_EQ (n.terminal_count (), size_t (0)); EXPECT_EQ (n.is_floating (), true); + EXPECT_EQ (n.is_passive (), true); EXPECT_EQ (n.is_internal (), false); } @@ -781,6 +782,7 @@ TEST(7_NetTerminalsEditing) EXPECT_EQ (n1->terminal_count (), size_t (1)); EXPECT_EQ (n1->pin_count (), size_t (0)); EXPECT_EQ (n1->is_floating (), false); + EXPECT_EQ (n1->is_passive (), false); EXPECT_EQ (n1->is_internal (), false); d2->connect_terminal (1, n1); @@ -789,6 +791,7 @@ TEST(7_NetTerminalsEditing) EXPECT_EQ (n1->terminal_count (), size_t (2)); EXPECT_EQ (n1->pin_count (), size_t (0)); EXPECT_EQ (n1->is_floating (), false); + EXPECT_EQ (n1->is_passive (), false); EXPECT_EQ (n1->is_internal (), true); EXPECT_EQ (d1->net_for_terminal (0), n1); @@ -871,7 +874,8 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (n1->terminal_count (), size_t (0)); EXPECT_EQ (n1->pin_count (), size_t (1)); - EXPECT_EQ (n1->is_floating (), true); + EXPECT_EQ (n1->is_floating (), false); + EXPECT_EQ (n1->is_passive (), true); EXPECT_EQ (n1->is_internal (), false); EXPECT_NE (n1->pin_count (), size_t (0)); @@ -886,6 +890,7 @@ TEST(8_NetSubCircuitsEditing) EXPECT_EQ (n1->pin_count (), size_t (1)); EXPECT_EQ (n1->subcircuit_pin_count (), size_t (1)); EXPECT_EQ (n1->is_floating (), false); + EXPECT_EQ (n1->is_passive (), false); EXPECT_EQ (n1->is_internal (), false); sc2->connect_pin (1, n1); diff --git a/testdata/algo/lvs_test2_au.lvsdb.1 b/testdata/algo/lvs_test2_au.lvsdb.1 index 5526f557a..23a4ccef6 100644 --- a/testdata/algo/lvs_test2_au.lvsdb.1 +++ b/testdata/algo/lvs_test2_au.lvsdb.1 @@ -918,23 +918,24 @@ reference( net(2 name('2')) net(3 name('3')) net(4 name('4')) - net(5 name('6')) - net(6 name('7')) + net(5 name('5')) + net(6 name('6')) + net(7 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) pin(2 name('2')) pin(3 name('3')) pin(4 name('4')) - pin(name('5')) - pin(5 name('6')) - pin(6 name('7')) + pin(5 name('5')) + pin(6 name('6')) + pin(7 name('7')) # Subcircuits and their connections circuit(1 INV2 name($2) - pin(0 6) + pin(0 7) pin(1 4) - pin(2 5) + pin(2 6) pin(3 3) pin(4 2) pin(5 1) @@ -1017,23 +1018,24 @@ reference( net(2 name('2')) net(3 name('3')) net(4 name('4')) - net(5 name('6')) - net(6 name('7')) + net(5 name('5')) + net(6 name('6')) + net(7 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) pin(2 name('2')) pin(3 name('3')) pin(4 name('4')) - pin(name('5')) - pin(5 name('6')) - pin(6 name('7')) + pin(5 name('5')) + pin(6 name('6')) + pin(7 name('7')) # Subcircuits and their connections circuit(1 INV2 name($2) - pin(0 6) + pin(0 7) pin(1 4) - pin(2 5) + pin(2 6) pin(3 3) pin(4 2) pin(5 1) @@ -1068,28 +1070,57 @@ xref( ) circuit(INV2PAIR INV2PAIR nomatch xref( - net(4 () mismatch) net(2 2 mismatch) net(3 3 mismatch) net(5 4 match) - net(6 5 match) - net(7 6 mismatch) + net(4 5 mismatch) + net(6 6 match) + net(7 7 mismatch) net(1 1 mismatch) - pin(() 4 mismatch) - pin(3 () mismatch) pin(1 1 match) pin(2 2 match) pin(4 3 match) + pin(3 4 match) pin(5 5 match) pin(6 6 match) pin(0 0 match) - circuit(() 1 mismatch) - circuit(1 () mismatch) circuit(2 () mismatch) + circuit(1 1 mismatch) ) ) - circuit(RINGO RINGO skipped + circuit(RINGO RINGO nomatch xref( + net(() 7 mismatch) + net(() 9 mismatch) + net(() 11 mismatch) + net(() 6 mismatch) + net(() 8 mismatch) + net(5 () mismatch) + net(6 () mismatch) + net(7 () mismatch) + net(9 () mismatch) + net(11 () mismatch) + net(12 () mismatch) + net(10 1 mismatch) + net(8 10 mismatch) + net(1 5 mismatch) + net(2 2 match) + net(3 3 match) + net(4 4 match) + pin(() 0 match) + pin(0 () match) + pin(1 1 match) + pin(2 2 match) + pin(3 3 match) + circuit(() 2 mismatch) + circuit(() 3 mismatch) + circuit(() 4 mismatch) + circuit(() 5 mismatch) + circuit(2 () mismatch) + circuit(3 () mismatch) + circuit(4 () mismatch) + circuit(5 () mismatch) + circuit(1 1 mismatch) ) ) ) diff --git a/testdata/algo/lvs_test2b_au.lvsdb.1 b/testdata/algo/lvs_test2b_au.lvsdb.1 index 612ed7a51..9828a5742 100644 --- a/testdata/algo/lvs_test2b_au.lvsdb.1 +++ b/testdata/algo/lvs_test2b_au.lvsdb.1 @@ -918,23 +918,24 @@ reference( net(2 name('2')) net(3 name('3')) net(4 name('4')) - net(5 name('6')) - net(6 name('7')) + net(5 name('5')) + net(6 name('6')) + net(7 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) pin(2 name('2')) pin(3 name('3')) pin(4 name('4')) - pin(name('5')) - pin(5 name('6')) - pin(6 name('7')) + pin(5 name('5')) + pin(6 name('6')) + pin(7 name('7')) # Subcircuits and their connections circuit(1 INV2 name($2) - pin(0 6) + pin(0 7) pin(1 4) - pin(2 5) + pin(2 6) pin(3 3) pin(4 2) pin(5 1) @@ -1017,23 +1018,24 @@ reference( net(2 name('2')) net(3 name('3')) net(4 name('4')) - net(5 name('6')) - net(6 name('7')) + net(5 name('5')) + net(6 name('6')) + net(7 name('7')) # Outgoing pins and their connections to nets pin(1 name('1')) pin(2 name('2')) pin(3 name('3')) pin(4 name('4')) - pin(name('5')) - pin(5 name('6')) - pin(6 name('7')) + pin(5 name('5')) + pin(6 name('6')) + pin(7 name('7')) # Subcircuits and their connections circuit(1 INV2 name($2) - pin(0 6) + pin(0 7) pin(1 4) - pin(2 5) + pin(2 6) pin(3 3) pin(4 2) pin(5 1) @@ -1068,28 +1070,57 @@ xref( ) circuit(INV2PAIR INV2PAIR nomatch xref( - net(4 () mismatch) net(2 2 mismatch) net(3 3 mismatch) net(5 4 match) - net(6 5 match) - net(7 6 mismatch) + net(4 5 mismatch) + net(6 6 match) + net(7 7 mismatch) net(1 1 mismatch) - pin(() 4 mismatch) - pin(3 () mismatch) pin(1 1 match) pin(2 2 match) pin(4 3 match) + pin(3 4 match) pin(5 5 match) pin(6 6 match) pin(0 0 match) - circuit(() 1 mismatch) - circuit(1 () mismatch) circuit(2 () mismatch) + circuit(1 1 mismatch) ) ) - circuit(RINGO RINGO skipped + circuit(RINGO RINGO nomatch xref( + net(() 7 mismatch) + net(() 9 mismatch) + net(() 11 mismatch) + net(() 6 mismatch) + net(() 8 mismatch) + net(5 () mismatch) + net(6 () mismatch) + net(7 () mismatch) + net(9 () mismatch) + net(11 () mismatch) + net(12 () mismatch) + net(10 1 mismatch) + net(8 10 mismatch) + net(1 5 mismatch) + net(2 2 match) + net(3 3 match) + net(4 4 match) + pin(() 0 match) + pin(0 () match) + pin(1 1 match) + pin(2 2 match) + pin(3 3 match) + circuit(() 2 mismatch) + circuit(() 3 mismatch) + circuit(() 4 mismatch) + circuit(() 5 mismatch) + circuit(2 () mismatch) + circuit(3 () mismatch) + circuit(4 () mismatch) + circuit(5 () mismatch) + circuit(1 1 mismatch) ) ) ) From a3cecb2ebe046e049c70fd4960d21d12002168ea Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 30 Sep 2019 23:08:15 +0200 Subject: [PATCH 3/5] WIP: enable multiple layout versions of one schematic circuit using 'same_circuit' --- src/db/db/dbNetlistCompare.cc | 100 ++- src/lvs/unit_tests/lvsSimpleTests.cc | 6 + testdata/lvs/ringo_layout_var.cir | 102 +++ testdata/lvs/ringo_layout_var.gds | Bin 0 -> 12456 bytes testdata/lvs/ringo_layout_var.lvs | 78 ++ testdata/lvs/ringo_layout_var.lvsdb | 1076 ++++++++++++++++++++++++++ 6 files changed, 1319 insertions(+), 43 deletions(-) create mode 100644 testdata/lvs/ringo_layout_var.cir create mode 100644 testdata/lvs/ringo_layout_var.gds create mode 100644 testdata/lvs/ringo_layout_var.lvs create mode 100644 testdata/lvs/ringo_layout_var.lvsdb diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 7eedbe941..593810056 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -492,10 +492,11 @@ public: if (ca && has_cat_for (ca)) { throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + ca->name ()); } +#if 0 // can pair multiple layout cells with one schematic circuit if (cb && has_cat_for (cb)) { throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + cb->name ()); } - +#endif generic_categorizer::same (ca, cb); } @@ -2274,13 +2275,13 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const bool good = true; - std::map > cat2circuits; + std::map, std::vector > > cat2circuits; std::set verified_circuits_a, verified_circuits_b; for (db::Netlist::const_circuit_iterator i = a->begin_circuits (); i != a->end_circuits (); ++i) { size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ()); if (cat) { - cat2circuits[cat].first = i.operator-> (); + cat2circuits[cat].first.push_back (i.operator-> ()); } else { // skip circuit (but count it as verified) verified_circuits_a.insert (i.operator-> ()); @@ -2290,7 +2291,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const for (db::Netlist::const_circuit_iterator i = b->begin_circuits (); i != b->end_circuits (); ++i) { size_t cat = circuit_categorizer.cat_for_circuit (i.operator-> ()); if (cat) { - cat2circuits[cat].second = i.operator-> (); + cat2circuits[cat].second.push_back (i.operator-> ()); } else { // skip circuit (but count it as verified) verified_circuits_b.insert (i.operator-> ()); @@ -2342,11 +2343,21 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const // check for circuits that don't match - for (std::map >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) { - if (! i->second.first || ! i->second.second) { + for (std::map, std::vector > >::const_iterator i = cat2circuits.begin (); i != cat2circuits.end (); ++i) { + if (i->second.first.empty ()) { good = false; if (mp_logger) { - mp_logger->circuit_mismatch (i->second.first, i->second.second); + for (std::vector::const_iterator j = i->second.second.begin (); j != i->second.second.end (); ++j) { + mp_logger->circuit_mismatch (0, *j); + } + } + } + if (i->second.second.empty ()) { + good = false; + if (mp_logger) { + for (std::vector::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) { + mp_logger->circuit_mismatch (*j, 0); + } } } } @@ -2355,59 +2366,62 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) { - size_t ccat = circuit_categorizer.cat_for_circuit (c.operator-> ()); + const db::Circuit *ca = c.operator-> (); + + size_t ccat = circuit_categorizer.cat_for_circuit (ca); if (! ccat) { continue; } - std::map >::const_iterator i = cat2circuits.find (ccat); + std::map, std::vector > >::const_iterator i = cat2circuits.find (ccat); tl_assert (i != cat2circuits.end ()); + tl_assert (! i->second.first.empty ()); + if (i->second.second.empty ()) { + continue; + } - if (i->second.first && i->second.second) { + // NOTE: there can only be one schematic circuit + tl_assert (i->second.second.size () == size_t (1)); + const db::Circuit *cb = i->second.second.front (); - const db::Circuit *ca = i->second.first; - const db::Circuit *cb = i->second.second; + std::vector > empty; + const std::vector > *net_identity = ∅ + std::map, std::vector > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb)); + if (sn != m_same_nets.end ()) { + net_identity = &sn->second; + } - std::vector > empty; - const std::vector > *net_identity = ∅ - std::map, std::vector > >::const_iterator sn = m_same_nets.find (std::make_pair (ca, cb)); - if (sn != m_same_nets.end ()) { - net_identity = &sn->second; - } - - if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) { + if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) { #if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name (); + tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name (); #endif - if (mp_logger) { - mp_logger->begin_circuit (ca, cb); - } + if (mp_logger) { + mp_logger->begin_circuit (ca, cb); + } - bool pin_mismatch = false; - bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, *net_identity, pin_mismatch, c12_pin_mapping, c22_pin_mapping); - if (! g) { - good = false; - } + bool pin_mismatch = false; + bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, circuit_pin_mapper, *net_identity, pin_mismatch, c12_pin_mapping, c22_pin_mapping); + if (! g) { + good = false; + } - if (! pin_mismatch) { - verified_circuits_a.insert (ca); - verified_circuits_b.insert (cb); - } + if (! pin_mismatch) { + verified_circuits_a.insert (ca); + verified_circuits_b.insert (cb); + } - derive_pin_equivalence (ca, cb, &circuit_pin_mapper); + derive_pin_equivalence (ca, cb, &circuit_pin_mapper); - if (mp_logger) { - mp_logger->end_circuit (ca, cb, g); - } + if (mp_logger) { + mp_logger->end_circuit (ca, cb, g); + } - } else { - - if (mp_logger) { - mp_logger->circuit_skipped (ca, cb); - good = false; - } + } else { + if (mp_logger) { + mp_logger->circuit_skipped (ca, cb); + good = false; } } diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index 2fa9252d2..3df15643e 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -154,3 +154,9 @@ TEST(16_floating) { run_test (_this, "floating", "floating.gds", false, "TOP"); } + +TEST(17_layout_variants) +{ + run_test (_this, "ringo_layout_var", "ringo_layout_var.gds"); +} + diff --git a/testdata/lvs/ringo_layout_var.cir b/testdata/lvs/ringo_layout_var.cir new file mode 100644 index 000000000..93b5336ec --- /dev/null +++ b/testdata/lvs/ringo_layout_var.cir @@ -0,0 +1,102 @@ +* Extracted by KLayout + +* cell RINGO +* pin FB +* pin VDD +* pin OUT +* pin ENABLE +* pin VSS +.SUBCKT RINGO 11 12 13 14 15 +* net 11 FB +* net 12 VDD +* net 13 OUT +* net 14 ENABLE +* net 15 VSS +* cell instance $1 r0 *1 1.8,0 +X$1 12 1 15 12 11 14 15 ND2X1 +* cell instance $2 r0 *1 4.2,0 +X$2 12 2 15 12 1 15 INVX1B +* cell instance $3 r0 *1 6,0 +X$3 12 3 15 12 2 15 INVX1 +* cell instance $4 r0 *1 7.8,0 +X$4 12 4 15 12 3 15 INVX1B +* cell instance $5 r0 *1 9.6,0 +X$5 12 5 15 12 4 15 INVX1 +* cell instance $6 r0 *1 11.4,0 +X$6 12 6 15 12 5 15 INVX1B +* cell instance $7 r0 *1 13.2,0 +X$7 12 7 15 12 6 15 INVX1 +* cell instance $8 r0 *1 15,0 +X$8 12 8 15 12 7 15 INVX1 +* cell instance $9 r0 *1 16.8,0 +X$9 12 9 15 12 8 15 INVX1 +* cell instance $10 r0 *1 18.6,0 +X$10 12 10 15 12 9 15 INVX1 +* cell instance $11 r0 *1 20.4,0 +X$11 12 11 15 12 10 15 INVX1 +* cell instance $12 r0 *1 22.2,0 +X$12 12 13 15 12 11 15 INVX1 +.ENDS RINGO + +* cell INVX1B +* pin VDD +* pin OUT +* pin VSS +* pin +* pin IN +* pin SUBSTRATE +.SUBCKT INVX1B 1 2 3 4 5 6 +* net 1 VDD +* net 2 OUT +* net 3 VSS +* net 5 IN +* net 6 SUBSTRATE +* device instance $1 r0 *1 0.85,5.8 PMOS +M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U +* device instance $2 r0 *1 0.85,2.135 NMOS +M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U +.ENDS INVX1B + +* cell INVX1 +* pin VDD +* pin OUT +* pin VSS +* pin +* pin IN +* pin SUBSTRATE +.SUBCKT INVX1 1 2 3 4 5 6 +* net 1 VDD +* net 2 OUT +* net 3 VSS +* net 5 IN +* net 6 SUBSTRATE +* device instance $1 r0 *1 0.85,5.8 PMOS +M$1 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.6375P PS=3.85U PD=3.85U +* device instance $2 r0 *1 0.85,2.135 NMOS +M$2 3 5 2 6 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.40375P PS=2.75U PD=2.75U +.ENDS INVX1 + +* cell ND2X1 +* pin VDD +* pin OUT +* pin VSS +* pin +* pin B +* pin A +* pin SUBSTRATE +.SUBCKT ND2X1 1 2 3 4 5 6 7 +* net 1 VDD +* net 2 OUT +* net 3 VSS +* net 5 B +* net 6 A +* net 7 SUBSTRATE +* device instance $1 r0 *1 0.85,5.8 PMOS +M$1 2 6 1 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U +* device instance $2 r0 *1 1.55,5.8 PMOS +M$2 1 5 2 4 PMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U +* device instance $3 r0 *1 0.85,2.135 NMOS +M$3 3 6 8 7 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U +* device instance $4 r0 *1 1.55,2.135 NMOS +M$4 8 5 2 7 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U +.ENDS ND2X1 diff --git a/testdata/lvs/ringo_layout_var.gds b/testdata/lvs/ringo_layout_var.gds new file mode 100644 index 0000000000000000000000000000000000000000..e5a18d6f95875b515405d272516106b11092fba0 GIT binary patch literal 12456 zcmeHNUx-~t9iIE|+`BiM?q(CS+3ih@S}}yBx=F;gNKMuxc4Kxo-K=37w3JdL6cG_0 zM5Opo#6KVviWDtjQP3(P#fMP(P)Z4*Pt^xo`XGI%Qqm%!57Ni3-#0VgIWza}nS0Ns zeR2=Xe#>vpcYZT-e!rP-=3JARdVSsWYW4QN%$T{u>^F6DPx!y-)U$Jo3&!kgwC+3k z(=UAW`XAoA=hX9`-T2L=HPdUA^SW7fe&yVQOY^4LF(%txH!YLhRyW4XO*S?+Hy=}h zmooJeSjQEXrLjDK$ZEm_^Ozq{c$W9FTrW5ive~;(e0^gUyB0DkSk45|n?Qff5 zBelG=a^Yy+({QBFvp=FG84));XH5NfLfI{rj1=y_iQeJi#Ksfg&K4*;u$0exRLHMA ze{n;2;ysjWY`NEON+M_SD1Ju2ieLWQ!& zd{Y{!t$(^m72?Ud!v5bPAMZ2F6hspv!ba6LBApSYh*E?JWsf6m(7!Sw%o6@DJ22>f z%>OVlrTGG)8~tc8vydr5*@310*+$++B#-SD${zDg!{p;1WfRPJ7BbCYRA>DU&$Pwm zi|g|Xrr9;7JEgU7e6oRev~J9J&-KIA`uX41*5=^#hheSH*}QgdGzM`F)?YJb7oI?z zdI@9rw*qAc+CGfgbve(W>=Sj2U1tIg zZ(fA(f?tc6ky;3seL~p}m-FeDe2d`GKlv7APw?rN{UoyA^e>b>)qnEXPa^wGzEJjI z{mc7s?JS9Y6M)_YuiszlE}=_-yysr1L*^&H2w!_Q|w=^68&E`p;4Jm>;N2 zn|{nidr|u_4~4P=!~PHOXFdO*=L=;Amhx*48MF64Xg_e~QMCVO1!ZvWurqp^4n3ROL4u|H6fB@cjys&18#y_Nd~WBR8?Z)~|eR z&3i{+agVmUSPyN`<$peY!bP7juZa1zf{!)x8DsW5<gS zr^DGftYuH&?Rk`4bG~o?0H6Ae&*{GB_(Iu%_U#Q>&pTPRG{1yhlJk?VnRDFBZeuSR zWGTkyVHLD>BP_BLqbTndD`P9+% zc|-;Bv`_aS;`?-uKOwL=)q-b4rF|QYyFFFp{knaQ%hnr+Bd?hTp9~F~>#dH?vi)ap!$R@~SFJ`lT|oc+L5z zGGrX(_E;H4@lU^_DodArR5tefHQeXTnd8j9HdbcpG2*TtV`e#0;1vF^{TFkd$CTbP zxTH&|GRBb2LfNb6Rr0AIr_We0|{n%*juh-){;o9*x7U9kN^*@2cnj$wl08%ggr-?}xuOMc^! z)yvz`yPe~MinU7n;hXCo^zuo(oT_S_T5)27>;=#6xUoyBaD4P2Kcw426j%rIOqG*v2gZ^)^pbDluM^xLfJ<@{aRZ*jfrfuwS`}dn6K5p z7?D-|e1fd%YbIIM*G#hdz8FQ{fSFU%|8Tj*ol9fY?O=$q1H-pAz~`LD=WsVho>2C_ z9aQiQ6TCUcCAP0PH7DdVeSPRZ__cwnpZ=}GgKs&$P!6%~B{~Dm| zXVZLgS;!5G?7*b|*~^Z9d(ZKOvICR+CbEmZnr}FMj2$@rAMj zll~8YNB;-jcl;b>$5&OcG~R{LJG z|0d$lV^EjmAIQ-Em*Mwu#}~>DwEQY-7I(ruw*%eQ7aQ^$eLGk`{>fb+$B(->VsM51 zPwoP_^CF+vzY83`3p>4Ze(gaxAAR2D+FE_y4)=7U`I^|kyM-^H9gEReT=&STK5vuN zH*XKbz4C+aiuVg;uaY<9GjE6`d6SGA^7!6~!BrAB?hbrQvzK^6+4Ze$c-*WmE`MbO z1JJd*cmGAleoLVS$7S1r+Rl{wE@tb-|6aV${<;f)?ys|o!t%cHQvWlHI^Tc!!&!ol zY0G@%I}x+5*4CA@wR^Zw8m^cA#KJ!J;`7mSqh5afb5T#=)Bn=PGAA!bOx3~}&*!EG z+8c83_Et4_G37+=6yu+W{wspJFt}B!%l?v5y?M z9iK?vXRtyG$@lf8{*PRDd?I;woh^`jUth|ff7S7c8MjlTfTUY;G z%uv47U=9COi=Ww|--T4+`#H5clbv2Zxp3}uq|!!e!MJNVPTJ3Sjf=Ia*);zHzFG psd, "G" => pgate, "W" => nwell, + "tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell }) + +# NMOS transistor device extraction +extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk, + "tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk }) + +# Define connectivity for netlist extraction + +# Inter-layer +connect(psd, contact) +connect(nsd, contact) +connect(poly, contact) +connect(ntie, contact) +connect(nwell, ntie) +connect(ptie, contact) +connect(contact, metal1) +connect(metal1, via1) +connect(via1, metal2) + +# Global +connect_global(bulk, "SUBSTRATE") +connect_global(ptie, "SUBSTRATE") + +# Compare section + +netlist.simplify + +# both INVX1 and INVX1B are the same schematic cell +same_circuits("INVX1", "INVX1") +same_circuits("INVX1B", "INVX1") + +compare + diff --git a/testdata/lvs/ringo_layout_var.lvsdb b/testdata/lvs/ringo_layout_var.lvsdb new file mode 100644 index 000000000..35a52028c --- /dev/null +++ b/testdata/lvs/ringo_layout_var.lvsdb @@ -0,0 +1,1076 @@ +#%lvsdb-klayout + +# Layout +layout( + top(RINGO) + unit(0.001) + + # Layer section + # This section lists the mask layers (drawing or derived) and their connections. + + # Mask layers + layer(l3 '1/0') + layer(l4 '5/0') + layer(l8 '8/0') + layer(l11 '9/0') + layer(l12 '10/0') + layer(l13 '11/0') + layer(l7) + layer(l2) + layer(l9) + layer(l6) + layer(l10) + + # Mask layer connectivity + connect(l3 l3 l9) + connect(l4 l4 l8) + connect(l8 l4 l8 l11 l2 l9 l6 l10) + connect(l11 l8 l11 l12) + connect(l12 l11 l12 l13) + connect(l13 l12 l13) + connect(l7 l7) + connect(l2 l8 l2) + connect(l9 l3 l8 l9) + connect(l6 l8 l6) + connect(l10 l8 l10) + + # Global nets and connectivity + global(l7 SUBSTRATE) + global(l10 SUBSTRATE) + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Device abstracts section + # Device abstracts list the pin shapes of the devices. + device(D$PMOS PMOS + terminal(S + rect(l2 (-550 -750) (425 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (450 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$PMOS$1 PMOS + terminal(S + rect(l2 (-575 -750) (450 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (425 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$PMOS$2 PMOS + terminal(S + rect(l2 (-550 -750) (425 1500)) + ) + terminal(G + rect(l4 (-125 -750) (250 1500)) + ) + terminal(D + rect(l2 (125 -750) (425 1500)) + ) + terminal(B + rect(l3 (-125 -750) (250 1500)) + ) + ) + device(D$NMOS NMOS + terminal(S + rect(l6 (-550 -475) (425 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (450 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + device(D$NMOS$1 NMOS + terminal(S + rect(l6 (-575 -475) (450 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (425 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + device(D$NMOS$2 NMOS + terminal(S + rect(l6 (-550 -475) (425 950)) + ) + terminal(G + rect(l4 (-125 -475) (250 950)) + ) + terminal(D + rect(l6 (125 -475) (425 950)) + ) + terminal(B + rect(l7 (-125 -475) (250 950)) + ) + ) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(ND2X1 + + # Circuit boundary + rect((-100 400) (2600 7600)) + + # Nets with their geometries + net(1 name(VDD) + rect(l8 (1110 5160) (180 180)) + rect(l8 (-180 920) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l11 (-240 -790) (300 1700)) + rect(l11 (-1350 0) (2400 800)) + rect(l11 (-1151 -401) (2 2)) + rect(l2 (-276 -2151) (425 1500)) + rect(l2 (-400 -1500) (425 1500)) + ) + net(2 name(OUT) + rect(l8 (1810 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-1580 3760) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (1220 920) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + polygon(l11 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090)) + rect(l11 (-110 1390) (300 1400)) + polygon(l11 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300)) + rect(l11 (-141 -501) (2 2)) + rect(l11 (-1751 1099) (300 1400)) + rect(l11 (1100 -1700) (300 300)) + rect(l11 (-300 0) (300 1400)) + rect(l2 (-1750 -1450) (425 1500)) + rect(l2 (950 -1500) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 name(VSS) + rect(l8 (410 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -1300) (300 1360)) + rect(l11 (-650 -2160) (2400 800)) + rect(l11 (-1151 -401) (2 2)) + rect(l6 (-951 859) (425 950)) + ) + net(4 + rect(l3 (-100 4500) (2600 3500)) + ) + net(5 name(B) + rect(l4 (1425 2860) (250 1940)) + rect(l4 (-345 -950) (300 300)) + rect(l4 (-205 650) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-285 1050) (180 180)) + rect(l11 (-71 -91) (2 2)) + rect(l11 (-171 -151) (300 300)) + ) + net(6 name(A) + rect(l4 (725 2860) (250 1940)) + rect(l4 (-325 -1850) (300 300)) + rect(l4 (-225 1550) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-265 150) (180 180)) + rect(l11 (-91 -91) (2 2)) + rect(l11 (-151 -151) (300 300)) + ) + net(7 name(SUBSTRATE)) + net(8 + rect(l6 (975 1660) (425 950)) + rect(l6 (-400 -950) (425 950)) + ) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4) + pin(5 name(B)) + pin(6 name(A)) + pin(7 name(SUBSTRATE)) + + # Devices and their connections + device(1 D$PMOS + location(850 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.6375) + param(AD 0.3375) + param(PS 3.85) + param(PD 1.95) + terminal(S 2) + terminal(G 6) + terminal(D 1) + terminal(B 4) + ) + device(2 D$PMOS$1 + location(1550 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.3375) + param(AD 0.6375) + param(PS 1.95) + param(PD 3.85) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(3 D$NMOS + location(850 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.40375) + param(AD 0.21375) + param(PS 2.75) + param(PD 1.4) + terminal(S 3) + terminal(G 6) + terminal(D 8) + terminal(B 7) + ) + device(4 D$NMOS$1 + location(1550 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.21375) + param(AD 0.40375) + param(PS 1.4) + param(PD 2.75) + terminal(S 8) + terminal(G 5) + terminal(D 2) + terminal(B 7) + ) + + ) + circuit(INVX1 + + # Circuit boundary + rect((-100 400) (2000 7600)) + + # Nets with their geometries + net(1 name(VDD) + rect(l8 (410 6260) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l11 (-240 -240) (300 1400)) + rect(l11 (-650 300) (1800 800)) + rect(l11 (-1450 -1100) (300 300)) + rect(l11 (299 399) (2 2)) + rect(l2 (-651 -2151) (425 1500)) + ) + net(2 name(OUT) + rect(l8 (1110 5160) (180 180)) + rect(l8 (-180 920) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -4120) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -790) (300 4790)) + rect(l11 (-151 -2501) (2 2)) + rect(l2 (-226 1049) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 name(VSS) + rect(l8 (410 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -1300) (300 1360)) + rect(l11 (-650 -2160) (1800 800)) + rect(l11 (-851 -401) (2 2)) + rect(l6 (-651 859) (425 950)) + ) + net(4 + rect(l3 (-100 4500) (2000 3500)) + ) + net(5 name(IN) + rect(l4 (725 2860) (250 1940)) + rect(l4 (-525 -1850) (300 300)) + rect(l4 (-25 1550) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-465 150) (180 180)) + rect(l11 (-91 -91) (2 2)) + rect(l11 (-151 -151) (300 300)) + ) + net(6 name(SUBSTRATE)) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4) + pin(5 name(IN)) + pin(6 name(SUBSTRATE)) + + # Devices and their connections + device(1 D$PMOS$2 + location(850 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.6375) + param(AD 0.6375) + param(PS 3.85) + param(PD 3.85) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(2 D$NMOS$2 + location(850 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.40375) + param(AD 0.40375) + param(PS 2.75) + param(PD 2.75) + terminal(S 3) + terminal(G 5) + terminal(D 2) + terminal(B 6) + ) + + ) + circuit(INVX1B + + # Circuit boundary + rect((-100 400) (2000 7600)) + + # Nets with their geometries + net(1 name(VDD) + rect(l8 (410 6260) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l11 (-240 -240) (300 1400)) + rect(l11 (-650 300) (1800 800)) + rect(l11 (-1450 -1100) (300 300)) + rect(l11 (299 399) (2 2)) + rect(l2 (-651 -2151) (425 1500)) + ) + net(2 name(OUT) + rect(l8 (1110 5160) (180 180)) + rect(l8 (-180 920) (180 180)) + rect(l8 (-180 -730) (180 180)) + rect(l8 (-180 -4120) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -790) (300 4790)) + rect(l11 (-151 -2501) (2 2)) + rect(l2 (-226 1049) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 name(VSS) + rect(l8 (410 1770) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-240 -1300) (300 1360)) + rect(l11 (-650 -2160) (1800 800)) + rect(l11 (-851 -401) (2 2)) + rect(l6 (-651 859) (425 950)) + ) + net(4 + rect(l3 (-100 4500) (2000 3500)) + ) + net(5 name(IN) + rect(l4 (725 2860) (250 1940)) + rect(l4 (-525 -1850) (300 300)) + rect(l4 (-25 1550) (250 2000)) + rect(l4 (-250 -2000) (250 2000)) + rect(l4 (-250 -5390) (250 1450)) + rect(l8 (-465 150) (180 180)) + rect(l11 (-91 -91) (2 2)) + rect(l11 (-151 -151) (300 300)) + ) + net(6 name(SUBSTRATE)) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4) + pin(5 name(IN)) + pin(6 name(SUBSTRATE)) + + # Devices and their connections + device(1 D$PMOS$2 + location(850 5800) + param(L 0.25) + param(W 1.5) + param(AS 0.6375) + param(AD 0.6375) + param(PS 3.85) + param(PD 3.85) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(2 D$NMOS$2 + location(850 2135) + param(L 0.25) + param(W 0.95) + param(AS 0.40375) + param(AD 0.40375) + param(PS 2.75) + param(PD 2.75) + terminal(S 3) + terminal(G 5) + terminal(D 2) + terminal(B 6) + ) + + ) + circuit(RINGO + + # Circuit boundary + rect((0 350) (25800 7650)) + + # Nets with their geometries + net(1 + rect(l8 (4710 3010) (180 180)) + rect(l11 (-850 -240) (610 300)) + rect(l2 (-2550 1800) (425 1500)) + rect(l2 (950 -1500) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(2 + rect(l8 (6510 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(3 + rect(l8 (8310 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(4 + rect(l8 (10110 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(5 + rect(l8 (11910 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(6 + rect(l8 (13710 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(7 + rect(l8 (15510 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(8 + rect(l8 (17310 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(9 + rect(l8 (19110 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(10 + rect(l8 (20910 3010) (180 180)) + rect(l11 (-1140 -240) (900 300)) + rect(l2 (-1275 1800) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(11 name(FB) + rect(l8 (22710 3010) (180 180)) + rect(l8 (-19700 720) (180 180)) + rect(l11 (18380 -1140) (900 300)) + rect(l11 (-19530 590) (320 320)) + rect(l11 (17820 -320) (320 320)) + rect(l12 (-18400 -260) (200 200)) + rect(l12 (17940 -200) (200 200)) + rect(l13 (-18040 -300) (17740 400)) + rect(l13 (-17921 -201) (2 2)) + rect(l13 (-221 -201) (400 400)) + rect(l13 (17740 -400) (400 400)) + rect(l2 (-245 850) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(12 name(VDD) + rect(l3 (500 4500) (1400 3500)) + rect(l3 (-1900 -3500) (600 3500)) + rect(l3 (23300 -3500) (1400 3500)) + rect(l3 (-100 -3500) (600 3500)) + rect(l8 (-24690 -1240) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (23220 370) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l11 (-21741 859) (2 2)) + rect(l11 (-2351 -451) (1200 800)) + rect(l11 (-750 -1450) (300 1400)) + rect(l11 (-101 -351) (2 2)) + rect(l11 (-1251 -401) (600 800)) + rect(l11 (23400 -800) (1200 800)) + rect(l11 (-750 -1450) (300 1400)) + rect(l11 (-101 -351) (2 2)) + rect(l11 (549 -401) (600 800)) + rect(l2 (-23025 -2550) (425 1500)) + rect(l2 (-400 -1500) (425 1500)) + rect(l2 (1275 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (1375 -1500) (425 1500)) + rect(l2 (3175 -1500) (425 1500)) + rect(l2 (-2225 -1500) (425 1500)) + rect(l9 (-20175 -450) (500 1500)) + rect(l9 (22900 -1500) (500 1500)) + ) + net(13 name(OUT) + rect(l11 (23440 3840) (320 320)) + rect(l12 (-260 -260) (200 200)) + rect(l13 (-101 -101) (2 2)) + rect(l13 (-201 -201) (400 400)) + rect(l2 (-625 850) (425 1500)) + rect(l6 (-425 -4890) (425 950)) + ) + net(14 name(ENABLE) + rect(l8 (2510 3010) (180 180)) + rect(l11 (-250 -250) (320 320)) + rect(l12 (-260 -260) (200 200)) + rect(l13 (-101 -101) (2 2)) + rect(l13 (-201 -201) (400 400)) + ) + net(15 name(VSS) + rect(l8 (1110 1610) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l8 (23220 370) (180 180)) + rect(l8 (-180 -1280) (180 180)) + rect(l8 (-180 370) (180 180)) + rect(l11 (-21741 -391) (2 2)) + rect(l11 (-1901 -401) (300 1400)) + rect(l11 (-750 -1450) (1200 800)) + rect(l11 (-551 -401) (2 2)) + rect(l11 (-1251 -401) (600 800)) + rect(l11 (23850 -750) (300 1400)) + rect(l11 (-750 -1450) (1200 800)) + rect(l11 (-551 -401) (2 2)) + rect(l11 (549 -401) (600 800)) + rect(l6 (-23700 460) (425 950)) + rect(l6 (1975 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (1375 -950) (425 950)) + rect(l6 (3175 -950) (425 950)) + rect(l6 (-2225 -950) (425 950)) + rect(l10 (-20175 -2210) (500 1500)) + rect(l10 (22900 -1500) (500 1500)) + ) + + # Outgoing pins and their connections to nets + pin(11 name(FB)) + pin(12 name(VDD)) + pin(13 name(OUT)) + pin(14 name(ENABLE)) + pin(15 name(VSS)) + + # Subcircuits and their connections + circuit(1 ND2X1 location(1800 0) + pin(0 12) + pin(1 1) + pin(2 15) + pin(3 12) + pin(4 11) + pin(5 14) + pin(6 15) + ) + circuit(2 INVX1B location(4200 0) + pin(0 12) + pin(1 2) + pin(2 15) + pin(3 12) + pin(4 1) + pin(5 15) + ) + circuit(3 INVX1 location(6000 0) + pin(0 12) + pin(1 3) + pin(2 15) + pin(3 12) + pin(4 2) + pin(5 15) + ) + circuit(4 INVX1B location(7800 0) + pin(0 12) + pin(1 4) + pin(2 15) + pin(3 12) + pin(4 3) + pin(5 15) + ) + circuit(5 INVX1 location(9600 0) + pin(0 12) + pin(1 5) + pin(2 15) + pin(3 12) + pin(4 4) + pin(5 15) + ) + circuit(6 INVX1B location(11400 0) + pin(0 12) + pin(1 6) + pin(2 15) + pin(3 12) + pin(4 5) + pin(5 15) + ) + circuit(7 INVX1 location(13200 0) + pin(0 12) + pin(1 7) + pin(2 15) + pin(3 12) + pin(4 6) + pin(5 15) + ) + circuit(8 INVX1 location(15000 0) + pin(0 12) + pin(1 8) + pin(2 15) + pin(3 12) + pin(4 7) + pin(5 15) + ) + circuit(9 INVX1 location(16800 0) + pin(0 12) + pin(1 9) + pin(2 15) + pin(3 12) + pin(4 8) + pin(5 15) + ) + circuit(10 INVX1 location(18600 0) + pin(0 12) + pin(1 10) + pin(2 15) + pin(3 12) + pin(4 9) + pin(5 15) + ) + circuit(11 INVX1 location(20400 0) + pin(0 12) + pin(1 11) + pin(2 15) + pin(3 12) + pin(4 10) + pin(5 15) + ) + circuit(12 INVX1 location(22200 0) + pin(0 12) + pin(1 13) + pin(2 15) + pin(3 12) + pin(4 11) + pin(5 15) + ) + + ) +) + +# Reference netlist +reference( + + # Device class section + class(PMOS MOS4) + class(NMOS MOS4) + + # Circuit section + # Circuits are the hierarchical building blocks of the netlist. + circuit(ND2X1 + + # Nets + net(1 name(VDD)) + net(2 name(OUT)) + net(3 name(VSS)) + net(4 name(NWELL)) + net(5 name(B)) + net(6 name(A)) + net(7 name(BULK)) + net(8 name('1')) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4 name(NWELL)) + pin(5 name(B)) + pin(6 name(A)) + pin(7 name(BULK)) + + # Devices and their connections + device(1 PMOS + name($1) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 2) + terminal(G 6) + terminal(D 1) + terminal(B 4) + ) + device(2 PMOS + name($2) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(3 NMOS + name($3) + param(L 0.25) + param(W 0.95) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 3) + terminal(G 6) + terminal(D 8) + terminal(B 7) + ) + device(4 NMOS + name($4) + param(L 0.25) + param(W 0.95) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 8) + terminal(G 5) + terminal(D 2) + terminal(B 7) + ) + + ) + circuit(INVX1 + + # Nets + net(1 name(VDD)) + net(2 name(OUT)) + net(3 name(VSS)) + net(4 name(NWELL)) + net(5 name(IN)) + net(6 name(BULK)) + + # Outgoing pins and their connections to nets + pin(1 name(VDD)) + pin(2 name(OUT)) + pin(3 name(VSS)) + pin(4 name(NWELL)) + pin(5 name(IN)) + pin(6 name(BULK)) + + # Devices and their connections + device(1 PMOS + name($1) + param(L 0.25) + param(W 1.5) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 1) + terminal(G 5) + terminal(D 2) + terminal(B 4) + ) + device(2 NMOS + name($2) + param(L 0.25) + param(W 0.95) + param(AS 0) + param(AD 0) + param(PS 0) + param(PD 0) + terminal(S 3) + terminal(G 5) + terminal(D 2) + terminal(B 6) + ) + + ) + circuit(RINGO + + # Nets + net(1 name(VSS)) + net(2 name(VDD)) + net(3 name(FB)) + net(4 name(ENABLE)) + net(5 name(OUT)) + net(6 name('1')) + net(7 name('2')) + net(8 name('3')) + net(9 name('4')) + net(10 name('5')) + net(11 name('6')) + net(12 name('7')) + net(13 name('8')) + net(14 name('9')) + net(15 name('10')) + + # Outgoing pins and their connections to nets + pin(1 name(VSS)) + pin(2 name(VDD)) + pin(3 name(FB)) + pin(4 name(ENABLE)) + pin(5 name(OUT)) + + # Subcircuits and their connections + circuit(1 ND2X1 name($1) + pin(0 2) + pin(1 6) + pin(2 1) + pin(3 2) + pin(4 3) + pin(5 4) + pin(6 1) + ) + circuit(2 INVX1 name($2) + pin(0 2) + pin(1 7) + pin(2 1) + pin(3 2) + pin(4 6) + pin(5 1) + ) + circuit(3 INVX1 name($3) + pin(0 2) + pin(1 8) + pin(2 1) + pin(3 2) + pin(4 7) + pin(5 1) + ) + circuit(4 INVX1 name($4) + pin(0 2) + pin(1 9) + pin(2 1) + pin(3 2) + pin(4 8) + pin(5 1) + ) + circuit(5 INVX1 name($5) + pin(0 2) + pin(1 10) + pin(2 1) + pin(3 2) + pin(4 9) + pin(5 1) + ) + circuit(6 INVX1 name($6) + pin(0 2) + pin(1 11) + pin(2 1) + pin(3 2) + pin(4 10) + pin(5 1) + ) + circuit(7 INVX1 name($7) + pin(0 2) + pin(1 12) + pin(2 1) + pin(3 2) + pin(4 11) + pin(5 1) + ) + circuit(8 INVX1 name($8) + pin(0 2) + pin(1 13) + pin(2 1) + pin(3 2) + pin(4 12) + pin(5 1) + ) + circuit(9 INVX1 name($9) + pin(0 2) + pin(1 14) + pin(2 1) + pin(3 2) + pin(4 13) + pin(5 1) + ) + circuit(10 INVX1 name($10) + pin(0 2) + pin(1 15) + pin(2 1) + pin(3 2) + pin(4 14) + pin(5 1) + ) + circuit(11 INVX1 name($11) + pin(0 2) + pin(1 3) + pin(2 1) + pin(3 2) + pin(4 15) + pin(5 1) + ) + circuit(12 INVX1 name($12) + pin(0 2) + pin(1 5) + pin(2 1) + pin(3 2) + pin(4 3) + pin(5 1) + ) + + ) +) + +# Cross reference +xref( + circuit(INVX1 INVX1 match + xref( + net(4 4 match) + net(5 5 match) + net(2 2 match) + net(6 6 match) + net(1 1 match) + net(3 3 match) + pin(3 3 match) + pin(4 4 match) + pin(1 1 match) + pin(5 5 match) + pin(0 0 match) + pin(2 2 match) + device(2 2 match) + device(1 1 match) + ) + ) + circuit(INVX1B INVX1 match + xref( + net(4 4 match) + net(5 5 match) + net(2 2 match) + net(6 6 match) + net(1 1 match) + net(3 3 match) + pin(3 3 match) + pin(4 4 match) + pin(1 1 match) + pin(5 5 match) + pin(0 0 match) + pin(2 2 match) + device(2 2 match) + device(1 1 match) + ) + ) + circuit(ND2X1 ND2X1 match + xref( + net(8 8 match) + net(4 4 match) + net(6 6 match) + net(5 5 match) + net(2 2 match) + net(7 7 match) + net(1 1 match) + net(3 3 match) + pin(3 3 match) + pin(5 5 match) + pin(4 4 match) + pin(1 1 match) + pin(6 6 match) + pin(0 0 match) + pin(2 2 match) + device(3 3 match) + device(4 4 match) + device(1 1 match) + device(2 2 match) + ) + ) + circuit(RINGO RINGO match + xref( + net(1 6 match) + net(10 15 match) + net(2 7 match) + net(3 8 match) + net(4 9 match) + net(5 10 match) + net(6 11 match) + net(7 12 match) + net(8 13 match) + net(9 14 match) + net(14 4 match) + net(11 3 match) + net(13 5 match) + net(12 2 match) + net(15 1 match) + pin(3 3 match) + pin(0 2 match) + pin(2 4 match) + pin(1 1 match) + pin(4 0 match) + circuit(3 3 match) + circuit(5 5 match) + circuit(7 7 match) + circuit(8 8 match) + circuit(9 9 match) + circuit(10 10 match) + circuit(11 11 match) + circuit(12 12 match) + circuit(2 2 match) + circuit(4 4 match) + circuit(6 6 match) + circuit(1 1 match) + ) + ) +) From 0bc2321ade7993d2ac83bde6f297237595826e38 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 30 Sep 2019 23:17:42 +0200 Subject: [PATCH 4/5] Some code cleanup. --- src/db/db/dbNetlistCompare.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 593810056..96682f9ef 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -489,14 +489,10 @@ public: void same_circuit (const db::Circuit *ca, const db::Circuit *cb) { // no arbitrary cross-pairing + // NOTE: many layout circuits are allowed for one schematic to account for layout alternatives. if (ca && has_cat_for (ca)) { throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + ca->name ()); } -#if 0 // can pair multiple layout cells with one schematic circuit - if (cb && has_cat_for (cb)) { - throw tl::Exception (tl::to_string (tr ("Circuit is already paired with other circuit: ")) + cb->name ()); - } -#endif generic_categorizer::same (ca, cb); } From ca747771acbde817a67ca5fcc3c46adb7845f868 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 1 Oct 2019 00:21:27 +0200 Subject: [PATCH 5/5] Allow preempt LVS configuration same_nets, equivalent_pins, same_circuits and same_device_classes can now be given at the beginning of the LVS script. This will simplify building universal scripts with the run specific part at the beginning (one "load" section). The price are somewhat less specific error messages when something fails in these methods. --- src/lvs/lvs/built-in-macros/_lvs_netter.rb | 40 ++++++++++++++++--- testdata/lvs/ringo_layout_var.lvs | 8 ++-- ...ngo_simple_net_and_circuit_equivalence.lvs | 4 +- testdata/lvs/ringo_simple_pin_swapping.lvs | 4 +- .../lvs/ringo_simple_same_device_classes.lvs | 4 +- 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/lvs/lvs/built-in-macros/_lvs_netter.rb b/src/lvs/lvs/built-in-macros/_lvs_netter.rb index 23335311b..c6317d310 100644 --- a/src/lvs/lvs/built-in-macros/_lvs_netter.rb +++ b/src/lvs/lvs/built-in-macros/_lvs_netter.rb @@ -48,6 +48,7 @@ module LVS def initialize(engine) super + @comparer_config = [] end def _make_data @@ -161,6 +162,11 @@ module LVS nl = _ensure_two_netlists lvs_data.reference = nl[1] + # execute the configuration commands + @comparer_config.each do |cc| + cc.call + end + lvs_data.compare(@comparer) end @@ -217,6 +223,12 @@ module LVS n.is_a?(String) || n.is_a?(RBA::Net) || raise("Net arguments of 'same_nets' must be strings or Net objects") end + @comparer_config << lambda { self._same_nets(ca, a, cb, b) } + + end + + def _same_nets(ca, a, cb, b) + ( nl_a, nl_b ) = _ensure_two_netlists if ca.is_a?(String) @@ -234,13 +246,13 @@ module LVS if circuit_a && circuit_b if a.is_a?(String) - net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist: #{a} (for circuit #{circuit_a})") + net_a = circuit_a.net_by_name(a) || raise("Not a valid net name in extracted netlist in 'same_nets': #{a} (for circuit #{circuit_a})") else net_a = a end if b.is_a?(String) - net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist: #{b} (for circuit #{circuit_b})") + net_b = circuit_b.net_by_name(b) || raise("Not a valid net name in extracted netlist in 'same_nets': #{b} (for circuit #{circuit_b})") else net_b = b end @@ -271,6 +283,12 @@ module LVS a.is_a?(String) || a == nil || b.is_a?(String) || b == nil || raise("Both arguments of 'same_circuits' need to be strings or nil") + @comparer_config << lambda { self._same_circuits(a, b) } + + end + + def _same_circuits(a, b) + ( nl_a, nl_b ) = _ensure_two_netlists circuit_a = a && nl_a.circuit_by_name(a) @@ -301,9 +319,15 @@ module LVS a.is_a?(String) || a == nil || b.is_a?(String) || b == nil || raise("Both arguments of 'same_device_classes' need to be strings or nil") + @comparer_config << lambda { self._same_device_classes(a, b) } + + end + + def _same_device_classes(a, b) + ( nl_a, nl_b ) = _ensure_two_netlists - dc_a = a && (nl_a.device_class_by_name(a) || raise("Not a valid device class in extracted netlist: #{a}")) + dc_a = a && (nl_a.device_class_by_name(a) || raise("Not a valid device class in extracted netlist in 'same_device_class': #{a}")) dc_b = b && nl_b.device_class_by_name(b) # NOTE: a device class is allowed to be missing in the reference netlist because the @@ -347,6 +371,12 @@ module LVS raise("All pin arguments of 'equivalent_pins' need to be strings or numbers") end + @comparer_config << lambda { self._equivalent_pins(circuit, *pins) } + + end + + def _equivalent_pins(circuit, *pins) + ( nl_a, nl_b ) = _ensure_two_netlists circuit_b = nl_b.circuit_by_name(circuit) @@ -357,9 +387,9 @@ module LVS pin_ids_b = pins.collect do |p| if p.is_a?(String) - pin = circuit_b.pin_by_name(p) || raise("Not a valid pin name in circuit '#{circuit}': #{p}") + pin = circuit_b.pin_by_name(p) || raise("Not a valid pin name in circuit '#{circuit}' in 'equivalent_pins': #{p}") else - pin = pins_by_index[p.to_i] || raise("Not a valid pin index in circuit '#{circuit}': #{p}") + pin = pins_by_index[p.to_i] || raise("Not a valid pin index in circuit '#{circuit}' in 'equivalent_pins': #{p}") end pin.id end diff --git a/testdata/lvs/ringo_layout_var.lvs b/testdata/lvs/ringo_layout_var.lvs index 4f6c718e3..afe79c3e2 100644 --- a/testdata/lvs/ringo_layout_var.lvs +++ b/testdata/lvs/ringo_layout_var.lvs @@ -5,6 +5,10 @@ report_lvs($lvs_test_target_lvsdb, true) target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") +# both INVX1 and INVX1B are the same schematic cell +same_circuits("INVX1", "INVX1") +same_circuits("INVX1B", "INVX1") + schematic("ringo.cir") deep @@ -70,9 +74,5 @@ connect_global(ptie, "SUBSTRATE") netlist.simplify -# both INVX1 and INVX1B are the same schematic cell -same_circuits("INVX1", "INVX1") -same_circuits("INVX1B", "INVX1") - compare diff --git a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvs b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvs index 878c69698..7ff601882 100644 --- a/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvs +++ b/testdata/lvs/ringo_simple_net_and_circuit_equivalence.lvs @@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") schematic("ringo.cir") +# preempt configuration (see below) +same_nets("top", "ENABLE", "RINGO", "ENABLE") + deep # Drawing layers @@ -71,7 +74,6 @@ connect_global(ptie, "SUBSTRATE") same_circuits("top", "RINGO") same_circuits("INV", "INVX1") same_circuits("DOESNOTEXIST", "DOESNOTEXIST2") -same_nets("top", "ENABLE", "RINGO", "ENABLE") same_nets("DOESNOTEXIST", "ENABLE", "DOESNOTEXIST2", "ENABLE") netlist.simplify diff --git a/testdata/lvs/ringo_simple_pin_swapping.lvs b/testdata/lvs/ringo_simple_pin_swapping.lvs index dcfa49dd4..d54d3f1fa 100644 --- a/testdata/lvs/ringo_simple_pin_swapping.lvs +++ b/testdata/lvs/ringo_simple_pin_swapping.lvs @@ -7,6 +7,9 @@ target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout") schematic("ringo_pin_swapping.cir") +# preempt configuration +equivalent_pins("ND2X1", 4, 5) + deep # Drawing layers @@ -68,7 +71,6 @@ connect_global(ptie, "SUBSTRATE") # Compare section -equivalent_pins("ND2X1", 4, 5) equivalent_pins("DOESNOTEXIST", 4, 5) netlist.simplify diff --git a/testdata/lvs/ringo_simple_same_device_classes.lvs b/testdata/lvs/ringo_simple_same_device_classes.lvs index 9a2bad4d1..8005d70cc 100644 --- a/testdata/lvs/ringo_simple_same_device_classes.lvs +++ b/testdata/lvs/ringo_simple_same_device_classes.lvs @@ -8,6 +8,9 @@ target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout") schematic("ringo.cir") +# preempt configuration +same_device_classes("PM", "PMOS") + deep # Drawing layers @@ -90,7 +93,6 @@ connect_global(ptie, "SUBSTRATE") netlist.simplify -same_device_classes("PM", "PMOS") same_device_classes("NM", "NMOS") same_device_classes("PMHV", "PMOSHV") same_device_classes("NMHV", "NMOSHV")