From 699e94a45f58e60aa570b79759701ba47fa282d5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 14 Apr 2019 19:11:42 +0200 Subject: [PATCH] WIP: added configuration options (complexity, depth) for net compare --- src/db/db/dbNetlistCompare.cc | 73 +++++++++----- src/db/db/dbNetlistCompare.h | 44 +++++++++ src/db/db/gsiDeclDbNetlistCompare.cc | 23 +++++ src/db/unit_tests/dbNetlistCompareTests.cc | 109 +++++++++++++++++++++ 4 files changed, 223 insertions(+), 26 deletions(-) diff --git a/src/db/db/dbNetlistCompare.cc b/src/db/db/dbNetlistCompare.cc index 91d72f621..9ddcae997 100644 --- a/src/db/db/dbNetlistCompare.cc +++ b/src/db/db/dbNetlistCompare.cc @@ -29,7 +29,7 @@ #include "tlLog.h" // verbose debug output -// #define PRINT_DEBUG_NETCOMPARE +#define PRINT_DEBUG_NETCOMPARE namespace db { @@ -874,9 +874,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, TentativeNodeMapping *tentative, bool with_ambiguous); + size_t derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *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, TentativeNodeMapping *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 max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous); private: std::vector m_nodes; @@ -941,10 +941,6 @@ private: // -------------------------------------------------------------------------------------------------------------------- -// @@@ make attribute -const size_t depth_max = 8; -const size_t n_branch_max = 100; - void NetDeviceGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, CircuitCategorizer &circuit_categorizer, const db::DeviceFilter &device_filter, const std::map *circuit_and_pin_mapping, const CircuitPinMapper *circuit_pin_mapper) { @@ -982,7 +978,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, TentativeNodeMapping *tentative, bool with_ambiguous) +NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous) { NetGraphNode *n = & m_nodes[net_index]; NetGraphNode *nother = & other.m_nodes[n->other_net_index ()]; @@ -1076,7 +1072,7 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, // 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); + size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, other, depth, max_depth, n_branch, max_n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); if (bt_count == std::numeric_limits::max ()) { if (tentative) { @@ -1102,18 +1098,22 @@ NetDeviceGraph::derive_node_identities (size_t net_index, NetDeviceGraph &other, } 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, TentativeNodeMapping *tentative, bool with_ambiguous) +NetDeviceGraph::derive_node_identities_from_node_set (const std::vector &nodes, const std::vector &other_nodes, NetDeviceGraph &other, size_t depth, size_t max_depth, size_t n_branch, size_t max_n_branch, NetlistCompareLogger *logger, CircuitPinMapper *circuit_pin_mapper, TentativeNodeMapping *tentative, bool with_ambiguous) { #if defined(PRINT_DEBUG_NETCOMPARE) std::string indent; for (size_t d = 0; d < depth; ++d) { indent += " "; } + indent += "*" + tl::to_string (n_branch) + " "; #endif size_t new_nodes = 0; - if (depth + 1 == depth_max) { + if (depth > max_depth) { +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << indent << "max. depth exhausted (" << depth + 1 << ">" << max_depth << ")"; +#endif return std::numeric_limits::max (); } @@ -1139,7 +1139,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::max ()) { new_nodes += bt_count; @@ -1232,6 +1232,8 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::const_iterator nr = node_ranges.begin (); nr != node_ranges.end (); ++nr) { + // @@@ node ranges might have changed - adjust to real count and skip leading pairs assigned already + if (nr->num == 1) { if (! (*nr->n1)->has_other () && ! (*nr->n2)->has_other ()) { @@ -1254,7 +1256,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector::max ()) { new_nodes += bt_count; @@ -1277,12 +1279,18 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectornum * n_branch > n_branch_max) { + } else if (nr->num * n_branch > max_n_branch) { +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << indent << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << max_n_branch << ") - mismatch."; +#endif return std::numeric_limits::max (); } else { +#if defined(PRINT_DEBUG_NETCOMPARE) + tl::info << indent << "analyzing ambiguity group with " << nr->num << " members"; +#endif std::vector > pairs; tl::equivalence_clusters equivalent_other_nodes; std::set seen; @@ -1316,7 +1324,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectornet ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name (); #endif - size_t bt_count = derive_node_identities (ni, other, depth + 1, nr->num * n_branch, logger, circuit_pin_mapper, &tn, with_ambiguous); + size_t bt_count = derive_node_identities (ni, other, depth + 1, max_depth, nr->num * n_branch, max_n_branch, logger, circuit_pin_mapper, &tn, with_ambiguous); if (bt_count != std::numeric_limits::max ()) { @@ -1386,7 +1394,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectorfirst->net ()); - size_t bt_count = derive_node_identities (ni, other, depth + 1, nr->num * n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); + size_t bt_count = derive_node_identities (ni, other, depth + 1, max_depth, nr->num * n_branch, max_n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous); tl_assert (bt_count != std::numeric_limits::max ()); } @@ -1404,6 +1412,10 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vectornum << " members"; +#endif + } } @@ -1424,6 +1436,9 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger) m_cap_threshold = -1.0; // not set m_res_threshold = -1.0; // not set + + m_max_depth = 8; + m_max_n_branch = 100; } void @@ -1737,32 +1752,38 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, for (int pass = 0; pass < 2; ++pass) { +#if defined(PRINT_DEBUG_NETCOMPARE) + if (pass > 0) { + tl::info << "including ambiguous nodes now."; + } +#endif + good = true; while (true) { - #if defined(PRINT_DEBUG_NETCOMPARE) +#if defined(PRINT_DEBUG_NETCOMPARE) ++iter; tl::info << "new compare iteration #" << iter; tl::info << "deducing from present nodes ..."; - #endif +#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, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); + size_t ni = g1.derive_node_identities (i1 - g1.begin (), g2, 0, m_max_depth, 1, m_max_n_branch, mp_logger, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); if (ni > 0 && ni != std::numeric_limits::max ()) { new_identities += ni; - #if defined(PRINT_DEBUG_NETCOMPARE) +#if defined(PRINT_DEBUG_NETCOMPARE) tl::info << ni << " new identities."; - #endif +#endif } } } - #if defined(PRINT_DEBUG_NETCOMPARE) +#if defined(PRINT_DEBUG_NETCOMPARE) tl::info << "checking topological identity ..."; - #endif +#endif // derive new identities through topology: first collect all nets with the same topological signature @@ -1793,12 +1814,12 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2, 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, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); + size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, g2, 0, m_max_depth, 1, m_max_n_branch, mp_logger, &circuit_pin_mapper, 0 /*not tentative*/, pass > 0 /*with ambiguities*/); if (ni > 0 && ni != std::numeric_limits::max ()) { new_identities += ni; - #if defined(PRINT_DEBUG_NETCOMPARE) +#if defined(PRINT_DEBUG_NETCOMPARE) tl::info << ni << " new identities."; - #endif +#endif } if (new_identities == 0) { diff --git a/src/db/db/dbNetlistCompare.h b/src/db/db/dbNetlistCompare.h index 88e76af2b..c2946a997 100644 --- a/src/db/db/dbNetlistCompare.h +++ b/src/db/db/dbNetlistCompare.h @@ -211,6 +211,48 @@ public: */ void exclude_resistors (double threshold); + /** + * @brief Sets the maximum seach depth + * + * This value limits the search depth of the backtracking algorithm to the + * given number of jumps. + */ + void set_max_depth (size_t n) + { + m_max_depth = n; + } + + /** + * @brief Gets the maximum search depth + */ + size_t max_depth () const + { + return m_max_depth; + } + + /** + * @brief Sets the maximum branch complexity + * + * This value limits the maximum branch complexity of the backtracking algorithm. + * The complexity is the accumulated number of branch options with ambiguous + * net matches. Backtracking will stop when the maximum number of options + * has been exceeded. + * As the computational complexity is the square of the branch count, + * this value should be adjusted carefully. + */ + void set_max_branch_complexity (size_t n) + { + m_max_n_branch = n; + } + + /** + * @brief Gets the maximum branch complexity + */ + size_t max_branch_complexity () const + { + return m_max_n_branch; + } + /** * @brief Actually compares the two netlists */ @@ -228,6 +270,8 @@ protected: std::auto_ptr mp_circuit_categorizer; double m_cap_threshold; double m_res_threshold; + size_t m_max_n_branch; + size_t m_max_depth; }; } diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc index 5fd810d39..e5a652ecb 100644 --- a/src/db/db/gsiDeclDbNetlistCompare.cc +++ b/src/db/db/gsiDeclDbNetlistCompare.cc @@ -482,6 +482,29 @@ Class decl_dbNetlistComparer ("db", "NetlistComparer", "@brief Excludes all resistor devices with a resistance values higher than the given threshold.\n" "To reset this constraint, set this attribute to zero." ) + + gsi::method ("max_depth=", &db::NetlistComparer::set_max_depth, gsi::arg ("n"), + "@brief Sets the maximum seach depth\n" + "This value limits the search depth of the backtracking algorithm to the\n" + "given number of jumps.\n" + ) + + gsi::method ("max_depth", &db::NetlistComparer::max_depth, + "@brief Gets the maximum seach depth\n" + "See \\max_depth= for details." + ) + + gsi::method ("max_branch_complexity=", &db::NetlistComparer::set_max_branch_complexity, gsi::arg ("n"), + "@brief Sets the maximum branch complexity\n" + "This value limits the maximum branch complexity of the backtracking algorithm.\n" + "The complexity is the accumulated number of branch options with ambiguous\n" + "net matches. Backtracking will stop when the maximum number of options\n" + "has been exceeded.\n" + "\n" + "As the computational complexity is the square of the branch count,\n" + "this value should be adjusted carefully.\n" + ) + + gsi::method ("max_branch_complexity", &db::NetlistComparer::max_branch_complexity, + "@brief Gets the maximum branch complexity\n" + "See \\max_branch_complexity= for details." + ) + gsi::method ("compare", &db::NetlistComparer::compare, gsi::arg ("netlist_a"), gsi::arg ("netlist_b"), "@brief Compares two netlists.\n" "This method will perform the actual netlist compare. It will return true if both netlists are identical. " diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 92c907966..0df3f06ff 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2193,3 +2193,112 @@ TEST(17_InherentlyAmbiguousDecoder) EXPECT_EQ (good, true); } +TEST(18_ClockTree) +{ + const char *nls1 = + "circuit INV (IN=IN,OUT=OUT,VDD=VDD,VSS=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n" + "circuit TREE ();\n" + " subcircuit INV T (IN=IN,OUT=S,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TR (IN=S,OUT=SR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TL (IN=S,OUT=SL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRR (IN=SR,OUT=SRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRL (IN=SR,OUT=SRL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLR (IN=SL,OUT=SLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLL (IN=SL,OUT=SLL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRRR (IN=SRR,OUT=SRRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRRL (IN=SRR,OUT=SRRL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRLR (IN=SRL,OUT=SRLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRLL (IN=SRL,OUT=SRLL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLRR (IN=SLR,OUT=SLRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLRL (IN=SLR,OUT=SLRL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLLR (IN=SLL,OUT=SLLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLLL (IN=SLL,OUT=SLLL,VDD=VDD,VSS=VSS);\n" + "end;\n"; + + const char *nls2 = + "circuit INV (IN=IN,OUT=OUT,VDD=VDD,VSS=VSS);\n" + " device PMOS $1 (S=VDD,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + " device NMOS $2 (S=VSS,G=IN,D=OUT) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n" + "end;\n" + "circuit TREE ();\n" + " subcircuit INV TLRR (IN=SLR,OUT=SLRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TR (IN=S,OUT=SR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRRL (IN=SRR,OUT=SRRL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRLR (IN=SRL,OUT=SRLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLR (IN=SL,OUT=SLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLL (IN=SL,OUT=SLL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRRR (IN=SRR,OUT=SRRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLLL (IN=SLL,OUT=SLLL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLRL (IN=SLR,OUT=SLRL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV T (IN=IN,OUT=S,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TLLR (IN=SLL,OUT=SLLR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TL (IN=S,OUT=SL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRR (IN=SR,OUT=SRR,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRLL (IN=SRL,OUT=SRLL,VDD=VDD,VSS=VSS);\n" + " subcircuit INV TRL (IN=SR,OUT=SRL,VDD=VDD,VSS=VSS);\n" + "end;\n"; + + db::Netlist nl1, nl2; + prep_nl (nl1, nls1); + prep_nl (nl2, nls2); + + NetlistCompareTestLogger logger; + db::NetlistComparer comp (&logger); + + bool good = comp.compare (&nl1, &nl2); + + EXPECT_EQ (logger.text (), + "begin_circuit INV INV\n" + "match_nets VDD VDD\n" + "match_nets OUT OUT\n" + "match_nets IN IN\n" + "match_nets VSS VSS\n" + "match_pins IN IN\n" + "match_pins OUT OUT\n" + "match_pins VDD VDD\n" + "match_pins VSS VSS\n" + "match_devices $1 $1\n" + "match_devices $2 $2\n" + "end_circuit INV INV MATCH\n" + "begin_circuit TREE TREE\n" + "match_nets IN IN\n" + "match_nets S S\n" + "match_nets VDD VDD\n" + "match_nets VSS VSS\n" + "match_ambiguous_nets SL SR\n" + "match_ambiguous_nets SR SL\n" + "match_ambiguous_nets SLL SRL\n" + "match_ambiguous_nets SLR SRR\n" + "match_ambiguous_nets SLLL SRLL\n" + "match_ambiguous_nets SLLR SRLR\n" + "match_ambiguous_nets SLRL SRRL\n" + "match_ambiguous_nets SLRR SRRR\n" + "match_ambiguous_nets SRL SLL\n" + "match_ambiguous_nets SRR SLR\n" + "match_ambiguous_nets SRLL SLLR\n" + "match_ambiguous_nets SRLR SLLL\n" + "match_ambiguous_nets SRRL SLRR\n" + "match_ambiguous_nets SRRR SLRL\n" + "match_subcircuits TRRL TLRR\n" + "match_subcircuits TL TR\n" + "match_subcircuits TLRL TRRL\n" + "match_subcircuits TLLR TRLR\n" + "match_subcircuits TRR TLR\n" + "match_subcircuits TRL TLL\n" + "match_subcircuits TLRR TRRR\n" + "match_subcircuits TRLR TLLL\n" + "match_subcircuits TRRR TLRL\n" + "match_subcircuits T T\n" + "match_subcircuits TRLL TLLR\n" + "match_subcircuits TR TL\n" + "match_subcircuits TLR TRR\n" + "match_subcircuits TLLL TRLL\n" + "match_subcircuits TLL TRL\n" + "end_circuit TREE TREE MATCH" + ); + EXPECT_EQ (good, true); +} +