diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 69637e00f..5d8227a3a 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -616,13 +616,14 @@ class NetGraph; struct CompareData { CompareData () - : other (0), max_depth (0), max_n_branch (0), dont_consider_net_names (false), logger (0), + : other (0), max_depth (0), max_n_branch (0), depth_first (true), dont_consider_net_names (false), logger (0), circuit_pin_mapper (0), subcircuit_equivalence (0), device_equivalence (0) { } NetGraph *other; size_t max_depth; size_t max_n_branch; + bool depth_first; bool dont_consider_net_names; NetlistCompareLogger *logger; CircuitPinMapper *circuit_pin_mapper; @@ -2328,16 +2329,15 @@ NetGraph::derive_node_identities_from_node_set (std::vectordepth_first || tentative) { size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data); if (bt_count == failed_match) { - return failed_match; + if (tentative) { + return failed_match; + } + } else { + new_nodes += bt_count; } - - new_nodes += bt_count; - } new_nodes += 1; @@ -2501,16 +2501,15 @@ NetGraph::derive_node_identities_from_node_set (std::vectordepth_first || tentative) { size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data); if (bt_count == failed_match) { - return failed_match; + if (tentative) { + return failed_match; + } + } else { + new_nodes += bt_count; } - - new_nodes += bt_count; - } new_nodes += 1; @@ -2733,6 +2732,7 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger) m_max_depth = 50; m_max_n_branch = 500; + m_depth_first = true; m_dont_consider_net_names = false; } @@ -3080,6 +3080,42 @@ compute_device_key (const db::Device &device, const db::NetGraph &g, bool strict return k; } +static std::vector > +compute_device_key_for_this (const db::Device &device, const db::NetGraph &g, bool strict, bool &mapped) +{ + std::vector > k = compute_device_key (device, g, strict); + + mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { + if (! g.begin () [i->second].has_other ()) { + i->second = invalid_id; // normalization + mapped = false; + } + } + + std::sort (k.begin (), k.end ()); + return k; +} + +static std::vector > +compute_device_key_for_other (const db::Device &device, const db::NetGraph &g, bool strict, bool &mapped) +{ + std::vector > k = compute_device_key (device, g, strict); + + mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { + if (! g.begin () [i->second].has_other ()) { + i->second = invalid_id; // normalization + mapped = false; + } else { + i->second = g.begin () [i->second].other_net_index (); + } + } + + std::sort (k.begin (), k.end ()); + return k; +} + static bool compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map *circuit_map, const CircuitPinMapper *pin_map, std::vector > &k) { @@ -3114,6 +3150,46 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g, return true; } +static std::vector > +compute_subcircuit_key_for_this (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map *circuit_map, const CircuitPinMapper *pin_map, bool &mapped) +{ + std::vector > k; + if (! compute_subcircuit_key (subcircuit, g, circuit_map, pin_map, k)) { + k.clear (); + } + + mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end () && mapped; ++i) { + if (! g.begin () [i->second].has_other ()) { + mapped = false; + } + } + + std::sort (k.begin (), k.end ()); + return k; +} + +static std::vector > +compute_subcircuit_key_for_other (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map *circuit_map, const CircuitPinMapper *pin_map, bool &mapped) +{ + std::vector > k; + if (! compute_subcircuit_key (subcircuit, g, circuit_map, pin_map, k)) { + k.clear (); + } + + mapped = true; + for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { + if (! g.begin () [i->second].has_other ()) { + mapped = false; + } else { + i->second = g.begin () [i->second].other_net_index (); + } + } + + std::sort (k.begin (), k.end ()); + return k; +} + namespace { inline double size_dist (size_t a, size_t b) @@ -3297,7 +3373,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, bool good = false; - for (int pass = 0; pass < 2 /*&& ! good*/; ++pass) { + for (int pass = 0; pass < 2 && ! good; ++pass) { if (options ()->debug_netcompare) { if (pass > 0) { @@ -3324,6 +3400,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, data.other = &g2; data.max_depth = m_max_depth; data.max_n_branch = m_max_n_branch; + data.depth_first = m_depth_first; data.dont_consider_net_names = m_dont_consider_net_names; data.circuit_pin_mapper = &circuit_pin_mapper; data.subcircuit_equivalence = &subcircuit_equivalence; @@ -3375,6 +3452,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (std::vector >::const_iterator n = other_nodes.begin (); n != other_nodes.end () && good; ++n) { good = is_passive_net (n->first->net (), c22_circuit_and_pin_mapping); } + if (options ()->debug_netcompare) { + tl::info << "Stopped with " << nodes.size () << "/" << other_nodes.size () << " nodes left unresolved " << (good ? "(accepted)" : "(not accepted)"); + } // this assumes that we don't gain anything here. Stop now. break; } @@ -3416,6 +3496,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { if (! i->has_other ()) { + if (options ()->debug_netcompare) { + tl::info << "Unresolved net from left: " << i->net ()->expanded_name () << " " << (good ? "(accepted)" : "(not accepted)"); + } if (mp_logger) { if (good) { mp_logger->match_nets (i->net (), 0); @@ -3432,6 +3515,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) { if (! i->has_other ()) { + if (options ()->debug_netcompare) { + tl::info << "Unresolved net from right: " << i->net ()->expanded_name () << " " << (good ? "(accepted)" : "(not accepted)"); + } if (mp_logger) { if (good) { mp_logger->match_nets (0, i->net ()); @@ -3672,6 +3758,69 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph typedef std::vector >, std::pair > > unmatched_list; unmatched_list unmatched_a, unmatched_b; + // check mapping of devices whose equivalence is established topologically + + for (db::Circuit::const_device_iterator d = c1->begin_devices (); d != c1->end_devices (); ++d) { + + if (! device_filter.filter (d.operator-> ())) { + continue; + } + + const db::Device *d_other = device_eq.other (d.operator-> ()); + if (! d_other) { + continue; + } + + size_t device_cat = device_categorizer.cat_for_device (d.operator-> ()); + if (! device_cat) { + // device is ignored + continue; + } + + size_t device_cat_other = device_categorizer.cat_for_device (d_other); + if (! device_cat_other) { + // device is ignored + continue; + } + + bool mapped1 = true, mapped2 = true; + std::vector > k = compute_device_key_for_this (*d, g1, device_categorizer.is_strict_device_category (device_cat), mapped1); + std::vector > k_other = compute_device_key_for_other (*d_other, g2, device_categorizer.is_strict_device_category (device_cat_other), mapped2); + + if (! mapped1 || ! mapped2 || k != k_other) { + + // topological mismatch + if (mp_logger) { + mp_logger->device_mismatch (d.operator-> (), d_other); + } + good = false; + + } else { + + db::DeviceCompare dc; + + if (! dc.equals (std::make_pair (d.operator-> (), device_cat), std::make_pair (d_other, device_cat_other))) { + if (device_cat != device_cat_other) { + if (mp_logger) { + mp_logger->match_devices_with_different_device_classes (d.operator-> (), d_other); + } + good = false; + } else { + if (mp_logger) { + mp_logger->match_devices_with_different_parameters (d.operator-> (), d_other); + } + good = false; + } + } else { + if (mp_logger) { + mp_logger->match_devices (d.operator-> (), d_other); + } + } + + } + + } + for (db::Circuit::const_device_iterator d = c1->begin_devices (); d != c1->end_devices (); ++d) { if (! device_filter.filter (d.operator-> ())) { @@ -3688,17 +3837,8 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph continue; } - std::vector > k = compute_device_key (*d, g1, device_categorizer.is_strict_device_category (device_cat)); - bool mapped = true; - for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g1.begin () [i->second].has_other ()) { - i->second = invalid_id; // normalization - mapped = false; - } - } - - std::sort (k.begin (), k.end ()); + std::vector > k = compute_device_key_for_this (*d, g1, device_categorizer.is_strict_device_category (device_cat), mapped); if (! mapped) { if (mp_logger) { @@ -3718,52 +3858,37 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph continue; } + if (device_eq.other (d.operator-> ())) { + continue; + } + size_t device_cat = device_categorizer.cat_for_device (d.operator-> ()); if (! device_cat) { // device is ignored continue; } - const db::Device *c1_device = device_eq.other (d.operator-> ()); + const db::Device *c1_device = 0; size_t c1_device_cat = 0; - if (c1_device) { + bool mapped = true; + std::vector > k = compute_device_key_for_other (*d, g2, device_categorizer.is_strict_device_category (device_cat), mapped); - c1_device_cat = device_categorizer.cat_for_device (c1_device); + std::multimap >, std::pair >::iterator dm = device_map.find (k); + + if (! mapped || dm == device_map.end () || dm->first != k) { + + if (mp_logger) { + unmatched_b.push_back (std::make_pair (k, std::make_pair (d.operator-> (), device_cat))); + } + good = false; } else { - std::vector > k = compute_device_key (*d, g2, device_categorizer.is_strict_device_category (device_cat)); + c1_device = dm->second.first; + c1_device_cat = dm->second.second; - bool mapped = true; - for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g2.begin () [i->second].has_other ()) { - i->second = invalid_id; // normalization - mapped = false; - } else { - i->second = g2.begin () [i->second].other_net_index (); - } - } - - std::sort (k.begin (), k.end ()); - - std::multimap >, std::pair >::iterator dm = device_map.find (k); - - if (! mapped || dm == device_map.end () || dm->first != k) { - - if (mp_logger) { - unmatched_b.push_back (std::make_pair (k, std::make_pair (d.operator-> (), device_cat))); - } - good = false; - - } else { - - c1_device = dm->second.first; - c1_device_cat = dm->second.second; - - device_map.erase (dm); - - } + device_map.erase (dm); } @@ -3878,6 +4003,42 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG std::multimap >, std::pair > subcircuit_map; + for (db::Circuit::const_subcircuit_iterator sc = c1->begin_subcircuits (); sc != c1->end_subcircuits (); ++sc) { + + size_t sc_cat = circuit_categorizer.cat_for_subcircuit (sc.operator-> ()); + if (! sc_cat) { + // subcircuit is ignored + continue; + } + + const db::SubCircuit *sc_other = subcircuit_eq.other (sc.operator-> ()); + if (! sc_other) { + continue; + } + + size_t sc_cat_other = circuit_categorizer.cat_for_subcircuit (sc_other); + if (! sc_cat_other) { + // subcircuit is ignored + continue; + } + + bool mapped1 = true, mapped2 = true; + std::vector > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped1); + std::vector > k_other = compute_subcircuit_key_for_other (*sc_other, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, mapped2); + + if (! mapped1 || ! mapped2 || k != k_other || sc_cat != sc_cat_other) { + if (mp_logger) { + mp_logger->subcircuit_mismatch (sc.operator-> (), sc_other); + } + good = false; + } else { + if (mp_logger) { + mp_logger->match_subcircuits (sc.operator-> (), sc_other); + } + } + + } + for (db::Circuit::const_subcircuit_iterator sc = c1->begin_subcircuits (); sc != c1->end_subcircuits (); ++sc) { size_t sc_cat = circuit_categorizer.cat_for_subcircuit (sc.operator-> ()); @@ -3890,24 +4051,15 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG continue; } - std::vector > k; - bool valid = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, k); - bool mapped = true; - for (std::vector >::iterator i = k.begin (); i != k.end () && mapped; ++i) { - if (! g1.begin () [i->second].has_other ()) { - mapped = false; - } - } - - std::sort (k.begin (), k.end ()); + std::vector > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped); if (! mapped) { if (mp_logger) { mp_logger->subcircuit_mismatch (sc.operator-> (), 0); } good = false; - } else if (valid) { + } else if (! k.empty ()) { // TODO: report devices which cannot be distiguished topologically? subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat))); } @@ -3925,87 +4077,68 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG continue; } - const db::SubCircuit *c1_subcircuit = subcircuit_eq.other (sc.operator-> ()); + if (subcircuit_eq.other (sc.operator-> ())) { + continue; + } - if (c1_subcircuit) { + bool mapped = true; + std::vector > k = compute_subcircuit_key_for_other (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, mapped); + + std::multimap >, std::pair >::iterator scm = subcircuit_map.find (k); + + if (! mapped || scm == subcircuit_map.end () || scm->first != k) { if (mp_logger) { - mp_logger->match_subcircuits (c1_subcircuit, sc.operator-> ()); + unmatched_b.push_back (std::make_pair (k, sc.operator-> ())); } + good = false; } else { - std::vector > k; - compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, k); + db::SubCircuitCompare scc; - bool mapped = true; - for (std::vector >::iterator i = k.begin (); i != k.end (); ++i) { - if (! g2.begin () [i->second].has_other ()) { - mapped = false; - } else { - i->second = g2.begin () [i->second].other_net_index (); + std::multimap >, std::pair >::iterator scm_start = scm; + + bool found = false; + size_t nscm = 0; + while (! found && scm != subcircuit_map.end () && scm->first == k) { + ++nscm; + if (scc.equals (scm->second, std::make_pair (sc.operator-> (), sc_cat))) { + found = true; } } - std::sort (k.begin (), k.end ()); + if (! found) { - std::multimap >, std::pair >::iterator scm = subcircuit_map.find (k); + if (nscm == 1) { - if (! mapped || scm == subcircuit_map.end ()) { + // unique match, but doesn't fit: report this one as paired, but mismatching: + if (mp_logger) { + mp_logger->subcircuit_mismatch (scm_start->second.first, sc.operator-> ()); + } + + // no longer look for this one + subcircuit_map.erase (scm_start); + + } else { + + // no unqiue match + if (mp_logger) { + mp_logger->subcircuit_mismatch (0, sc.operator-> ()); + } - if (mp_logger) { - unmatched_b.push_back (std::make_pair (k, sc.operator-> ())); } + good = false; } else { - db::SubCircuitCompare scc; - - std::multimap >, std::pair >::iterator scm_start = scm; - - bool found = false; - size_t nscm = 0; - while (! found && scm != subcircuit_map.end () && scm->first == k) { - ++nscm; - if (scc.equals (scm->second, std::make_pair (sc.operator-> (), sc_cat))) { - found = true; - } + if (mp_logger) { + mp_logger->match_subcircuits (scm->second.first, sc.operator-> ()); } - if (! found) { - - if (nscm == 1) { - - // unique match, but doesn't fit: report this one as paired, but mismatching: - if (mp_logger) { - mp_logger->subcircuit_mismatch (scm_start->second.first, sc.operator-> ()); - } - - // no longer look for this one - subcircuit_map.erase (scm_start); - - } else { - - // no unqiue match - if (mp_logger) { - mp_logger->subcircuit_mismatch (0, sc.operator-> ()); - } - - } - - good = false; - - } else { - - if (mp_logger) { - mp_logger->match_subcircuits (scm->second.first, sc.operator-> ()); - } - - // no longer look for this one - subcircuit_map.erase (scm); - - } + // no longer look for this one + subcircuit_map.erase (scm); } diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index d9748d36d..2edd6062c 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -287,6 +287,26 @@ public: return m_max_n_branch; } + /** + * @brief Sets a value indicating depth-first traversal + * + * With depth first (the default), the algorithm looks for further identities before moving to another + * node. With breadth first (false), the algorithm will work in "waves" rather than digging deerly + * into the direction of a node. + */ + void set_depth_first (bool df) + { + m_depth_first = df; + } + + /** + * @brief Gets a value indicating depth-first traversal + */ + bool depth_first () const + { + return m_depth_first; + } + /** * @brief Gets the list of circuits without matching circuit in the other netlist * The result can be used to flatten these circuits prior to compare. @@ -341,6 +361,7 @@ protected: double m_res_threshold; size_t m_max_n_branch; size_t m_max_depth; + bool m_depth_first; bool m_dont_consider_net_names; };