WIP: added configuration options (complexity, depth) for net compare

This commit is contained in:
Matthias Koefferlein 2019-04-14 19:11:42 +02:00
parent 92524dcf57
commit 699e94a45f
4 changed files with 223 additions and 26 deletions

View File

@ -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<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &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<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &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<NetGraphNode> 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<const db::Circuit *, CircuitMapper> *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<size_t>::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<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &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<const NetGraphNode *> &nodes, const std::vector<const NetGraphNode *> &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<size_t>::max ();
}
@ -1139,7 +1139,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
}
// continue here.
size_t bt_count = derive_node_identities (ni, other, depth + 1, n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous);
size_t bt_count = derive_node_identities (ni, other, depth + 1, max_depth, n_branch, max_n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous);
if (bt_count != std::numeric_limits<size_t>::max ()) {
new_nodes += bt_count;
@ -1232,6 +1232,8 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
for (std::vector<NodeRange>::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<const Ne
}
// continue here.
size_t bt_count = derive_node_identities (ni, other, depth + 1, n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous);
size_t bt_count = derive_node_identities (ni, other, depth + 1, max_depth, n_branch, max_n_branch, logger, circuit_pin_mapper, tentative, with_ambiguous);
if (bt_count != std::numeric_limits<size_t>::max ()) {
new_nodes += bt_count;
@ -1277,12 +1279,18 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
}
} else if (nr->num * 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<size_t>::max ();
} else {
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "analyzing ambiguity group with " << nr->num << " members";
#endif
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
std::set<const NetGraphNode *> seen;
@ -1316,7 +1324,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "trying in tentative mode: " << (*i1)->net ()->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<size_t>::max ()) {
@ -1386,7 +1394,7 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
size_t ni = node_index_for_net (p->first->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<size_t>::max ());
}
@ -1404,6 +1412,10 @@ NetDeviceGraph::derive_node_identities_from_node_set (const std::vector<const Ne
}
#if defined(PRINT_DEBUG_NETCOMPARE)
tl::info << indent << "finished analysis of ambiguity group with " << nr->num << " 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<size_t>::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<size_t>::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) {

View File

@ -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<CircuitCategorizer> mp_circuit_categorizer;
double m_cap_threshold;
double m_res_threshold;
size_t m_max_n_branch;
size_t m_max_depth;
};
}

View File

@ -482,6 +482,29 @@ Class<db::NetlistComparer> 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. "

View File

@ -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);
}