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 73ece855b..6fbeeb989 100644 Binary files a/testdata/algo/device_extract_l6.gds and b/testdata/algo/device_extract_l6.gds differ