diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 6094148e9..f0395199f 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -859,14 +859,9 @@ public: * If tentative is true, assignments will not be retained and just the * status is reported. */ - size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative); + size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool with_ambiguous); - size_t derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool picky); - - size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper) - { - return derive_node_identities (net_index, other, 0, 1, logger, circuit_pin_mapper, false); - } + size_t derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool with_ambiguous); private: std::vector m_nodes; @@ -915,7 +910,7 @@ NetDeviceGraph::build (const db::Circuit *c, DeviceCategorizer &device_categoriz } size_t -NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative) +NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool with_ambiguous) { NetGraphNode *n = & m_nodes[net_index]; NetGraphNode *nother = & other.m_nodes[n->other_net_index ()]; @@ -984,7 +979,34 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, std::sort (nodes.begin (), nodes.end (), CompareNodePtr ()); std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ()); - derive_node_identities_from_node_set (nodes, other_nodes, other, depth, n_branch, logger, circuit_pin_mapper, tentative, true); + // for the purpose of match evaluation we require an exact match of the node structure + + if (tentative && (nodes.size () > 1 || other_nodes.size () > 1)) { + + if (nodes.size () != other_nodes.size ()) { + return std::numeric_limits::max (); + } + + for (size_t i = 0; i < nodes.size (); ++i) { + if (! (*nodes[i] == *other_nodes[i]) || nodes[i]->has_other () != other_nodes[i]->has_other ()) { + return std::numeric_limits::max (); + } + } + + } + + // propagate pairing in picky mode: this means we only accept exact a match if the node set + // is exactly identical and no ambiguous nodes are present when ambiguous nodes are forbidden + + size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, other, depth, n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); + + if (bt_count == std::numeric_limits::max ()) { + if (tentative) { + return bt_count; + } + } else { + new_nodes += bt_count; + } } @@ -993,7 +1015,7 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, } #if defined(PRINT_DEBUG_NETCOMPARE) - if (! tentative && new_nodes > 0 && new_nodes != std::numeric_limits::max ()) { + if (! tentative && new_nodes > 0) { tl::info << "finished pair deduction: " << n->net ()->expanded_name () << " vs. " << nother->net ()->expanded_name () << " with " << new_nodes << " new pairs"; } #endif @@ -1001,8 +1023,29 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, return new_nodes; } +namespace { + +struct NodeRange +{ + NodeRange (size_t _num, std::vector::const_iterator _n1, std::vector::const_iterator _nn1, std::vector::const_iterator _n2, std::vector::const_iterator _nn2) + : num (_num), n1 (_n1), nn1 (_nn1), n2 (_n2), nn2 (_nn2) + { + // .. nothing yet .. + } + + bool operator< (const NodeRange &other) const + { + return num < other.num; + } + + size_t num; + std::vector::const_iterator n1, nn1, n2, nn2; +}; + +} + size_t -NetDeviceGraph::derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool picky) +NetDeviceGraph::derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, bool tentative, bool with_ambiguous) { size_t new_nodes = 0; @@ -1031,7 +1074,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::max (); - } - - for (size_t i = 0; i < nodes.size (); ++i) { - if (! (*nodes[i] == *other_nodes[i]) || nodes[i]->has_other () != other_nodes[i]->has_other ()) { - return std::numeric_limits::max (); - } - } - - } + std::vector node_ranges; std::vector::const_iterator n1 = nodes.begin (); std::vector::const_iterator n2 = other_nodes.begin (); @@ -1094,36 +1127,61 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector this may render - // inexact matches, but further propagates net pairing + // in tentative mode ambiguous nodes don't make a match without + // with_ambiguous + if (num > 1 && tentative && ! with_ambiguous) { + return std::numeric_limits::max (); + } - if (! tentative) { + n1 = nn1; + n2 = nn2; - size_t ni = node_index_for_net ((*n1)->net ()); - size_t other_ni = other.node_index_for_net ((*n2)->net ()); + } - identify (ni, other_ni); - other.identify (other_ni, ni); + if (with_ambiguous) { + std::stable_sort (node_ranges.begin (), node_ranges.end ()); + } + + for (std::vector::const_iterator nr = node_ranges.begin (); nr != node_ranges.end (); ++nr) { + + if (nr->num == 1) { + + if (! (*nr->n1)->has_other () && ! (*nr->n2)->has_other ()) { + + // A single candiate: just take this one -> this may render + // inexact matches, but further propagates net pairing + + if (! tentative) { + + size_t ni = node_index_for_net ((*nr->n1)->net ()); + size_t other_ni = other.node_index_for_net ((*nr->n2)->net ()); + + identify (ni, other_ni); + other.identify (other_ni, ni); + + #if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name (); + #endif + if (logger) { + logger->match_nets ((*nr->n1)->net (), (*nr->n2)->net ()); + } + + // unconditionally continue here. + derive_node_identities (ni, other, depth + 1, n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "deduced match (singular): " << (*n1)->net ()->expanded_name () << " vs. " << (*n2)->net ()->expanded_name (); -#endif - if (logger) { - logger->match_nets ((*n1)->net (), (*n2)->net ()); } - // unconditionally continue here. - derive_node_identities (ni, other, depth + 1, n_branch, logger, circuit_pin_mapper, false); + new_nodes += 1; } - new_nodes += 1; - } else { - if (num * n_branch > n_branch_max) { + if (nr->num * n_branch > n_branch_max) { return std::numeric_limits::max (); } @@ -1131,7 +1189,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector equivalent_other_nodes; std::set seen; - for (std::vector::const_iterator i1 = n1; i1 != nn1; ++i1) { + for (std::vector::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) { if ((*i1)->has_other ()) { continue; @@ -1140,7 +1198,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::const_iterator i2; - for (i2 = n2; i2 != nn2; ++i2) { + for (i2 = nr->n2; i2 != nr->nn2; ++i2) { if ((*i2)->has_other ()) { continue; @@ -1156,13 +1214,16 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectornum * n_branch, logger, circuit_pin_mapper, true /*tentative*/, with_ambiguous); unidentify (ni); other.unidentify (other_ni); if (bt_count != std::numeric_limits::max ()) { + // we have a match ... + if (any) { // there is already a known pair, so we can mark *i2 and the previous *i2 as equivalent @@ -1183,7 +1244,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::max (); } @@ -1262,7 +1323,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectorfirst->net ()); - size_t bt_count = derive_node_identities (ni, other, depth + 1, num * n_branch, logger, circuit_pin_mapper, false /*not tentative*/); + size_t bt_count = derive_node_identities (ni, other, depth + 1, nr->num * n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); tl_assert (bt_count != std::numeric_limits::max ()); } @@ -1271,9 +1332,6 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectorhas_other () && i1->net ()) { - size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, mp_logger, mp_circuit_pin_mapper.get ()); - if (ni > 0 && ni != std::numeric_limits::max ()) { - new_identities += ni; -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << ni << " new identities."; -#endif + good = true; + while (true) { + + #if defined(PRINT_DEBUG_NETCOMPARE) + ++iter; + tl::info << "new compare iteration #" << iter; + tl::info << "deducing from present nodes ..."; + #endif + + size_t new_identities = 0; + + for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { + if (i1->has_other () && i1->net ()) { + size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), false /*not tentative*/, pass > 0 /*with ambiguities*/); + if (ni > 0 && ni != std::numeric_limits::max ()) { + new_identities += ni; + #if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << ni << " new identities."; + #endif + } } } - } -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << "checking topological identity ..."; -#endif + #if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << "checking topological identity ..."; + #endif - // derive new identities through topology: first collect all nets with the same topological signature + // derive new identities through topology: first collect all nets with the same topological signature - std::vector nodes, other_nodes; + std::vector nodes, other_nodes; - nodes.reserve (g1.end () - g1.begin ()); - for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { - if (! i1->has_other () && i1->net ()) { - nodes.push_back (i1.operator-> ()); + nodes.reserve (g1.end () - g1.begin ()); + for (db::NetDeviceGraph::node_iterator i1 = g1.begin (); i1 != g1.end (); ++i1) { + if (! i1->has_other () && i1->net ()) { + nodes.push_back (i1.operator-> ()); + } } - } - other_nodes.reserve (g2.end () - g2.begin ()); - for (db::NetDeviceGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) { - if (! i2->has_other () && i2->net ()) { - other_nodes.push_back (i2.operator-> ()); + other_nodes.reserve (g2.end () - g2.begin ()); + for (db::NetDeviceGraph::node_iterator i2 = g2.begin (); i2 != g2.end (); ++i2) { + if (! i2->has_other () && i2->net ()) { + other_nodes.push_back (i2.operator-> ()); + } } - } - if (nodes.empty () || other_nodes.empty ()) { - if (! nodes.empty () || ! other_nodes.empty ()) { + if (nodes.empty () || other_nodes.empty ()) { + if (! nodes.empty () || ! other_nodes.empty ()) { + good = false; + } + // this assumes that we don't gain anything here. Stop now. + break; + } + + std::sort (nodes.begin (), nodes.end (), CompareNodePtr ()); + std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ()); + + size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), false /*not tentative*/, pass > 0 /*with ambiguities*/); + if (ni > 0 && ni != std::numeric_limits::max ()) { + new_identities += ni; + #if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << ni << " new identities."; + #endif + } + + if (new_identities == 0) { good = false; + break; } - break; - } - std::sort (nodes.begin (), nodes.end (), CompareNodePtr ()); - std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ()); - - size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, 1, mp_logger, mp_circuit_pin_mapper.get (), false /*not tentative*/, false /*don't require a full match*/); - if (ni > 0 && ni != std::numeric_limits::max ()) { - new_identities += ni; -#if defined(PRINT_DEBUG_NETCOMPARE) - tl::info << ni << " new identities."; -#endif - } - - if (new_identities == 0) { - good = false; - break; } } - // Report missing net assignment for (db::NetDeviceGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) { diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 4cb7c998d..36760f41c 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -335,9 +335,9 @@ TEST(1_SimpleInverter) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -384,9 +384,9 @@ TEST(1_SimpleInverterMatchedDeviceClasses) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -427,8 +427,8 @@ TEST(1_SimpleInverterSkippedDevices) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" + "match_nets VSS VSS\n" "match_nets IN IN\n" "match_pins $0 $1\n" "match_pins $1 $3\n" @@ -451,9 +451,9 @@ TEST(1_SimpleInverterSkippedDevices) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -536,11 +536,11 @@ TEST(3_Buffer) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" - "match_nets OUT OUT\n" "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets INT $10\n" "match_nets IN IN\n" "match_nets VSS VSS\n" - "match_nets INT $10\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -591,12 +591,12 @@ TEST(4_BufferTwoPaths) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" - "match_nets OUT OUT\n" "match_nets VDD VDD\n" - "match_nets IN IN\n" + "match_nets OUT OUT\n" "match_nets VSS VSS\n" - "match_nets INT $10\n" - "match_nets INT2 $11\n" + "match_nets IN IN\n" + "match_ambiguous_nets INT $10\n" + "match_ambiguous_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -658,9 +658,9 @@ TEST(5_BufferTwoPathsDifferentParameters) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" - "match_ambiguous_nets INT $10\n" - "match_nets INT2 $11\n" + "match_nets INT $10\n" "match_nets IN IN\n" + "match_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -685,8 +685,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" "match_nets IN IN\n" - "match_nets INT2 $11\n" - "match_nets INT $10\n" + "match_ambiguous_nets INT $10\n" + "match_ambiguous_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -710,9 +710,9 @@ TEST(5_BufferTwoPathsDifferentParameters) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" - "match_ambiguous_nets INT $10\n" - "match_nets INT2 $11\n" + "match_nets INT $10\n" "match_nets IN IN\n" + "match_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -736,9 +736,9 @@ TEST(5_BufferTwoPathsDifferentParameters) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" - "match_ambiguous_nets INT $10\n" - "match_nets INT2 $11\n" + "match_nets INT $10\n" "match_nets IN IN\n" + "match_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -763,8 +763,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" "match_nets IN IN\n" - "match_nets INT2 $11\n" - "match_nets INT $10\n" + "match_ambiguous_nets INT $10\n" + "match_ambiguous_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -790,8 +790,8 @@ TEST(5_BufferTwoPathsDifferentParameters) "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" "match_nets IN IN\n" - "match_nets INT2 $11\n" - "match_nets INT $10\n" + "match_ambiguous_nets INT $10\n" + "match_ambiguous_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -816,9 +816,9 @@ TEST(5_BufferTwoPathsDifferentParameters) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" "match_nets OUT OUT\n" - "match_ambiguous_nets INT $10\n" - "match_nets INT2 $11\n" + "match_nets INT $10\n" "match_nets IN IN\n" + "match_nets INT2 $11\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1006,11 +1006,11 @@ TEST(6_BufferTwoPathsAdditionalDevices) EXPECT_EQ (logger.text (), "begin_circuit BUF BUF\n" "match_nets INT $11\n" - "match_nets IN IN\n" "match_nets VDD VDD\n" - "match_nets OUT OUT\n" - "match_nets VSS VSS\n" + "match_nets IN IN\n" "match_nets INT2 $10\n" + "match_nets VSS VSS\n" + "match_nets OUT OUT\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1057,9 +1057,9 @@ TEST(7_Resistors) EXPECT_EQ (logger.text (), "begin_circuit TRIANGLE TRIANGLE\n" + "match_nets P2 P2\n" "match_nets P1 P1\n" "match_nets P3 P3\n" - "match_nets P2 P2\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1223,7 +1223,7 @@ TEST(8_DiodesDontMatchOnSwappedPins) EXPECT_EQ (logger.text (), "begin_circuit TRIANGLE TRIANGLE\n" - "match_ambiguous_nets P1 P3\n" + "match_nets P1 P3\n" "match_nets P2 P1\n" "match_nets P3 P2\n" "match_pins $0 $2\n" @@ -1272,9 +1272,9 @@ TEST(10_SimpleSubCircuits) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1284,9 +1284,9 @@ 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 VDD VDD\n" "match_nets INT INT\n" "match_pins $0 $2\n" "match_pins $1 $0\n" @@ -1339,9 +1339,9 @@ TEST(10_SimpleSubCircuitsMatchedNames) EXPECT_EQ (logger.text (), "begin_circuit INV INVB\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1351,9 +1351,9 @@ 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 VDD VDD\n" "match_nets INT INT\n" "match_pins $0 $2\n" "match_pins $1 $0\n" @@ -1404,18 +1404,28 @@ TEST(11_MismatchingSubcircuits) "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" - "net_mismatch VDD (null)\n" - "net_mismatch (null) VDD\n" + "match_nets VDD VDD\n" "match_pins $0 $1\n" "match_pins $1 $3\n" - "pin_mismatch $2 (null)\n" + "match_pins $2 $0\n" "match_pins $3 $2\n" - "pin_mismatch (null) $0\n" - "device_mismatch $1 (null)\n" "match_devices $2 $1\n" "device_mismatch (null) $2\n" + "device_mismatch $1 (null)\n" "end_circuit INV INV NOMATCH\n" - "circuit_skipped TOP TOP" + "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_pins $0 $2\n" + "match_pins $1 $0\n" + "match_pins $2 $1\n" + "match_pins $3 $3\n" + "match_subcircuits $2 $1\n" + "match_subcircuits $1 $2\n" + "end_circuit TOP TOP MATCH" ); EXPECT_EQ (good, false); @@ -1456,9 +1466,9 @@ TEST(12_MismatchingSubcircuitsDuplicates) EXPECT_EQ (logger.text (), "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1471,17 +1481,14 @@ TEST(12_MismatchingSubcircuitsDuplicates) "match_nets VDD VDD\n" "match_nets VSS VSS\n" "match_nets INT INT\n" - "net_mismatch OUT (null)\n" - "net_mismatch (null) OUT\n" + "match_nets OUT OUT\n" "match_pins $0 $1\n" - "pin_mismatch $1 (null)\n" + "match_pins $1 $0\n" "match_pins $2 $2\n" "match_pins $3 $3\n" - "pin_mismatch (null) $0\n" - "subcircuit_mismatch $2 (null)\n" - "subcircuit_mismatch $3 (null)\n" - "subcircuit_mismatch (null) $1\n" + "match_subcircuits $2 $1\n" "match_subcircuits $1 $2\n" + "subcircuit_mismatch $3 (null)\n" "end_circuit TOP TOP NOMATCH" ); @@ -1527,9 +1534,9 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy) "circuit_mismatch VIA (null)\n" "begin_circuit INV INV\n" "match_nets VDD VDD\n" - "match_nets VSS VSS\n" "match_nets OUT OUT\n" "match_nets IN IN\n" + "match_nets VSS VSS\n" "match_pins $0 $1\n" "match_pins $1 $3\n" "match_pins $2 $0\n" @@ -1539,9 +1546,9 @@ 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 VDD VDD\n" "match_nets INT INT\n" "match_pins $0 $1\n" "match_pins $1 $0\n" @@ -1594,11 +1601,11 @@ TEST(14_Subcircuit2Nand) EXPECT_EQ (logger.text (), "begin_circuit NAND NAND\n" "match_nets VSS VSS\n" + "match_nets INT INT\n" + "match_nets OUT OUT\n" "match_nets VDD VDD\n" "match_nets B B\n" - "match_nets OUT OUT\n" "match_nets A A\n" - "match_nets INT INT\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1611,11 +1618,11 @@ TEST(14_Subcircuit2Nand) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets VSS VSS\n" - "match_nets VDD VDD\n" "match_nets IN1 IN1\n" - "match_nets INT INT\n" "match_nets IN2 IN2\n" + "match_nets INT INT\n" + "match_nets VDD VDD\n" + "match_nets VSS VSS\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1668,11 +1675,11 @@ TEST(14_Subcircuit2NandMismatchNoSwap) EXPECT_EQ (logger.text (), "begin_circuit NAND NAND\n" "match_nets VSS VSS\n" + "match_nets INT INT\n" + "match_nets OUT OUT\n" "match_nets VDD VDD\n" "match_nets B B\n" - "match_nets OUT OUT\n" "match_nets A A\n" - "match_nets INT INT\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1689,18 +1696,16 @@ TEST(14_Subcircuit2NandMismatchNoSwap) "match_nets INT IN1\n" "match_nets VDD VDD\n" "match_nets VSS VSS\n" - "net_mismatch IN2 (null)\n" - "net_mismatch (null) IN2\n" + "match_nets IN2 IN2\n" "pin_mismatch $0 (null)\n" - "pin_mismatch $1 (null)\n" + "match_pins $1 $1\n" "match_pins $2 $2\n" "match_pins $3 $3\n" "match_pins $4 $4\n" - "pin_mismatch (null) $1\n" "pin_mismatch (null) $0\n" - "subcircuit_mismatch $1 (null)\n" "match_subcircuits $2 $1\n" "subcircuit_mismatch (null) $2\n" + "subcircuit_mismatch $1 (null)\n" "end_circuit TOP TOP NOMATCH" ); @@ -1746,11 +1751,11 @@ TEST(14_Subcircuit2MatchWithSwap) EXPECT_EQ (logger.text (), "begin_circuit NAND NAND\n" "match_nets VSS VSS\n" + "match_nets INT INT\n" + "match_nets OUT OUT\n" "match_nets VDD VDD\n" "match_nets B B\n" - "match_nets OUT OUT\n" "match_nets A A\n" - "match_nets INT INT\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1763,11 +1768,11 @@ TEST(14_Subcircuit2MatchWithSwap) "end_circuit NAND NAND MATCH\n" "begin_circuit TOP TOP\n" "match_nets OUT OUT\n" - "match_nets VSS VSS\n" - "match_nets VDD VDD\n" "match_nets IN1 IN1\n" - "match_nets INT INT\n" "match_nets IN2 IN2\n" + "match_nets INT INT\n" + "match_nets VDD VDD\n" + "match_nets VSS VSS\n" "match_pins $0 $0\n" "match_pins $1 $1\n" "match_pins $2 $2\n" @@ -1831,11 +1836,11 @@ TEST(15_EmptySubCircuitTest) "match_pins D D\n" "end_circuit TRANS TRANS MATCH\n" "begin_circuit INV2 INV2\n" - "match_nets IN IN\n" - "match_nets OUT OUT\n" "match_nets $5 $5\n" - "match_nets $4 $4\n" + "match_nets OUT OUT\n" "match_nets $2 $2\n" + "match_nets IN IN\n" + "match_nets $4 $4\n" "match_pins IN IN\n" "match_pins $1 $1\n" "match_pins OUT OUT\n" @@ -1905,11 +1910,11 @@ TEST(15_EmptySubCircuitWithoutPinNames) "match_pins $2 $2\n" "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 $2 $2\n" - "match_nets $5 $5\n" "match_pins IN IN\n" "match_pins $1 $1\n" "match_pins OUT OUT\n" @@ -1980,12 +1985,12 @@ TEST(16_UniqueSubCircuitMatching) EXPECT_EQ (logger.text (), "begin_circuit INV2 INV2\n" "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets $3 $3\n" "match_nets $1 $1\n" + "match_nets IN IN\n" "match_nets VSS VSS\n" "match_nets BULK BULK\n" - "match_nets OUT OUT\n" - "match_nets IN IN\n" - "match_nets $3 $3\n" "match_pins $0 $0\n" "match_pins IN IN\n" "match_pins $2 $2\n" @@ -2000,14 +2005,14 @@ TEST(16_UniqueSubCircuitMatching) "end_circuit INV2 INV2 MATCH\n" "begin_circuit INV2PAIR INV2PAIR\n" "match_nets $I2 $I2\n" - "match_nets $I3 $I3\n" - "match_nets BULK BULK\n" - "match_nets $I6 $I6\n" - "match_nets $I5 $I5\n" - "match_nets $I4 $I4\n" "match_nets $I1 $I1\n" + "match_nets $I3 $I3\n" "match_nets $I7 $I7\n" + "match_nets $I4 $I4\n" + "match_nets $I5 $I5\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" @@ -2020,17 +2025,17 @@ TEST(16_UniqueSubCircuitMatching) "end_circuit INV2PAIR INV2PAIR MATCH\n" "begin_circuit RINGO RINGO\n" "match_nets OSC OSC\n" - "match_nets FB FB\n" - "match_nets VDD VDD\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 $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 $I25 $I25\n" "match_nets $I7 $I7\n" + "match_nets $I25 $I25\n" + "match_nets $I6 $I6\n" + "match_nets $I24 $I24\n" "match_subcircuits $1 $1\n" "match_subcircuits $4 $2\n" "match_subcircuits $3 $3\n" @@ -2041,3 +2046,97 @@ TEST(16_UniqueSubCircuitMatching) EXPECT_EQ (good, true); } + +TEST(17_InherentlyAmbiguousDecoder) +{ + const char *nls1 = + "circuit NAND ($0=A,$1=B,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=A,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $3 (S=VSS,G=A,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=INT,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n" + "circuit DECODER ($0=A,$1=B,$2=NQ0,$3=NQ1,$4=NQ2,$5=NQ3,$6=VDD,$7=VSS);\n" + " subcircuit NAND $1 ($0=A,$1=A,$2=NA,$3=VDD,$4=VSS);\n" + " subcircuit NAND $2 ($0=B,$1=B,$2=NB,$3=VDD,$4=VSS);\n" + " subcircuit NAND $3 ($0=NA,$1=NB,$2=NQ0,$3=VDD,$4=VSS);\n" + " subcircuit NAND $4 ($0=A,$1=NB,$2=NQ1,$3=VDD,$4=VSS);\n" + " subcircuit NAND $5 ($0=NA,$1=B,$2=NQ2,$3=VDD,$4=VSS);\n" + " subcircuit NAND $6 ($0=A,$1=B,$2=NQ3,$3=VDD,$4=VSS);\n" + "end;\n"; + + const char *nls2 = + "circuit NAND ($0=A,$1=B,$2=OUT,$3=VDD,$4=VSS);\n" + " device PMOS $1 (S=VDD,G=A,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device PMOS $2 (S=VDD,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $3 (S=VSS,G=A,D=INT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $4 (S=INT,G=B,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n" + "circuit DECODER ($0=A,$1=B,$2=NQ0,$3=NQ1,$4=NQ2,$5=NQ3,$6=VDD,$7=VSS);\n" + " subcircuit NAND $1 ($0=B,$1=B,$2=NB,$3=VDD,$4=VSS);\n" + " subcircuit NAND $2 ($0=A,$1=NB,$2=NQ1,$3=VDD,$4=VSS);\n" + " subcircuit NAND $3 ($0=A,$1=A,$2=NA,$3=VDD,$4=VSS);\n" + " subcircuit NAND $4 ($0=A,$1=B,$2=NQ3,$3=VDD,$4=VSS);\n" + " subcircuit NAND $5 ($0=NA,$1=NB,$2=NQ0,$3=VDD,$4=VSS);\n" + " subcircuit NAND $6 ($0=NA,$1=B,$2=NQ2,$3=VDD,$4=VSS);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + comp.equivalent_pins (nl2.circuit_by_name ("NAND"), 0, 1); + + bool good = comp.compare (&nl1, &nl2); + + EXPECT_EQ (logger.text (), + "begin_circuit NAND NAND\n" + "match_nets VSS VSS\n" + "match_nets INT INT\n" + "match_nets OUT OUT\n" + "match_nets VDD VDD\n" + "match_nets B B\n" + "match_nets A A\n" + "match_pins $0 $0\n" + "match_pins $1 $1\n" + "match_pins $2 $2\n" + "match_pins $3 $3\n" + "match_pins $4 $4\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "match_devices $3 $3\n" + "match_devices $4 $4\n" + "end_circuit NAND NAND MATCH\n" + "begin_circuit DECODER DECODER\n" + "match_nets NA NB\n" + "match_nets A B\n" + "match_nets VDD VDD\n" + "match_nets B A\n" + "match_nets NB NA\n" + "match_nets VSS VSS\n" + "match_ambiguous_nets NQ0 NQ0\n" + "match_ambiguous_nets NQ2 NQ1\n" + "match_ambiguous_nets NQ1 NQ2\n" + "match_ambiguous_nets NQ3 NQ3\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 $5 $5\n" + "match_pins $6 $6\n" + "match_pins $7 $7\n" + "match_subcircuits $1 $1\n" + "match_subcircuits $5 $2\n" + "match_subcircuits $2 $3\n" + "match_subcircuits $6 $4\n" + "match_subcircuits $3 $5\n" + "match_subcircuits $4 $6\n" + "end_circuit DECODER DECODER MATCH" + ); + + EXPECT_EQ (good, true); +} +