diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 28464f085..8c36c8e75 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -333,6 +333,63 @@ private: double m_cap_threshold, m_res_threshold; }; +// -------------------------------------------------------------------------------------------------------------------- +// A generic equivalence mapper + +template +class generic_equivalence_tracker +{ +public: + generic_equivalence_tracker () + { + // .. nothing yet .. + } + + bool map (const Obj *a, const Obj *b) + { + std::pair::iterator, bool> inserted1 = m_eq.insert (std::make_pair (a, b)); + tl_assert (inserted1.first->second == b); + std::pair::iterator, bool> inserted2 = m_eq.insert (std::make_pair (b, a)); + tl_assert (inserted2.first->second == a); + return inserted1.second; + } + + void unmap (const Obj *a, const Obj *b) + { + m_eq.erase (a); + m_eq.erase (b); + } + + const Obj *other (const Obj *o) const + { + typename std::map::const_iterator i = m_eq.find (o); + return i == m_eq.end () ? 0 : i->second; + } + +public: + std::map m_eq; +}; + +// -------------------------------------------------------------------------------------------------------------------- +// A class describing the equivalence between subcircuits we established so far + +class SubCircuitEquivalenceTracker + : public generic_equivalence_tracker +{ +public: + SubCircuitEquivalenceTracker () : generic_equivalence_tracker () { } +}; + +// -------------------------------------------------------------------------------------------------------------------- +// A class describing the equivalence between devices we established so far + +class DeviceEquivalenceTracker + : public generic_equivalence_tracker +{ +public: + DeviceEquivalenceTracker () : generic_equivalence_tracker () { } +}; + // -------------------------------------------------------------------------------------------------------------------- // generic_categorizer definition and implementation @@ -559,7 +616,8 @@ class NetGraph; struct CompareData { CompareData () - : other (0), max_depth (0), max_n_branch (0), dont_consider_net_names (false), logger (0), circuit_pin_mapper (0) + : other (0), max_depth (0), max_n_branch (0), dont_consider_net_names (false), logger (0), + circuit_pin_mapper (0), subcircuit_equivalence (0), device_equivalence (0) { } NetGraph *other; @@ -568,6 +626,8 @@ struct CompareData bool dont_consider_net_names; NetlistCompareLogger *logger; CircuitPinMapper *circuit_pin_mapper; + SubCircuitEquivalenceTracker *subcircuit_equivalence; + DeviceEquivalenceTracker *device_equivalence; }; // -------------------------------------------------------------------------------------------------------------------- @@ -619,6 +679,16 @@ public: m_id2 = pin2_id; } + size_t id1 () const + { + return m_id1; + } + + size_t id2 () const + { + return m_id2; + } + bool operator< (const Transition &other) const { if (is_for_subcircuit () != other.is_for_subcircuit ()) { @@ -888,9 +958,9 @@ namespace db struct CompareNodePtr { - bool operator() (const NetGraphNode *a, const NetGraphNode *b) const + bool operator() (const std::pair &a, const std::pair &b) const { - return *a < *b; + return *a.first < *b.first; } }; @@ -1053,7 +1123,7 @@ public: * with a proposed identity. With "with_ambiguous", amiguities are resolved by trying * different combinations in tentative mode and deciding for one combination if possible. */ - size_t derive_node_identities_from_node_set (std::vector &nodes, std::vector &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data); + size_t derive_node_identities_from_node_set (std::vector > &nodes, std::vector > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data); private: std::vector m_nodes; @@ -1426,7 +1496,8 @@ NetGraphNode::edge_equal (const db::Net *a, const db::Net *b) */ struct NodeRange { - NodeRange (size_t _num, std::vector::iterator _n1, std::vector::iterator _nn1, std::vector::iterator _n2, std::vector::iterator _nn2) + NodeRange (size_t _num, std::vector >::iterator _n1, std::vector >::iterator _nn1, + std::vector >::iterator _n2, std::vector >::iterator _nn2) : num (_num), n1 (_n1), nn1 (_nn1), n2 (_n2), nn2 (_nn2) { // .. nothing yet .. @@ -1438,11 +1509,163 @@ struct NodeRange } size_t num; - std::vector::iterator n1, nn1, n2, nn2; + std::vector >::iterator n1, nn1, n2, nn2; }; // -------------------------------------------------------------------------------------------------------------------- +struct CatAndIds +{ +public: + CatAndIds (size_t _cat, size_t _id1, size_t _id2) + : cat (_cat), id1 (_id1), id2 (_id2) + { } + + bool operator== (const CatAndIds &other) const + { + return cat == other.cat && id1 == other.id1 && id2 == other.id2; + } + + bool operator< (const CatAndIds &other) const + { + if (cat != other.cat) { + return cat < other.cat; + } + if (id1 != other.id1) { + return id1 < other.id1; + } + if (id2 != other.id2) { + return id2 < other.id2; + } + return false; + } + + size_t cat, id1, id2; +}; + +template +class generic_mapper_for_target_node +{ +public: + generic_mapper_for_target_node () + { + // .. nothing yet .. + } + + static void derive_mapping (const generic_mapper_for_target_node &m1, const generic_mapper_for_target_node &m2, size_t n1, size_t n2, std::vector > &mapped) + { + if (m1.empty () || m2.empty ()) { + return; + } + + const std::set > &s1 = m1.for_node (n1); + const std::set > &s2 = m2.for_node (n2); + + typename std::set >::const_iterator i1 = s1.begin (), i2 = s2.begin (); + + while (i1 != s1.end () && i2 != s2.end ()) { + + if (i1->first < i2->first) { + ++i1; + } else if (i2->first < i1->first) { + ++i2; + } else { + typename std::set >::const_iterator i10 = i1, i20 = i2; + size_t n1 = 0, n2 = 0; + while (i1 != s1.end () && i1->first == i10->first) { + ++i1; + ++n1; + } + while (i2 != s2.end () && i2->first == i20->first) { + ++i2; + ++n2; + } + if (n1 == 1 && n2 == 1) { + // unique mapping - one device of one category + mapped.push_back (std::make_pair (i10->second, i20->second)); + } + } + + } + + } + +protected: + const std::set > &for_node (size_t ni) const + { + typename std::map > >::const_iterator d = m_per_target_node.find (ni); + tl_assert (d != m_per_target_node.end ()); + return d->second; + } + + std::set > &for_node_nc (size_t ni) + { + return m_per_target_node [ni]; + } + + bool empty () const + { + return m_per_target_node.empty (); + } + +private: + std::map > > m_per_target_node; +}; + +class DeviceMapperForTargetNode + : public generic_mapper_for_target_node +{ +public: + DeviceMapperForTargetNode () + : generic_mapper_for_target_node () + { + // .. nothing yet .. + } + + void insert (const NetGraphNode::edge_type &e) + { + if (e.first.empty ()) { + // happens initially + return; + } + + size_t ni = e.second.first; + std::set > &dev = for_node_nc (ni); + for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { + if (! j->is_for_subcircuit ()) { + dev.insert (std::make_pair (CatAndIds (j->device_pair ().second, j->id1 (), j->id2 ()), j->device_pair ().first)); + } + } + } +}; + +class SubCircuitMapperForTargetNode + : public generic_mapper_for_target_node +{ +public: + SubCircuitMapperForTargetNode () + : generic_mapper_for_target_node () + { + // .. nothing yet .. + } + + void insert (const NetGraphNode::edge_type &e) + { + if (e.first.empty ()) { + // happens initially + return; + } + + size_t ni = e.second.first; + std::set > &sc = for_node_nc (ni); + for (std::vector::const_iterator j = e.first.begin (); j != e.first.end (); ++j) { + if (j->is_for_subcircuit ()) { + sc.insert (std::make_pair (CatAndIds (j->subcircuit_pair ().second, j->id1 (), j->id2 ()), j->subcircuit_pair ().first)); + } + } + } +}; + /** * @brief An audit object which allows reverting tentative node assignments */ @@ -1460,26 +1683,46 @@ public: for (std::vector >::const_iterator i = m_to_undo_to_unknown.begin (); i != m_to_undo_to_unknown.end (); ++i) { i->first->identify (i->second, unknown_id); } + for (std::vector > >::const_iterator i = m_to_undo_devices.begin (); i != m_to_undo_devices.end (); ++i) { + i->first->unmap (i->second.first, i->second.second); + } + for (std::vector > >::const_iterator i = m_to_undo_subcircuits.begin (); i != m_to_undo_subcircuits.end (); ++i) { + i->first->unmap (i->second.first, i->second.second); + } } - static void map_pair (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2) + static void map_pair (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2, + const DeviceMapperForTargetNode &dm1, const DeviceMapperForTargetNode &dm2, DeviceEquivalenceTracker &device_eq, + const SubCircuitMapperForTargetNode &scm1, const SubCircuitMapperForTargetNode &scm2, SubCircuitEquivalenceTracker &subcircuit_eq, + size_t depth) { g1->identify (n1, n2); g2->identify (n2, n1); + if (nm) { nm->keep (g1, n1); nm->keep (g2, n2); } + + derive_device_equivalence (nm, n1, n2, dm1, dm2, device_eq, depth); + derive_subcircuit_equivalence (nm, n1, n2, scm1, scm2, subcircuit_eq, depth); } - static void map_pair_from_unknown (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2) + static void map_pair_from_unknown (TentativeNodeMapping *nm, NetGraph *g1, size_t n1, NetGraph *g2, size_t n2, + const DeviceMapperForTargetNode &dm1, const DeviceMapperForTargetNode &dm2, DeviceEquivalenceTracker &device_eq, + const SubCircuitMapperForTargetNode &scm1, const SubCircuitMapperForTargetNode &scm2, SubCircuitEquivalenceTracker &subcircuit_eq, + size_t depth) { g1->identify (n1, n2); g2->identify (n2, n1); + if (nm) { nm->keep_for_unknown (g1, n1); nm->keep_for_unknown (g2, n2); } + + derive_device_equivalence (nm, n1, n2, dm1, dm2, device_eq, depth); + derive_subcircuit_equivalence (nm, n1, n2, scm1, scm2, subcircuit_eq, depth); } static void map_to_unknown (TentativeNodeMapping *nm, NetGraph *g1, size_t n1) @@ -1490,8 +1733,48 @@ public: } } + static void derive_device_equivalence (TentativeNodeMapping *nm, size_t n1, size_t n2, + const DeviceMapperForTargetNode &dm1, const DeviceMapperForTargetNode &dm2, DeviceEquivalenceTracker &device_eq, size_t depth) + { + std::vector > device_map; + DeviceMapperForTargetNode::derive_mapping (dm1, dm2, n1, n2, device_map); + + for (std::vector >::const_iterator dd = device_map.begin (); dd != device_map.end (); ++dd) { + if (device_eq.map (dd->first, dd->second)) { + if (nm) { + nm->keep (&device_eq, dd->first, dd->second); + } else { + if (options ()->debug_netcompare) { + tl::info << indent(depth) << "enforcing device equivalence: " << dd->first->expanded_name () << " vs. " << dd->second->expanded_name (); + } + } + } + } + } + + static void derive_subcircuit_equivalence (TentativeNodeMapping *nm, size_t n1, size_t n2, + const SubCircuitMapperForTargetNode &scm1, const SubCircuitMapperForTargetNode &scm2, SubCircuitEquivalenceTracker &subcircuit_eq, size_t depth) + { + std::vector > subcircuit_map; + SubCircuitMapperForTargetNode::derive_mapping (scm1, scm2, n1, n2, subcircuit_map); + + for (std::vector >::const_iterator cc = subcircuit_map.begin (); cc != subcircuit_map.end (); ++cc) { + if (subcircuit_eq.map (cc->first, cc->second)) { + if (nm) { + nm->keep (&subcircuit_eq, cc->first, cc->second); + } else { + if (options ()->debug_netcompare) { + tl::info << indent(depth) << "enforcing subcircuit equivalence: " << cc->first->expanded_name () << " vs. " << cc->second->expanded_name (); + } + } + } + } + } + private: std::vector > m_to_undo, m_to_undo_to_unknown; + std::vector > > m_to_undo_devices; + std::vector > > m_to_undo_subcircuits; void keep (NetGraph *g1, size_t n1) { @@ -1502,6 +1785,16 @@ private: { m_to_undo_to_unknown.push_back (std::make_pair (g1, n1)); } + + void keep (DeviceEquivalenceTracker *dt, const db::Device *a, const db::Device *b) + { + m_to_undo_devices.push_back (std::make_pair (dt, std::make_pair (a, b))); + } + + void keep (SubCircuitEquivalenceTracker *dt, const db::SubCircuit *a, const db::SubCircuit *b) + { + m_to_undo_subcircuits.push_back (std::make_pair (dt, std::make_pair (a, b))); + } }; // -------------------------------------------------------------------------------------------------------------------- @@ -1533,8 +1826,6 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci } } - 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 ())); } @@ -1579,16 +1870,66 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci } } +/** + * @brief Returns true if the edges (given by transition iterators) are compatible with already established device or subcircuit equivalences. + */ +static bool edges_are_compatible (const NetGraphNode::edge_type &e, const NetGraphNode::edge_type &e_other, const DeviceEquivalenceTracker &device_eq, const SubCircuitEquivalenceTracker &sc_eq) +{ + std::vector::const_iterator t1 = e.first.begin (), tt1 = e.first.end (); + std::vector::const_iterator t2 = e_other.first.begin (), tt2 = e_other.first.end (); + + std::vector p1, p2; + + while (t1 != tt1 && t2 != tt2) { + + std::vector::const_iterator t10 = t1, t20 = t2; + + p1.clear (); + while (t1 != tt1 && *t1 == *t10) { + if (t1->is_for_subcircuit ()) { + p1.push_back ((void *) sc_eq.other (t1->subcircuit_pair ().first)); + } else { + p1.push_back ((void *) device_eq.other (t1->device_pair ().first)); + } + ++t1; + } + + p2.clear (); + while (t2 != tt2 && *t2 == *t20) { + if (t2->is_for_subcircuit ()) { + p2.push_back ((void *) (sc_eq.other (t2->subcircuit_pair ().first) ? t2->subcircuit_pair ().first : 0)); + } else { + p2.push_back ((void *) (device_eq.other (t2->device_pair ().first) ? t2->device_pair ().first : 0)); + } + ++t2; + } + + std::sort (p1.begin (), p1.end ()); + std::sort (p2.begin (), p2.end ()); + + if (p1 != p2) { + return false; + } + + } + + tl_assert (t1 == tt1 && t2 == tt2); + return true; +} + 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) { size_t new_nodes = 0; - std::vector nodes; + std::vector > nodes; nodes.reserve (ee - e); - std::vector other_nodes; + std::vector > other_nodes; other_nodes.reserve (ee - e); + + tl_assert (e->first == e_other->first); + if (options ()->debug_netcompare) { tl::info << indent(depth) << "considering transitions:"; } @@ -1609,7 +1950,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr } tl::info << ""; } - nodes.push_back (nn); + nodes.push_back (std::make_pair (nn, i)); } } @@ -1631,7 +1972,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr } tl::info << ""; } - other_nodes.push_back (nn); + other_nodes.push_back (std::make_pair (nn, i)); } } @@ -1656,7 +1997,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr // 1:1 pairing is less strict if (nodes.size () > 1 || other_nodes.size () > 1) { for (size_t i = 0; i < nodes.size (); ++i) { - if (! (*nodes[i] == *other_nodes[i])) { + if (! (*nodes[i].first == *other_nodes[i].first)) { if (options ()->debug_netcompare) { tl::info << indent(depth) << "=> rejected branch."; } @@ -1827,10 +2168,10 @@ namespace { struct SortNodeByNet { public: - bool operator() (const NetGraphNode *a, const NetGraphNode *b) const + bool operator() (const std::pair &a, const std::pairb) const { - tl_assert (a->net () && b->net ()); - return name_compare (a->net ()->name (), b->net ()->name ()) < 0; + tl_assert (a.first->net () && b.first->net ()); + return name_compare (a.first->net ()->name (), b.first->net ()->name ()) < 0; } }; @@ -1841,12 +2182,12 @@ static void sort_node_range_by_best_match (NodeRange &nr) std::stable_sort (nr.n1, nr.nn1, SortNodeByNet ()); std::stable_sort (nr.n2, nr.nn2, SortNodeByNet ()); - std::vector nomatch1, nomatch2; + std::vector > nomatch1, nomatch2; nomatch1.reserve (nr.nn1 - nr.n1); nomatch2.reserve (nr.nn2 - nr.n2); - std::vector::const_iterator i = nr.n1, j = nr.n2; - std::vector::iterator iw = nr.n1, jw = nr.n2; + std::vector >::const_iterator i = nr.n1, j = nr.n2; + std::vector >::iterator iw = nr.n1, jw = nr.n2; SortNodeByNet compare; @@ -1896,7 +2237,7 @@ static bool net_names_are_different (const db::Net *a, const db::Net *b) } size_t -NetGraph::derive_node_identities_from_node_set (std::vector &nodes, std::vector &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data) +NetGraph::derive_node_identities_from_node_set (std::vector > &nodes, std::vector > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data) { std::string indent_s; if (options ()->debug_netcompare) { @@ -1913,27 +2254,53 @@ NetGraph::derive_node_identities_from_node_set (std::vector >::const_iterator i = nodes.begin (); i != nodes.end (); ++i) { + dm.insert (*i->second); + scm.insert (*i->second); + } + + DeviceMapperForTargetNode dm_other; + SubCircuitMapperForTargetNode scm_other; + for (std::vector >::const_iterator i = other_nodes.begin (); i != other_nodes.end (); ++i) { + dm_other.insert (*i->second); + scm_other.insert (*i->second); + } + if (nodes.size () == 1 && other_nodes.size () == 1) { - if (! nodes.front ()->has_any_other () && ! other_nodes.front ()->has_any_other ()) { + const NetGraphNode *n = nodes.front ().first; + const NetGraphNode *n_other = other_nodes.front ().first; + + // reject the transition if the edges provide a contradiction to already established equivalences + + if (! edges_are_compatible (*nodes.front ().second, *other_nodes.front ().second, *data->device_equivalence, *data->subcircuit_equivalence)) { + + if (options ()->debug_netcompare) { + tl::info << indent(depth) << "=> rejected because edges are incompatible with already established device or subcircuit equivalences"; + } + return tentative ? failed_match : 0; + + } else if (! n->has_any_other () && ! n_other->has_any_other ()) { // 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.front ()->net ()); - size_t other_ni = data->other->node_index_for_net (other_nodes.front ()->net ()); + size_t ni = node_index_for_net (n->net ()); + size_t other_ni = data->other->node_index_for_net (n_other->net ()); - TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni); + TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth); if (options ()->debug_netcompare) { - tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name (); + 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 (nodes.front ()->net (), other_nodes.front ()->net ()); + data->logger->net_mismatch (n->net (), n_other->net ()); } else { - data->logger->match_nets (nodes.front ()->net (), other_nodes.front ()->net ()); + data->logger->match_nets (n->net (), n_other->net ()); } } @@ -1948,14 +2315,14 @@ NetGraph::derive_node_identities_from_node_set (std::vectorhas_unknown_other ()) { + } else if (n->has_unknown_other ()) { // accept this solution as the pairing is possible - } else if (nodes.front ()->has_other ()) { + } else if (n->has_other ()) { // this decision leads to a contradiction - if (data->other->node_index_for_net (other_nodes.front ()->net ()) != nodes.front ()->other_net_index ()) { + if (data->other->node_index_for_net (n_other->net ()) != n->other_net_index ()) { return failed_match; } @@ -1974,38 +2341,38 @@ NetGraph::derive_node_identities_from_node_set (std::vector node_ranges; - std::vector::iterator n1 = nodes.begin (); - std::vector::iterator n2 = other_nodes.begin (); + std::vector >::iterator n1 = nodes.begin (); + std::vector >::iterator n2 = other_nodes.begin (); while (n1 != nodes.end () && n2 != other_nodes.end ()) { - if ((*n1)->has_any_other ()) { + if (n1->first->has_any_other ()) { ++n1; continue; - } else if ((*n2)->has_any_other ()) { + } else if (n2->first->has_any_other ()) { ++n2; continue; } - if (**n1 < **n2) { + if (*n1->first < *n2->first) { ++n1; continue; - } else if (**n2 < **n1) { + } else if (*n2->first < *n1->first) { ++n2; continue; } - std::vector::iterator nn1 = n1, nn2 = n2; + std::vector >::iterator nn1 = n1, nn2 = n2; size_t num = 1; ++nn1; ++nn2; while (nn1 != nodes.end () && nn2 != other_nodes.end ()) { - if ((*nn1)->has_any_other ()) { + if (nn1->first->has_any_other ()) { ++nn1; - } else if ((*nn2)->has_any_other ()) { + } else if (nn2->first->has_any_other ()) { ++nn2; - } else if (! (**nn1 == **n1) || ! (**nn2 == **n2)) { + } else if (! (*nn1->first == *n1->first) || ! (*nn2->first == *n2->first)) { break; } else { ++num; @@ -2038,9 +2405,9 @@ NetGraph::derive_node_identities_from_node_set (std::vectorn1 != nr->nn1 && nr->n2 != nr->nn2) { - if ((*nr->n1)->has_any_other ()) { + if (nr->n1->first->has_any_other ()) { ++nr->n1; - } else if ((*nr->n2)->has_any_other ()) { + } else if (nr->n2->first->has_any_other ()) { ++nr->n2; } else { break; @@ -2048,12 +2415,12 @@ NetGraph::derive_node_identities_from_node_set (std::vectornum = 0; - std::vector::const_iterator i1 = nr->n1, i2 = nr->n2; + std::vector >::const_iterator i1 = nr->n1, i2 = nr->n2; while (i1 != nr->nn1 && i2 != nr->nn2) { - if ((*i1)->has_any_other ()) { + if (i1->first->has_any_other ()) { ++i1; - } else if ((*i2)->has_any_other ()) { + } else if (i2->first->has_any_other ()) { ++i2; } else { ++nr->num; @@ -2068,14 +2435,14 @@ NetGraph::derive_node_identities_from_node_set (std::vectornum == 1) { - if (! (*nr->n1)->has_any_other () && ! (*nr->n2)->has_any_other ()) { + if (! nr->n1->first->has_any_other () && ! nr->n2->first->has_any_other ()) { // in tentative mode, reject this choice if both nets are named and // their names differ -> this favors net matching by name - if (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) { + if (tentative && ! data->dont_consider_net_names && net_names_are_different (nr->n1->first->net (), nr->n2->first->net ())) { if (options ()->debug_netcompare) { - tl::info << indent_s << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name (); + tl::info << indent_s << "rejecting pair as names are not identical: " << nr->n1->first->net ()->expanded_name () << " vs. " << nr->n2->first->net ()->expanded_name (); } return failed_match; } @@ -2083,20 +2450,20 @@ NetGraph::derive_node_identities_from_node_set (std::vector this may render // inexact matches, but further propagates net pairing - size_t ni = node_index_for_net ((*nr->n1)->net ()); - size_t other_ni = data->other->node_index_for_net ((*nr->n2)->net ()); + size_t ni = node_index_for_net (nr->n1->first->net ()); + size_t other_ni = data->other->node_index_for_net (nr->n2->first->net ()); - TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni); + TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth); if (options ()->debug_netcompare) { - tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name (); + 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)->net (), (*nr->n2)->net ()); + data->logger->net_mismatch (nr->n1->first->net (), nr->n2->first->net ()); } else { - data->logger->match_nets ((*nr->n1)->net (), (*nr->n2)->net ()); + data->logger->match_nets (nr->n1->first->net (), nr->n2->first->net ()); } } @@ -2110,14 +2477,14 @@ NetGraph::derive_node_identities_from_node_set (std::vectorn1)->has_unknown_other ()) { + } else if (nr->n1->first->has_unknown_other ()) { // accept any other net - } else if ((*nr->n1)->has_other ()) { + } else if (nr->n1->first->has_other ()) { // this decision leads to a contradiction - if (data->other->node_index_for_net ((*nr->n2)->net ()) != (*nr->n1)->other_net_index ()) { + if (data->other->node_index_for_net (nr->n2->first->net ()) != nr->n1->first->other_net_index ()) { return failed_match; } @@ -2157,48 +2524,56 @@ NetGraph::derive_node_identities_from_node_set (std::vector::const_iterator> iters1, iters2; + std::vector >::const_iterator> iters1, iters2; - for (std::vector::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) { - if (! (*i1)->has_any_other ()) { + for (std::vector >::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) { + if (! i1->first->has_any_other ()) { iters1.push_back (i1); - size_t ni = node_index_for_net ((*i1)->net ()); + size_t ni = node_index_for_net (i1->first->net ()); TentativeNodeMapping::map_to_unknown (&tn2unknown, this, ni); } } - for (std::vector::const_iterator i2 = nr->n2; i2 != nr->nn2; ++i2) { - if (! (*i2)->has_any_other ()) { + for (std::vector >::const_iterator i2 = nr->n2; i2 != nr->nn2; ++i2) { + if (! i2->first->has_any_other ()) { iters2.push_back (i2); - size_t other_ni = data->other->node_index_for_net ((*i2)->net ()); + size_t other_ni = data->other->node_index_for_net (i2->first->net ()); TentativeNodeMapping::map_to_unknown (&tn2unknown, data->other, other_ni); } } - for (std::vector::const_iterator>::const_iterator ii1 = iters1.begin (); ii1 != iters1.end (); ++ii1) { + for (std::vector >::const_iterator>::const_iterator ii1 = iters1.begin (); ii1 != iters1.end (); ++ii1) { - std::vector::const_iterator i1 = *ii1; + std::vector >::const_iterator i1 = *ii1; bool any = false; - for (std::vector::const_iterator>::const_iterator ii2 = iters2.begin (); ii2 != iters2.end (); ++ii2) { + for (std::vector >::const_iterator>::const_iterator ii2 = iters2.begin (); ii2 != iters2.end (); ++ii2) { - std::vector::const_iterator i2 = *ii2; + std::vector >::const_iterator i2 = *ii2; - if (seen.find (*i2) != seen.end ()) { + if (seen.find (i2->first) != seen.end ()) { continue; } - size_t ni = node_index_for_net ((*i1)->net ()); - size_t other_ni = data->other->node_index_for_net ((*i2)->net ()); - - TentativeNodeMapping tn; - TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni); - // try this candidate in tentative mode if (options ()->debug_netcompare) { - tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name (); + tl::info << indent_s << "trying in tentative mode: " << i1->first->net ()->expanded_name () << " vs. " << i2->first->net ()->expanded_name (); } + + if (! edges_are_compatible (*i1->second, *i2->second, *data->device_equivalence, *data->subcircuit_equivalence)) { + if (options ()->debug_netcompare) { + tl::info << indent_s << "=> rejected because edges are incompatible with already established device or subcircuit equivalences"; + } + continue; + } + + size_t ni = node_index_for_net (i1->first->net ()); + size_t other_ni = data->other->node_index_for_net (i2->first->net ()); + + TentativeNodeMapping tn; + TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth); + size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data); if (bt_count != failed_match) { @@ -2212,14 +2587,14 @@ NetGraph::derive_node_identities_from_node_set (std::vectorfirst, pairs.back ().second); } else { // identified a new pair new_nodes += bt_count + 1; - pairs.push_back (std::make_pair (*i1, *i2)); - seen.insert (*i2); + pairs.push_back (std::make_pair (i1->first, i2->first)); + seen.insert (i2->first); any = true; } @@ -2249,7 +2624,7 @@ NetGraph::derive_node_identities_from_node_set (std::vectorfirst->net ()); size_t other_ni = data->other->node_index_for_net (p->second->net ()); - TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni); + TentativeNodeMapping::map_pair (0, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth); if (options ()->debug_netcompare) { if (equivalent_other_nodes.has_attribute (p->second)) { @@ -2287,7 +2662,7 @@ NetGraph::derive_node_identities_from_node_set (std::vectorfirst->net ()); size_t other_ni = data->other->node_index_for_net (p->second->net ()); - TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni); + TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth); } @@ -2854,6 +3229,8 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, std::map &c22_circuit_and_pin_mapping) const { db::DeviceFilter device_filter (m_cap_threshold, m_res_threshold); + SubCircuitEquivalenceTracker subcircuit_equivalence; + DeviceEquivalenceTracker device_equivalence; db::NetGraph g1, g2; @@ -2908,6 +3285,8 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, data.max_n_branch = m_max_n_branch; data.dont_consider_net_names = m_dont_consider_net_names; data.circuit_pin_mapper = &circuit_pin_mapper; + data.subcircuit_equivalence = &subcircuit_equivalence; + data.device_equivalence = &device_equivalence; data.logger = mp_logger; size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data); @@ -2928,29 +3307,32 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, // derive new identities through topology: first collect all nets with the same topological signature - std::vector nodes, other_nodes; + std::vector > nodes, other_nodes; + + std::vector no_edges; + no_edges.push_back (NetGraphNode::edge_type ()); nodes.reserve (g1.end () - g1.begin ()); for (db::NetGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { if (! i1->has_other () && i1->net ()) { - nodes.push_back (i1.operator-> ()); + nodes.push_back (std::make_pair (i1.operator-> (), no_edges.begin ())); } } other_nodes.reserve (g2.end () - g2.begin ()); for (db::NetGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) { if (! i2->has_other () && i2->net ()) { - other_nodes.push_back (i2.operator-> ()); + other_nodes.push_back (std::make_pair (i2.operator-> (), no_edges.begin ())); } } if (nodes.empty () || other_nodes.empty ()) { // active mismatched nodes give an error - for (std::vector::const_iterator n = nodes.begin (); n != nodes.end () && good; ++n) { - good = is_passive_net ((*n)->net (), c12_circuit_and_pin_mapping); + for (std::vector >::const_iterator n = nodes.begin (); n != nodes.end () && good; ++n) { + good = is_passive_net (n->first->net (), c12_circuit_and_pin_mapping); } - for (std::vector::const_iterator n = other_nodes.begin (); n != other_nodes.end () && good; ++n) { - good = is_passive_net ((*n)->net (), c22_circuit_and_pin_mapping); + 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); } // this assumes that we don't gain anything here. Stop now. break; @@ -2965,9 +3347,11 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, data.max_n_branch = m_max_n_branch; data.dont_consider_net_names = m_dont_consider_net_names; data.circuit_pin_mapper = &circuit_pin_mapper; + data.subcircuit_equivalence = &subcircuit_equivalence; + data.device_equivalence = &device_equivalence; data.logger = mp_logger; - size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data); + 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) { new_identities += ni; if (options ()->debug_netcompare) { @@ -3019,8 +3403,8 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, } do_pin_assignment (c1, g1, c2, g2, c12_circuit_and_pin_mapping, c22_circuit_and_pin_mapping, pin_mismatch, good); - do_device_assignment (c1, g1, c2, g2, device_filter, device_categorizer, good); - do_subcircuit_assignment (c1, g1, c2, g2, circuit_categorizer, circuit_pin_mapper, c12_circuit_and_pin_mapping, c22_circuit_and_pin_mapping, good); + do_device_assignment (c1, g1, c2, g2, device_filter, device_categorizer, device_equivalence, good); + do_subcircuit_assignment (c1, g1, c2, g2, circuit_categorizer, circuit_pin_mapper, c12_circuit_and_pin_mapping, c22_circuit_and_pin_mapping, subcircuit_equivalence, good); return good; } @@ -3235,7 +3619,7 @@ NetlistComparer::do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g } void -NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, db::DeviceCategorizer &device_categorizer, bool &good) const +NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, db::DeviceCategorizer &device_categorizer, DeviceEquivalenceTracker &device_eq, bool &good) const { // Report device assignment @@ -3250,6 +3634,10 @@ 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 @@ -3290,53 +3678,71 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph continue; } - std::vector > k = compute_device_key (*d, g2, device_categorizer.is_strict_device_category (device_cat)); + const db::Device *c1_device = device_eq.other (d.operator-> ()); + size_t c1_device_cat = 0; - 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 (); - } - } + if (c1_device) { - 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; + c1_device_cat = device_categorizer.cat_for_device (c1_device); } else { + std::vector > k = compute_device_key (*d, g2, device_categorizer.is_strict_device_category (device_cat)); + + 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); + + } + + } + + if (c1_device) { + db::DeviceCompare dc; - if (! dc.equals (dm->second, std::make_pair (d.operator-> (), device_cat))) { - if (dm->second.second != device_cat) { + if (! dc.equals (std::make_pair (c1_device, c1_device_cat), std::make_pair (d.operator-> (), device_cat))) { + if (c1_device_cat != device_cat) { if (mp_logger) { - mp_logger->match_devices_with_different_device_classes (dm->second.first, d.operator-> ()); + mp_logger->match_devices_with_different_device_classes (c1_device, d.operator-> ()); } good = false; } else { if (mp_logger) { - mp_logger->match_devices_with_different_parameters (dm->second.first, d.operator-> ()); + mp_logger->match_devices_with_different_parameters (c1_device, d.operator-> ()); } good = false; } } else { if (mp_logger) { - mp_logger->match_devices (dm->second.first, d.operator-> ()); + mp_logger->match_devices (c1_device, d.operator-> ()); } } - device_map.erase (dm); - } } @@ -3420,7 +3826,7 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph } void -NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &good) const +NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const { // Report subcircuit assignment @@ -3434,6 +3840,10 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG continue; } + if (subcircuit_eq.other (sc.operator-> ())) { + continue; + } + std::vector > k; bool valid = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, k); @@ -3467,75 +3877,87 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG continue; } - std::vector > k; - compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, k); + const db::SubCircuit *c1_subcircuit = subcircuit_eq.other (sc.operator-> ()); - 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::sort (k.begin (), k.end ()); - - std::multimap >, std::pair >::iterator scm = subcircuit_map.find (k); - - if (! mapped || scm == subcircuit_map.end ()) { + if (c1_subcircuit) { if (mp_logger) { - unmatched_b.push_back (std::make_pair (k, sc.operator-> ())); + mp_logger->match_subcircuits (c1_subcircuit, sc.operator-> ()); } - good = false; } else { - db::SubCircuitCompare scc; + std::vector > k; + compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, k); - 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; + 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 (); } } - if (! found) { + std::sort (k.begin (), k.end ()); - if (nscm == 1) { + std::multimap >, std::pair >::iterator scm = subcircuit_map.find (k); - // 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 (! mapped || scm == subcircuit_map.end ()) { + if (mp_logger) { + unmatched_b.push_back (std::make_pair (k, sc.operator-> ())); } - good = false; } else { - if (mp_logger) { - mp_logger->match_subcircuits (scm->second.first, sc.operator-> ()); + 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; + } } - // no longer look for this one - subcircuit_map.erase (scm); + 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); + + } } @@ -3725,12 +4147,15 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit) // nodes are identical if the attached devices and circuits are of the same kind and with the same parameters // and connect to other nodes in identical configurations. - std::vector nodes; + std::vector > nodes; + + std::vector no_edges; + no_edges.push_back (NetGraphNode::edge_type ()); nodes.reserve (graph.end () - graph.begin ()); for (db::NetGraph::node_iterator i = graph.begin (); i != graph.end (); ++i) { if (! i->has_other () && i->net ()) { - nodes.push_back (i.operator-> ()); + nodes.push_back (std::make_pair (i.operator-> (), no_edges.begin ())); } } @@ -3740,18 +4165,18 @@ NetlistComparer::join_symmetric_nets (db::Circuit *circuit) tl::equivalence_clusters identical_nodes; - for (std::vector::const_iterator np = nodes.begin (); np + 1 != nodes.end (); ++np) { - if (*np[0] == *np[1]) { - identical_nodes.same (np[0], np[1]); + for (std::vector >::const_iterator np = nodes.begin (); np + 1 != nodes.end (); ++np) { + if (*np[0].first == *np[1].first) { + identical_nodes.same (np[0].first, np[1].first); } } std::vector > symmetry_groups; std::set visited; - for (std::vector::const_iterator np = nodes.begin (); np != nodes.end (); ++np) { + for (std::vector >::const_iterator np = nodes.begin (); np != nodes.end (); ++np) { - size_t node_id = graph.node_index_for_net (np[0]->net ()); + size_t node_id = graph.node_index_for_net (np[0].first->net ()); if (visited.find (node_id) != visited.end ()) { continue; } diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index d639ed12f..d9748d36d 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -38,6 +38,8 @@ class DeviceCategorizer; class CircuitCategorizer; class CircuitMapper; class NetGraph; +class SubCircuitEquivalenceTracker; +class DeviceEquivalenceTracker; /** * @brief A receiver for netlist compare events @@ -326,8 +328,8 @@ protected: 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); void do_pin_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &pin_mismatch, bool &good) const; - void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, bool &good) const; - void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, bool &good) const; + void do_device_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, const db::DeviceFilter &device_filter, DeviceCategorizer &device_categorizer, db::DeviceEquivalenceTracker &device_eq, bool &good) const; + void do_subcircuit_assignment (const db::Circuit *c1, const db::NetGraph &g1, const db::Circuit *c2, const db::NetGraph &g2, CircuitCategorizer &circuit_categorizer, const db::CircuitPinMapper &circuit_pin_mapper, std::map &c12_circuit_and_pin_mapping, std::map &c22_circuit_and_pin_mapping, db::SubCircuitEquivalenceTracker &subcircuit_eq, bool &good) const; bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const; mutable NetlistCompareLogger *mp_logger; diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index c0d190f6d..8d50548aa 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2552,8 +2552,8 @@ TEST(17_InherentlyAmbiguousDecoder) "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 NA NA\n" + "match_nets NB NB\n" "match_nets B B\n" "match_nets A A\n" "match_pins $0 $1\n" @@ -2657,10 +2657,10 @@ TEST(17_InherentlyAmbiguousDecoder) "match_nets B B\n" "match_nets NB NB\n" "match_nets NA NA\n" - "match_nets NQ0 NQ0\n" - "match_nets NQ2 NQ2\n" "match_nets NQ1 NQ1\n" "match_nets NQ3 NQ3\n" + "match_nets NQ2 NQ2\n" + "match_nets NQ0 NQ0\n" "match_pins $0 $1\n" "match_pins $1 $0\n" "match_pins $2 $2\n" @@ -2922,24 +2922,24 @@ TEST(19_SymmetricCircuit) "match_nets g1 G1\n" "match_nets $44 YI\n" "match_nets $14 WELL\n" - "match_nets $8 NET215\n" - "match_nets $9 NET175\n" - "match_nets $6 NET181\n" - "match_nets $4 NET200\n" - "match_nets nn1 NN1\n" - "match_nets $11 CS0\n" - "match_nets $13 CS1\n" "match_nets nn2 NN2\n" "match_nets nn2_ NN2_\n" "match_nets q0 Q0\n" "match_nets q1 Q1\n" + "match_nets $11 CS0\n" "match_nets q0_ Q0_\n" + "match_nets $6 NET181\n" + "match_nets nn1 NN1\n" + "match_nets $8 NET215\n" + "match_nets $13 CS1\n" "match_nets q1_ Q1_\n" - "match_nets a0_ A0_\n" - "match_nets $34 HNET48\n" - "match_nets nn1_ NN1_\n" "match_nets a0 A0\n" "match_nets $35 HNET44\n" + "match_nets nn1_ NN1_\n" + "match_nets $9 NET175\n" + "match_nets $4 NET200\n" + "match_nets a0_ A0_\n" + "match_nets $34 HNET48\n" "match_pins VDD VDD\n" "match_pins nn1_ NN1_\n" "match_pins nn1 NN1\n" @@ -3576,7 +3576,7 @@ TEST(23_NodesRemovedWithError) "pin_mismatch (null) BULK\n" "pin_mismatch (null) $6\n" "match_subcircuits $1 $1\n" - "subcircuit_mismatch $2 $2\n" + "match_subcircuits $2 $2\n" "end_circuit INV2PAIR INV2PAIR NOMATCH\n" "circuit_skipped RINGO RINGO" ); @@ -3805,11 +3805,11 @@ TEST(25c_JoinSymmetricNetsMultipleMessedUp) // NOTE $1 and $2 are joined because they are symmetric EXPECT_EQ (nl.to_string (), "circuit NOR3 (A=A,C=C,B=B,OUT=OUT,VSS=VSS,VDD=VDD);\n" - " device PMOS $1 (S=$5,G=B,D=$3) (L=0.27,W=3.3,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $1 (S=$6,G=B,D=$3) (L=0.27,W=3.3,AS=0,AD=0,PS=0,PD=0);\n" " device NMOS $2 (S=OUT,G=A,D=VSS) (L=0.23,W=2.05,AS=0,AD=0,PS=0,PD=0);\n" " device PMOS $3 (S=$3,G=A,D=OUT) (L=0.27,W=3.3,AS=0,AD=0,PS=0,PD=0);\n" " device NMOS $4 (S=OUT,G=B,D=VSS) (L=0.23,W=2.05,AS=0,AD=0,PS=0,PD=0);\n" - " device PMOS $8 (S=VDD,G=C,D=$5) (L=0.27,W=3.3,AS=0,AD=0,PS=0,PD=0);\n" + " device PMOS $8 (S=VDD,G=C,D=$6) (L=0.27,W=3.3,AS=0,AD=0,PS=0,PD=0);\n" " device NMOS $12 (S=VSS,G=C,D=OUT) (L=0.23,W=2.05,AS=0,AD=0,PS=0,PD=0);\n" "end;\n" ) diff --git a/testdata/lvs/double_height2.lvsdb b/testdata/lvs/double_height2.lvsdb index f9d933d9c..b75ed63bc 100644 --- a/testdata/lvs/double_height2.lvsdb +++ b/testdata/lvs/double_height2.lvsdb @@ -314,8 +314,8 @@ Z( N(5 2 1) N(4 1 1) N(2 4 1) - P(2 () 1) P(0 () 1) + P(2 () 1) P(4 () 1) P(3 () 1) P(1 () 1) diff --git a/testdata/lvs/ringo_simple_dmos.lvsdb.1 b/testdata/lvs/ringo_simple_dmos.lvsdb.1 index 47ac96fa8..5af17e7b3 100644 --- a/testdata/lvs/ringo_simple_dmos.lvsdb.1 +++ b/testdata/lvs/ringo_simple_dmos.lvsdb.1 @@ -850,7 +850,7 @@ xref( device(1 1 match) ) ) - circuit(ND2X1 ND2X1 nomatch + circuit(ND2X1 ND2X1 match xref( net(4 8 mismatch) net(5 4 mismatch) @@ -867,10 +867,10 @@ xref( pin(6 6 match) pin(0 0 match) pin(2 2 match) + device(3 3 match) device(4 4 match) - device(3 3 mismatch) + device(1 1 match) device(2 2 match) - device(1 1 mismatch) ) ) circuit(RINGO RINGO match diff --git a/testdata/lvs/ringo_simple_dmos.lvsdb.2 b/testdata/lvs/ringo_simple_dmos.lvsdb.2 deleted file mode 100644 index 45fc263a5..000000000 --- a/testdata/lvs/ringo_simple_dmos.lvsdb.2 +++ /dev/null @@ -1,912 +0,0 @@ -#%lvsdb-klayout - -# Layout -layout( - top(RINGO) - unit(0.001) - - # Layer section - # This section lists the mask layers (drawing or derived) and their connections. - - # Mask layers - layer(l4 '1/0') - layer(l5 '5/0') - layer(l10 '8/0') - layer(l13 '9/0') - layer(l14 '10/0') - layer(l15 '11/0') - layer(l9) - layer(l3) - layer(l1) - layer(l11) - layer(l8) - layer(l6) - layer(l12) - - # Mask layer connectivity - connect(l4 l4 l11) - connect(l5 l5 l10) - connect(l10 l5 l10 l13 l3 l1 l11 l8 l6 l12) - connect(l13 l10 l13 l14) - connect(l14 l13 l14 l15) - connect(l15 l14 l15) - connect(l9 l9) - connect(l3 l10 l3) - connect(l1 l10 l1) - connect(l11 l4 l10 l11) - connect(l8 l10 l8) - connect(l6 l10 l6) - connect(l12 l10 l12) - - # Global nets and connectivity - global(l9 SUBSTRATE) - global(l12 SUBSTRATE) - - # Device class section - class(PMOS MOS4) - class(NMOS MOS4) - - # Device abstracts section - # Device abstracts list the pin shapes of the devices. - device(D$PMOS PMOS - terminal(S - rect(l3 (125 -750) (450 1500)) - ) - terminal(G - rect(l5 (-125 -750) (250 1500)) - ) - terminal(D - rect(l1 (-550 -750) (425 1500)) - ) - terminal(B - rect(l4 (-125 -750) (250 1500)) - ) - ) - device(D$PMOS$1 PMOS - terminal(S - rect(l3 (-575 -750) (450 1500)) - ) - terminal(G - rect(l5 (-125 -750) (250 1500)) - ) - terminal(D - rect(l1 (125 -750) (425 1500)) - ) - terminal(B - rect(l4 (-125 -750) (250 1500)) - ) - ) - device(D$PMOS$2 PMOS - terminal(S - rect(l3 (-550 -750) (425 1500)) - ) - terminal(G - rect(l5 (-125 -750) (250 1500)) - ) - terminal(D - rect(l1 (125 -750) (425 1500)) - ) - terminal(B - rect(l4 (-125 -750) (250 1500)) - ) - ) - device(D$NMOS NMOS - terminal(S - rect(l8 (125 -475) (450 950)) - ) - terminal(G - rect(l5 (-125 -475) (250 950)) - ) - terminal(D - rect(l6 (-550 -475) (425 950)) - ) - terminal(B - rect(l9 (-125 -475) (250 950)) - ) - ) - device(D$NMOS$1 NMOS - terminal(S - rect(l8 (-575 -475) (450 950)) - ) - terminal(G - rect(l5 (-125 -475) (250 950)) - ) - terminal(D - rect(l6 (125 -475) (425 950)) - ) - terminal(B - rect(l9 (-125 -475) (250 950)) - ) - ) - device(D$NMOS$2 NMOS - terminal(S - rect(l8 (-550 -475) (425 950)) - ) - terminal(G - rect(l5 (-125 -475) (250 950)) - ) - terminal(D - rect(l6 (125 -475) (425 950)) - ) - terminal(B - rect(l9 (-125 -475) (250 950)) - ) - ) - - # Circuit section - # Circuits are the hierarchical building blocks of the netlist. - circuit(ND2X1 - - # Circuit boundary - rect((-100 400) (2600 7600)) - - # Nets with their geometries - net(1 name(VDD) - rect(l10 (1110 5160) (180 180)) - rect(l10 (-180 920) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l13 (-240 -790) (300 1700)) - rect(l13 (-1350 0) (2400 800)) - rect(l13 (-1151 -401) (2 2)) - rect(l3 (-251 -2151) (425 1500)) - rect(l3 (-450 -1500) (425 1500)) - ) - net(2 name(OUT) - rect(l10 (1810 1770) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l10 (-1580 3760) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l10 (1220 920) (180 180)) - rect(l10 (-180 -1280) (180 180)) - rect(l10 (-180 370) (180 180)) - polygon(l13 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090)) - rect(l13 (-110 1390) (300 1400)) - polygon(l13 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300)) - rect(l13 (-141 -501) (2 2)) - rect(l13 (-1751 1099) (300 1400)) - rect(l13 (1100 -1700) (300 300)) - rect(l13 (-300 0) (300 1400)) - rect(l1 (-1750 -1450) (425 1500)) - rect(l1 (950 -1500) (425 1500)) - rect(l6 (-425 -4890) (425 950)) - ) - net(3 name(VSS) - rect(l10 (410 1770) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l13 (-240 -1300) (300 1360)) - rect(l13 (-650 -2160) (2400 800)) - rect(l13 (-1151 -401) (2 2)) - rect(l6 (-951 859) (425 950)) - ) - net(4 - rect(l8 (1000 1660) (425 950)) - rect(l8 (-450 -950) (425 950)) - ) - net(5 - rect(l4 (-100 4500) (2600 3500)) - ) - net(6 name(B) - rect(l5 (1425 2860) (250 1940)) - rect(l5 (-345 -950) (300 300)) - rect(l5 (-205 650) (250 2000)) - rect(l5 (-250 -2000) (250 2000)) - rect(l5 (-250 -5390) (250 1450)) - rect(l10 (-285 1050) (180 180)) - rect(l13 (-71 -91) (2 2)) - rect(l13 (-171 -151) (300 300)) - ) - net(7 name(A) - rect(l5 (725 2860) (250 1940)) - rect(l5 (-325 -1850) (300 300)) - rect(l5 (-225 1550) (250 2000)) - rect(l5 (-250 -2000) (250 2000)) - rect(l5 (-250 -5390) (250 1450)) - rect(l10 (-265 150) (180 180)) - rect(l13 (-91 -91) (2 2)) - rect(l13 (-151 -151) (300 300)) - ) - net(8 name(SUBSTRATE)) - - # Outgoing pins and their connections to nets - pin(1 name(VDD)) - pin(2 name(OUT)) - pin(3 name(VSS)) - pin(5) - pin(6 name(B)) - pin(7 name(A)) - pin(8 name(SUBSTRATE)) - - # Devices and their connections - device(1 D$PMOS - location(850 5800) - param(L 0.25) - param(W 1.5) - param(AS 0.3375) - param(AD 0.6375) - param(PS 1.95) - param(PD 3.85) - terminal(S 1) - terminal(G 7) - terminal(D 2) - terminal(B 5) - ) - device(2 D$PMOS$1 - location(1550 5800) - param(L 0.25) - param(W 1.5) - param(AS 0.3375) - param(AD 0.6375) - param(PS 1.95) - param(PD 3.85) - terminal(S 1) - terminal(G 6) - terminal(D 2) - terminal(B 5) - ) - device(3 D$NMOS - location(850 2135) - param(L 0.25) - param(W 0.95) - param(AS 0.21375) - param(AD 0.40375) - param(PS 1.4) - param(PD 2.75) - terminal(S 4) - terminal(G 7) - terminal(D 3) - terminal(B 8) - ) - device(4 D$NMOS$1 - location(1550 2135) - param(L 0.25) - param(W 0.95) - param(AS 0.21375) - param(AD 0.40375) - param(PS 1.4) - param(PD 2.75) - terminal(S 4) - terminal(G 6) - terminal(D 2) - terminal(B 8) - ) - - ) - circuit(INVX1 - - # Circuit boundary - rect((-100 400) (2000 7600)) - - # Nets with their geometries - net(1 name(VDD) - rect(l10 (410 6260) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l13 (-240 -240) (300 1400)) - rect(l13 (-650 300) (1800 800)) - rect(l13 (-1450 -1100) (300 300)) - rect(l13 (299 399) (2 2)) - rect(l3 (-651 -2151) (425 1500)) - ) - net(2 name(OUT) - rect(l10 (1110 5160) (180 180)) - rect(l10 (-180 920) (180 180)) - rect(l10 (-180 -730) (180 180)) - rect(l10 (-180 -4120) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l13 (-240 -790) (300 4790)) - rect(l13 (-151 -2501) (2 2)) - rect(l1 (-226 1049) (425 1500)) - rect(l6 (-425 -4890) (425 950)) - ) - net(3 name(VSS) - rect(l10 (410 1770) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l13 (-240 -1300) (300 1360)) - rect(l13 (-650 -2160) (1800 800)) - rect(l13 (-851 -401) (2 2)) - rect(l8 (-651 859) (425 950)) - ) - net(4 - rect(l4 (-100 4500) (2000 3500)) - ) - net(5 name(IN) - rect(l5 (725 2860) (250 1940)) - rect(l5 (-525 -1850) (300 300)) - rect(l5 (-25 1550) (250 2000)) - rect(l5 (-250 -2000) (250 2000)) - rect(l5 (-250 -5390) (250 1450)) - rect(l10 (-465 150) (180 180)) - rect(l13 (-91 -91) (2 2)) - rect(l13 (-151 -151) (300 300)) - ) - net(6 name(SUBSTRATE)) - - # Outgoing pins and their connections to nets - pin(1 name(VDD)) - pin(2 name(OUT)) - pin(3 name(VSS)) - pin(4) - pin(5 name(IN)) - pin(6 name(SUBSTRATE)) - - # Devices and their connections - device(1 D$PMOS$2 - location(850 5800) - param(L 0.25) - param(W 1.5) - param(AS 0.6375) - param(AD 0.6375) - param(PS 3.85) - param(PD 3.85) - terminal(S 1) - terminal(G 5) - terminal(D 2) - terminal(B 4) - ) - device(2 D$NMOS$2 - location(850 2135) - param(L 0.25) - param(W 0.95) - param(AS 0.40375) - param(AD 0.40375) - param(PS 2.75) - param(PD 2.75) - terminal(S 3) - terminal(G 5) - terminal(D 2) - terminal(B 6) - ) - - ) - circuit(RINGO - - # Circuit boundary - rect((0 350) (25800 7650)) - - # Nets with their geometries - net(1 - rect(l13 (4040 2950) (610 300)) - ) - net(2 - rect(l13 (5550 2950) (900 300)) - ) - net(3 - rect(l13 (7350 2950) (900 300)) - ) - net(4 - rect(l13 (9150 2950) (900 300)) - ) - net(5 - rect(l13 (10950 2950) (900 300)) - ) - net(6 - rect(l13 (12750 2950) (900 300)) - ) - net(7 - rect(l13 (14550 2950) (900 300)) - ) - net(8 - rect(l13 (16350 2950) (900 300)) - ) - net(9 - rect(l13 (18150 2950) (900 300)) - ) - net(10 - rect(l13 (19950 2950) (900 300)) - ) - net(11 name(FB) - rect(l13 (21750 2950) (900 300)) - rect(l13 (-19530 590) (320 320)) - rect(l13 (17820 -320) (320 320)) - rect(l14 (-18400 -260) (200 200)) - rect(l14 (17940 -200) (200 200)) - rect(l15 (-18040 -300) (17740 400)) - rect(l15 (-17921 -201) (2 2)) - rect(l15 (-221 -201) (400 400)) - rect(l15 (17740 -400) (400 400)) - ) - net(12 name(VDD) - rect(l4 (500 4500) (1400 3500)) - rect(l4 (-1900 -3500) (600 3500)) - rect(l4 (23300 -3500) (1400 3500)) - rect(l4 (-100 -3500) (600 3500)) - rect(l10 (-24690 -1240) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l10 (-180 -1280) (180 180)) - rect(l10 (23220 370) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l10 (-180 -1280) (180 180)) - rect(l13 (-21741 859) (2 2)) - rect(l13 (-2351 -451) (1200 800)) - rect(l13 (-750 -1450) (300 1400)) - rect(l13 (-101 -351) (2 2)) - rect(l13 (-1251 -401) (600 800)) - rect(l13 (23400 -800) (1200 800)) - rect(l13 (-750 -1450) (300 1400)) - rect(l13 (-101 -351) (2 2)) - rect(l13 (549 -401) (600 800)) - rect(l11 (-24850 -1500) (500 1500)) - rect(l11 (22900 -1500) (500 1500)) - ) - net(13 name(OUT) - rect(l13 (23440 3840) (320 320)) - rect(l14 (-260 -260) (200 200)) - rect(l15 (-101 -101) (2 2)) - rect(l15 (-201 -201) (400 400)) - ) - net(14 name(ENABLE) - rect(l13 (2440 2940) (320 320)) - rect(l14 (-260 -260) (200 200)) - rect(l15 (-101 -101) (2 2)) - rect(l15 (-201 -201) (400 400)) - ) - net(15 name(VSS) - rect(l10 (1110 1610) (180 180)) - rect(l10 (-180 -1280) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l10 (23220 370) (180 180)) - rect(l10 (-180 -1280) (180 180)) - rect(l10 (-180 370) (180 180)) - rect(l13 (-21741 -391) (2 2)) - rect(l13 (-1901 -401) (300 1400)) - rect(l13 (-750 -1450) (1200 800)) - rect(l13 (-551 -401) (2 2)) - rect(l13 (-1251 -401) (600 800)) - rect(l13 (23850 -750) (300 1400)) - rect(l13 (-750 -1450) (1200 800)) - rect(l13 (-551 -401) (2 2)) - rect(l13 (549 -401) (600 800)) - rect(l12 (-24850 -800) (500 1500)) - rect(l12 (22900 -1500) (500 1500)) - ) - - # Outgoing pins and their connections to nets - pin(11 name(FB)) - pin(12 name(VDD)) - pin(13 name(OUT)) - pin(14 name(ENABLE)) - pin(15 name(VSS)) - - # Subcircuits and their connections - circuit(1 ND2X1 location(1800 0) - pin(0 12) - pin(1 1) - pin(2 15) - pin(3 12) - pin(4 11) - pin(5 14) - pin(6 15) - ) - circuit(2 INVX1 location(4200 0) - pin(0 12) - pin(1 2) - pin(2 15) - pin(3 12) - pin(4 1) - pin(5 15) - ) - circuit(3 INVX1 location(6000 0) - pin(0 12) - pin(1 3) - pin(2 15) - pin(3 12) - pin(4 2) - pin(5 15) - ) - circuit(4 INVX1 location(7800 0) - pin(0 12) - pin(1 4) - pin(2 15) - pin(3 12) - pin(4 3) - pin(5 15) - ) - circuit(5 INVX1 location(9600 0) - pin(0 12) - pin(1 5) - pin(2 15) - pin(3 12) - pin(4 4) - pin(5 15) - ) - circuit(6 INVX1 location(11400 0) - pin(0 12) - pin(1 6) - pin(2 15) - pin(3 12) - pin(4 5) - pin(5 15) - ) - circuit(7 INVX1 location(13200 0) - pin(0 12) - pin(1 7) - pin(2 15) - pin(3 12) - pin(4 6) - pin(5 15) - ) - circuit(8 INVX1 location(15000 0) - pin(0 12) - pin(1 8) - pin(2 15) - pin(3 12) - pin(4 7) - pin(5 15) - ) - circuit(9 INVX1 location(16800 0) - pin(0 12) - pin(1 9) - pin(2 15) - pin(3 12) - pin(4 8) - pin(5 15) - ) - circuit(10 INVX1 location(18600 0) - pin(0 12) - pin(1 10) - pin(2 15) - pin(3 12) - pin(4 9) - pin(5 15) - ) - circuit(11 INVX1 location(20400 0) - pin(0 12) - pin(1 11) - pin(2 15) - pin(3 12) - pin(4 10) - pin(5 15) - ) - circuit(12 INVX1 location(22200 0) - pin(0 12) - pin(1 13) - pin(2 15) - pin(3 12) - pin(4 11) - pin(5 15) - ) - - ) -) - -# Reference netlist -reference( - - # Device class section - class(PMOS MOS4) - class(NMOS MOS4) - - # Circuit section - # Circuits are the hierarchical building blocks of the netlist. - circuit(ND2X1 - - # Nets - net(1 name(VDD)) - net(2 name(OUT)) - net(3 name(VSS)) - net(4 name(NWELL)) - net(5 name(B)) - net(6 name(A)) - net(7 name(BULK)) - net(8 name('1')) - - # Outgoing pins and their connections to nets - pin(1 name(VDD)) - pin(2 name(OUT)) - pin(3 name(VSS)) - pin(4 name(NWELL)) - pin(5 name(B)) - pin(6 name(A)) - pin(7 name(BULK)) - - # Devices and their connections - device(1 PMOS - name($1) - param(L 0.25) - param(W 1.5) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 2) - terminal(G 6) - terminal(D 1) - terminal(B 4) - ) - device(2 PMOS - name($2) - param(L 0.25) - param(W 1.5) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 1) - terminal(G 5) - terminal(D 2) - terminal(B 4) - ) - device(3 NMOS - name($3) - param(L 0.25) - param(W 0.95) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 3) - terminal(G 6) - terminal(D 8) - terminal(B 7) - ) - device(4 NMOS - name($4) - param(L 0.25) - param(W 0.95) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 8) - terminal(G 5) - terminal(D 2) - terminal(B 7) - ) - - ) - circuit(INVX1 - - # Nets - net(1 name(VDD)) - net(2 name(OUT)) - net(3 name(VSS)) - net(4 name(NWELL)) - net(5 name(IN)) - net(6 name(BULK)) - - # Outgoing pins and their connections to nets - pin(1 name(VDD)) - pin(2 name(OUT)) - pin(3 name(VSS)) - pin(4 name(NWELL)) - pin(5 name(IN)) - pin(6 name(BULK)) - - # Devices and their connections - device(1 PMOS - name($1) - param(L 0.25) - param(W 1.5) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 1) - terminal(G 5) - terminal(D 2) - terminal(B 4) - ) - device(2 NMOS - name($2) - param(L 0.25) - param(W 0.95) - param(AS 0) - param(AD 0) - param(PS 0) - param(PD 0) - terminal(S 3) - terminal(G 5) - terminal(D 2) - terminal(B 6) - ) - - ) - circuit(RINGO - - # Nets - net(1 name(VSS)) - net(2 name(VDD)) - net(3 name(FB)) - net(4 name(ENABLE)) - net(5 name(OUT)) - net(6 name('1')) - net(7 name('2')) - net(8 name('3')) - net(9 name('4')) - net(10 name('5')) - net(11 name('6')) - net(12 name('7')) - net(13 name('8')) - net(14 name('9')) - net(15 name('10')) - - # Outgoing pins and their connections to nets - pin(1 name(VSS)) - pin(2 name(VDD)) - pin(3 name(FB)) - pin(4 name(ENABLE)) - pin(5 name(OUT)) - - # Subcircuits and their connections - circuit(1 ND2X1 name($1) - pin(0 2) - pin(1 6) - pin(2 1) - pin(3 2) - pin(4 3) - pin(5 4) - pin(6 1) - ) - circuit(2 INVX1 name($2) - pin(0 2) - pin(1 7) - pin(2 1) - pin(3 2) - pin(4 6) - pin(5 1) - ) - circuit(3 INVX1 name($3) - pin(0 2) - pin(1 8) - pin(2 1) - pin(3 2) - pin(4 7) - pin(5 1) - ) - circuit(4 INVX1 name($4) - pin(0 2) - pin(1 9) - pin(2 1) - pin(3 2) - pin(4 8) - pin(5 1) - ) - circuit(5 INVX1 name($5) - pin(0 2) - pin(1 10) - pin(2 1) - pin(3 2) - pin(4 9) - pin(5 1) - ) - circuit(6 INVX1 name($6) - pin(0 2) - pin(1 11) - pin(2 1) - pin(3 2) - pin(4 10) - pin(5 1) - ) - circuit(7 INVX1 name($7) - pin(0 2) - pin(1 12) - pin(2 1) - pin(3 2) - pin(4 11) - pin(5 1) - ) - circuit(8 INVX1 name($8) - pin(0 2) - pin(1 13) - pin(2 1) - pin(3 2) - pin(4 12) - pin(5 1) - ) - circuit(9 INVX1 name($9) - pin(0 2) - pin(1 14) - pin(2 1) - pin(3 2) - pin(4 13) - pin(5 1) - ) - circuit(10 INVX1 name($10) - pin(0 2) - pin(1 15) - pin(2 1) - pin(3 2) - pin(4 14) - pin(5 1) - ) - circuit(11 INVX1 name($11) - pin(0 2) - pin(1 3) - pin(2 1) - pin(3 2) - pin(4 15) - pin(5 1) - ) - circuit(12 INVX1 name($12) - pin(0 2) - pin(1 5) - pin(2 1) - pin(3 2) - pin(4 3) - pin(5 1) - ) - - ) -) - -# Cross reference -xref( - circuit(INVX1 INVX1 match - xref( - net(4 4 match) - net(5 5 match) - net(2 2 match) - net(6 6 match) - net(1 1 match) - net(3 3 match) - pin(3 3 match) - pin(4 4 match) - pin(1 1 match) - pin(5 5 match) - pin(0 0 match) - pin(2 2 match) - device(2 2 match) - device(1 1 match) - ) - ) - circuit(ND2X1 ND2X1 nomatch - xref( - net(4 8 mismatch) - net(5 4 mismatch) - net(7 6 match) - net(6 5 match) - net(2 2 mismatch) - net(8 7 mismatch) - net(1 1 mismatch) - net(3 3 mismatch) - pin(3 3 match) - pin(5 5 match) - pin(4 4 match) - pin(1 1 match) - pin(6 6 match) - pin(0 0 match) - pin(2 2 match) - device(4 4 match) - device(3 3 mismatch) - device(2 2 match) - device(1 1 mismatch) - ) - ) - circuit(RINGO RINGO match - xref( - net(1 6 match) - net(10 15 match) - net(2 7 match) - net(3 8 match) - net(4 9 match) - net(5 10 match) - net(6 11 match) - net(7 12 match) - net(8 13 match) - net(9 14 match) - net(14 4 match) - net(11 3 match) - net(13 5 match) - net(12 2 match) - net(15 1 match) - pin(3 3 match) - pin(0 2 match) - pin(2 4 match) - pin(1 1 match) - pin(4 0 match) - circuit(2 2 match) - circuit(3 3 match) - circuit(4 4 match) - circuit(5 5 match) - circuit(6 6 match) - circuit(7 7 match) - circuit(8 8 match) - circuit(9 9 match) - circuit(10 10 match) - circuit(11 11 match) - circuit(12 12 match) - circuit(1 1 match) - ) - ) -)