diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index d21c4388b..9033ece44 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -706,196 +706,30 @@ public: size_t m_id1, m_id2; }; + typedef std::pair, std::pair > edge_type; + struct EdgeToEdgeOnlyCompare { - bool operator() (const std::pair, std::pair > &a, const std::vector &b) const + bool operator() (const edge_type &a, const std::vector &b) const { return a.first < b; } }; - typedef std::vector, std::pair > >::const_iterator edge_iterator; + typedef std::vector::const_iterator edge_iterator; - NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map) - : mp_net (net), m_other_net_index (std::numeric_limits::max ()) + NetGraphNode () + : mp_net (0) { - if (! net) { - return; - } - - std::map n2entry; - - for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) { - - const db::SubCircuit *sc = i->subcircuit (); - size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc); - if (! circuit_cat) { - // circuit is ignored - continue; - } - - size_t pin_id = i->pin ()->id (); - const db::Circuit *cr = sc->circuit_ref (); - - 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; - } - - const CircuitMapper *cm = & icm->second; - - // 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; - } - - // 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. - - pin_id = cm->other_pin_from_this_pin (pin_id); - - // realize pin swapping by normalization of pin ID - - pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); - - // Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit. - // The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins. - - Transition ed (sc, circuit_cat, pin_id, pin_id); - - std::map::const_iterator in = n2entry.find ((const void *) sc); - if (in == n2entry.end ()) { - in = n2entry.insert (std::make_pair ((const void *) sc, m_edges.size ())).first; - m_edges.push_back (std::make_pair (std::vector (), std::make_pair (size_t (0), (const db::Net *) 0))); - } - - m_edges [in->second].first.push_back (ed); - - } - - for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) { - - const db::Device *d = i->device (); - if (! device_filter.filter (d)) { - continue; - } - - size_t device_cat = device_categorizer.cat_for_device (d); - if (! device_cat) { - // device is ignored - continue; - } - - size_t terminal1_id = translate_terminal_id (i->terminal_id (), d); - - const std::vector &td = d->device_class ()->terminal_definitions (); - for (std::vector::const_iterator it = td.begin (); it != td.end (); ++it) { - - if (it->id () != i->terminal_id ()) { - - size_t terminal2_id = translate_terminal_id (it->id (), d); - Transition ed2 (d, device_cat, terminal1_id, terminal2_id); - - const db::Net *net2 = d->net_for_terminal (it->id ()); - - std::map::const_iterator in = n2entry.find ((const void *) net2); - if (in == n2entry.end ()) { - in = n2entry.insert (std::make_pair ((const void *) net2, m_edges.size ())).first; - m_edges.push_back (std::make_pair (std::vector (), std::make_pair (size_t (0), net2))); - } - - m_edges [in->second].first.push_back (ed2); - - } - - } - - } + // .. nothing yet .. } - NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map) - : mp_net (0), m_other_net_index (std::numeric_limits::max ()) - { - std::map n2entry; + NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map); + NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map); - size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc); - tl_assert (circuit_cat != 0); + void expand_subcircuit_nodes (NetGraph *graph); - const db::Circuit *cr = sc->circuit_ref (); - tl_assert (cr != 0); - - std::map::const_iterator icm = circuit_map->find (cr); - tl_assert (icm != circuit_map->end ()); - - const CircuitMapper *cm = & icm->second; - - for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) { - - size_t pin_id = p->id (); - const db::Net *net_at_pin = sc->net_for_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; - } - - // 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. - - pin_id = cm->other_pin_from_this_pin (pin_id); - - // realize pin swapping by normalization of pin ID - - pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); - - // Make the other endpoint - - Transition ed (sc, circuit_cat, pin_id, pin_id); - - std::map::const_iterator in = n2entry.find (net_at_pin); - if (in == n2entry.end ()) { - in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first; - m_edges.push_back (std::make_pair (std::vector (), std::make_pair (size_t (0), net_at_pin))); - } - - m_edges [in->second].first.push_back (ed); - - } - } - - std::string to_string () const - { - std::string res = std::string ("["); - if (mp_net) { - res += mp_net->expanded_name (); - } else { - res += "(null)"; - } - res += "]"; - if (m_other_net_index != std::numeric_limits::max ()) { - res += " (other: #" + tl::to_string (m_other_net_index) + ")"; - } - res += "\n"; - - for (std::vector, std::pair > >::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) { - res += " (\n"; - for (std::vector::const_iterator i = e->first.begin (); i != e->first.end (); ++i) { - res += std::string (" ") + i->to_string () + "\n"; - } - res += " )->"; - if (! e->second.second) { - res += "(null)"; - } else { - res += e->second.second->expanded_name () + "[#" + tl::to_string (e->second.first) + "]"; - } - res += "\n"; - } - return res; - } + std::string to_string () const; const db::Net *net () const { @@ -927,55 +761,10 @@ public: return m_edges.empty (); } - void apply_net_index (const std::map &ni) - { - for (std::vector, std::pair > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) { - std::map::const_iterator j = ni.find (i->second.second); - tl_assert (j != ni.end ()); - i->second.first = j->second; - } + void apply_net_index (const std::map &ni); - // "deep sorting" of the edge descriptor - for (std::vector, std::pair > >::iterator i = m_edges.begin (); i != m_edges.end (); ++i) { - std::sort (i->first.begin (), i->first.end ()); - } - - std::sort (m_edges.begin (), m_edges.end ()); - } - - bool operator< (const NetGraphNode &node) const - { - if (m_edges.size () != node.m_edges.size ()) { - return m_edges.size () < node.m_edges.size (); - } - for (size_t i = 0; i < m_edges.size (); ++i) { - if (m_edges [i].first != node.m_edges [i].first) { - return m_edges [i].first < node.m_edges [i].first; - } - } - if (m_edges.empty ()) { - // do a more detailed analysis on the edges - return edge_less (net (), node.net ()); - } - return false; - } - - bool operator== (const NetGraphNode &node) const - { - if (m_edges.size () != node.m_edges.size ()) { - return false; - } - for (size_t i = 0; i < m_edges.size (); ++i) { - if (m_edges [i].first != node.m_edges [i].first) { - return false; - } - } - if (m_edges.empty ()) { - // do a more detailed analysis on the edges - return edge_equal (net (), node.net ()); - } - return true; - } + bool operator< (const NetGraphNode &node) const; + bool operator== (const NetGraphNode &node) const; void swap (NetGraphNode &other) { @@ -1007,59 +796,19 @@ public: private: const db::Net *mp_net; size_t m_other_net_index; - std::vector, std::pair > > m_edges; + std::vector m_edges; /** * @brief Compares edges as "less" * Edge comparison is based on the pins attached (name of the first pin). */ - static bool edge_less (const db::Net *a, const db::Net *b) - { - if ((a != 0) != (b != 0)) { - return (a != 0) < (b != 0); - } - if (a != 0) { - if (a->pin_count () != b->pin_count ()) { - return a->pin_count () < b->pin_count (); - } - if (a->pin_count () > 0) { - const std::string &pna = a->begin_pins ()->pin ()->name (); - const std::string &pnb = b->begin_pins ()->pin ()->name (); - if (! pna.empty () && ! pnb.empty ()) { - return pna < pnb; - } - } - return false; - } else { - return false; - } - } + static bool edge_less (const db::Net *a, const db::Net *b); /** * @brief Compares edges as "equal" * See edge_less for the comparison details. */ - static bool edge_equal (const db::Net *a, const db::Net *b) - { - if ((a != 0) != (b != 0)) { - return false; - } - if (a != 0) { - if (a->pin_count () != b->pin_count ()) { - return false; - } - if (a->pin_count () > 0) { - const std::string &pna = a->begin_pins ()->pin ()->name (); - const std::string &pnb = b->begin_pins ()->pin ()->name (); - if (! pna.empty () && ! pnb.empty ()) { - return pna == pnb; - } - } - return true; - } else { - return true; - } - } + static bool edge_equal (const db::Net *a, const db::Net *b); }; // -------------------------------------------------------------------------------------------------------------------- @@ -1253,11 +1002,352 @@ private: std::map m_net_index; const db::Circuit *mp_circuit; - size_t derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data); + size_t 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, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data); }; // -------------------------------------------------------------------------------------------------------------------- +NetGraphNode::NetGraphNode (const db::Net *net, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const DeviceFilter &device_filter, const std::map *circuit_map, const CircuitPinMapper *pin_map) + : mp_net (net), m_other_net_index (std::numeric_limits::max ()) +{ + if (! net) { + return; + } + + std::map n2entry; + + for (db::Net::const_subcircuit_pin_iterator i = net->begin_subcircuit_pins (); i != net->end_subcircuit_pins (); ++i) { + + const db::SubCircuit *sc = i->subcircuit (); + size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc); + if (! circuit_cat) { + // circuit is ignored + continue; + } + + size_t pin_id = i->pin ()->id (); + const db::Circuit *cr = sc->circuit_ref (); + + 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; + } + + const CircuitMapper *cm = & icm->second; + + // 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; + } + + // 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. + + pin_id = cm->other_pin_from_this_pin (pin_id); + + // realize pin swapping by normalization of pin ID + + pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); + + // Subcircuits are routed to a null node and descend from a virtual node inside the subcircuit. + // The reasoning is that this way we don't need #pins*(#pins-1) edges but rather #pins. + + Transition ed (sc, circuit_cat, pin_id, pin_id); + + std::map::const_iterator in = n2entry.find ((const void *) sc); + if (in == n2entry.end ()) { + in = n2entry.insert (std::make_pair ((const void *) sc, m_edges.size ())).first; + m_edges.push_back (edge_type (std::vector (), std::make_pair (size_t (0), (const db::Net *) 0))); + } + + m_edges [in->second].first.push_back (ed); + + } + + for (db::Net::const_terminal_iterator i = net->begin_terminals (); i != net->end_terminals (); ++i) { + + const db::Device *d = i->device (); + if (! device_filter.filter (d)) { + continue; + } + + size_t device_cat = device_categorizer.cat_for_device (d); + if (! device_cat) { + // device is ignored + continue; + } + + size_t terminal1_id = translate_terminal_id (i->terminal_id (), d); + + const std::vector &td = d->device_class ()->terminal_definitions (); + for (std::vector::const_iterator it = td.begin (); it != td.end (); ++it) { + + if (it->id () != i->terminal_id ()) { + + size_t terminal2_id = translate_terminal_id (it->id (), d); + Transition ed2 (d, device_cat, terminal1_id, terminal2_id); + + const db::Net *net2 = d->net_for_terminal (it->id ()); + + std::map::const_iterator in = n2entry.find ((const void *) net2); + if (in == n2entry.end ()) { + in = n2entry.insert (std::make_pair ((const void *) net2, m_edges.size ())).first; + m_edges.push_back (edge_type (std::vector (), std::make_pair (size_t (0), net2))); + } + + m_edges [in->second].first.push_back (ed2); + + } + + } + + } +} + +NetGraphNode::NetGraphNode (const db::SubCircuit *sc, CircuitCategorizer &circuit_categorizer, const std::map *circuit_map, const CircuitPinMapper *pin_map) + : mp_net (0), m_other_net_index (std::numeric_limits::max ()) +{ + std::map n2entry; + + size_t circuit_cat = circuit_categorizer.cat_for_subcircuit (sc); + tl_assert (circuit_cat != 0); + + const db::Circuit *cr = sc->circuit_ref (); + tl_assert (cr != 0); + + std::map::const_iterator icm = circuit_map->find (cr); + tl_assert (icm != circuit_map->end ()); + + const CircuitMapper *cm = & icm->second; + + for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) { + + size_t pin_id = p->id (); + const db::Net *net_at_pin = sc->net_for_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; + } + + // 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. + + pin_id = cm->other_pin_from_this_pin (pin_id); + + // realize pin swapping by normalization of pin ID + + pin_id = pin_map->normalize_pin_id (cm->other (), pin_id); + + // Make the other endpoint + + Transition ed (sc, circuit_cat, pin_id, pin_id); + + std::map::const_iterator in = n2entry.find (net_at_pin); + if (in == n2entry.end ()) { + in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first; + m_edges.push_back (edge_type (std::vector (), std::make_pair (size_t (0), net_at_pin))); + } + + m_edges [in->second].first.push_back (ed); + + } +} + +void +NetGraphNode::expand_subcircuit_nodes (NetGraph *graph) +{ + std::map n2entry; + + std::list sc_edges; + + for (size_t i = 0; i < m_edges.size (); ) { + if (m_edges [i].second.second == 0) { + // subcircuit pin + sc_edges.push_back (m_edges [i]); + m_edges.erase (m_edges.begin () + i); + } else { + n2entry.insert (std::make_pair (m_edges [i].second.second, i)); + ++i; + } + } + + for (std::list::const_iterator e = sc_edges.begin (); e != sc_edges.end (); ++e) { + + const db::SubCircuit *sc = 0; + for (std::vector::const_iterator t = e->first.begin (); t != e->first.end (); ++t) { + tl_assert (t->is_for_subcircuit ()); + if (! sc) { + sc = t->subcircuit_pair ().first; + } else { + tl_assert (sc == t->subcircuit_pair ().first); + } + } + + const NetGraphNode &dn = graph->distro_node (sc); + for (NetGraphNode::edge_iterator de = dn.begin (); de != dn.end (); ++de) { + + const db::Net *net_at_pin = de->second.second; + if (net_at_pin == net ()) { + continue; + } + + std::map::const_iterator in = n2entry.find (net_at_pin); + if (in == n2entry.end ()) { + in = n2entry.insert (std::make_pair ((const db::Net *) net_at_pin, m_edges.size ())).first; + m_edges.push_back (edge_type (std::vector (), de->second)); + } + + m_edges [in->second].first.insert (m_edges [in->second].first.end (), de->first.begin (), de->first.end ()); + + } + + } + + // "deep sorting" of the edge descriptor + for (std::vector::iterator i = m_edges.begin (); i != m_edges.end (); ++i) { + std::sort (i->first.begin (), i->first.end ()); + } + + std::sort (m_edges.begin (), m_edges.end ()); +} + +std::string +NetGraphNode::to_string () const +{ + std::string res = std::string ("["); + if (mp_net) { + res += mp_net->expanded_name (); + } else { + res += "(null)"; + } + res += "]"; + if (m_other_net_index != std::numeric_limits::max ()) { + res += " (other: #" + tl::to_string (m_other_net_index) + ")"; + } + res += "\n"; + + for (std::vector::const_iterator e = m_edges.begin (); e != m_edges.end (); ++e) { + res += " (\n"; + for (std::vector::const_iterator i = e->first.begin (); i != e->first.end (); ++i) { + res += std::string (" ") + i->to_string () + "\n"; + } + res += " )->"; + if (! e->second.second) { + res += "(null)"; + } else { + res += e->second.second->expanded_name () + "[#" + tl::to_string (e->second.first) + "]"; + } + res += "\n"; + } + return res; +} + +void +NetGraphNode::apply_net_index (const std::map &ni) +{ + for (std::vector::iterator i = m_edges.begin (); i != m_edges.end (); ++i) { + std::map::const_iterator j = ni.find (i->second.second); + tl_assert (j != ni.end ()); + i->second.first = j->second; + } + + // "deep sorting" of the edge descriptor + for (std::vector::iterator i = m_edges.begin (); i != m_edges.end (); ++i) { + std::sort (i->first.begin (), i->first.end ()); + } + + std::sort (m_edges.begin (), m_edges.end ()); +} + +bool +NetGraphNode::operator< (const NetGraphNode &node) const +{ + if (m_edges.size () != node.m_edges.size ()) { + return m_edges.size () < node.m_edges.size (); + } + for (size_t i = 0; i < m_edges.size (); ++i) { + if (m_edges [i].first != node.m_edges [i].first) { + return m_edges [i].first < node.m_edges [i].first; + } + } + if (m_edges.empty ()) { + // do a more detailed analysis on the edges + return edge_less (net (), node.net ()); + } + return false; +} + +bool +NetGraphNode::operator== (const NetGraphNode &node) const +{ + if (m_edges.size () != node.m_edges.size ()) { + return false; + } + for (size_t i = 0; i < m_edges.size (); ++i) { + if (m_edges [i].first != node.m_edges [i].first) { + return false; + } + } + if (m_edges.empty ()) { + // do a more detailed analysis on the edges + return edge_equal (net (), node.net ()); + } + return true; +} + +bool +NetGraphNode::edge_less (const db::Net *a, const db::Net *b) +{ + if ((a != 0) != (b != 0)) { + return (a != 0) < (b != 0); + } + if (a != 0) { + if (a->pin_count () != b->pin_count ()) { + return a->pin_count () < b->pin_count (); + } + if (a->pin_count () > 0) { + const std::string &pna = a->begin_pins ()->pin ()->name (); + const std::string &pnb = b->begin_pins ()->pin ()->name (); + if (! pna.empty () && ! pnb.empty ()) { + return pna < pnb; + } + } + return false; + } else { + return false; + } +} + +bool +NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) +{ + if ((a != 0) != (b != 0)) { + return false; + } + if (a != 0) { + if (a->pin_count () != b->pin_count ()) { + return false; + } + if (a->pin_count () > 0) { + const std::string &pna = a->begin_pins ()->pin ()->name (); + const std::string &pnb = b->begin_pins ()->pin ()->name (); + if (! pna.empty () && ! pnb.empty ()) { + return pna == pnb; + } + } + return true; + } else { + return true; + } +} + +// -------------------------------------------------------------------------------------------------------------------- + /** * @brief Represents an interval of NetGraphNode objects in a node set */ @@ -1391,7 +1481,7 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci } size_t -NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, size_t net_index, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data) +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, NetGraphNode *n, size_t other_net_index, NetGraphNode *nother, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data) { size_t new_nodes = 0; @@ -1419,29 +1509,17 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr 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; - } - - 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); + 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 defined(PRINT_DEBUG_NETCOMPARE) - tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via"; - for (std::vector::const_iterator t = i->first.begin (); t != i->first.end(); ++t) { - tl::info << indent(depth) << " " << t->to_string(); - } -#endif - other_nodes.push_back (nn); + tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via"; + for (std::vector::const_iterator t = i->first.begin (); t != i->first.end(); ++t) { + tl::info << indent(depth) << " " << t->to_string(); } +#endif + other_nodes.push_back (nn); } - } } @@ -1488,28 +1566,17 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr return new_nodes; } -const db::SubCircuit *subcircuit_on_edges (NetGraphNode::edge_iterator e, NetGraphNode::edge_iterator ee, CompareData *data) +static bool has_subcircuits (db::NetGraphNode::edge_iterator e, db::NetGraphNode::edge_iterator ee) { - const db::SubCircuit *subcircuit_on_node = 0; - bool subcircuit_on_node_ambiguous = false; - while (e != ee) { for (std::vector::const_iterator t = e->first.begin (); t != e->first.end (); ++t) { if (t->is_for_subcircuit ()) { - const db::SubCircuit *sc = t->subcircuit_pair ().first; - if (data->subcircuit_categorizer->has_cat_for (sc)) { - // ignore known subcircuits - } else if (! subcircuit_on_node || subcircuit_on_node == sc) { - subcircuit_on_node = sc; - } else { - subcircuit_on_node_ambiguous = true; - } + return true; } } ++e; } - - return subcircuit_on_node_ambiguous ? 0 : subcircuit_on_node; + return false; } size_t @@ -1518,28 +1585,60 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc NetGraphNode *n = & node (net_index); size_t other_net_index = n->other_net_index (); - NetGraphNode *nother = & data->other->node (other_net_index); + NetGraphNode *n_other = & data->other->node (other_net_index); #if defined(PRINT_DEBUG_NETCOMPARE) if (! tentative) { - tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name (); + tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name (); } #endif size_t new_nodes = 0; + NetGraphNode nn, nn_other; + + // If there are subcircuits on the graph we temporarily create edges from our node to the other nodes of + // the subcircuit. This way we don't need to keep #pin*(#pin-1) edges + + if (has_subcircuits (n->begin (), n->end ())) { + + nn = *n; + nn.expand_subcircuit_nodes (this); + n = &nn; + + nn_other = *n_other; + nn_other.expand_subcircuit_nodes (data->other); + n_other = &nn_other; + + } + // 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; } - new_nodes += derive_node_identities_for_edges (e, ee, net_index, n, other_net_index, nother, depth, n_branch, tentative, with_ambiguous, data); + 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; + } + + new_nodes += derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, n, other_net_index, n_other, depth, n_branch, tentative, with_ambiguous, data); + + } + +#if 0 // @@@ // Subcircuits are handled explicitly: the edges aren't real edges, but pin descriptors with // a single endpoint and nil at the other end. The subcircuit provides a set of edges // providing the other endpoints and nil at our side. This saves us creating #pin*(#pin-1) edges @@ -1580,6 +1679,7 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc } } +#endif e = ee; @@ -1587,7 +1687,7 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc #if defined(PRINT_DEBUG_NETCOMPARE) if (! tentative && new_nodes > 0) { - tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name () << " with " << new_nodes << " new pairs"; + tl::info << indent(depth) << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs"; } #endif @@ -1609,7 +1709,7 @@ NetGraph::derive_node_identities_from_node_set (const std::vector data->max_depth) { #if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << max_depth << ")"; + tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")"; #endif return std::numeric_limits::max (); } @@ -1814,7 +1914,7 @@ NetGraph::derive_node_identities_from_node_set (const std::vectornum * n_branch > data->max_n_branch) { #if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << max_n_branch << ") - mismatch."; + tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch."; #endif return std::numeric_limits::max (); @@ -2376,7 +2476,7 @@ bool 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); - db::SubCircuitCategorizer subcircuit_categorizer; + db::SubCircuitCategorizer subcircuit_categorizer; // @@@ no longer required db::NetGraph g1, g2; diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 994bd052f..d01980573 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -1550,10 +1550,10 @@ TEST(10_SimpleSubCircuits) "end_circuit INV INV MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets VDD VDD\n" - "match_nets IN IN\n" "match_nets VSS VSS\n" "match_nets INT INT\n" + "match_nets IN IN\n" + "match_nets VDD VDD\n" "match_pins $0 $2\n" "match_pins $1 $0\n" "match_pins $2 $1\n" @@ -1617,10 +1617,10 @@ TEST(10_SimpleSubCircuitsMatchedNames) "end_circuit INV INVB MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets VDD VDD\n" - "match_nets IN IN\n" "match_nets VSS VSS\n" "match_nets INT INT\n" + "match_nets IN IN\n" + "match_nets VDD VDD\n" "match_pins $0 $2\n" "match_pins $1 $0\n" "match_pins $2 $1\n" @@ -1681,12 +1681,10 @@ TEST(11_MismatchingSubcircuits) "end_circuit INV INV NOMATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - // because VDD is a floating pin in #1 and floating pins are treated different from - // connected ones - "net_mismatch VDD VDD\n" + "match_nets VSS VSS\n" "match_nets INT INT\n" "match_nets IN IN\n" - "match_nets VSS VSS\n" + "match_nets VDD VDD\n" "match_pins $0 $2\n" "match_pins $1 $0\n" "match_pins $2 $1\n" @@ -1743,7 +1741,7 @@ TEST(11_MismatchingSubcircuits) " net OUT:OUT [Match]\n" " pin $1:$0\n" " subcircuit_pin $2[$1]:$1[$3]\n" - " net VDD:VDD [Mismatch]\n" + " net VDD:VDD [Match]\n" " pin $2:$1\n" " subcircuit_pin $1[$2]:$2[$0]\n" " subcircuit_pin $2[$2]:$1[$0]\n" @@ -1841,9 +1839,9 @@ TEST(12_MismatchingSubcircuitsDuplicates) "end_circuit INV INV MATCH\n" "begin_circuit TOP TOP\n" "match_nets IN IN\n" - "net_mismatch VDD VDD\n" - "net_mismatch VSS VSS\n" "net_mismatch INT INT\n" + "net_mismatch VSS VSS\n" + "net_mismatch VDD VDD\n" "net_mismatch OUT OUT\n" "match_pins $0 $1\n" "match_pins $1 $0\n" @@ -1909,10 +1907,10 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "end_circuit INV INV MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets VDD VDD\n" - "match_nets IN IN\n" "match_nets VSS VSS\n" "match_nets INT INT\n" + "match_nets IN IN\n" + "match_nets VDD VDD\n" "match_pins $0 $1\n" "match_pins $1 $0\n" "match_pins $2 $2\n" @@ -1980,12 +1978,12 @@ TEST(14_Subcircuit2Nand) "match_devices $4 $4\n" "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" - "match_nets IN2 IN2\n" - "match_nets INT INT\n" - "match_nets IN1 IN1\n" "match_nets OUT OUT\n" - "match_nets VDD VDD\n" "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets INT INT\n" + "match_nets IN2 IN2\n" + "match_nets IN1 IN1\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -2055,10 +2053,10 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "net_mismatch IN1 INT\n" + "match_nets VSS VSS\n" + "match_nets VDD VDD\n" "net_mismatch INT IN1\n" - "net_mismatch VDD VDD\n" - "net_mismatch VSS VSS\n" + "net_mismatch IN1 INT\n" "net_mismatch IN2 IN2\n" "pin_mismatch $0 (null)\n" "match_pins $1 $1\n" @@ -2136,11 +2134,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) " net OUT:OUT [Match]\n" " pin $2:$2\n" " subcircuit_pin $2[$2]:$1[$2]\n" - " net VDD:VDD [Mismatch]\n" + " net VDD:VDD [Match]\n" " pin $3:$3\n" " subcircuit_pin $1[$3]:$2[$3]\n" " subcircuit_pin $2[$3]:$1[$3]\n" - " net VSS:VSS [Mismatch]\n" + " net VSS:VSS [Match]\n" " pin $4:$4\n" " subcircuit_pin $1[$4]:$2[$4]\n" " subcircuit_pin $2[$4]:$1[$4]\n" @@ -2205,12 +2203,12 @@ TEST(14_Subcircuit2MatchWithSwap) "match_devices $4 $4\n" "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" - "match_nets IN2 IN2\n" - "match_nets INT INT\n" - "match_nets IN1 IN1\n" "match_nets OUT OUT\n" - "match_nets VDD VDD\n" "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets INT INT\n" + "match_nets IN2 IN2\n" + "match_nets IN1 IN1\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -2275,10 +2273,10 @@ TEST(15_EmptySubCircuitTest) "end_circuit TRANS TRANS MATCH\n" "begin_circuit INV2 INV2\n" "match_nets $5 $5\n" - "match_nets OUT OUT\n" "match_nets $2 $2\n" "match_nets IN IN\n" "match_nets $4 $4\n" + "match_nets OUT OUT\n" "match_pins IN IN\n" "match_pins $1 $1\n" "match_pins OUT OUT\n" @@ -2350,10 +2348,10 @@ TEST(15_EmptySubCircuitWithoutPinNames) "end_circuit TRANS TRANS MATCH\n" "begin_circuit INV2 INV2\n" "match_nets $5 $5\n" - "match_nets OUT OUT\n" "match_nets $2 $2\n" "match_nets IN IN\n" "match_nets $4 $4\n" + "match_nets OUT OUT\n" "match_pins IN IN\n" "match_pins $1 $1\n" "match_pins OUT OUT\n" @@ -2444,14 +2442,14 @@ TEST(16_UniqueSubCircuitMatching) "end_circuit INV2 INV2 MATCH\n" "begin_circuit INV2PAIR INV2PAIR\n" "match_nets $I2 $I2\n" - "match_nets $I1 $I1\n" + "match_nets BULK BULK\n" + "match_nets $I6 $I6\n" + "match_nets $I5 $I5\n" + "match_nets $I4 $I4\n" "match_nets $I3 $I3\n" "match_nets $I7 $I7\n" - "match_nets $I4 $I4\n" - "match_nets $I5 $I5\n" + "match_nets $I1 $I1\n" "match_nets $I8 $I8\n" - "match_nets $I6 $I6\n" - "match_nets BULK BULK\n" "match_pins BULK BULK\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -2464,17 +2462,17 @@ TEST(16_UniqueSubCircuitMatching) "end_circuit INV2PAIR INV2PAIR MATCH\n" "begin_circuit RINGO RINGO\n" "match_nets OSC OSC\n" - "match_nets BULK,VSS BULK,VSS\n" - "match_nets FB FB\n" - "match_nets $I22 $I22\n" "match_nets VDD VDD\n" + "match_nets FB FB\n" "match_nets $I13 $I13\n" - "match_nets $I23 $I23\n" "match_nets $I5 $I5\n" - "match_nets $I24 $I24\n" "match_nets $I6 $I6\n" "match_nets $I7 $I7\n" + "match_nets BULK,VSS BULK,VSS\n" "match_nets $I25 $I25\n" + "match_nets $I24 $I24\n" + "match_nets $I23 $I23\n" + "match_nets $I22 $I22\n" "match_subcircuits $1 $1\n" "match_subcircuits $4 $2\n" "match_subcircuits $3 $3\n" @@ -2552,28 +2550,28 @@ TEST(17_InherentlyAmbiguousDecoder) "begin_circuit DECODER DECODER\n" "match_nets VSS VSS\n" "match_nets VDD VDD\n" - "match_ambiguous_nets A B\n" - "match_ambiguous_nets B A\n" - "match_nets NQ1 NQ2\n" - "match_nets NQ3 NQ3\n" - "match_nets NB NA\n" "match_nets NQ0 NQ0\n" - "match_nets NA NB\n" - "match_nets NQ2 NQ1\n" - "match_pins $0 $0\n" - "match_pins $1 $1\n" + "match_ambiguous_nets NQ1 NQ1\n" + "match_ambiguous_nets NQ2 NQ2\n" + "match_nets NQ3 NQ3\n" + "match_ambiguous_nets NA NA\n" + "match_ambiguous_nets NB NB\n" + "match_nets B B\n" + "match_nets A A\n" + "match_pins $0 $1\n" + "match_pins $1 $0\n" "match_pins $2 $2\n" - "match_pins $3 $4\n" - "match_pins $4 $3\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 $2 $1\n" - "match_subcircuits $1 $2\n" - "match_subcircuits $5 $3\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 $4 $6\n" + "match_subcircuits $5 $6\n" "end_circuit DECODER DECODER MATCH" ); @@ -2602,11 +2600,11 @@ TEST(17_InherentlyAmbiguousDecoder) "match_devices $4 $4\n" "end_circuit NAND NAND MATCH\n" "begin_circuit DECODER DECODER\n" - "match_nets NA NA\n" + "match_nets VSS VSS\n" "match_nets VDD VDD\n" "match_nets B B\n" "match_nets NB NB\n" - "match_nets VSS VSS\n" + "match_nets NA NA\n" "match_nets NQ0 NQ0\n" "match_nets NQ2 NQ2\n" "match_nets NQ1 NQ1\n" @@ -2709,9 +2707,9 @@ TEST(18_ClockTree) "end_circuit INV INV MATCH\n" "begin_circuit TXEE TXEE\n" "match_nets IN IN\n" - "match_nets S S\n" - "match_nets VDD VDD\n" "match_nets VSS VSS\n" + "match_nets VDD VDD\n" + "match_nets S S\n" "match_ambiguous_nets SX SX\n" "match_ambiguous_nets SX SX\n" "match_ambiguous_nets SXX SXX\n"