From f3c549ca73bc2db92d958888cd0a2c175d36d9bd Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 26 Jun 2020 16:33:16 +0200 Subject: [PATCH] Net compare algorithm enhancement (pre-analsysis of node connections for shortcut) --- src/db/db/dbNetlistCompare.cc | 183 ++++++++++++++++++++++++---------- 1 file changed, 129 insertions(+), 54 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 18fa58682..7844e4f1b 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -617,7 +617,7 @@ struct CompareData { CompareData () : 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) + circuit_pin_mapper (0), subcircuit_equivalence (0), device_equivalence (0), progress (0) { } NetGraph *other; @@ -629,6 +629,7 @@ struct CompareData CircuitPinMapper *circuit_pin_mapper; SubCircuitEquivalenceTracker *subcircuit_equivalence; DeviceEquivalenceTracker *device_equivalence; + tl::RelativeProgress *progress; }; // -------------------------------------------------------------------------------------------------------------------- @@ -1921,6 +1922,8 @@ static bool edges_are_compatible (const NetGraphNode::edge_type &e, const NetGra size_t NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, NetGraphNode::edge_iterator e_other, NetGraphNode::edge_iterator ee_other, size_t net_index, size_t other_net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data) { + // NOTE: we can skip edges to known nodes because we did a pre-analysis making sure those are compatible + std::vector > nodes; nodes.reserve (ee - e); @@ -2085,18 +2088,107 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc } - bool any = false; - for (NetGraphNode::edge_iterator e = n->begin (); e != n->end () && ! any; ++e) { - any = ! node (e->second.first).has_other (); + // do a pre-analysis filtering out all nodes with fully satisfied edges or which provide a contradiction + + bool analysis_required = false; + + for (NetGraphNode::edge_iterator e = n->begin (); e != n->end (); ) { + + NetGraphNode::edge_iterator ee = e; + ++ee; + + while (ee != n->end () && ee->first == e->first) { + ++ee; + } + + NetGraphNode::edge_iterator e_other = n_other->find_edge (e->first); + if (e_other != n_other->end ()) { + + NetGraphNode::edge_iterator ee_other = e_other; + ++ee_other; + + while (ee_other != n_other->end () && ee_other->first == e_other->first) { + ++ee_other; + } + + std::vector nodes; + nodes.reserve (ee - e); + + std::vector other_nodes_translated; + other_nodes_translated.reserve (ee - e); + + tl_assert (e->first == e_other->first); + + for (NetGraphNode::edge_iterator i = e; i != ee; ++i) { + if (i->second.first != net_index) { + const NetGraphNode *nn = &node (i->second.first); + if (nn->has_other ()) { + nodes.push_back (nn); + } else { + analysis_required = true; + } + } + } + + for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) { + if (i->second.first != other_net_index) { + const NetGraphNode *nn = &data->other->node (i->second.first); + if (nn->has_other ()) { + other_nodes_translated.push_back (&node (nn->other_net_index ())); + } else { + analysis_required = true; + } + } + } + + std::sort (nodes.begin (), nodes.end ()); + std::sort (other_nodes_translated.begin (), other_nodes_translated.end ()); + + // No fit, we can shortcut + if (nodes != other_nodes_translated) { + return tentative ? failed_match : 0; + } + + } else if (tentative) { + // in tentative mode an exact match is required: no having the same edges for a node disqualifies the node + // as matching. + return failed_match; + } + + e = ee; + } - for (NetGraphNode::edge_iterator e = n_other->begin (); e != n_other->end () && ! any; ++e) { - any = ! data->other->node (e->second.first).has_other (); + + if (tentative) { + + // in tentative mode, again an exact match is required + + for (NetGraphNode::edge_iterator e_other = n_other->begin (); e_other != n_other->end (); ) { + + NetGraphNode::edge_iterator ee_other = e_other; + ++ee_other; + + while (ee_other != n_other->end () && ee_other->first == e_other->first) { + ++ee_other; + } + + NetGraphNode::edge_iterator e = n->find_edge (e_other->first); + if (e == n->end ()) { + return failed_match; + } + + e_other = ee_other; + + } + } - if (! any) { - // all target nodes are satisfied - skip + + if (! analysis_required) { return 0; } + // do a detailed analysis + size_t new_nodes = 0; if (options ()->debug_netcompare) { @@ -2139,46 +2231,12 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc new_nodes += bt_count; } - } else if (tentative) { - // in tentative mode an exact match is required: no having the same edges for a node disqualifies the node - // as matching. - if (options ()->debug_netcompare) { - tl::info << indent(depth) << "=> rejected pair for missing edge."; - } - return failed_match; } e = ee; } - if (tentative) { - - // in tentative mode, again an exact match is required - - for (NetGraphNode::edge_iterator e_other = n_other->begin (); e_other != n_other->end (); ) { - - NetGraphNode::edge_iterator ee_other = e_other; - ++ee_other; - - while (ee_other != n_other->end () && ee_other->first == e_other->first) { - ++ee_other; - } - - NetGraphNode::edge_iterator e = n->find_edge (e_other->first); - if (e == n->end ()) { - if (options ()->debug_netcompare) { - tl::info << indent(depth) << "=> rejected pair for missing edge."; - } - return failed_match; - } - - e_other = ee_other; - - } - - } - if (options ()->debug_netcompare) { if (! tentative && new_nodes > 0) { tl::info << indent(depth) << "=> finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs"; @@ -2320,12 +2378,15 @@ NetGraph::derive_node_identities_from_node_set (std::vectordebug_netcompare) { tl::info << indent_s << "deduced match (singular): " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name (); } - if (data->logger && ! tentative) { - if (! (node (ni) == data->other->node (other_ni))) { - // this is a mismatch but we continue, because that is the only candidate - data->logger->net_mismatch (n->net (), n_other->net ()); - } else { - data->logger->match_nets (n->net (), n_other->net ()); + if (! tentative) { + ++*data->progress; + if (data->logger) { + if (! (node (ni) == data->other->node (other_ni))) { + // this is a mismatch but we continue, because that is the only candidate + data->logger->net_mismatch (n->net (), n_other->net ()); + } else { + data->logger->match_nets (n->net (), n_other->net ()); + } } } @@ -2492,12 +2553,15 @@ NetGraph::derive_node_identities_from_node_set (std::vectordebug_netcompare) { tl::info << indent_s << "deduced match (singular): " << nr->n1->first->net ()->expanded_name () << " vs. " << nr->n2->first->net ()->expanded_name (); } - if (data->logger && ! tentative) { - if (! (node (ni) == data->other->node (other_ni))) { - // this is a mismatch, but we continue with this - data->logger->net_mismatch (nr->n1->first->net (), nr->n2->first->net ()); - } else { - data->logger->match_nets (nr->n1->first->net (), nr->n2->first->net ()); + if (! tentative) { + ++*data->progress; + if (data->logger) { + if (! (node (ni) == data->other->node (other_ni))) { + // this is a mismatch, but we continue with this + data->logger->net_mismatch (nr->n1->first->net (), nr->n2->first->net ()); + } else { + data->logger->match_nets (nr->n1->first->net (), nr->n2->first->net ()); + } } } @@ -2670,6 +2734,7 @@ NetGraph::derive_node_identities_from_node_set (std::vectorfirst->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name (); } } + if (data->logger) { bool ambiguous = equivalent_other_nodes.has_attribute (p->second); if (ambiguous) { @@ -2679,6 +2744,8 @@ NetGraph::derive_node_identities_from_node_set (std::vectorprogress; + } // And seek further from these pairs @@ -2944,6 +3011,8 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const std::map c12_pin_mapping, c22_pin_mapping; + tl::RelativeProgress progress (tl::to_string (tr ("Comparing netlists")), a->circuit_count (), 1); + for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) { const db::Circuit *ca = c.operator-> (); @@ -3007,6 +3076,8 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const } + ++progress; + } if (mp_logger) { @@ -3371,6 +3442,8 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, int iter = 0; + tl::RelativeProgress progress (tl::to_string (tr ("Comparing circuits ")) + c1->name () + "/" + c2->name (), std::max (g1.end () - g1.begin (), g2.end () - g2.begin ()), 1); + // two passes: one without ambiguities, the second one with bool good = false; @@ -3408,6 +3481,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, data.subcircuit_equivalence = &subcircuit_equivalence; data.device_equivalence = &device_equivalence; data.logger = mp_logger; + data.progress = &progress; size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data); if (ni > 0 && ni != failed_match) { @@ -3473,6 +3547,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, data.subcircuit_equivalence = &subcircuit_equivalence; data.device_equivalence = &device_equivalence; data.logger = mp_logger; + data.progress = &progress; size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentatively*/, pass > 0 /*with ambiguities*/, &data); if (ni > 0 && ni != failed_match) {