From c0b1c4f775ba72d3b751ab0dafae172568839adb Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 11 Apr 2019 00:13:19 +0200 Subject: [PATCH] WIP: enhanced backtracking for netlist compare --- src/db/db/dbNetlistCompare.cc | 769 +++++++++++++++++++--------------- 1 file changed, 420 insertions(+), 349 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 1aa331426..530ef240c 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 { @@ -796,38 +796,7 @@ public: // .. nothing yet .. } - void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper) - { - tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ()); - - m_nodes.clear (); - m_net_index.clear (); - - // create a dummy node for a null net - m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper)); - - size_t nets = 0; - for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { - ++nets; - } - m_nodes.reserve (nets); - - for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { - NetGraphNode node (n.operator-> (), device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper); - if (! node.empty () || n->pin_count () > 0) { - m_nodes.push_back (node); - } - } - - std::sort (m_nodes.begin (), m_nodes.end ()); - - for (std::vector::const_iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) { - m_net_index.insert (std::make_pair (i->net (), i - m_nodes.begin ())); - } - for (std::vector::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) { - i->apply_net_index (m_net_index); - } - } + void build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper); size_t node_index_for_net (const db::Net *net) const { @@ -861,6 +830,11 @@ public: return m_nodes.end (); } + const db::Circuit *circuit () const + { + return mp_circuit; + } + /** * @brief Implementation of the backtracking algorithm * @@ -885,251 +859,394 @@ public: * If tentative is true, assignments will not be retained and just the * status is reported. */ - size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, bool tentative) + size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative); + + size_t derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool picky); + + size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper) { - const size_t depth_max = 8; - const size_t n_branch_max = 100; - - NetGraphNode *n = & m_nodes[net_index]; - NetGraphNode *nother = & other.m_nodes[n->other_net_index ()]; - -#if defined(PRINT_DEBUG_NETCOMPARE) - if (! tentative) { - tl::info << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name (); - } -#endif - - size_t new_nodes = 0; - - // non-ambiguous paths to non-assigned nodes create a node identity on the - // end of this path - - 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; - } - - std::vector nodes_with_same_path; - nodes_with_same_path.reserve (ee - e); - - std::vector other_nodes_with_same_path; - other_nodes_with_same_path.reserve (ee - e); - - for (NetGraphNode::edge_iterator i = e; i != ee; ++i) { - const NetGraphNode *n = &m_nodes[i->second.first]; - if (! n->has_other ()) { - nodes_with_same_path.push_back (n); - } - } - - if (! nodes_with_same_path.empty ()) { // if non-ambiguous, non-assigned - - std::sort (nodes_with_same_path.begin (), nodes_with_same_path.end (), CompareNodePtr ()); - - NetGraphNode::edge_iterator e_other = nother->find_edge (e->first); - if (e_other != nother->end ()) { - - NetGraphNode::edge_iterator ee_other = e_other; - ++ee_other; - - while (ee_other != nother->end () && ee_other->first == e_other->first) { - ++ee_other; - } - - size_t count_other = 0; - for (NetGraphNode::edge_iterator i = e_other; i != ee_other && count_other < 2; ++i) { - - const NetGraphNode *n = &other.m_nodes[i->second.first]; - if (! n->has_other ()) { - other_nodes_with_same_path.push_back (n); - } - - } - - std::sort (other_nodes_with_same_path.begin (), other_nodes_with_same_path.end (), CompareNodePtr ()); - - } - - } - - if (nodes_with_same_path.size () == 1 && other_nodes_with_same_path.size () == 1) { - - if (depth + 1 == depth_max) { - return std::numeric_limits::max (); - } - - // a single candiate: just take this one -> this may render - // inexact matches, but further propagates net pairing - - size_t ni = node_index_for_net (nodes_with_same_path.front ()->net ()); - size_t other_ni = other.node_index_for_net (other_nodes_with_same_path.front ()->net ()); - if (! tentative) { - - identify (ni, other_ni); - other.identify (other_ni, ni); - -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "deduced match (singular): " << nodes_with_same_path.front ()->net ()->expanded_name () << " vs. " << other_nodes_with_same_path.front ()->net ()->expanded_name (); -#endif - if (logger) { - logger->match_nets (nodes_with_same_path.front ()->net (), other_nodes_with_same_path.front ()->net ()); - } - - // unconditionally continue here. - derive_node_identities (ni, other, depth + 1, n_branch, logger, false); - - } - - new_nodes += 1; - - } else if (! nodes_with_same_path.empty () || ! other_nodes_with_same_path.empty ()) { - - if (depth + 1 == depth_max) { - return std::numeric_limits::max (); - } - - if (nodes_with_same_path.size () != other_nodes_with_same_path.size ()) { - return std::numeric_limits::max (); - } - - for (size_t i = 0; i < nodes_with_same_path.size (); ++i) { - if (! (*nodes_with_same_path[i] == *other_nodes_with_same_path[i])) { - return std::numeric_limits::max (); - } - } - - std::vector::iterator n1 = nodes_with_same_path.begin (); - std::vector::iterator n2 = other_nodes_with_same_path.begin (); - - while (n1 != nodes_with_same_path.end () && n2 != other_nodes_with_same_path.end ()) { - - std::vector::iterator nn1 = n1, nn2 = n2; - - ++nn1; - ++nn2; - while (nn1 != nodes_with_same_path.end () && **nn1 == **n1) { - ++nn1; - ++nn2; - } - - size_t num = nn1 - n1; - if (num * n_branch > n_branch_max) { - return std::numeric_limits::max (); - } - - std::vector > pairs; - - for (std::vector::iterator i1 = n1; i1 != nn1; ++i1) { - - std::vector::iterator i2; - for (i2 = n2; i2 != nn2; ++i2) { - - if (! *i2) { - continue; - } - - size_t ni = node_index_for_net ((*i1)->net ()); - size_t other_ni = other.node_index_for_net ((*i2)->net ()); - - identify (ni, other_ni); - other.identify (other_ni, ni); - - size_t bt_count = derive_node_identities (ni, other, depth + 1, num * n_branch, logger, true /*tentative*/); - - unidentify (ni); - other.unidentify (other_ni); - - if (bt_count != std::numeric_limits::max ()) { - // identified a pair - new_nodes += bt_count + 1; - pairs.push_back (std::make_pair (*i1, *i2)); - *i2 = 0; - break; - } - - } - - if (i2 == nn2) { - // a mismatch - stop here. - return std::numeric_limits::max (); - } - - } - - if (! tentative) { - - for (std::vector >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) { - - if (p->first->has_other () || p->second->has_other ()) { - // this may happen if "derive_node_identities" creates new pairs - // TODO: actually *both* should be paired, not just one. - continue; - } - - size_t ni = node_index_for_net (p->first->net ()); - size_t other_ni = other.node_index_for_net (p->second->net ()); - - identify (ni, other_ni); - other.identify (other_ni, ni); - - size_t bt_count = derive_node_identities (ni, other, depth + 1, num * n_branch, logger, false /*not tentative*/); - tl_assert (bt_count != std::numeric_limits::max ()); - -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name (); -#endif - if (logger) { - logger->match_nets (p->first->net (), p->second->net ()); - } - - } - - } - - } - - } - - e = ee; - - } - -#if defined(PRINT_DEBUG_NETCOMPARE) - if (! tentative && new_nodes > 0 && new_nodes != std::numeric_limits::max ()) { - tl::info << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name () << " with " << new_nodes << " new pairs"; - } -#endif - - return new_nodes; - } - - size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, NetlistCompareLogger *logger) - { - return derive_node_identities (net_index, other, 0, 1, logger, false); - } - - static void confirm_identity (db::NetDeviceGraph &g1, db::NetDeviceGraph::node_iterator s1, db::NetDeviceGraph &g2, db::NetDeviceGraph::node_iterator s2, db::NetlistCompareLogger *logger, bool ambiguous = false) - { - if (logger) { - if (ambiguous) { - logger->match_ambiguous_nets (s1->net (), s2->net ()); - } else { - logger->match_nets (s1->net (), s2->net ()); - } - } - g1.identify (s1 - g1.begin (), s2 - g2.begin ()); - g2.identify (s2 - g2.begin (), s1 - g1.begin ()); + return derive_node_identities (net_index, other, 0, 1, logger, circuit_pin_mapper, false); } private: std::vector m_nodes; std::map m_net_index; + const db::Circuit *mp_circuit; }; +// @@@ make attribute +const size_t depth_max = 8; +const size_t n_branch_max = 100; + +void +NetDeviceGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper) +{ + tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("Building net graph for circuit: ")) + c->name ()); + + mp_circuit = c; + + m_nodes.clear (); + m_net_index.clear (); + + // create a dummy node for a null net + m_nodes.push_back (NetGraphNode (0, device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper)); + + size_t nets = 0; + for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { + ++nets; + } + m_nodes.reserve (nets); + + for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) { + NetGraphNode node (n.operator-> (), device_categorizer, circuit_categorizer, device_filter, circuit_and_pin_mapping, circuit_pin_mapper); + if (! node.empty () || n->pin_count () > 0) { + m_nodes.push_back (node); + } + } + + std::sort (m_nodes.begin (), m_nodes.end ()); + + for (std::vector::const_iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) { + m_net_index.insert (std::make_pair (i->net (), i - m_nodes.begin ())); + } + for (std::vector::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) { + i->apply_net_index (m_net_index); + } +} + +size_t +NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative) +{ + NetGraphNode *n = & m_nodes[net_index]; + NetGraphNode *nother = & other.m_nodes[n->other_net_index ()]; + +#if defined(PRINT_DEBUG_NETCOMPARE) + if (! tentative) { + tl::info << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name (); + } +#endif + + size_t new_nodes = 0; + + // non-ambiguous paths to non-assigned nodes create a node identity on the + // end of this path + + 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; + } + + std::vector nodes; + nodes.reserve (ee - e); + + std::vector other_nodes; + other_nodes.reserve (ee - e); + + for (NetGraphNode::edge_iterator i = e; i != ee; ++i) { + const NetGraphNode *n = &m_nodes[i->second.first]; + if (! n->has_other ()) { + nodes.push_back (n); + } + } + + if (! nodes.empty ()) { // if non-ambiguous, non-assigned + + NetGraphNode::edge_iterator e_other = nother->find_edge (e->first); + if (e_other != nother->end ()) { + + NetGraphNode::edge_iterator ee_other = e_other; + ++ee_other; + + while (ee_other != nother->end () && ee_other->first == e_other->first) { + ++ee_other; + } + + size_t count_other = 0; + for (NetGraphNode::edge_iterator i = e_other; i != ee_other && count_other < 2; ++i) { + + const NetGraphNode *n = &other.m_nodes[i->second.first]; + if (! n->has_other ()) { + other_nodes.push_back (n); + } + + } + + } + + } + + if (! nodes.empty () || ! other_nodes.empty ()) { + + std::sort (nodes.begin (), nodes.end (), CompareNodePtr ()); + std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ()); + + derive_node_identities_from_node_set (nodes, other_nodes, other, depth, n_branch, logger, circuit_pin_mapper, tentative, true); + + } + + e = ee; + + } + +#if defined(PRINT_DEBUG_NETCOMPARE) + if (! tentative && new_nodes > 0 && new_nodes != std::numeric_limits::max ()) { + tl::info << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name () << " with " << new_nodes << " new pairs"; + } +#endif + + return new_nodes; +} + +size_t +NetDeviceGraph::derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool picky) +{ + size_t new_nodes = 0; + + if (depth + 1 == depth_max) { + return std::numeric_limits::max (); + } + + if (picky) { + + if (nodes.size () != other_nodes.size ()) { + return std::numeric_limits::max (); + } + + for (size_t i = 0; i < nodes.size (); ++i) { + if (! (*nodes[i] == *other_nodes[i]) || nodes[i]->has_other () != other_nodes[i]->has_other ()) { + return std::numeric_limits::max (); + } + } + + } + + std::vector::const_iterator n1 = nodes.begin (); + std::vector::const_iterator n2 = other_nodes.begin (); + + while (n1 != nodes.end () && n2 != other_nodes.end ()) { + + if (**n1 < **n2) { + ++n1; + continue; + } else if (**n2 < **n1) { + ++n2; + continue; + } else if ((*n1)->has_other ()) { + ++n1; + continue; + } else if ((*n2)->has_other ()) { + ++n2; + continue; + } + + std::vector::const_iterator nn1 = n1, nn2 = n2; + + size_t num = 1; + ++nn1; + ++nn2; + while (nn1 != nodes.end () && nn2 != other_nodes.end ()) { + if ((*nn1)->has_other ()) { + ++nn1; + } else if ((*nn2)->has_other ()) { + ++nn2; + } else if (! (**nn1 == **n1) || ! (**nn2 == **n2)) { + break; + } else { + ++num; + ++nn1; + ++nn2; + } + } + + if (num == 1) { + + // a single candiate: just take this one -> this may render + // inexact matches, but further propagates net pairing + + size_t ni = node_index_for_net ((*n1)->net ()); + size_t other_ni = other.node_index_for_net ((*n2)->net ()); + if (! tentative) { + + identify (ni, other_ni); + other.identify (other_ni, ni); + +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "deduced match (singular): " << (*n1)->net ()->expanded_name () << " vs. " << (*n2)->net ()->expanded_name (); +#endif + if (logger) { + logger->match_nets ((*n1)->net (), (*n2)->net ()); + } + + // unconditionally continue here. + derive_node_identities (ni, other, depth + 1, n_branch, logger, circuit_pin_mapper, false); + + } + + new_nodes += 1; + + } else { + + if (num * n_branch > n_branch_max) { + return std::numeric_limits::max (); + } + + std::vector > pairs; + tl::equivalence_clusters equivalent_other_nodes; + std::set seen; + + for (std::vector::const_iterator i1 = n1; i1 != nn1; ++i1) { + + if ((*i1)->has_other ()) { + continue; + } + + bool any = false; + + std::vector::const_iterator i2; + for (i2 = n2; i2 != nn2; ++i2) { + + if ((*i2)->has_other ()) { + continue; + } + + if (seen.find (*i2) != seen.end ()) { + continue; + } + + size_t ni = node_index_for_net ((*i1)->net ()); + size_t other_ni = other.node_index_for_net ((*i2)->net ()); + + identify (ni, other_ni); + other.identify (other_ni, ni); + + size_t bt_count = derive_node_identities (ni, other, depth + 1, num * n_branch, logger, circuit_pin_mapper, true /*tentative*/); + + unidentify (ni); + other.unidentify (other_ni); + + if (bt_count != std::numeric_limits::max ()) { + + if (any) { + + // there is already a known pair, so we can mark *i2 and the previous *i2 as equivalent + // (makes them ambiguous) + equivalent_other_nodes.same (*i2, pairs.back ().second); + + } else { + + // identified a new pair + new_nodes += bt_count + 1; + pairs.push_back (std::make_pair (*i1, *i2)); + seen.insert (*i2); + any = true; + + } + + } + + } + + if (! any && picky) { + // a mismatch - stop here. + return std::numeric_limits::max (); + } + + } + + if (! tentative) { + + // collect ambiguous nodes and mark their pins as swappable + + std::map other2this; + for (std::vector >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) { + other2this.insert (std::make_pair (p->second, p->first)); + } + + for (size_t cid = 1; cid <= equivalent_other_nodes.size (); ++cid) { + + tl::equivalence_clusters::cluster_iterator c = equivalent_other_nodes.begin_cluster (cid); + const NetGraphNode *c1 = other2this[(*c)->first]; + + tl::equivalence_clusters::cluster_iterator cc = c; + ++cc; + for ( ; cc != equivalent_other_nodes.end_cluster (cid); ++cc) { + + for (db::Net::const_pin_iterator pp = (*cc)->first->net ()->begin_pins (); pp != (*cc)->first->net ()->end_pins (); ++pp) { + for (db::Net::const_pin_iterator p = (*c)->first->net ()->begin_pins (); p != (*c)->first->net ()->end_pins (); ++p) { +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "pin swapping due to ambiguous nets for circuit (B) " << other.circuit ()->name () << ": " << pp->pin ()->expanded_name () << " and " << p->pin ()->expanded_name (); +#endif + circuit_pin_mapper->map_pins (other.circuit (), pp->pin_id (), p->pin_id ()); + } + } + + const NetGraphNode *cc1 = other2this[(*cc)->first]; + + for (db::Net::const_pin_iterator pp = cc1->net ()->begin_pins (); pp != cc1->net ()->end_pins (); ++pp) { + for (db::Net::const_pin_iterator p = c1->net ()->begin_pins (); p != c1->net ()->end_pins (); ++p) { +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "pin swapping due to ambiguous nets for circuit (A) " << circuit ()->name () << ": " << pp->pin ()->expanded_name () << " and " << p->pin ()->expanded_name (); +#endif + circuit_pin_mapper->map_pins (circuit (), pp->pin_id (), p->pin_id ()); + } + } + + } + + } + + // issue the matching pairs + + for (std::vector >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) { + + size_t ni = node_index_for_net (p->first->net ()); + size_t other_ni = other.node_index_for_net (p->second->net ()); + + identify (ni, other_ni); + other.identify (other_ni, ni); + +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name (); +#endif + if (logger) { + bool ambiguous = equivalent_other_nodes.has_attribute (p->second); + if (ambiguous) { + logger->match_ambiguous_nets (p->first->net (), p->second->net ()); + } else { + logger->match_nets (p->first->net (), p->second->net ()); + } + } + + } + + // And seek further from these pairs + + for (std::vector >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) { + + size_t ni = node_index_for_net (p->first->net ()); + + size_t bt_count = derive_node_identities (ni, other, depth + 1, num * n_branch, logger, circuit_pin_mapper, false /*not tentative*/); + tl_assert (bt_count != std::numeric_limits::max ()); + + } + + } + + } + + n1 = nn1; + n2 = nn2; + + } + + return new_nodes; +} + + // -------------------------------------------------------------------------------------------------------------------- // NetlistComparer implementation @@ -1417,7 +1534,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, #endif bool good = true; - while (good) { + while (true) { #if defined(PRINT_DEBUG_NETCOMPARE) ++iter; @@ -1425,10 +1542,13 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, tl::info << "deducing from present nodes ..."; #endif + size_t new_identities = 0; + 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, mp_logger); + size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, mp_logger, mp_circuit_pin_mapper.get ()); if (ni > 0 && ni != std::numeric_limits::max ()) { + new_identities += ni; #if defined(PRINT_DEBUG_NETCOMPARE) tl::info << ni << " new identities."; #endif @@ -1436,95 +1556,46 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, } } - bool any_without = false; - for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end () && ! any_without; ++i1) { - any_without = ! i1->has_other (); - } - - if (! any_without) { - break; - } - - size_t new_identities = 0; - #if defined(PRINT_DEBUG_NETCOMPARE) tl::info << "checking topological identity ..."; #endif - // first pass: without ambiguities, second pass: match ambiguous nets - for (int pass = 0; pass < 2 && new_identities == 0; ++pass) { + // derive new identities through topology: first collect all nets with the same topological signature - // derive new identities through topology - - bool same_as_prev = false; - - db::NetDeviceGraph::node_iterator i1 = g1.begin (), i2 = g2.begin (); - for ( ; i1 != g1.end () && i2 != g2.end (); ) { - - bool same_as_next = false; - - if (i1->has_other ()) { - ++i1; - } else if (i2->has_other ()) { - ++i2; - } else if (*i1 < *i2) { - ++i1; - } else if (*i2 < *i1) { - ++i2; - } else { - - db::NetDeviceGraph::node_iterator ii1 = i1, ii2 = i2; - - ++i1; - ++i2; - - same_as_next = (i1 != g1.end () && *i1 == *ii1) || (i2 != g2.end () && *i2 == *ii2); - - // found a candidate - a single node with the same edges - - bool ambiguous = (same_as_next || same_as_prev); - if (! ambiguous || pass) { - - // For ambiguous nets make the pins exchangable - - if (same_as_next) { - - if (ii1->net () && i1->net ()) { - for (db::Net::const_pin_iterator pp = ii1->net ()->begin_pins (); pp != ii1->net ()->end_pins (); ++pp) { - for (db::Net::const_pin_iterator p = i1->net ()->begin_pins (); p != i1->net ()->end_pins (); ++p) { - mp_circuit_pin_mapper->map_pins (c1, pp->pin_id (), p->pin_id ()); - } - } - } - - if (ii2->net () && i2->net ()) { - for (db::Net::const_pin_iterator pp = ii2->net ()->begin_pins (); pp != ii2->net ()->end_pins (); ++pp) { - for (db::Net::const_pin_iterator p = i2->net ()->begin_pins (); p != i2->net ()->end_pins (); ++p) { - mp_circuit_pin_mapper->map_pins (c2, pp->pin_id (), p->pin_id ()); - } - } - } - - } - -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "topological match: " << ii1->net ()->expanded_name () << " vs. " << ii2->net ()->expanded_name (); -#endif - db::NetDeviceGraph::confirm_identity (g1, ii1, g2, ii2, mp_logger, ambiguous); - ++new_identities; - - } - - } - - same_as_prev = same_as_next; + std::vector nodes, other_nodes; + nodes.reserve (g1.end () - g1.begin ()); + for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { + if (! i1->has_other () && i1->net ()) { + nodes.push_back (i1.operator-> ()); } + } + other_nodes.reserve (g2.end () - g2.begin ()); + for (db::NetDeviceGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) { + if (! i2->has_other () && i2->net ()) { + other_nodes.push_back (i2.operator-> ()); + } + } + + if (nodes.empty () || other_nodes.empty ()) { + if (! nodes.empty () || ! other_nodes.empty ()) { + good = false; + } + break; + } + + size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), false /*not tentative*/, false /*don't require a full match*/); + if (ni > 0 && ni != std::numeric_limits::max ()) { + new_identities += ni; +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << ni << " new identities."; +#endif } if (new_identities == 0) { good = false; + break; } }