From 92524dcf57f8af85945a8b9345ca2fda48c053ad Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 13 Apr 2019 19:56:08 +0200 Subject: [PATCH] WIP: netlist compare - bugfixed latest version and updated tests. --- src/db/db/dbNetlistCompare.cc | 61 +++++++++++-- src/db/db/dbNetlistCompare.h | 3 +- src/db/unit_tests/dbNetlistCompareTests.cc | 99 +++++++++++++++++----- testdata/ruby/dbNetlistCompare.rb | 8 +- 4 files changed, 134 insertions(+), 37 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 145ddac63..91d72f621 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -29,7 +29,7 @@ #include "tlLog.h" // verbose debug output -#define PRINT_DEBUG_NETCOMPARE +// #define PRINT_DEBUG_NETCOMPARE namespace db { @@ -100,6 +100,16 @@ public: } } + size_t is_mapped (const db::Circuit *circuit, size_t pin_id) const + { + std::map >::const_iterator pm = m_pin_map.find (circuit); + if (pm != m_pin_map.end ()) { + return pm->second.has_attribute (pin_id); + } else { + return false; + } + } + size_t normalize_pin_id (const db::Circuit *circuit, size_t pin_id) const { std::map >::const_iterator pm = m_pin_map.find (circuit); @@ -1468,6 +1478,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const // we need to create a copy because this method is supposed to be const. db::CircuitCategorizer circuit_categorizer = *mp_circuit_categorizer; db::DeviceCategorizer device_categorizer = *mp_device_categorizer; + db::CircuitPinMapper circuit_pin_mapper = *mp_circuit_pin_mapper; bool good = true; @@ -1553,7 +1564,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, c12_pin_mapping, c22_pin_mapping); + 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; } @@ -1563,6 +1574,8 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const verified_circuits_b.insert (cb); } + derive_pin_equivalence (ca, cb, &circuit_pin_mapper); + if (mp_logger) { mp_logger->end_circuit (ca, cb, g); } @@ -1586,6 +1599,36 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const return good; } +static +std::vector collect_pins_with_empty_nets (const db::Circuit *c, CircuitPinMapper *circuit_pin_mapper) +{ + std::vector pins; + + for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { + const db::Net *net = n.operator-> (); + if (net->pin_count () > 0 && net->terminal_count () == 0 && net->subcircuit_pin_count () == 0) { + for (db::Net::const_pin_iterator p = net->begin_pins (); p != net->end_pins (); ++p) { + if (! circuit_pin_mapper->is_mapped (c, p->pin_id ())) { + pins.push_back (p->pin_id ()); + } + } + } + } + + return pins; +} + +void +NetlistComparer::derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper) +{ + std::vector pa, pb; + pa = collect_pins_with_empty_nets (ca, circuit_pin_mapper); + pb = collect_pins_with_empty_nets (cb, circuit_pin_mapper); + + circuit_pin_mapper->map_pins (ca, pa); + circuit_pin_mapper->map_pins (cb, pb); +} + bool NetlistComparer::all_subcircuits_verified (const db::Circuit *c, const std::set &verified_circuits) const { @@ -1662,7 +1705,7 @@ 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 &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const +NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, const std::vector > &net_identity, bool &pin_mismatch, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const { db::DeviceFilter device_filter (m_cap_threshold, m_res_threshold); @@ -1670,8 +1713,8 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // 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, device_filter, &c12_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); - g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); + g1.build (c1, device_categorizer, circuit_categorizer, device_filter, &c12_circuit_and_pin_mapping, &circuit_pin_mapper); + g2.build (c2, device_categorizer, circuit_categorizer, device_filter, &c22_circuit_and_pin_mapping, &circuit_pin_mapper); // Match dummy nodes for null nets g1.identify (0, 0); @@ -1707,7 +1750,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { if (i1->has_other () && i1->net ()) { - size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), 0 /*not tentative*/, pass > 0 /*with ambiguities*/); + size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, 0, 1, mp_logger, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); if (ni > 0 && ni != std::numeric_limits::max ()) { new_identities += ni; #if defined(PRINT_DEBUG_NETCOMPARE) @@ -1750,7 +1793,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, std::sort (nodes.begin (), nodes.end (), CompareNodePtr ()); std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ()); - size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), 0 /*not tentative*/, pass > 0 /*with ambiguities*/); + size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, 1, mp_logger, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); if (ni > 0 && ni != std::numeric_limits::max ()) { new_identities += ni; #if defined(PRINT_DEBUG_NETCOMPARE) @@ -1960,7 +2003,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, &c12_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); + std::vector > k = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper); bool mapped = true; for (std::vector >::iterator i = k.begin (); i != k.end () && mapped; ++i) { @@ -1983,7 +2026,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, &c22_circuit_and_pin_mapping, mp_circuit_pin_mapper.get ()); + std::vector > k = compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper); 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 f2cfa9bf3..88e76af2b 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -217,8 +217,9 @@ 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 &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping) const; + bool compare_circuits (const db::Circuit *c1, const db::Circuit *c2, db::DeviceCategorizer &device_categorizer, db::CircuitCategorizer &circuit_categorizer, db::CircuitPinMapper &circuit_pin_mapper, 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; + static void derive_pin_equivalence (const db::Circuit *ca, const db::Circuit *cb, CircuitPinMapper *circuit_pin_mapper); NetlistCompareLogger *mp_logger; std::map, std::vector > > m_same_nets; diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index bf229877d..92c907966 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -335,8 +335,9 @@ TEST(1_SimpleInverter) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" + "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -880,8 +881,8 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses) "begin_circuit BUF BUF\n" "match_nets INT $10\n" "match_nets IN IN\n" - "match_nets INT2 $11\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" @@ -945,8 +946,8 @@ TEST(6_BufferTwoPathsAdditionalResistor) "begin_circuit BUF BUF\n" "match_nets INT $10\n" "match_nets IN IN\n" - "match_nets INT2 $11\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" @@ -1007,9 +1008,9 @@ TEST(6_BufferTwoPathsAdditionalDevices) "match_nets INT $11\n" "match_nets VDD VDD\n" "match_nets IN IN\n" - "match_nets INT2 $10\n" "match_nets VSS VSS\n" "match_nets OUT OUT\n" + "match_nets INT2 $10\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1617,9 +1618,9 @@ TEST(14_Subcircuit2Nand) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets IN1 IN1\n" - "match_nets IN2 IN2\n" "match_nets INT INT\n" + "match_nets IN2 IN2\n" + "match_nets IN1 IN1\n" "match_nets VDD VDD\n" "match_nets VSS VSS\n" "match_pins $0 $0\n" @@ -1767,9 +1768,9 @@ TEST(14_Subcircuit2MatchWithSwap) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets IN1 IN1\n" - "match_nets IN2 IN2\n" "match_nets INT INT\n" + "match_nets IN2 IN2\n" + "match_nets IN1 IN1\n" "match_nets VDD VDD\n" "match_nets VSS VSS\n" "match_pins $0 $0\n" @@ -1886,7 +1887,8 @@ TEST(15_EmptySubCircuitWithoutPinNames) " subcircuit TRANS $3 ($1=OUT,$2=$5,$3=$2);\n" " subcircuit TRANS $4 ($1=OUT,$2=$4,$3=$2);\n" "end;\n" - // This circuit is an abstract and it's pins are defined by the pin names + // This circuit is an abstract and it's pins are not defined by the pin names -> + // they are internally marked as swappable "circuit TRANS ($1=$1,$2=$2,$3=$3);\n" "end;\n"; @@ -2110,27 +2112,27 @@ TEST(17_InherentlyAmbiguousDecoder) "match_devices $4 $4\n" "end_circuit NAND NAND MATCH\n" "begin_circuit DECODER DECODER\n" - "match_nets NA NB\n" - "match_nets A B\n" - "match_nets VDD VDD\n" - "match_nets B A\n" - "match_nets NB NA\n" "match_nets VSS VSS\n" - "match_ambiguous_nets NQ0 NQ0\n" - "match_ambiguous_nets NQ2 NQ1\n" - "match_ambiguous_nets NQ1 NQ2\n" - "match_ambiguous_nets NQ3 NQ3\n" - "match_pins $0 $1\n" - "match_pins $1 $0\n" + "match_nets VDD VDD\n" + "match_ambiguous_nets A B\n" + "match_ambiguous_nets B A\n" + "match_nets NB NA\n" + "match_nets NA NB\n" + "match_nets NQ0 NQ0\n" + "match_nets NQ2 NQ1\n" + "match_nets NQ1 NQ2\n" + "match_nets NQ3 NQ3\n" + "match_pins $0 $0\n" + "match_pins $1 $1\n" "match_pins $2 $2\n" "match_pins $3 $4\n" "match_pins $4 $3\n" "match_pins $5 $5\n" "match_pins $6 $6\n" "match_pins $7 $7\n" - "match_subcircuits $1 $1\n" - "match_subcircuits $5 $2\n" - "match_subcircuits $2 $3\n" + "match_subcircuits $2 $1\n" + "match_subcircuits $1 $2\n" + "match_subcircuits $5 $3\n" "match_subcircuits $6 $4\n" "match_subcircuits $3 $5\n" "match_subcircuits $4 $6\n" @@ -2138,5 +2140,56 @@ TEST(17_InherentlyAmbiguousDecoder) ); EXPECT_EQ (good, true); + + logger.clear (); + comp.same_nets (nl1.circuit_by_name ("DECODER")->net_by_name ("A"), nl2.circuit_by_name ("DECODER")->net_by_name ("A")); + good = comp.compare (&nl1, &nl2); + + EXPECT_EQ (logger.text (), + "begin_circuit NAND NAND\n" + "match_nets VSS VSS\n" + "match_nets INT INT\n" + "match_nets OUT OUT\n" + "match_nets VDD VDD\n" + "match_nets B B\n" + "match_nets A A\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_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit NAND NAND MATCH\n" + "begin_circuit DECODER DECODER\n" + "match_nets NB NB\n" + "match_nets B B\n" + "match_nets NA NA\n" + "match_nets VDD VDD\n" + "match_nets VSS VSS\n" + "match_nets NQ0 NQ0\n" + "match_nets NQ2 NQ2\n" + "match_nets NQ1 NQ1\n" + "match_nets NQ3 NQ3\n" + "match_pins $0 $1\n" + "match_pins $1 $0\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_pins $7 $7\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $2 $2\n" + "match_subcircuits $4 $3\n" + "match_subcircuits $6 $4\n" + "match_subcircuits $3 $5\n" + "match_subcircuits $5 $6\n" + "end_circuit DECODER DECODER MATCH" + ); + + EXPECT_EQ (good, true); } diff --git a/testdata/ruby/dbNetlistCompare.rb b/testdata/ruby/dbNetlistCompare.rb index e78ad6564..f51bfd979 100644 --- a/testdata/ruby/dbNetlistCompare.rb +++ b/testdata/ruby/dbNetlistCompare.rb @@ -616,8 +616,8 @@ END begin_circuit BUF BUF match_nets INT $10 match_nets IN IN -match_nets INT2 $11 match_nets OUT OUT +match_nets INT2 $11 match_pins $0 $1 match_pins $1 $3 match_pins $2 $0 @@ -686,8 +686,8 @@ END begin_circuit BUF BUF match_nets INT $10 match_nets IN IN -match_nets INT2 $11 match_nets OUT OUT +match_nets INT2 $11 match_pins $0 $1 match_pins $1 $3 match_pins $2 $0 @@ -840,9 +840,9 @@ match_devices $4 $4 end_circuit NAND NAND MATCH begin_circuit TOP TOP match_nets OUT OUT -match_nets IN1 IN1 -match_nets IN2 IN2 match_nets INT INT +match_nets IN2 IN2 +match_nets IN1 IN1 match_nets VDD VDD match_nets VSS VSS match_pins $0 $0