From 9613ad72c8fb75213d138e7bebde8e9c55c442be Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 31 Mar 2019 23:59:43 +0200 Subject: [PATCH] WIP: netlist compare - using it for more tests Issue solved: some circuit pins may not have a net - these need to be ignored. Requirement: all pins with a net must be mapped. Detached pins are not present in the mapping table. A dummy mapping table was introduced to allow dropping of pins in the second circuit too. Output of compare should not depend on memory location anymore and pin mismatch reporting should include all pins. --- src/db/db/dbNetlistCompare.cc | 169 ++++++++------ src/db/db/dbNetlistCompare.h | 2 +- src/db/unit_tests/dbLayoutToNetlistTests.cc | 8 +- src/db/unit_tests/dbNetlistCompareTests.cc | 245 ++++++++++++++------ testdata/algo/device_extract_l6.gds | Bin 4430 -> 4430 bytes 5 files changed, 279 insertions(+), 145 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 0cff104fa..c2b43d015 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -157,6 +157,16 @@ public: m_rev_pin_map.insert (std::make_pair (other_pin, this_pin)); } + bool has_other_pin_for_this_pin (size_t this_pin) const + { + return m_pin_map.find (this_pin) != m_pin_map.end (); + } + + bool has_this_pin_for_other_pin (size_t other_pin) const + { + return m_rev_pin_map.find (other_pin) != m_rev_pin_map.end (); + } + size_t other_pin_from_this_pin (size_t this_pin) const { std::map::const_iterator i = m_pin_map.find (this_pin); @@ -440,28 +450,28 @@ public: size_t pin_id = i->pin ()->id (); const db::Circuit *cr = sc->circuit_ref (); - const CircuitMapper *cm = 0; + pin_id = pin_map->normalize_pin_id (cr, pin_id); - if (circuit_map) { - std::map::const_iterator icm = circuit_map->find (cr); - if (icm == circuit_map->end ()) { - // this can happen if the other circuit is not present - this is allowed for single-pin - // circuits. - continue; - } - cm = & icm->second; + std::map::const_iterator icm = circuit_map->find (cr); + if (icm == circuit_map->end ()) { + // this can happen if the other circuit is not present - this is allowed for single-pin + // circuits. + continue; } - // NOTE: if cm is given, cr and pin_id are given in terms of the "other" circuit + const CircuitMapper *cm = & icm->second; - if (cm) { - cr = cm->other (); - pin_id = cm->other_pin_from_this_pin (pin_id); + // A pin assignment may be missing because there is no net for a pin -> skip this + + if (! cm->has_other_pin_for_this_pin (pin_id)) { + continue; } - if (pin_map) { - pin_id = pin_map->normalize_pin_id (cr, pin_id); - } + // NOTE: if cm is given, cr and pin_id are given in terms of the canonical "other" circuit. + // For c1 this is the c1->c2 mapper, for c2 this is the c2->c2 dummy mapper. + + cr = cm->other (); + pin_id = cm->other_pin_from_this_pin (pin_id); // we cannot afford creating edges from all to all other pins, so we just create edges to the previous and next // pin. This may take more iterations to solve, but should be equivalent. @@ -469,17 +479,21 @@ public: std::vector pids; size_t pin_count = cr->pin_count (); - // take the previous, next and second-next pin as targets for edges - // (using the second-next pin avoid isolation of OUT vs. IN in case - // of a pin configuration of VSS-IN-VDD-OUT like for an inverter). + // take a number if additional pins as edges: this allows identifying a pin as dependent + // from other pins hence nets are propagated. We assume that there are 4 power pins max so + // 5 additional pins should be sufficient to capture one additional non-power pin. - if (pin_count >= 2) { - pids.push_back ((pin_id + pin_count - 1) % pin_count); - if (pin_count >= 3) { - pids.push_back ((pin_id + 1) % pin_count); - if (pin_count >= 4) { - pids.push_back ((pin_id + 2) % pin_count); - } + size_t take_additional_pins = 5; + for (size_t n = 0; n < take_additional_pins; ++n) { + size_t add_pin_id = (pin_id + n + 1) % pin_count; + if (add_pin_id == pin_id) { + break; + } + if (cm->has_this_pin_for_other_pin (add_pin_id)) { + pids.push_back (add_pin_id); + } else { + // skip pins without mapping + ++take_additional_pins; } } @@ -489,9 +503,9 @@ public: // NOTE: if a pin mapping is given, EdgeDesc::pin1_id and EdgeDesc::pin2_id are given // as pin ID's of the other circuit. - EdgeDesc ed (sc, circuit_categorizer.cat_for_subcircuit (sc), pin_id, pin_map ? pin_map->normalize_pin_id (cr, pin2_id) : pin2_id); + EdgeDesc ed (sc, circuit_categorizer.cat_for_subcircuit (sc), pin_id, pin_map->normalize_pin_id (cr, pin2_id)); - size_t this_pin2_id = cm ? cm->this_pin_from_other_pin (pin2_id) : pin2_id; + size_t this_pin2_id = cm->this_pin_from_other_pin (pin2_id); const db::Net *net2 = sc->net_for_pin (this_pin2_id); std::map::const_iterator in = n2entry.find (net2); @@ -966,7 +980,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const } std::set verified_circuits_a, verified_circuits_b; - std::map pin_mapping; + std::map c12_pin_mapping, c22_pin_mapping; for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) { @@ -994,7 +1008,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const } bool pin_mismatch = false; - bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, *net_identity, pin_mismatch, pin_mapping); + bool g = compare_circuits (ca, cb, device_categorizer, circuit_categorizer, *net_identity, pin_mismatch, c12_pin_mapping, c22_pin_mapping); if (! g) { good = false; } @@ -1070,29 +1084,30 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetDeviceGra const db::Circuit *cr = subcircuit.circuit_ref (); - const CircuitMapper *cm = 0; - - if (circuit_map) { - std::map::const_iterator icm = circuit_map->find (cr); - if (icm == circuit_map->end ()) { - // this can happen if the other circuit does not exist - in this case the key is an invalid one which cannot - // be produced by a regular subcircuit. - return k; - } - cm = & icm->second; - cr = cm->other (); + std::map::const_iterator icm = circuit_map->find (cr); + if (icm == circuit_map->end ()) { + // this can happen if the other circuit does not exist - in this case the key is an invalid one which cannot + // be produced by a regular subcircuit. + return k; } - // NOTE: if cm is given, cr is given in terms of the "other" circuit + const CircuitMapper *cm = & icm->second; + cr = cm->other (); + + // NOTE: cr is given in terms of the canonical "other" circuit. for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) { - size_t this_pin_id = cm ? cm->this_pin_from_other_pin (p->id ()) : p->id (); - size_t pin_id = pin_map ? pin_map->normalize_pin_id (cr, p->id ()) : p->id (); + if (cm->has_this_pin_for_other_pin (p->id ())) { - const db::Net *net = subcircuit.net_for_pin (this_pin_id); - size_t net_id = g.node_index_for_net (net); - k.push_back (std::make_pair (pin_id, net_id)); + size_t this_pin_id = cm->this_pin_from_other_pin (p->id ()); + size_t pin_id = pin_map->normalize_pin_id (cr, p->id ()); + + const db::Net *net = subcircuit.net_for_pin (this_pin_id); + size_t net_id = g.node_index_for_net (net); + k.push_back (std::make_pair (pin_id, net_id)); + + } } @@ -1102,14 +1117,14 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetDeviceGra } bool -NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, const std::vector > &net_identity, bool &pin_mismatch, std::map &circuit_and_pin_mapping) const +NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, const std::vector > &net_identity, bool &pin_mismatch, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const { db::NetDeviceGraph g1, g2; // NOTE: for normalization we map all subcircuits of c1 to c2. // Also, pin swapping will only happen there. - g1.build (c1, device_categorizer, circuit_categorizer, &circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); - g2.build (c2, device_categorizer, circuit_categorizer, 0, mp_circuit_pin_mapper.get ()); + g1.build (c1, device_categorizer, circuit_categorizer, &c12_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); + g2.build (c2, device_categorizer, circuit_categorizer, &c22_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); // Match dummy nodes for null nets g1.identify (0, 0); @@ -1228,48 +1243,54 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // Report pin assignment + // This step also does the pin identity mapping. - std::multimap net2pin; + std::multimap net2pin; 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 ()); - tl_assert (net != 0); - net2pin.insert (std::make_pair (net, p.operator-> ())); + if (net) { + net2pin.insert (std::make_pair (g2.node_index_for_net (net), p.operator-> ())); + } } - CircuitMapper &pin_mapping = circuit_and_pin_mapping [c1]; - pin_mapping.set_other (c2); + CircuitMapper &c12_pin_mapping = c12_circuit_and_pin_mapping [c1]; + c12_pin_mapping.set_other (c2); - for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { + // dummy mapping: we show this circuit is used. + CircuitMapper &c22_pin_mapping = c22_circuit_and_pin_mapping [c2]; + c22_pin_mapping.set_other (c2); - const db::Net *net = i->net (); - if (! net || net->pin_count () == 0) { + for (db::Circuit::const_pin_iterator p = c1->begin_pins (); p != c1->end_pins (); ++p) { + + const db::Net *net = c1->net_for_pin (p->id ()); + if (! net) { continue; } - if (! i->has_other ()) { - for (db::Net::const_pin_iterator pi = net->begin_pins (); pi != net->end_pins (); ++pi) { - if (mp_logger) { - mp_logger->pin_mismatch (pi->pin (), 0); - } - pin_mismatch = true; - good = false; + const db::NetGraphNode &n = *(g1.begin () + g1.node_index_for_net (net)); + + if (! n.has_other ()) { + if (mp_logger) { + mp_logger->pin_mismatch (p.operator-> (), 0); } + pin_mismatch = true; + good = false; continue; } - const db::Net *other_net = g2.net_by_node_index (i->other_net_index ()); - - std::multimap::iterator np = net2pin.find (other_net); + std::multimap::iterator np = net2pin.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 == other_net) { + if (np != net2pin.end () && np->first == n.other_net_index ()) { if (mp_logger) { mp_logger->match_pins (pi->pin (), np->second); } - pin_mapping.map_pin (pi->pin ()->id (), np->second->id ()); + c12_pin_mapping.map_pin (pi->pin ()->id (), np->second->id ()); + // dummy mapping: we show this pin is used. + c22_pin_mapping.map_pin (np->second->id (), np->second->id ()); - std::multimap::iterator np_delete = np; + std::multimap::iterator np_delete = np; ++np; net2pin.erase (np_delete); @@ -1287,7 +1308,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, } - for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { + for (std::multimap::iterator np = net2pin.begin (); np != net2pin.end (); ++np) { if (mp_logger) { mp_logger->pin_mismatch (0, np->second); } @@ -1391,7 +1412,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (db::Circuit::const_subcircuit_iterator sc = c1->begin_subcircuits (); sc != c1->end_subcircuits (); ++sc) { - std::vector > k = compute_subcircuit_key (*sc, g1, &circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); + std::vector > k = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end () && mapped; ++i) { @@ -1414,7 +1435,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (db::Circuit::const_subcircuit_iterator sc = c2->begin_subcircuits (); sc != c2->end_subcircuits (); ++sc) { - std::vector > k = compute_subcircuit_key (*sc, g2, 0, mp_circuit_pin_mapper.get ()); + std::vector > k = compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index a752302d2..b0fcf8009 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -201,7 +201,7 @@ public: bool compare (const db::Netlist *a, const db::Netlist *b) const; protected: - bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, const std::vector > &net_identity, bool &pin_mismatch, std::map &circuit_and_pin_mapping) const; + bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, const std::vector > &net_identity, bool &pin_mismatch, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const; bool all_subcircuits_verified (const db::Circuit *c, const std::set &verified_circuits) const; NetlistCompareLogger *mp_logger; diff --git a/src/db/unit_tests/dbLayoutToNetlistTests.cc b/src/db/unit_tests/dbLayoutToNetlistTests.cc index 7b5999a74..b2d8b8fe9 100644 --- a/src/db/unit_tests/dbLayoutToNetlistTests.cc +++ b/src/db/unit_tests/dbLayoutToNetlistTests.cc @@ -1780,7 +1780,7 @@ TEST(6_MoreDeviceTypes) "circuit TOP ();\n" " device HVPMOS $1 (S=Z,G=$5,D=VDD2,B=$8) (L=1.5,W=4.05,AS=5.4675,AD=2.73375,PS=10.8,PD=5.4);\n" " device HVPMOS $2 (S=VDD2,G=Z,D=$5,B=$8) (L=1.5,W=4.05,AS=2.73375,AD=5.4675,PS=5.4,PD=10.8);\n" - " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=1.11375,AD=3.155625,PS=5.85,PD=7.5);\n" + " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=4.77675,AD=3.155625,PS=8.81,PD=7.5);\n" " device HVNMOS $4 (S=Z,G=$6,D=VSS,B=BULK) (L=1.5,W=5.25,AS=7.0875,AD=3.54375,PS=13.2,PD=6.6);\n" " device HVNMOS $5 (S=VSS,G=A,D=$5,B=BULK) (L=1.5,W=5.25,AS=3.54375,AD=7.0875,PS=6.6,PD=13.2);\n" " device LVNMOS $6 (S=VSS,G=A,D=$6,B=BULK) (L=1.2,W=1.7,AS=2.346,AD=2.1165,PS=6.16,PD=5.89);\n" @@ -1937,7 +1937,7 @@ TEST(7_MoreByEmptyDeviceTypes) "circuit TOP ();\n" " device LVPMOS $1 (S=Z,G=$5,D=VDD2,B=$8) (L=1.5,W=4.05,AS=5.4675,AD=2.73375,PS=10.8,PD=5.4);\n" " device LVPMOS $2 (S=VDD2,G=Z,D=$5,B=$8) (L=1.5,W=4.05,AS=2.73375,AD=5.4675,PS=5.4,PD=10.8);\n" - " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=1.11375,AD=3.155625,PS=5.85,PD=7.5);\n" + " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=4.77675,AD=3.155625,PS=8.81,PD=7.5);\n" " device LVNMOS $4 (S=VSS,G=A,D=$6,B=BULK) (L=1.2,W=1.7,AS=2.346,AD=2.1165,PS=6.16,PD=5.89);\n" " device LVNMOS $5 (S=Z,G=$6,D=VSS,B=BULK) (L=1.5,W=5.25,AS=7.0875,AD=3.54375,PS=13.2,PD=6.6);\n" " device LVNMOS $6 (S=VSS,G=A,D=$5,B=BULK) (L=1.5,W=5.25,AS=3.54375,AD=7.0875,PS=6.6,PD=13.2);\n" @@ -2116,7 +2116,7 @@ TEST(8_FlatExtraction) "circuit TOP ();\n" " device HVPMOS $1 (S=Z,G=$5,D=VDD2,B=$8) (L=1.5,W=4.05,AS=5.4675,AD=2.73375,PS=10.8,PD=5.4);\n" " device HVPMOS $2 (S=VDD2,G=Z,D=$5,B=$8) (L=1.5,W=4.05,AS=2.73375,AD=5.4675,PS=5.4,PD=10.8);\n" - " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=1.11375,AD=3.155625,PS=5.85,PD=7.5);\n" + " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=4.77675,AD=3.155625,PS=8.81,PD=7.5);\n" " device HVNMOS $4 (S=Z,G=$6,D=VSS,B=BULK) (L=1.5,W=5.25,AS=7.0875,AD=3.54375,PS=13.2,PD=6.6);\n" " device HVNMOS $5 (S=VSS,G=A,D=$5,B=BULK) (L=1.5,W=5.25,AS=3.54375,AD=7.0875,PS=6.6,PD=13.2);\n" " device LVNMOS $6 (S=VSS,G=A,D=$6,B=BULK) (L=1.2,W=1.7,AS=2.346,AD=2.1165,PS=6.16,PD=5.89);\n" @@ -2300,7 +2300,7 @@ TEST(9_FlatExtractionWithExternalDSS) "circuit TOP ();\n" " device LVPMOS $1 (S=Z,G=$5,D=VDD2,B=$8) (L=1.5,W=4.05,AS=5.4675,AD=2.73375,PS=10.8,PD=5.4);\n" " device LVPMOS $2 (S=VDD2,G=Z,D=$5,B=$8) (L=1.5,W=4.05,AS=2.73375,AD=5.4675,PS=5.4,PD=10.8);\n" - " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=1.11375,AD=3.155625,PS=5.85,PD=7.5);\n" + " device LVPMOS $3 (S=$10,G=A,D=$6,B=$9) (L=1.5,W=2.475,AS=4.77675,AD=3.155625,PS=8.81,PD=7.5);\n" " device LVNMOS $4 (S=VSS,G=A,D=$6,B=BULK) (L=1.2,W=1.7,AS=2.346,AD=2.1165,PS=6.16,PD=5.89);\n" " device LVNMOS $5 (S=Z,G=$6,D=VSS,B=BULK) (L=1.5,W=5.25,AS=7.0875,AD=3.54375,PS=13.2,PD=6.6);\n" " device LVNMOS $6 (S=VSS,G=A,D=$5,B=BULK) (L=1.5,W=5.25,AS=3.54375,AD=7.0875,PS=6.6,PD=13.2);\n" diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 8dade2799..7d21d100b 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -228,10 +228,10 @@ TEST(1_SimpleInverter) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH" @@ -274,10 +274,10 @@ TEST(1_SimpleInverterMatchedDeviceClasses) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH" @@ -316,10 +316,10 @@ TEST(2_SimpleInverterWithForcedNetAssignment) "begin_circuit INV INV\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH" @@ -361,9 +361,9 @@ TEST(3_Buffer) "match_nets IN IN\n" "match_nets VSS VSS\n" "match_nets INT $10\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -417,9 +417,9 @@ TEST(4_BufferTwoPaths) "match_nets VSS VSS\n" "match_ambiguous_nets INT $10\n" "match_ambiguous_nets INT2 $11\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -481,9 +481,9 @@ TEST(5_BufferTwoPathsDifferentParameters) "match_nets IN IN\n" "match_ambiguous_nets INT $10\n" "match_nets INT2 $11\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -545,9 +545,9 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses) "match_nets INT $10\n" "match_nets OUT OUT\n" "match_nets INT2 $11\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -610,9 +610,9 @@ TEST(6_BufferTwoPathsAdditionalResistor) "match_nets OUT OUT\n" "match_nets INT2 $11\n" "match_nets IN IN\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -673,9 +673,9 @@ TEST(6_BufferTwoPathsAdditionalDevices) "match_nets OUT OUT\n" "match_nets VSS VSS\n" "match_nets INT2 $10\n" + "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" - "match_pins $0 $1\n" "match_pins $3 $2\n" "match_devices $5 $1\n" "match_devices $7 $2\n" @@ -722,8 +722,8 @@ TEST(7_Resistors) "match_nets P1 P1\n" "match_nets P3 P3\n" "match_nets P2 P2\n" - "match_pins $1 $1\n" "match_pins $0 $0\n" + "match_pins $1 $1\n" "match_pins $2 $2\n" "match_devices $2 $1\n" "match_devices $1 $2\n" @@ -763,8 +763,8 @@ TEST(7_ResistorsParameterMismatch) "match_nets P2 P2\n" "match_nets P1 P1\n" "match_nets P3 P3\n" - "match_pins $1 $1\n" "match_pins $0 $0\n" + "match_pins $1 $1\n" "match_pins $2 $2\n" "match_devices $1 $1\n" "match_devices_with_different_parameters $3 $2\n" @@ -805,8 +805,8 @@ TEST(7_ResistorsPlusOneDevice) "match_nets P3 P3\n" "match_nets P2 P2\n" "match_nets P1 P1\n" - "match_pins $1 $1\n" "match_pins $0 $0\n" + "match_pins $1 $1\n" "match_pins $2 $2\n" "match_devices $1 $1\n" "match_devices $3 $2\n" @@ -848,8 +848,8 @@ TEST(8_Diodes) "match_nets P3 P3\n" "match_nets P2 P2\n" "match_pins $0 $0\n" - "match_pins $2 $2\n" "match_pins $1 $1\n" + "match_pins $2 $2\n" "match_devices $3 $1\n" "match_devices $2 $2\n" "match_devices $1 $3\n" @@ -937,10 +937,10 @@ TEST(10_SimpleSubCircuits) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH\n" @@ -950,10 +950,10 @@ TEST(10_SimpleSubCircuits) "match_nets VSS VSS\n" "match_nets VDD VDD\n" "match_nets INT INT\n" - "match_pins $1 $0\n" "match_pins $0 $2\n" - "match_pins $3 $3\n" + "match_pins $1 $0\n" "match_pins $2 $1\n" + "match_pins $3 $3\n" "match_subcircuits $2 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -1004,10 +1004,10 @@ TEST(10_SimpleSubCircuitsMatchedNames) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INVB MATCH\n" @@ -1017,10 +1017,10 @@ TEST(10_SimpleSubCircuitsMatchedNames) "match_nets VSS VSS\n" "match_nets VDD VDD\n" "match_nets INT INT\n" - "match_pins $1 $0\n" "match_pins $0 $2\n" - "match_pins $3 $3\n" + "match_pins $1 $0\n" "match_pins $2 $1\n" + "match_pins $3 $3\n" "match_subcircuits $2 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -1068,10 +1068,10 @@ TEST(11_MismatchingSubcircuits) "match_nets IN IN\n" "net_mismatch VDD (null)\n" "net_mismatch (null) VDD\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "pin_mismatch $2 (null)\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "pin_mismatch (null) $0\n" "device_mismatch $1 (null)\n" "match_devices $2 $1\n" @@ -1121,10 +1121,10 @@ TEST(12_MismatchingSubcircuitsDuplicates) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH\n" @@ -1135,10 +1135,10 @@ TEST(12_MismatchingSubcircuitsDuplicates) "match_nets INT INT\n" "net_mismatch OUT (null)\n" "net_mismatch (null) OUT\n" - "pin_mismatch $1 (null)\n" "match_pins $0 $1\n" - "match_pins $3 $3\n" + "pin_mismatch $1 (null)\n" "match_pins $2 $2\n" + "match_pins $3 $3\n" "pin_mismatch (null) $0\n" "subcircuit_mismatch $2 (null)\n" "subcircuit_mismatch $3 (null)\n" @@ -1192,10 +1192,10 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_pins $0 $1\n" + "match_pins $1 $3\n" "match_pins $2 $0\n" "match_pins $3 $2\n" - "match_pins $1 $3\n" - "match_pins $0 $1\n" "match_devices $2 $1\n" "match_devices $1 $2\n" "end_circuit INV INV MATCH\n" @@ -1205,10 +1205,10 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "match_nets VSS VSS\n" "match_nets VDD VDD\n" "match_nets INT INT\n" - "match_pins $1 $0\n" "match_pins $0 $1\n" - "match_pins $3 $3\n" + "match_pins $1 $0\n" "match_pins $2 $2\n" + "match_pins $3 $3\n" "match_subcircuits $3 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -1261,11 +1261,11 @@ TEST(14_Subcircuit2Nand) "match_nets OUT OUT\n" "match_nets A A\n" "match_nets INT INT\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" + "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" - "match_pins $0 $0\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_devices $1 $1\n" "match_devices $2 $2\n" "match_devices $3 $3\n" @@ -1276,13 +1276,13 @@ TEST(14_Subcircuit2Nand) "match_nets IN2 IN2\n" "match_nets VSS VSS\n" "match_nets VDD VDD\n" - "match_nets IN1 IN1\n" "match_nets INT INT\n" - "match_pins $2 $2\n" - "match_pins $1 $1\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" + "match_nets IN1 IN1\n" "match_pins $0 $0\n" + "match_pins $1 $1\n" + "match_pins $2 $2\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_subcircuits $2 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -1335,11 +1335,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "match_nets OUT OUT\n" "match_nets A A\n" "match_nets INT INT\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" + "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" - "match_pins $0 $0\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_devices $1 $1\n" "match_devices $2 $2\n" "match_devices $3 $3\n" @@ -1347,22 +1347,22 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" + "match_nets IN1 INT\n" "match_nets INT IN1\n" "match_nets VDD VDD\n" "match_nets VSS VSS\n" - "match_nets IN1 IN2\n" "net_mismatch IN2 (null)\n" - "net_mismatch (null) INT\n" - "match_pins $2 $2\n" + "net_mismatch (null) IN2\n" + "pin_mismatch $0 (null)\n" "pin_mismatch $1 (null)\n" - "match_pins $4 $4\n" + "match_pins $2 $2\n" "match_pins $3 $3\n" - "match_pins $0 $1\n" + "match_pins $4 $4\n" + "pin_mismatch (null) $1\n" "pin_mismatch (null) $0\n" "subcircuit_mismatch $1 (null)\n" - "subcircuit_mismatch (null) $1\n" + "match_subcircuits $2 $1\n" "subcircuit_mismatch (null) $2\n" - "subcircuit_mismatch $2 (null)\n" "end_circuit TOP TOP NOMATCH" ); @@ -1413,11 +1413,11 @@ TEST(14_Subcircuit2MatchWithSwap) "match_nets OUT OUT\n" "match_nets A A\n" "match_nets INT INT\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" + "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" - "match_pins $0 $0\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_devices $1 $1\n" "match_devices $2 $2\n" "match_devices $3 $3\n" @@ -1427,14 +1427,14 @@ TEST(14_Subcircuit2MatchWithSwap) "match_nets OUT OUT\n" "match_nets IN2 IN2\n" "match_nets VSS VSS\n" - "match_nets INT INT\n" "match_nets VDD VDD\n" + "match_nets INT INT\n" "match_nets IN1 IN1\n" - "match_pins $2 $2\n" - "match_pins $1 $1\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" "match_pins $0 $0\n" + "match_pins $1 $1\n" + "match_pins $2 $2\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_subcircuits $2 $1\n" "match_subcircuits $1 $2\n" "end_circuit TOP TOP MATCH" @@ -1488,21 +1488,21 @@ TEST(15_EmptySubCircuitTest) "match_nets $3 $3\n" "match_nets $2 $1\n" "match_nets $1 $2\n" - "match_pins D D\n" - "match_pins G G\n" "match_pins S S\n" + "match_pins G G\n" + "match_pins D D\n" "end_circuit TRANS TRANS MATCH\n" "begin_circuit INV2 INV2\n" "match_nets IN IN\n" + "match_nets OUT OUT\n" "match_nets $5 $5\n" "match_nets $4 $4\n" - "match_nets OUT OUT\n" "match_nets $2 $2\n" "match_pins IN IN\n" - "match_pins $4 $4\n" - "match_pins $3 $3\n" - "match_pins OUT OUT\n" "match_pins $1 $1\n" + "match_pins OUT OUT\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" "match_devices $1 $1\n" "match_devices $3 $2\n" "match_devices $2 $3\n" @@ -1516,3 +1516,116 @@ TEST(15_EmptySubCircuitTest) EXPECT_EQ (good, true); } + +TEST(16_UniqueSubCircuitMatching) +{ + const char *nls1 = + "circuit RINGO ();\n" + " subcircuit INV2PAIR $1 (BULK='BULK,VSS',$2=FB,$3=VDD,$4='BULK,VSS',$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK='BULK,VSS',$2=$I22,$3=VDD,$4='BULK,VSS',$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK='BULK,VSS',$2=$I23,$3=VDD,$4='BULK,VSS',$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK='BULK,VSS',$2=$I24,$3=VDD,$4='BULK,VSS',$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK='BULK,VSS',$2=$I25,$3=VDD,$4='BULK,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 PMOS4 $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS4 $2 (S=VDD,G=$3,D=OUT,B=$1) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS4 $3 (S=$3,G=IN,D=VSS,B=BULK) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS4 $4 (S=VSS,G=$3,D=OUT,B=BULK) (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 ();\n" + " subcircuit INV2PAIR $1 (BULK='BULK,VSS',$2=FB,$3=VDD,$4='BULK,VSS',$5=$I7,$6=OSC,$7=VDD);\n" + " subcircuit INV2PAIR $2 (BULK='BULK,VSS',$2=$I24,$3=VDD,$4='BULK,VSS',$5=$I5,$6=$I6,$7=VDD);\n" + " subcircuit INV2PAIR $3 (BULK='BULK,VSS',$2=$I23,$3=VDD,$4='BULK,VSS',$5=$I13,$6=$I5,$7=VDD);\n" + " subcircuit INV2PAIR $4 (BULK='BULK,VSS',$2=$I22,$3=VDD,$4='BULK,VSS',$5=FB,$6=$I13,$7=VDD);\n" + " subcircuit INV2PAIR $5 (BULK='BULK,VSS',$2=$I25,$3=VDD,$4='BULK,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=$I4,$3=$I8,OUT=$I2,VSS=$I5,VDD=$I6,BULK=BULK);\n" + " subcircuit INV2 $2 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,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 PMOS4 $1 (S=$3,G=IN,D=VDD,B=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS4 $2 (S=$3,G=IN,D=VSS,B=BULK) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS4 $3 (S=VDD,G=$3,D=OUT,B=$1) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n" + " device NMOS4 $4 (S=VSS,G=$3,D=OUT,B=BULK) (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); + + EXPECT_EQ (logger.text (), + "begin_circuit INV2 INV2\n" + "match_nets VDD VDD\n" + "match_nets $1 $1\n" + "match_nets VSS VSS\n" + "match_nets BULK BULK\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_nets $3 $3\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 BULK BULK\n" + "match_devices $1 $1\n" + "match_devices $3 $2\n" + "match_devices $2 $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 $I3 $I3\n" + "match_nets BULK BULK\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I4 $I4\n" + "match_nets $I1 $I1\n" + "match_nets $I7 $I7\n" + "match_nets $I8 $I8\n" + "match_pins BULK BULK\n" + "match_pins $1 $1\n" + "match_pins $2 $2\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" + "match_pins $5 $5\n" + "match_pins $6 $6\n" + "match_subcircuits $2 $1\n" + "match_subcircuits $1 $2\n" + "end_circuit INV2PAIR INV2PAIR MATCH\n" + "begin_circuit RINGO RINGO\n" + "match_nets OSC OSC\n" + "match_nets FB FB\n" + "match_nets VDD VDD\n" + "match_nets BULK,VSS BULK,VSS\n" + "match_nets $I22 $I22\n" + "match_nets $I13 $I13\n" + "match_nets $I7 $I7\n" + "match_nets $I23 $I23\n" + "match_nets $I5 $I5\n" + "match_nets $I25 $I25\n" + "match_nets $I24 $I24\n" + "match_nets $I6 $I6\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $4 $2\n" + "match_subcircuits $3 $3\n" + "match_subcircuits $2 $4\n" + "match_subcircuits $5 $5\n" + "end_circuit RINGO RINGO MATCH" + ); + + EXPECT_EQ (good, true); +} diff --git a/testdata/algo/device_extract_l6.gds b/testdata/algo/device_extract_l6.gds index 73ece855b6fadc7120d50dc3f5ce3073412e95f1..6fbeeb989217480ef9429f47f1c557c3f0922771 100644 GIT binary patch delta 201 zcmX@7bWTZ$fsKKQDS|gD`^;gA_7*qLQ)GHt9j2VaV=nAFm`2N0MRxd x7#L(35i~@6au#2l5?2ocgOMaq8ITSNW?+!3K+q8J$*=gFnD}>Y*5g-T0sw8LD delta 202 zcmX@7bWTZ$fsKKQDS|gA6izqLQ)