mirror of https://github.com/KLayout/klayout.git
Merge remote-tracking branch 'origin/netlist-compare-hardening' into macos-fixes
This commit is contained in:
commit
91eca19b3a
|
|
@ -616,18 +616,20 @@ 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), subcircuit_equivalence (0), device_equivalence (0)
|
||||
: other (0), max_depth (0), max_n_branch (0), depth_first (true), dont_consider_net_names (false), logger (0),
|
||||
circuit_pin_mapper (0), subcircuit_equivalence (0), device_equivalence (0), progress (0)
|
||||
{ }
|
||||
|
||||
NetGraph *other;
|
||||
size_t max_depth;
|
||||
size_t max_n_branch;
|
||||
bool depth_first;
|
||||
bool dont_consider_net_names;
|
||||
NetlistCompareLogger *logger;
|
||||
CircuitPinMapper *circuit_pin_mapper;
|
||||
SubCircuitEquivalenceTracker *subcircuit_equivalence;
|
||||
DeviceEquivalenceTracker *device_equivalence;
|
||||
tl::RelativeProgress *progress;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1920,7 +1922,7 @@ static bool edges_are_compatible (const NetGraphNode::edge_type &e, const NetGra
|
|||
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;
|
||||
// NOTE: we can skip edges to known nodes because we did a pre-analysis making sure those are compatible
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > nodes;
|
||||
nodes.reserve (ee - e);
|
||||
|
|
@ -1930,100 +1932,114 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
|
||||
tl_assert (e->first == e_other->first);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "considering transitions:";
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (NetGraphNode::edge_iterator i = e; i != ee; ++i) {
|
||||
if (i->second.first != net_index) {
|
||||
const NetGraphNode *nn = &node (i->second.first);
|
||||
if (options ()->debug_netcompare) {
|
||||
if (first) {
|
||||
tl::info << indent (depth) << " here: " << (node (net_index).net () ? node (net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||
first = false;
|
||||
}
|
||||
tl::info << indent (depth) << " " << (nn->net () ? nn->net ()->expanded_name ().c_str() : "(null)") << " via: " << tl::noendl;
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
||||
tl::info << (t != i->first.begin () ? "; " : "") << t->to_string() << tl::noendl;
|
||||
}
|
||||
tl::info << "";
|
||||
if (! nn->has_other ()) {
|
||||
nodes.push_back (std::make_pair (nn, i));
|
||||
}
|
||||
nodes.push_back (std::make_pair (nn, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (! nodes.empty ()) { // if non-ambiguous, non-assigned
|
||||
|
||||
first = true;
|
||||
|
||||
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
|
||||
if (i->second.first != other_net_index) {
|
||||
const NetGraphNode *nn = &data->other->node (i->second.first);
|
||||
if (options ()->debug_netcompare) {
|
||||
if (first) {
|
||||
tl::info << indent (depth) << " there: " << (data->other->node (other_net_index).net () ? data->other->node (other_net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||
first = false;
|
||||
}
|
||||
tl::info << indent(depth) << " " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via: " << tl::noendl;
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
||||
tl::info << (t != i->first.begin () ? "; " : "") << t->to_string() << tl::noendl;
|
||||
}
|
||||
tl::info << "";
|
||||
if (! nn->has_other ()) {
|
||||
other_nodes.push_back (std::make_pair (nn, i));
|
||||
}
|
||||
other_nodes.push_back (std::make_pair (nn, i));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! nodes.empty () || ! other_nodes.empty ()) {
|
||||
if (nodes.empty () || other_nodes.empty ()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::sort (nodes.begin (), nodes.end (), CompareNodePtr ());
|
||||
std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ());
|
||||
std::sort (nodes.begin (), nodes.end (), CompareNodePtr ());
|
||||
std::sort (other_nodes.begin (), other_nodes.end (), CompareNodePtr ());
|
||||
|
||||
// for the purpose of match evaluation we require an exact match of the node structure
|
||||
size_t new_nodes = 0;
|
||||
|
||||
if (tentative) {
|
||||
if (options ()->debug_netcompare) {
|
||||
|
||||
if (nodes.size () != other_nodes.size ()) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
// print transitions if requested
|
||||
|
||||
tl::info << indent(depth) << "considering transitions:";
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i = nodes.begin (); i != nodes.end (); ++i) {
|
||||
const NetGraphNode *nn = i->first;
|
||||
if (first) {
|
||||
tl::info << indent (depth) << " here: " << (node (net_index).net () ? node (net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||
first = false;
|
||||
}
|
||||
tl::info << indent (depth) << " " << (nn->net () ? nn->net ()->expanded_name ().c_str() : "(null)") << " via: " << tl::noendl;
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) {
|
||||
tl::info << (t != i->second->first.begin () ? "; " : "") << t->to_string() << tl::noendl;
|
||||
}
|
||||
tl::info << "";
|
||||
}
|
||||
|
||||
// 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].first == *other_nodes[i].first)) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
first = true;
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i = other_nodes.begin (); i != other_nodes.end (); ++i) {
|
||||
const NetGraphNode *nn = i->first;
|
||||
if (first) {
|
||||
tl::info << indent (depth) << " there: " << (data->other->node (other_net_index).net () ? data->other->node (other_net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||
first = false;
|
||||
}
|
||||
tl::info << indent(depth) << " " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via: " << tl::noendl;
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->second->first.begin (); t != i->second->first.end(); ++t) {
|
||||
tl::info << (t != i->second->first.begin () ? "; " : "") << t->to_string() << tl::noendl;
|
||||
}
|
||||
tl::info << "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// for the purpose of match evaluation we require an exact match of the node structure
|
||||
|
||||
if (tentative) {
|
||||
|
||||
if (nodes.size () != other_nodes.size ()) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
// 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].first == *other_nodes[i].first)) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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, depth, n_branch, tentative, with_ambiguous, data);
|
||||
// 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
|
||||
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return bt_count;
|
||||
size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, depth, n_branch, tentative, with_ambiguous, data);
|
||||
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
return bt_count;
|
||||
}
|
||||
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
}
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
|
|
@ -2055,16 +2071,6 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
size_t other_net_index = n->other_net_index ();
|
||||
NetGraphNode *n_other = & data->other->node (other_net_index);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (! tentative) {
|
||||
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
} else {
|
||||
tl::info << indent(depth) << "tentatively deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
}
|
||||
}
|
||||
|
||||
size_t new_nodes = 0;
|
||||
|
||||
NetGraphNode nn, nn_other;
|
||||
|
||||
// If there are subcircuits on the graph we temporarily create edges from our node to the other nodes of
|
||||
|
|
@ -2082,6 +2088,117 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
|
||||
}
|
||||
|
||||
// do a pre-analysis filtering out all nodes with fully satisfied edges or which provide a contradiction
|
||||
|
||||
bool analysis_required = false;
|
||||
|
||||
for (NetGraphNode::edge_iterator e = n->begin (); e != n->end (); ) {
|
||||
|
||||
NetGraphNode::edge_iterator ee = e;
|
||||
++ee;
|
||||
|
||||
while (ee != n->end () && ee->first == e->first) {
|
||||
++ee;
|
||||
}
|
||||
|
||||
NetGraphNode::edge_iterator e_other = n_other->find_edge (e->first);
|
||||
if (e_other != n_other->end ()) {
|
||||
|
||||
NetGraphNode::edge_iterator ee_other = e_other;
|
||||
++ee_other;
|
||||
|
||||
while (ee_other != n_other->end () && ee_other->first == e_other->first) {
|
||||
++ee_other;
|
||||
}
|
||||
|
||||
std::vector<const NetGraphNode *> nodes;
|
||||
nodes.reserve (ee - e);
|
||||
|
||||
std::vector<const NetGraphNode *> other_nodes_translated;
|
||||
other_nodes_translated.reserve (ee - e);
|
||||
|
||||
tl_assert (e->first == e_other->first);
|
||||
|
||||
for (NetGraphNode::edge_iterator i = e; i != ee; ++i) {
|
||||
if (i->second.first != net_index) {
|
||||
const NetGraphNode *nn = &node (i->second.first);
|
||||
if (nn->has_other ()) {
|
||||
nodes.push_back (nn);
|
||||
} else {
|
||||
analysis_required = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
|
||||
if (i->second.first != other_net_index) {
|
||||
const NetGraphNode *nn = &data->other->node (i->second.first);
|
||||
if (nn->has_other ()) {
|
||||
other_nodes_translated.push_back (&node (nn->other_net_index ()));
|
||||
} else {
|
||||
analysis_required = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (nodes.begin (), nodes.end ());
|
||||
std::sort (other_nodes_translated.begin (), other_nodes_translated.end ());
|
||||
|
||||
// No fit, we can shortcut
|
||||
if (nodes != other_nodes_translated) {
|
||||
return tentative ? failed_match : 0;
|
||||
}
|
||||
|
||||
} else if (tentative) {
|
||||
// in tentative mode an exact match is required: no having the same edges for a node disqualifies the node
|
||||
// as matching.
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
e = ee;
|
||||
|
||||
}
|
||||
|
||||
if (tentative) {
|
||||
|
||||
// in tentative mode, again an exact match is required
|
||||
|
||||
for (NetGraphNode::edge_iterator e_other = n_other->begin (); e_other != n_other->end (); ) {
|
||||
|
||||
NetGraphNode::edge_iterator ee_other = e_other;
|
||||
++ee_other;
|
||||
|
||||
while (ee_other != n_other->end () && ee_other->first == e_other->first) {
|
||||
++ee_other;
|
||||
}
|
||||
|
||||
NetGraphNode::edge_iterator e = n->find_edge (e_other->first);
|
||||
if (e == n->end ()) {
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
e_other = ee_other;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! analysis_required) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// do a detailed analysis
|
||||
|
||||
size_t new_nodes = 0;
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (! tentative) {
|
||||
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
} else {
|
||||
tl::info << indent(depth) << "tentatively deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
}
|
||||
}
|
||||
|
||||
// non-ambiguous paths to non-assigned nodes create a node identity on the
|
||||
// end of this path
|
||||
|
||||
|
|
@ -2114,46 +2231,12 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
new_nodes += bt_count;
|
||||
}
|
||||
|
||||
} else if (tentative) {
|
||||
// in tentative mode an exact match is required: no having the same edges for a node disqualifies the node
|
||||
// as matching.
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
e = ee;
|
||||
|
||||
}
|
||||
|
||||
if (tentative) {
|
||||
|
||||
// in tentative mode, again an exact match is required
|
||||
|
||||
for (NetGraphNode::edge_iterator e_other = n_other->begin (); e_other != n_other->end (); ) {
|
||||
|
||||
NetGraphNode::edge_iterator ee_other = e_other;
|
||||
++ee_other;
|
||||
|
||||
while (ee_other != n_other->end () && ee_other->first == e_other->first) {
|
||||
++ee_other;
|
||||
}
|
||||
|
||||
NetGraphNode::edge_iterator e = n->find_edge (e_other->first);
|
||||
if (e == n->end ()) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
e_other = ee_other;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (! tentative && new_nodes > 0) {
|
||||
tl::info << indent(depth) << "=> finished pair deduction: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name () << " with " << new_nodes << " new pairs";
|
||||
|
|
@ -2295,22 +2378,27 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
if (options ()->debug_netcompare) {
|
||||
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 (n->net (), n_other->net ());
|
||||
} else {
|
||||
data->logger->match_nets (n->net (), n_other->net ());
|
||||
if (! tentative) {
|
||||
++*data->progress;
|
||||
if (data->logger) {
|
||||
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 (n->net (), n_other->net ());
|
||||
} else {
|
||||
data->logger->match_nets (n->net (), n_other->net ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// continue here.
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||
|
||||
if (bt_count != failed_match) {
|
||||
new_nodes += bt_count;
|
||||
} else if (tentative) {
|
||||
return bt_count;
|
||||
if (data->depth_first || tentative) {
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
return failed_match;
|
||||
}
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
}
|
||||
}
|
||||
|
||||
new_nodes += 1;
|
||||
|
|
@ -2346,10 +2434,10 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
|
||||
while (n1 != nodes.end () && n2 != other_nodes.end ()) {
|
||||
|
||||
if (n1->first->has_any_other ()) {
|
||||
if (n1->first->has_other ()) {
|
||||
++n1;
|
||||
continue;
|
||||
} else if (n2->first->has_any_other ()) {
|
||||
} else if (n2->first->has_other ()) {
|
||||
++n2;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2368,9 +2456,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
++nn1;
|
||||
++nn2;
|
||||
while (nn1 != nodes.end () && nn2 != other_nodes.end ()) {
|
||||
if (nn1->first->has_any_other ()) {
|
||||
if (nn1->first->has_other ()) {
|
||||
++nn1;
|
||||
} else if (nn2->first->has_any_other ()) {
|
||||
} else if (nn2->first->has_other ()) {
|
||||
++nn2;
|
||||
} else if (! (*nn1->first == *n1->first) || ! (*nn2->first == *n2->first)) {
|
||||
break;
|
||||
|
|
@ -2405,9 +2493,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
// node ranges might have changed - adjust to real count and skip leading pairs assigned already
|
||||
|
||||
while (nr->n1 != nr->nn1 && nr->n2 != nr->nn2) {
|
||||
if (nr->n1->first->has_any_other ()) {
|
||||
if (nr->n1->first->has_other ()) {
|
||||
++nr->n1;
|
||||
} else if (nr->n2->first->has_any_other ()) {
|
||||
} else if (nr->n2->first->has_other ()) {
|
||||
++nr->n2;
|
||||
} else {
|
||||
break;
|
||||
|
|
@ -2418,9 +2506,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i1 = nr->n1, i2 = nr->n2;
|
||||
|
||||
while (i1 != nr->nn1 && i2 != nr->nn2) {
|
||||
if (i1->first->has_any_other ()) {
|
||||
if (i1->first->has_other ()) {
|
||||
++i1;
|
||||
} else if (i2->first->has_any_other ()) {
|
||||
} else if (i2->first->has_other ()) {
|
||||
++i2;
|
||||
} else {
|
||||
++nr->num;
|
||||
|
|
@ -2435,7 +2523,14 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
|
||||
} else if (nr->num == 1) {
|
||||
|
||||
if (! nr->n1->first->has_any_other () && ! nr->n2->first->has_any_other ()) {
|
||||
if (! edges_are_compatible (*nr->n1->second, *nr->n2->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 (! 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
|
||||
|
|
@ -2458,25 +2553,31 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
if (options ()->debug_netcompare) {
|
||||
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->first->net (), nr->n2->first->net ());
|
||||
} else {
|
||||
data->logger->match_nets (nr->n1->first->net (), nr->n2->first->net ());
|
||||
if (! tentative) {
|
||||
++*data->progress;
|
||||
if (data->logger) {
|
||||
if (! (node (ni) == data->other->node (other_ni))) {
|
||||
// this is a mismatch, but we continue with this
|
||||
data->logger->net_mismatch (nr->n1->first->net (), nr->n2->first->net ());
|
||||
} else {
|
||||
data->logger->match_nets (nr->n1->first->net (), nr->n2->first->net ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// continue here.
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||
|
||||
if (bt_count != failed_match) {
|
||||
new_nodes += bt_count;
|
||||
new_nodes += 1;
|
||||
} else if (tentative) {
|
||||
new_nodes = bt_count;
|
||||
if (data->depth_first || tentative) {
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, with_ambiguous, data);
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
return failed_match;
|
||||
}
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
}
|
||||
}
|
||||
|
||||
new_nodes += 1;
|
||||
|
||||
} else if (nr->n1->first->has_unknown_other ()) {
|
||||
|
||||
// accept any other net
|
||||
|
|
@ -2633,6 +2734,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
tl::info << indent_s << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||
}
|
||||
}
|
||||
|
||||
if (data->logger) {
|
||||
bool ambiguous = equivalent_other_nodes.has_attribute (p->second);
|
||||
if (ambiguous) {
|
||||
|
|
@ -2642,6 +2744,8 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
}
|
||||
}
|
||||
|
||||
++*data->progress;
|
||||
|
||||
}
|
||||
|
||||
// And seek further from these pairs
|
||||
|
|
@ -2695,6 +2799,7 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger)
|
|||
|
||||
m_max_depth = 50;
|
||||
m_max_n_branch = 500;
|
||||
m_depth_first = true;
|
||||
|
||||
m_dont_consider_net_names = false;
|
||||
}
|
||||
|
|
@ -2906,6 +3011,8 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
|
||||
std::map<const db::Circuit *, CircuitMapper> c12_pin_mapping, c22_pin_mapping;
|
||||
|
||||
tl::RelativeProgress progress (tl::to_string (tr ("Comparing netlists")), a->circuit_count (), 1);
|
||||
|
||||
for (db::Netlist::const_bottom_up_circuit_iterator c = a->begin_bottom_up (); c != a->end_bottom_up (); ++c) {
|
||||
|
||||
const db::Circuit *ca = c.operator-> ();
|
||||
|
|
@ -2936,6 +3043,7 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
if (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "----------------------------------------------------------------------";
|
||||
tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name ();
|
||||
}
|
||||
if (mp_logger) {
|
||||
|
|
@ -2968,6 +3076,8 @@ NetlistComparer::compare (const db::Netlist *a, const db::Netlist *b) const
|
|||
|
||||
}
|
||||
|
||||
++progress;
|
||||
|
||||
}
|
||||
|
||||
if (mp_logger) {
|
||||
|
|
@ -3038,8 +3148,42 @@ compute_device_key (const db::Device &device, const db::NetGraph &g, bool strict
|
|||
k.push_back (std::make_pair (terminal_id, net_id));
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
return k;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<size_t, size_t> >
|
||||
compute_device_key_for_this (const db::Device &device, const db::NetGraph &g, bool strict, bool &mapped)
|
||||
{
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key (device, g, strict);
|
||||
|
||||
mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||
if (! g.begin () [i->second].has_other ()) {
|
||||
i->second = invalid_id; // normalization
|
||||
mapped = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
return k;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<size_t, size_t> >
|
||||
compute_device_key_for_other (const db::Device &device, const db::NetGraph &g, bool strict, bool &mapped)
|
||||
{
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key (device, g, strict);
|
||||
|
||||
mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||
if (! g.begin () [i->second].has_other ()) {
|
||||
i->second = invalid_id; // normalization
|
||||
mapped = false;
|
||||
} else {
|
||||
i->second = g.begin () [i->second].other_net_index ();
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
return k;
|
||||
}
|
||||
|
||||
|
|
@ -3074,11 +3218,51 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g,
|
|||
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<size_t, size_t> >
|
||||
compute_subcircuit_key_for_this (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, bool &mapped, bool &valid)
|
||||
{
|
||||
valid = true;
|
||||
std::vector<std::pair<size_t, size_t> > k;
|
||||
if (! compute_subcircuit_key (subcircuit, g, circuit_map, pin_map, k)) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end () && mapped; ++i) {
|
||||
if (! g.begin () [i->second].has_other ()) {
|
||||
mapped = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
return k;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<size_t, size_t> >
|
||||
compute_subcircuit_key_for_other (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, bool &mapped, bool &valid)
|
||||
{
|
||||
valid = true;
|
||||
std::vector<std::pair<size_t, size_t> > k;
|
||||
if (! compute_subcircuit_key (subcircuit, g, circuit_map, pin_map, k)) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||
if (! g.begin () [i->second].has_other ()) {
|
||||
mapped = false;
|
||||
} else {
|
||||
i->second = g.begin () [i->second].other_net_index ();
|
||||
}
|
||||
}
|
||||
|
||||
std::sort (k.begin (), k.end ());
|
||||
return k;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
inline double size_dist (size_t a, size_t b)
|
||||
|
|
@ -3252,11 +3436,13 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
int iter = 0;
|
||||
|
||||
tl::RelativeProgress progress (tl::to_string (tr ("Comparing circuits ")) + c1->name () + "/" + c2->name (), std::max (g1.end () - g1.begin (), g2.end () - g2.begin ()), 1);
|
||||
|
||||
// two passes: one without ambiguities, the second one with
|
||||
|
||||
bool good;
|
||||
bool good = false;
|
||||
|
||||
for (int pass = 0; pass < 2; ++pass) {
|
||||
for (int pass = 0; pass < 2 && ! good; ++pass) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (pass > 0) {
|
||||
|
|
@ -3283,11 +3469,13 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
data.other = &g2;
|
||||
data.max_depth = m_max_depth;
|
||||
data.max_n_branch = m_max_n_branch;
|
||||
data.depth_first = m_depth_first;
|
||||
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;
|
||||
data.progress = &progress;
|
||||
|
||||
size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
||||
if (ni > 0 && ni != failed_match) {
|
||||
|
|
@ -3334,6 +3522,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator n = other_nodes.begin (); n != other_nodes.end () && good; ++n) {
|
||||
good = is_passive_net (n->first->net (), c22_circuit_and_pin_mapping);
|
||||
}
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "Stopped with " << nodes.size () << "/" << other_nodes.size () << " nodes left unresolved " << (good ? "(accepted)" : "(not accepted)");
|
||||
}
|
||||
// this assumes that we don't gain anything here. Stop now.
|
||||
break;
|
||||
}
|
||||
|
|
@ -3350,6 +3541,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
data.subcircuit_equivalence = &subcircuit_equivalence;
|
||||
data.device_equivalence = &device_equivalence;
|
||||
data.logger = mp_logger;
|
||||
data.progress = &progress;
|
||||
|
||||
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) {
|
||||
|
|
@ -3360,6 +3552,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
}
|
||||
|
||||
if (new_identities == 0) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "Stopped with " << nodes.size () << "/" << other_nodes.size () << " nodes left unresolved.";
|
||||
}
|
||||
good = false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -3372,6 +3567,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
for (db::NetGraph::node_iterator i = g1.begin (); i != g1.end (); ++i) {
|
||||
if (! i->has_other ()) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "Unresolved net from left: " << i->net ()->expanded_name () << " " << (good ? "(accepted)" : "(not accepted)");
|
||||
}
|
||||
if (mp_logger) {
|
||||
if (good) {
|
||||
mp_logger->match_nets (i->net (), 0);
|
||||
|
|
@ -3388,6 +3586,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
for (db::NetGraph::node_iterator i = g2.begin (); i != g2.end (); ++i) {
|
||||
if (! i->has_other ()) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "Unresolved net from right: " << i->net ()->expanded_name () << " " << (good ? "(accepted)" : "(not accepted)");
|
||||
}
|
||||
if (mp_logger) {
|
||||
if (good) {
|
||||
mp_logger->match_nets (0, i->net ());
|
||||
|
|
@ -3628,6 +3829,8 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph
|
|||
typedef std::vector<std::pair<std::vector<std::pair<size_t, size_t> >, std::pair<const db::Device *, size_t> > > unmatched_list;
|
||||
unmatched_list unmatched_a, unmatched_b;
|
||||
|
||||
// check mapping of devices whose equivalence is established topologically
|
||||
|
||||
for (db::Circuit::const_device_iterator d = c1->begin_devices (); d != c1->end_devices (); ++d) {
|
||||
|
||||
if (! device_filter.filter (d.operator-> ())) {
|
||||
|
|
@ -3644,15 +3847,8 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph
|
|||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key (*d, g1, device_categorizer.is_strict_device_category (device_cat));
|
||||
|
||||
bool mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
|
||||
if (! g1.begin () [i->second].has_other ()) {
|
||||
i->second = invalid_id; // normalization
|
||||
mapped = false;
|
||||
}
|
||||
}
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key_for_this (*d, g1, device_categorizer.is_strict_device_category (device_cat), mapped);
|
||||
|
||||
if (! mapped) {
|
||||
if (mp_logger) {
|
||||
|
|
@ -3678,28 +3874,41 @@ NetlistComparer::do_device_assignment (const db::Circuit *c1, const db::NetGraph
|
|||
continue;
|
||||
}
|
||||
|
||||
const db::Device *c1_device = device_eq.other (d.operator-> ());
|
||||
const db::Device *c1_device = 0;
|
||||
size_t c1_device_cat = 0;
|
||||
|
||||
if (c1_device) {
|
||||
const db::Device *d_this = device_eq.other (d.operator-> ());
|
||||
if (d_this) {
|
||||
|
||||
c1_device_cat = device_categorizer.cat_for_device (c1_device);
|
||||
size_t device_cat_this = device_categorizer.cat_for_device (d_this);
|
||||
if (! device_cat_this) {
|
||||
// device is ignored
|
||||
continue;
|
||||
}
|
||||
|
||||
bool mapped1 = true, mapped2 = true;
|
||||
std::vector<std::pair<size_t, size_t> > k_this = compute_device_key_for_this (*d_this, g1, device_categorizer.is_strict_device_category (device_cat_this), mapped1);
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key_for_other (*d, g2, device_categorizer.is_strict_device_category (device_cat), mapped2);
|
||||
|
||||
if (! mapped1 || ! mapped2 || k != k_this) {
|
||||
|
||||
// topological mismatch
|
||||
if (mp_logger) {
|
||||
mp_logger->device_mismatch (d_this, d.operator-> ());
|
||||
}
|
||||
good = false;
|
||||
|
||||
} else {
|
||||
|
||||
c1_device = d_this;
|
||||
c1_device_cat = device_cat_this;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_device_key (*d, g2, device_categorizer.is_strict_device_category (device_cat));
|
||||
|
||||
bool mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::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::vector<std::pair<size_t, size_t> > k = compute_device_key_for_other (*d, g2, device_categorizer.is_strict_device_category (device_cat), mapped);
|
||||
|
||||
std::multimap<std::vector<std::pair<size_t, size_t> >, std::pair<const db::Device *, size_t> >::iterator dm = device_map.find (k);
|
||||
|
||||
|
|
@ -3844,15 +4053,8 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
|
|||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > k;
|
||||
bool valid = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, k);
|
||||
|
||||
bool mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end () && mapped; ++i) {
|
||||
if (! g1.begin () [i->second].has_other ()) {
|
||||
mapped = false;
|
||||
}
|
||||
}
|
||||
bool mapped = true, valid = true;
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key_for_this (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid);
|
||||
|
||||
if (! mapped) {
|
||||
if (mp_logger) {
|
||||
|
|
@ -3877,33 +4079,39 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
|
|||
continue;
|
||||
}
|
||||
|
||||
const db::SubCircuit *c1_subcircuit = subcircuit_eq.other (sc.operator-> ());
|
||||
const db::SubCircuit *sc_this = subcircuit_eq.other (sc.operator-> ());
|
||||
if (sc_this) {
|
||||
|
||||
if (c1_subcircuit) {
|
||||
size_t sc_cat_this = circuit_categorizer.cat_for_subcircuit (sc_this);
|
||||
if (! sc_cat_this) {
|
||||
// subcircuit is ignored
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mp_logger) {
|
||||
mp_logger->match_subcircuits (c1_subcircuit, sc.operator-> ());
|
||||
bool mapped1 = true, mapped2 = true;
|
||||
bool valid1 = true, valid2 = true;
|
||||
std::vector<std::pair<size_t, size_t> > k_this = compute_subcircuit_key_for_this (*sc_this, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, mapped1, valid1);
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key_for_other (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, mapped2, valid2);
|
||||
|
||||
if (! valid1 || ! valid2 || ! mapped1 || ! mapped2 || k_this != k || sc_cat != sc_cat_this) {
|
||||
if (mp_logger) {
|
||||
mp_logger->subcircuit_mismatch (sc_this, sc.operator-> ());
|
||||
}
|
||||
good = false;
|
||||
} else {
|
||||
if (mp_logger) {
|
||||
mp_logger->match_subcircuits (sc_this, sc.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > k;
|
||||
compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, k);
|
||||
|
||||
bool mapped = true;
|
||||
for (std::vector<std::pair<size_t, size_t> >::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 ());
|
||||
bool mapped = true, valid = true;
|
||||
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key_for_other (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, mapped, valid);
|
||||
|
||||
std::multimap<std::vector<std::pair<size_t, size_t> >, std::pair<const db::SubCircuit *, size_t> >::iterator scm = subcircuit_map.find (k);
|
||||
|
||||
if (! mapped || scm == subcircuit_map.end ()) {
|
||||
if (! mapped || scm == subcircuit_map.end () || scm->first != k) {
|
||||
|
||||
if (mp_logger) {
|
||||
unmatched_b.push_back (std::make_pair (k, sc.operator-> ()));
|
||||
|
|
|
|||
|
|
@ -287,6 +287,26 @@ public:
|
|||
return m_max_n_branch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a value indicating depth-first traversal
|
||||
*
|
||||
* With depth first (the default), the algorithm looks for further identities before moving to another
|
||||
* node. With breadth first (false), the algorithm will work in "waves" rather than digging deerly
|
||||
* into the direction of a node.
|
||||
*/
|
||||
void set_depth_first (bool df)
|
||||
{
|
||||
m_depth_first = df;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating depth-first traversal
|
||||
*/
|
||||
bool depth_first () const
|
||||
{
|
||||
return m_depth_first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the list of circuits without matching circuit in the other netlist
|
||||
* The result can be used to flatten these circuits prior to compare.
|
||||
|
|
@ -341,6 +361,7 @@ protected:
|
|||
double m_res_threshold;
|
||||
size_t m_max_n_branch;
|
||||
size_t m_max_depth;
|
||||
bool m_depth_first;
|
||||
bool m_dont_consider_net_names;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1147,8 +1147,8 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses)
|
|||
"begin_circuit BUF BUF\n"
|
||||
"match_nets INT $10\n"
|
||||
"match_nets IN IN\n"
|
||||
"net_mismatch OUT OUT\n"
|
||||
"net_mismatch INT2 $11\n"
|
||||
"net_mismatch OUT OUT\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
|
|
@ -1212,8 +1212,35 @@ TEST(6_BufferTwoPathsAdditionalResistor)
|
|||
"begin_circuit BUF BUF\n"
|
||||
"net_mismatch INT $10\n"
|
||||
"match_nets IN IN\n"
|
||||
"net_mismatch INT2 $11\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
"match_pins $3 $2\n"
|
||||
"match_devices $1 $1\n"
|
||||
"match_devices $3 $2\n"
|
||||
"match_devices $5 $3\n"
|
||||
"match_devices $7 $4\n"
|
||||
"match_devices $2 $5\n"
|
||||
"match_devices $4 $6\n"
|
||||
"match_devices $6 $7\n"
|
||||
"match_devices $8 $8\n"
|
||||
"device_mismatch (null) $9\n"
|
||||
"end_circuit BUF BUF NOMATCH"
|
||||
);
|
||||
EXPECT_EQ (good, false);
|
||||
|
||||
comp.set_depth_first (false);
|
||||
logger.clear ();
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit BUF BUF\n"
|
||||
"net_mismatch INT $10\n"
|
||||
"match_nets OUT OUT\n"
|
||||
"net_mismatch INT2 $11\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
|
|
@ -1274,9 +1301,9 @@ TEST(6_BufferTwoPathsAdditionalDevices)
|
|||
"match_nets INT $11\n"
|
||||
"net_mismatch VDD VDD\n"
|
||||
"match_nets IN IN\n"
|
||||
"net_mismatch INT2 $10\n"
|
||||
"net_mismatch VSS VSS\n"
|
||||
"net_mismatch OUT OUT\n"
|
||||
"net_mismatch INT2 $10\n"
|
||||
"match_pins $0 $1\n"
|
||||
"match_pins $1 $3\n"
|
||||
"match_pins $2 $0\n"
|
||||
|
|
@ -2679,6 +2706,57 @@ TEST(17_InherentlyAmbiguousDecoder)
|
|||
);
|
||||
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
comp.set_depth_first (false);
|
||||
logger.clear ();
|
||||
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 VSS VSS\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_nets NA NA\n"
|
||||
"match_nets NB NB\n"
|
||||
"match_nets B B\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"
|
||||
"match_pins $3 $3\n"
|
||||
"match_pins $4 $4\n"
|
||||
"match_pins $5 $5\n"
|
||||
"match_pins $6 $6\n"
|
||||
"match_pins $7 $7\n"
|
||||
"match_subcircuits $1 $1\n"
|
||||
"match_subcircuits $2 $2\n"
|
||||
"match_subcircuits $4 $3\n"
|
||||
"match_subcircuits $6 $4\n"
|
||||
"match_subcircuits $3 $5\n"
|
||||
"match_subcircuits $5 $6\n"
|
||||
"end_circuit DECODER DECODER MATCH"
|
||||
);
|
||||
|
||||
EXPECT_EQ (good, true);
|
||||
}
|
||||
|
||||
TEST(18_ClockTree)
|
||||
|
|
@ -2794,6 +2872,67 @@ TEST(18_ClockTree)
|
|||
"end_circuit TXEE TXEE MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
comp.set_depth_first (false);
|
||||
logger.clear ();
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
txt = logger.text ();
|
||||
// because L/R matching is ambiguous, we need to do this to
|
||||
// establish reproducability on different platforms:
|
||||
txt = tl::replaced (txt, "L", "X");
|
||||
txt = tl::replaced (txt, "R", "X");
|
||||
|
||||
EXPECT_EQ (txt,
|
||||
"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 TXEE TXEE\n"
|
||||
"match_nets IN IN\n"
|
||||
"match_nets VSS VSS\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_nets S S\n"
|
||||
"match_ambiguous_nets SX SX\n"
|
||||
"match_ambiguous_nets SX SX\n"
|
||||
"match_ambiguous_nets SXX SXX\n"
|
||||
"match_ambiguous_nets SXX SXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXX SXX\n"
|
||||
"match_ambiguous_nets SXX SXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_ambiguous_nets SXXX SXXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TX TX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TXX TXX\n"
|
||||
"match_subcircuits TXX TXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits T T\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TX TX\n"
|
||||
"match_subcircuits TXX TXX\n"
|
||||
"match_subcircuits TXXX TXXX\n"
|
||||
"match_subcircuits TXX TXX\n"
|
||||
"end_circuit TXEE TXEE MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
}
|
||||
|
||||
TEST(19_SymmetricCircuit)
|
||||
|
|
@ -2924,8 +3063,8 @@ TEST(19_SymmetricCircuit)
|
|||
"match_nets $14 WELL\n"
|
||||
"match_nets nn2 NN2\n"
|
||||
"match_nets nn2_ NN2_\n"
|
||||
"match_nets q0 Q0\n"
|
||||
"match_nets q1 Q1\n"
|
||||
"match_ambiguous_nets q0 Q0\n"
|
||||
"match_ambiguous_nets q1 Q1\n"
|
||||
"match_nets $11 CS0\n"
|
||||
"match_nets q0_ Q0_\n"
|
||||
"match_nets $6 NET181\n"
|
||||
|
|
@ -3002,6 +3141,105 @@ TEST(19_SymmetricCircuit)
|
|||
"end_circuit DECODE DECODE MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
comp.set_depth_first (false);
|
||||
logger.clear ();
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
EXPECT_EQ (logger.text (),
|
||||
"begin_circuit DECODE DECODE\n"
|
||||
"match_nets $41 WL1_EN_\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_nets $39 NET194\n"
|
||||
"match_nets g0 G0\n"
|
||||
"match_nets $40 HNET52\n"
|
||||
"match_nets VSS VSS\n"
|
||||
"match_nets $42 NET189\n"
|
||||
"match_nets gtp NN3\n"
|
||||
"match_nets $37 NET193\n"
|
||||
"match_nets g1 G1\n"
|
||||
"match_nets $44 YI\n"
|
||||
"match_nets $14 WELL\n"
|
||||
"match_nets nn2 NN2\n"
|
||||
"match_nets nn2_ NN2_\n"
|
||||
"match_ambiguous_nets q0 Q0\n"
|
||||
"match_ambiguous_nets q1 Q1\n"
|
||||
"match_nets $11 CS0\n"
|
||||
"match_nets q0_ Q0_\n"
|
||||
"match_nets $4 NET200\n"
|
||||
"match_nets $13 CS1\n"
|
||||
"match_nets q1_ Q1_\n"
|
||||
"match_nets $9 NET175\n"
|
||||
"match_nets a0 A0\n"
|
||||
"match_nets a0_ A0_\n"
|
||||
"match_nets $35 HNET44\n"
|
||||
"match_nets $34 HNET48\n"
|
||||
"match_nets $6 NET181\n"
|
||||
"match_nets $8 NET215\n"
|
||||
"match_nets nn1 NN1\n"
|
||||
"match_nets nn1_ NN1_\n"
|
||||
"match_pins VDD VDD\n"
|
||||
"match_pins nn1_ NN1_\n"
|
||||
"match_pins nn1 NN1\n"
|
||||
"match_pins q0 Q0\n"
|
||||
"match_pins q0_ Q0_\n"
|
||||
"match_pins q1_ Q1_\n"
|
||||
"match_pins q1 Q1\n"
|
||||
"match_pins nn2 NN2\n"
|
||||
"match_pins nn2_ NN2_\n"
|
||||
"match_pins a0 A0\n"
|
||||
"match_pins a0_ A0_\n"
|
||||
"match_pins g1 G1\n"
|
||||
"match_pins g0 G0\n"
|
||||
"match_pins gtp NN3\n"
|
||||
"match_pins VSS VSS\n"
|
||||
"match_pins WELL WELL\n"
|
||||
"match_devices $30 0\n"
|
||||
"match_devices $29 1\n"
|
||||
"match_devices $9 10\n"
|
||||
"match_devices $10 11\n"
|
||||
"match_devices $36 12\n"
|
||||
"match_devices $35 13\n"
|
||||
"match_devices $34 14\n"
|
||||
"match_devices $38 15\n"
|
||||
"match_devices $37 16\n"
|
||||
"match_devices $33 17\n"
|
||||
"match_devices $27 18\n"
|
||||
"match_devices $28 19\n"
|
||||
"match_devices $17 2\n"
|
||||
"match_devices $31 20\n"
|
||||
"match_devices $32 21\n"
|
||||
"match_devices $22 22\n"
|
||||
"match_devices $26 23\n"
|
||||
"match_devices $23 24\n"
|
||||
"match_devices $43 25\n"
|
||||
"match_devices $20 26\n"
|
||||
"match_devices $25 27\n"
|
||||
"match_devices $15 28\n"
|
||||
"match_devices $14 29\n"
|
||||
"match_devices $16 3\n"
|
||||
"match_devices $18 30\n"
|
||||
"match_devices $21 31\n"
|
||||
"match_devices $13 32\n"
|
||||
"match_devices $19 33\n"
|
||||
"match_devices $7 34\n"
|
||||
"match_devices $8 35\n"
|
||||
"match_devices $24 36\n"
|
||||
"match_devices $3 37\n"
|
||||
"match_devices $6 38\n"
|
||||
"match_devices $4 39\n"
|
||||
"match_devices $39 4\n"
|
||||
"match_devices $5 40\n"
|
||||
"match_devices $2 41\n"
|
||||
"match_devices $1 42\n"
|
||||
"match_devices $40 5\n"
|
||||
"match_devices $11 6\n"
|
||||
"match_devices $12 7\n"
|
||||
"match_devices $41 8\n"
|
||||
"match_devices $42 9\n"
|
||||
"end_circuit DECODE DECODE MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
}
|
||||
|
||||
TEST(20_BusLikeConnections)
|
||||
|
|
@ -3576,7 +3814,7 @@ TEST(23_NodesRemovedWithError)
|
|||
"pin_mismatch (null) BULK\n"
|
||||
"pin_mismatch (null) $6\n"
|
||||
"match_subcircuits $1 $1\n"
|
||||
"match_subcircuits $2 $2\n"
|
||||
"subcircuit_mismatch $2 $2\n"
|
||||
"end_circuit INV2PAIR INV2PAIR NOMATCH\n"
|
||||
"circuit_skipped RINGO RINGO"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -850,7 +850,7 @@ xref(
|
|||
device(1 1 match)
|
||||
)
|
||||
)
|
||||
circuit(ND2X1 ND2X1 match
|
||||
circuit(ND2X1 ND2X1 nomatch
|
||||
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(3 3 mismatch)
|
||||
device(4 4 match)
|
||||
device(1 1 match)
|
||||
device(2 2 match)
|
||||
device(1 1 mismatch)
|
||||
)
|
||||
)
|
||||
circuit(RINGO RINGO match
|
||||
|
|
|
|||
Loading…
Reference in New Issue