mirror of https://github.com/KLayout/klayout.git
Netlist compare: Ambiguity resolution through name matching now default (can be turned off) (#594)
* WIP: some refactoring * WIP: some refactoring * Netlist compare: introducing ambiguity resolution by net names By default now net names are used for resolving ambiguities. If net names match, they will be used to associate nets if the choice is ambiguous. This is usually much faster and more reliable than trying to resolve ambiguities through topology analysis. This feature can be disabled using "consider_net_names(false)" in the LVS script. * Some refactoring, Jenkinsfile modified for better test coverage
This commit is contained in:
parent
e744eb32d1
commit
b413cb9d74
|
|
@ -16,6 +16,7 @@ node("master") {
|
|||
stage("Checkout sources") {
|
||||
|
||||
checkout scm
|
||||
checkout_private()
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@ class NetGraph;
|
|||
struct CompareData
|
||||
{
|
||||
CompareData ()
|
||||
: other (0), max_depth (0), max_n_branch (0), depth_first (true), dont_consider_net_names (false), logger (0),
|
||||
: other (0), max_depth (0), max_n_branch (0), depth_first (true), dont_consider_net_names (false), with_ambiguous (false), logger (0),
|
||||
circuit_pin_mapper (0), subcircuit_equivalence (0), device_equivalence (0), progress (0)
|
||||
{ }
|
||||
|
||||
|
|
@ -625,6 +625,7 @@ struct CompareData
|
|||
size_t max_n_branch;
|
||||
bool depth_first;
|
||||
bool dont_consider_net_names;
|
||||
bool with_ambiguous;
|
||||
NetlistCompareLogger *logger;
|
||||
CircuitPinMapper *circuit_pin_mapper;
|
||||
SubCircuitEquivalenceTracker *subcircuit_equivalence;
|
||||
|
|
@ -967,6 +968,9 @@ struct CompareNodePtr
|
|||
};
|
||||
|
||||
class TentativeNodeMapping;
|
||||
struct NodeRange;
|
||||
class DeviceMapperForTargetNode;
|
||||
class SubCircuitMapperForTargetNode;
|
||||
|
||||
std::string indent (size_t depth)
|
||||
{
|
||||
|
|
@ -1112,20 +1116,16 @@ public:
|
|||
*
|
||||
* If "tentative" is non-null, assignments will be recorded in the TentativeMapping
|
||||
* audit object and can be undone afterwards when backtracking recursion happens.
|
||||
*
|
||||
* If "with_ambiguous" is true, ambiguous matches are considered. This will happen
|
||||
* in a second pass to give exact and unique matches priority over ambiguous matches.
|
||||
*/
|
||||
size_t derive_node_identities (size_t net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
|
||||
size_t derive_node_identities (size_t net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data);
|
||||
|
||||
/**
|
||||
* @brief The backtracking driver
|
||||
*
|
||||
* This method will analyze the given nodes and call "derive_node_identities" for all nodes
|
||||
* with a proposed identity. With "with_ambiguous", amiguities are resolved by trying
|
||||
* different combinations in tentative mode and deciding for one combination if possible.
|
||||
* with a proposed identity.
|
||||
*/
|
||||
size_t derive_node_identities_from_node_set (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &nodes, std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data);
|
||||
size_t derive_node_identities_from_node_set (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &nodes, std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data);
|
||||
|
||||
private:
|
||||
std::vector<NetGraphNode> m_nodes;
|
||||
|
|
@ -1133,7 +1133,9 @@ private:
|
|||
std::map<const db::Net *, size_t> m_net_index;
|
||||
const db::Circuit *mp_circuit;
|
||||
|
||||
size_t 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 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, CompareData *data);
|
||||
size_t derive_node_identities_from_ambiguity_group (const NodeRange &nr, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data);
|
||||
size_t derive_node_identities_from_singular_match (const NetGraphNode *n, const NetGraphNode::edge_iterator &e, const NetGraphNode *n_other, const NetGraphNode::edge_iterator &e_other, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data, bool consider_net_names);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -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)
|
||||
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, CompareData *data)
|
||||
{
|
||||
// NOTE: we can skip edges to known nodes because we did a pre-analysis making sure those are compatible
|
||||
|
||||
|
|
@ -2029,7 +2031,7 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
// 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);
|
||||
size_t bt_count = derive_node_identities_from_node_set (nodes, other_nodes, depth, n_branch, tentative, data);
|
||||
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
|
|
@ -2064,7 +2066,7 @@ static bool has_subcircuits (db::NetGraphNode::edge_iterator e, db::NetGraphNode
|
|||
}
|
||||
|
||||
size_t
|
||||
NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
|
||||
NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data)
|
||||
{
|
||||
NetGraphNode *n = & node (net_index);
|
||||
|
||||
|
|
@ -2221,7 +2223,7 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
++ee_other;
|
||||
}
|
||||
|
||||
size_t bt_count = derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, other_net_index, depth, n_branch, tentative, with_ambiguous, data);
|
||||
size_t bt_count = derive_node_identities_for_edges (e, ee, e_other, ee_other, net_index, other_net_index, depth, n_branch, tentative, data);
|
||||
if (bt_count == failed_match) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair.";
|
||||
|
|
@ -2260,7 +2262,7 @@ namespace {
|
|||
|
||||
}
|
||||
|
||||
static void sort_node_range_by_best_match (NodeRange &nr)
|
||||
static void sort_node_range_by_best_match (const NodeRange &nr)
|
||||
{
|
||||
std::stable_sort (nr.n1, nr.nn1, SortNodeByNet ());
|
||||
std::stable_sort (nr.n2, nr.nn2, SortNodeByNet ());
|
||||
|
|
@ -2319,9 +2321,20 @@ static bool net_names_are_different (const db::Net *a, const db::Net *b)
|
|||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &nodes, std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
|
||||
static bool net_names_are_equal (const db::Net *a, const db::Net *b)
|
||||
{
|
||||
if (! a || ! b || a->name ().empty () || b->name ().empty ()) {
|
||||
return false;
|
||||
} else {
|
||||
return name_compare (a->name (), b->name ()) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
NetGraph::derive_node_identities_from_ambiguity_group (const NodeRange &nr, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data)
|
||||
{
|
||||
tl::AbsoluteProgress progress (tl::to_string (tr ("Deriving match for ambiguous net group")));
|
||||
|
||||
std::string indent_s;
|
||||
if (options ()->debug_netcompare) {
|
||||
indent_s = indent (depth);
|
||||
|
|
@ -2329,6 +2342,294 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
}
|
||||
|
||||
size_t new_nodes = 0;
|
||||
size_t complexity = nr.num;
|
||||
|
||||
// sort the ambiguity group such that net names match best
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
|
||||
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
|
||||
|
||||
sort_node_range_by_best_match (nr);
|
||||
|
||||
{
|
||||
|
||||
// marks the nodes from the ambiguity group as unknown so we don't revisit them (causing deep recursion)
|
||||
TentativeNodeMapping tn2unknown;
|
||||
|
||||
// collect and mark the ambiguity combinations to consider
|
||||
std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator> iters1, iters2;
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i1 = nr.n1; i1 != nr.nn1; ++i1) {
|
||||
if (! i1->first->has_any_other ()) {
|
||||
iters1.push_back (i1);
|
||||
size_t ni = node_index_for_net (i1->first->net ());
|
||||
TentativeNodeMapping::map_to_unknown (&tn2unknown, this, ni);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i2 = nr.n2; i2 != nr.nn2; ++i2) {
|
||||
if (! i2->first->has_any_other ()) {
|
||||
iters2.push_back (i2);
|
||||
size_t other_ni = data->other->node_index_for_net (i2->first->net ());
|
||||
TentativeNodeMapping::map_to_unknown (&tn2unknown, data->other, other_ni);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator>::const_iterator ii1 = iters1.begin (); ii1 != iters1.end (); ++ii1) {
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i1 = *ii1;
|
||||
|
||||
bool any = false;
|
||||
std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator>::iterator to_remove = iters2.end ();
|
||||
|
||||
for (std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator>::iterator ii2 = iters2.begin (); ii2 != iters2.end (); ++ii2) {
|
||||
|
||||
++progress;
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i2 = *ii2;
|
||||
|
||||
// try this candidate in tentative mode
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "trying in tentative mode: " << i1->first->net ()->expanded_name () << " vs. " << i2->first->net ()->expanded_name ();
|
||||
}
|
||||
|
||||
if (! edges_are_compatible (*i1->second, *i2->second, *data->device_equivalence, *data->subcircuit_equivalence)) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "=> rejected because edges are incompatible with already established device or subcircuit equivalences";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! data->dont_consider_net_names && net_names_are_equal (i1->first->net (), i2->first->net ())) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "=> accepted for identical names";
|
||||
}
|
||||
|
||||
// utilize net names to propose a match
|
||||
new_nodes += 1;
|
||||
pairs.push_back (std::make_pair (i1->first, i2->first));
|
||||
to_remove = ii2;
|
||||
any = true;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
size_t ni = node_index_for_net (i1->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (i2->first->net ());
|
||||
|
||||
TentativeNodeMapping tn;
|
||||
TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, complexity * n_branch, &tn, data);
|
||||
|
||||
if (bt_count != failed_match) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "match found";
|
||||
}
|
||||
// we have a match ...
|
||||
|
||||
if (any) {
|
||||
|
||||
// there is already a known pair, so we can mark *i2 and the previous *i2 as equivalent
|
||||
// (makes them ambiguous)
|
||||
equivalent_other_nodes.same (i2->first, pairs.back ().second);
|
||||
// we know enough now ...
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// identified a new pair
|
||||
new_nodes += bt_count + 1;
|
||||
pairs.push_back (std::make_pair (i1->first, i2->first));
|
||||
to_remove = ii2;
|
||||
any = true;
|
||||
|
||||
// no ambiguity analysis in tentative mode - we can stop now
|
||||
if (tentative) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (to_remove != iters2.end ()) {
|
||||
iters2.erase (to_remove);
|
||||
}
|
||||
|
||||
if (! any && tentative) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "mismatch.";
|
||||
}
|
||||
// a mismatch - stop here.
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! tentative) {
|
||||
|
||||
// issue the matching pairs
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (p->second->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (0, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (equivalent_other_nodes.has_attribute (p->second)) {
|
||||
tl::info << indent_s << "deduced ambiguous match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||
} else {
|
||||
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) {
|
||||
data->logger->match_ambiguous_nets (p->first->net (), p->second->net ());
|
||||
} else {
|
||||
data->logger->match_nets (p->first->net (), p->second->net ());
|
||||
}
|
||||
}
|
||||
|
||||
++*data->progress;
|
||||
|
||||
}
|
||||
|
||||
// And seek further from these pairs
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, complexity * n_branch, tentative, data);
|
||||
tl_assert (bt_count != failed_match);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (p->second->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new_nodes;
|
||||
}
|
||||
|
||||
size_t
|
||||
NetGraph::derive_node_identities_from_singular_match (const NetGraphNode *n, const NetGraphNode::edge_iterator &e, const NetGraphNode *n_other, const NetGraphNode::edge_iterator &e_other, DeviceMapperForTargetNode &dm, DeviceMapperForTargetNode &dm_other, SubCircuitMapperForTargetNode &scm, SubCircuitMapperForTargetNode &scm_other, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data, bool consider_net_names)
|
||||
{
|
||||
std::string indent_s;
|
||||
if (options ()->debug_netcompare) {
|
||||
indent_s = indent (depth);
|
||||
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||
}
|
||||
|
||||
if (! edges_are_compatible (*e, *e_other, *data->device_equivalence, *data->subcircuit_equivalence)) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected because edges are incompatible with already established device or subcircuit equivalences";
|
||||
}
|
||||
return tentative ? failed_match : 0;
|
||||
|
||||
} else if (! n->has_any_other () && ! n_other->has_any_other ()) {
|
||||
|
||||
// in tentative mode, reject this choice if both nets are named and
|
||||
// their names differ -> this favors net matching by name
|
||||
|
||||
if (tentative && consider_net_names && net_names_are_different (n->net (), n_other->net ())) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "rejecting pair as names are not identical: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
// A single candiate: just take this one -> this may render
|
||||
// inexact matches, but further propagates net pairing
|
||||
|
||||
size_t ni = node_index_for_net (n->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (n_other->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "deduced match (singular): " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
}
|
||||
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 (n->net (), n_other->net ());
|
||||
} else {
|
||||
data->logger->match_nets (n->net (), n_other->net ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t new_nodes = 1;
|
||||
|
||||
if (data->depth_first || tentative) {
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, n_branch, tentative, data);
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
return failed_match;
|
||||
}
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
}
|
||||
}
|
||||
|
||||
return new_nodes;
|
||||
|
||||
} else if (n->has_unknown_other ()) {
|
||||
|
||||
// accept any other net
|
||||
return 0;
|
||||
|
||||
} else if (n->has_other ()) {
|
||||
|
||||
// this decision leads to a contradiction
|
||||
if (data->other->node_index_for_net (n_other->net ()) != n->other_net_index ()) {
|
||||
return failed_match;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// mismatch of assignment state
|
||||
return failed_match;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &nodes, std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> > &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, CompareData *data)
|
||||
{
|
||||
std::string indent_s;
|
||||
if (options ()->debug_netcompare) {
|
||||
indent_s = indent (depth);
|
||||
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||
}
|
||||
|
||||
if (depth > data->max_depth) {
|
||||
if (options ()->debug_netcompare) {
|
||||
|
|
@ -2353,81 +2654,15 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
|
||||
if (nodes.size () == 1 && other_nodes.size () == 1) {
|
||||
|
||||
const NetGraphNode *n = nodes.front ().first;
|
||||
const NetGraphNode *n_other = other_nodes.front ().first;
|
||||
|
||||
// reject the transition if the edges provide a contradiction to already established equivalences
|
||||
|
||||
if (! edges_are_compatible (*nodes.front ().second, *other_nodes.front ().second, *data->device_equivalence, *data->subcircuit_equivalence)) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected because edges are incompatible with already established device or subcircuit equivalences";
|
||||
}
|
||||
return tentative ? failed_match : 0;
|
||||
|
||||
} else if (! n->has_any_other () && ! n_other->has_any_other ()) {
|
||||
|
||||
// a single candiate: just take this one -> this may render
|
||||
// inexact matches, but further propagates net pairing
|
||||
|
||||
size_t ni = node_index_for_net (n->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (n_other->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "deduced match (singular): " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||
}
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (n->has_unknown_other ()) {
|
||||
|
||||
// accept this solution as the pairing is possible
|
||||
|
||||
} else if (n->has_other ()) {
|
||||
|
||||
// this decision leads to a contradiction
|
||||
if (data->other->node_index_for_net (n_other->net ()) != n->other_net_index ()) {
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// mismatch of assignment state
|
||||
return failed_match;
|
||||
|
||||
}
|
||||
|
||||
return new_nodes;
|
||||
return derive_node_identities_from_singular_match (nodes.front ().first, nodes.front ().second, other_nodes.front ().first, other_nodes.front ().second,
|
||||
dm, dm_other, scm, scm_other, depth, n_branch, tentative, data, false /*don't consider net names*/);
|
||||
|
||||
}
|
||||
|
||||
// Determine the range of nodes with same identity
|
||||
|
||||
std::vector<NodeRange> node_ranges;
|
||||
size_t new_nodes = 0;
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::iterator n1 = nodes.begin ();
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::iterator n2 = other_nodes.begin ();
|
||||
|
|
@ -2469,13 +2704,13 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
}
|
||||
}
|
||||
|
||||
if (num == 1 || with_ambiguous) {
|
||||
if (num == 1 || data->with_ambiguous) {
|
||||
node_ranges.push_back (NodeRange (num, n1, nn1, n2, nn2));
|
||||
}
|
||||
|
||||
// in tentative mode ambiguous nodes don't make a match without
|
||||
// with_ambiguous
|
||||
if (num > 1 && tentative && ! with_ambiguous) {
|
||||
if (num > 1 && tentative && ! data->with_ambiguous) {
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -2484,7 +2719,7 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
|
||||
}
|
||||
|
||||
if (with_ambiguous) {
|
||||
if (data->with_ambiguous) {
|
||||
std::stable_sort (node_ranges.begin (), node_ranges.end ());
|
||||
}
|
||||
|
||||
|
|
@ -2523,79 +2758,13 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
|
||||
} else if (nr->num == 1) {
|
||||
|
||||
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
|
||||
|
||||
if (tentative && ! data->dont_consider_net_names && net_names_are_different (nr->n1->first->net (), nr->n2->first->net ())) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "rejecting pair as names are not identical: " << nr->n1->first->net ()->expanded_name () << " vs. " << nr->n2->first->net ()->expanded_name ();
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
// A single candiate: just take this one -> this may render
|
||||
// inexact matches, but further propagates net pairing
|
||||
|
||||
size_t ni = node_index_for_net (nr->n1->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (nr->n2->first->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "deduced match (singular): " << nr->n1->first->net ()->expanded_name () << " vs. " << nr->n2->first->net ()->expanded_name ();
|
||||
}
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
} else if (nr->n1->first->has_other ()) {
|
||||
|
||||
// this decision leads to a contradiction
|
||||
if (data->other->node_index_for_net (nr->n2->first->net ()) != nr->n1->first->other_net_index ()) {
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// mismatch of assignment state
|
||||
size_t n = derive_node_identities_from_singular_match (nr->n1->first, nr->n1->second, nr->n2->first, nr->n2->second, dm, dm_other, scm, scm_other, depth, n_branch, tentative, data, ! data->dont_consider_net_names);
|
||||
if (n == failed_match) {
|
||||
return failed_match;
|
||||
|
||||
}
|
||||
|
||||
new_nodes += n;
|
||||
|
||||
} else if (nr->num * n_branch > data->max_n_branch) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
|
|
@ -2609,168 +2778,12 @@ NetGraph::derive_node_identities_from_node_set (std::vector<std::pair<const NetG
|
|||
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
||||
}
|
||||
|
||||
// sort the ambiguity group such that net names match best
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> > pairs;
|
||||
tl::equivalence_clusters<const NetGraphNode *> equivalent_other_nodes;
|
||||
std::set<const NetGraphNode *> seen;
|
||||
|
||||
if (! data->dont_consider_net_names) {
|
||||
sort_node_range_by_best_match (*nr);
|
||||
size_t n = derive_node_identities_from_ambiguity_group (*nr, dm, dm_other, scm, scm_other, depth, n_branch, tentative, data);
|
||||
if (n == failed_match) {
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
// marks the nodes from the ambiguity group as unknown so we don't revisit them (causing deep recursion)
|
||||
TentativeNodeMapping tn2unknown;
|
||||
|
||||
// collect and mark the ambiguity combinations to consider
|
||||
std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator> iters1, iters2;
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i1 = nr->n1; i1 != nr->nn1; ++i1) {
|
||||
if (! i1->first->has_any_other ()) {
|
||||
iters1.push_back (i1);
|
||||
size_t ni = node_index_for_net (i1->first->net ());
|
||||
TentativeNodeMapping::map_to_unknown (&tn2unknown, this, ni);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i2 = nr->n2; i2 != nr->nn2; ++i2) {
|
||||
if (! i2->first->has_any_other ()) {
|
||||
iters2.push_back (i2);
|
||||
size_t other_ni = data->other->node_index_for_net (i2->first->net ());
|
||||
TentativeNodeMapping::map_to_unknown (&tn2unknown, data->other, other_ni);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator>::const_iterator ii1 = iters1.begin (); ii1 != iters1.end (); ++ii1) {
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i1 = *ii1;
|
||||
|
||||
bool any = false;
|
||||
|
||||
for (std::vector<std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator>::const_iterator ii2 = iters2.begin (); ii2 != iters2.end (); ++ii2) {
|
||||
|
||||
std::vector<std::pair<const NetGraphNode *, NetGraphNode::edge_iterator> >::const_iterator i2 = *ii2;
|
||||
|
||||
if (seen.find (i2->first) != seen.end ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// try this candidate in tentative mode
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "trying in tentative mode: " << i1->first->net ()->expanded_name () << " vs. " << i2->first->net ()->expanded_name ();
|
||||
}
|
||||
|
||||
if (! edges_are_compatible (*i1->second, *i2->second, *data->device_equivalence, *data->subcircuit_equivalence)) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "=> rejected because edges are incompatible with already established device or subcircuit equivalences";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t ni = node_index_for_net (i1->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (i2->first->net ());
|
||||
|
||||
TentativeNodeMapping tn;
|
||||
TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
||||
|
||||
if (bt_count != failed_match) {
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "match found";
|
||||
}
|
||||
// we have a match ...
|
||||
|
||||
if (any) {
|
||||
|
||||
// there is already a known pair, so we can mark *i2 and the previous *i2 as equivalent
|
||||
// (makes them ambiguous)
|
||||
equivalent_other_nodes.same (i2->first, pairs.back ().second);
|
||||
|
||||
} else {
|
||||
|
||||
// identified a new pair
|
||||
new_nodes += bt_count + 1;
|
||||
pairs.push_back (std::make_pair (i1->first, i2->first));
|
||||
seen.insert (i2->first);
|
||||
any = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! any && tentative) {
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "mismatch.";
|
||||
}
|
||||
// a mismatch - stop here.
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! tentative) {
|
||||
|
||||
// issue the matching pairs
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (p->second->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (0, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
if (equivalent_other_nodes.has_attribute (p->second)) {
|
||||
tl::info << indent_s << "deduced ambiguous match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||
} else {
|
||||
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) {
|
||||
data->logger->match_ambiguous_nets (p->first->net (), p->second->net ());
|
||||
} else {
|
||||
data->logger->match_nets (p->first->net (), p->second->net ());
|
||||
}
|
||||
}
|
||||
|
||||
++*data->progress;
|
||||
|
||||
}
|
||||
|
||||
// And seek further from these pairs
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, tentative, with_ambiguous, data);
|
||||
tl_assert (bt_count != failed_match);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (std::vector<std::pair<const NetGraphNode *, const NetGraphNode *> >::const_iterator p = pairs.begin (); p != pairs.end (); ++p) {
|
||||
|
||||
size_t ni = node_index_for_net (p->first->net ());
|
||||
size_t other_ni = data->other->node_index_for_net (p->second->net ());
|
||||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni, dm, dm_other, *data->device_equivalence, scm, scm_other, *data->subcircuit_equivalence, depth);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
new_nodes += n;
|
||||
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
||||
|
|
@ -3471,13 +3484,14 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
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.with_ambiguous = (pass > 0);
|
||||
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);
|
||||
size_t ni = g1.derive_node_identities (i1 - g1.begin (), 0, 1, 0 /*not tentative*/, &data);
|
||||
if (ni > 0 && ni != failed_match) {
|
||||
new_identities += ni;
|
||||
if (options ()->debug_netcompare) {
|
||||
|
|
@ -3537,13 +3551,14 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
data.max_depth = m_max_depth;
|
||||
data.max_n_branch = m_max_n_branch;
|
||||
data.dont_consider_net_names = m_dont_consider_net_names;
|
||||
data.with_ambiguous = (pass > 0);
|
||||
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_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentatively*/, pass > 0 /*with ambiguities*/, &data);
|
||||
size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentatively*/, &data);
|
||||
if (ni > 0 && ni != failed_match) {
|
||||
new_identities += ni;
|
||||
if (options ()->debug_netcompare) {
|
||||
|
|
|
|||
|
|
@ -538,6 +538,18 @@ Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
|
|||
"@brief Gets the maximum branch complexity\n"
|
||||
"See \\max_branch_complexity= for details."
|
||||
) +
|
||||
gsi::method ("dont_consider_net_names=", &db::NetlistComparer::set_dont_consider_net_names, gsi::arg ("f"),
|
||||
"@brief Sets a value indicating whether net names shall not be considered\n"
|
||||
"If this value is set to true, net names will not be considered when resolving ambiguities.\n"
|
||||
"Not considering net names usually is more expensive. The default is 'false' indicating that\n"
|
||||
"net names will be considered for ambiguity resolution.\n"
|
||||
"\n"
|
||||
"This property has been introduced in version 0.26.7.\n"
|
||||
) +
|
||||
gsi::method ("dont_consider_net_names", &db::NetlistComparer::dont_consider_net_names,
|
||||
"@brief Gets a value indicating whether net names shall not be considered\n"
|
||||
"See \\dont_consider_net_names= for details."
|
||||
) +
|
||||
gsi::method_ext ("unmatched_circuits_a", &unmatched_circuits_a, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief Returns a list of circuits in A for which there is not corresponding circuit in B\n"
|
||||
"This list can be used to flatten these circuits so they do not participate in the compare process.\n"
|
||||
|
|
|
|||
|
|
@ -449,6 +449,7 @@ TEST(1_SimpleInverter)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -470,6 +471,7 @@ TEST(1_SimpleInverter)
|
|||
|
||||
db::NetlistCrossReference xref;
|
||||
db::NetlistComparer comp_xref (&xref);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
good = comp_xref.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -519,6 +521,7 @@ TEST(1_SimpleInverterMatchedDeviceClasses)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
comp.same_device_classes (nl1.device_class_by_name ("PMOS"), nl2.device_class_by_name ("PMOSB"));
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
|
@ -571,6 +574,7 @@ TEST(1_SimpleInverterSkippedDevices)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -594,6 +598,7 @@ TEST(1_SimpleInverterSkippedDevices)
|
|||
|
||||
db::NetlistCrossReference xref;
|
||||
db::NetlistComparer comp_xref (&xref);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
good = comp_xref.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -751,6 +756,8 @@ TEST(2_SimpleInverterWithForcedNetAssignment)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
const db::Circuit *ca = nl1.circuit_by_name ("INV");
|
||||
const db::Circuit *cb = nl2.circuit_by_name ("INV");
|
||||
comp.same_nets (ca->net_by_name ("VDD"), cb->net_by_name ("VDD"));
|
||||
|
|
@ -797,6 +804,7 @@ TEST(3_Buffer)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -852,6 +860,7 @@ TEST(4_BufferTwoPaths)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -912,6 +921,7 @@ TEST(5_BufferTwoPathsDifferentParameters)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
// Forcing the power nets into equality makes the parameter error harder to detect
|
||||
const db::Circuit *ca = nl1.circuit_by_name ("BUF");
|
||||
|
|
@ -1134,6 +1144,7 @@ TEST(5_BufferTwoPathsDifferentDeviceClasses)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
// NOTE: adding this power hint makes the device class error harder to detect
|
||||
const db::Circuit *ca = nl1.circuit_by_name ("BUF");
|
||||
|
|
@ -1199,6 +1210,7 @@ TEST(6_BufferTwoPathsAdditionalResistor)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
// Forcing the power nets into equality makes the resistor error harder to detect
|
||||
const db::Circuit *ca = nl1.circuit_by_name ("BUF");
|
||||
|
|
@ -1293,6 +1305,7 @@ TEST(6_BufferTwoPathsAdditionalDevices)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1345,6 +1358,7 @@ TEST(7_Resistors)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1386,6 +1400,7 @@ TEST(7_ResistorsParameterMismatch)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1428,6 +1443,7 @@ TEST(7_ResistorsPlusOneDevice)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1470,6 +1486,7 @@ TEST(8_Diodes)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1511,6 +1528,7 @@ TEST(8_DiodesDontMatchOnSwappedPins)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1558,6 +1576,7 @@ TEST(10_SimpleSubCircuits)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1620,6 +1639,7 @@ TEST(10_SimpleSubCircuitsMatchedNames)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
EXPECT_EQ (good, false);
|
||||
|
|
@ -1788,22 +1808,22 @@ TEST(11_MismatchingSubcircuits)
|
|||
// nets are now ambiguous
|
||||
EXPECT_EQ (xref2s (xref),
|
||||
"TOP:TOP [Match]:\n"
|
||||
" pin $0:$0 [Match]\n"
|
||||
" pin $1:$1 [Match]\n"
|
||||
" pin $2:$2 [Match]\n"
|
||||
" pin $0:$2 [Match]\n"
|
||||
" pin $1:$0 [Match]\n"
|
||||
" pin $2:$1 [Match]\n"
|
||||
" pin $3:$3 [Match]\n"
|
||||
" net IN:OUT [MatchWithWarning]\n"
|
||||
" pin $0:$0\n"
|
||||
" subcircuit_pin (null):$1[$3]\n"
|
||||
" net IN:IN [MatchWithWarning]\n"
|
||||
" pin $0:$2\n"
|
||||
" subcircuit_pin (null):$2[$1]\n"
|
||||
" subcircuit_pin $1[$0]:(null)\n"
|
||||
" net OUT:VDD [MatchWithWarning]\n"
|
||||
" pin $1:$1\n"
|
||||
" net OUT:OUT [MatchWithWarning]\n"
|
||||
" pin $1:$0\n"
|
||||
" subcircuit_pin (null):$1[$3]\n"
|
||||
" subcircuit_pin $2[$1]:(null)\n"
|
||||
" net VDD:VDD [MatchWithWarning]\n"
|
||||
" pin $2:$1\n"
|
||||
" subcircuit_pin (null):$1[$0]\n"
|
||||
" subcircuit_pin (null):$2[$0]\n"
|
||||
" subcircuit_pin $2[$1]:(null)\n"
|
||||
" net VDD:IN [MatchWithWarning]\n"
|
||||
" pin $2:$2\n"
|
||||
" subcircuit_pin (null):$2[$1]\n"
|
||||
" subcircuit_pin $1[$2]:(null)\n"
|
||||
" subcircuit_pin $2[$2]:(null)\n"
|
||||
" net VSS:VSS [MatchWithWarning]\n"
|
||||
|
|
@ -1845,6 +1865,7 @@ TEST(12_MismatchingSubcircuitsDuplicates)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1912,6 +1933,7 @@ TEST(13_MismatchingSubcircuitsAdditionalHierarchy)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -1979,6 +2001,7 @@ TEST(14_Subcircuit2Nand)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
comp.equivalent_pins (nl2.circuit_by_name ("NAND"), 0, 1);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
|
@ -2053,6 +2076,7 @@ TEST(14_Subcircuit2NandMismatchNoSwap)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
// intentionally missing: comp.equivalent_pins (nl2.circuit_by_name ("NAND"), 0, 1);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
|
@ -2204,6 +2228,7 @@ TEST(14_Subcircuit2MatchWithSwap)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
comp.equivalent_pins (nl2.circuit_by_name ("NAND"), 0, 1);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
|
@ -2283,6 +2308,7 @@ TEST(15_EmptySubCircuitTest)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -2358,6 +2384,7 @@ TEST(15_EmptySubCircuitWithoutPinNames)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -2440,6 +2467,7 @@ TEST(16_UniqueSubCircuitMatching)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -2813,6 +2841,7 @@ TEST(18_ClockTree)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (false);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -2822,6 +2851,68 @@ TEST(18_ClockTree)
|
|||
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_nets SX SX\n"
|
||||
"match_nets SX SX\n"
|
||||
"match_nets SXX SXX\n"
|
||||
"match_nets SXX SXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXX SXX\n"
|
||||
"match_nets SXX SXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_nets SXXX SXXX\n"
|
||||
"match_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);
|
||||
|
||||
logger.clear ();
|
||||
|
||||
comp.set_dont_consider_net_names (true);
|
||||
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"
|
||||
|
|
@ -3103,6 +3194,7 @@ TEST(19_SymmetricCircuit)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -3122,8 +3214,8 @@ TEST(19_SymmetricCircuit)
|
|||
"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 nn2 NN2\n"
|
||||
"match_ambiguous_nets nn2_ NN2_\n"
|
||||
"match_ambiguous_nets q0 Q0\n"
|
||||
"match_ambiguous_nets q1 Q1\n"
|
||||
"match_nets $11 CS0\n"
|
||||
|
|
@ -3221,8 +3313,8 @@ TEST(19_SymmetricCircuit)
|
|||
"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 nn2 NN2\n"
|
||||
"match_ambiguous_nets nn2_ NN2_\n"
|
||||
"match_ambiguous_nets q0 Q0\n"
|
||||
"match_ambiguous_nets q1 Q1\n"
|
||||
"match_nets $11 CS0\n"
|
||||
|
|
@ -3359,6 +3451,7 @@ TEST(20_BusLikeConnections)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -3503,6 +3596,153 @@ TEST(20_BusLikeConnections)
|
|||
"end_circuit TOP TOP MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
|
||||
logger.clear ();
|
||||
|
||||
comp.set_dont_consider_net_names (false);
|
||||
good = comp.compare (&nl1, &nl2);
|
||||
|
||||
txt = logger.text ();
|
||||
|
||||
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 INV8 INV8\n"
|
||||
"match_nets VSS VSS\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_ambiguous_nets IN1 A1\n"
|
||||
"match_ambiguous_nets IN2 A2\n"
|
||||
"match_ambiguous_nets IN3 A3\n"
|
||||
"match_ambiguous_nets IN4 A4\n"
|
||||
"match_ambiguous_nets IN5 A5\n"
|
||||
"match_ambiguous_nets IN6 A6\n"
|
||||
"match_ambiguous_nets IN7 A7\n"
|
||||
"match_ambiguous_nets IN8 A8\n"
|
||||
"match_nets OUT1 Q1\n"
|
||||
"match_nets OUT2 Q2\n"
|
||||
"match_nets OUT3 Q3\n"
|
||||
"match_nets OUT4 Q4\n"
|
||||
"match_nets OUT5 Q5\n"
|
||||
"match_nets OUT6 Q6\n"
|
||||
"match_nets OUT7 Q7\n"
|
||||
"match_nets OUT8 Q8\n"
|
||||
"match_pins IN1 A1\n"
|
||||
"match_pins OUT1 Q1\n"
|
||||
"match_pins IN2 A2\n"
|
||||
"match_pins OUT2 Q2\n"
|
||||
"match_pins IN3 A3\n"
|
||||
"match_pins OUT3 Q3\n"
|
||||
"match_pins IN4 A4\n"
|
||||
"match_pins OUT4 Q4\n"
|
||||
"match_pins IN5 A5\n"
|
||||
"match_pins OUT5 Q5\n"
|
||||
"match_pins IN6 A6\n"
|
||||
"match_pins OUT6 Q6\n"
|
||||
"match_pins IN7 A7\n"
|
||||
"match_pins OUT7 Q7\n"
|
||||
"match_pins IN8 A8\n"
|
||||
"match_pins OUT8 Q8\n"
|
||||
"match_pins VDD VDD\n"
|
||||
"match_pins VSS VSS\n"
|
||||
"match_subcircuits I1 I1\n"
|
||||
"match_subcircuits I8 I8\n"
|
||||
"match_subcircuits I3 I3\n"
|
||||
"match_subcircuits I7 I7\n"
|
||||
"match_subcircuits I4 I4\n"
|
||||
"match_subcircuits I2 I2\n"
|
||||
"match_subcircuits I6 I6\n"
|
||||
"match_subcircuits I5 I5\n"
|
||||
"end_circuit INV8 INV8 MATCH\n"
|
||||
"begin_circuit INV8_WRAP INV8_WRAP\n"
|
||||
"match_nets VSS VSS\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_nets IN8 A8\n"
|
||||
"match_nets OUT8 Q8\n"
|
||||
"match_nets IN7 A7\n"
|
||||
"match_nets OUT7 Q7\n"
|
||||
"match_nets IN6 A6\n"
|
||||
"match_nets OUT6 Q6\n"
|
||||
"match_nets IN5 A5\n"
|
||||
"match_nets OUT5 Q5\n"
|
||||
"match_nets IN4 A4\n"
|
||||
"match_nets OUT4 Q4\n"
|
||||
"match_nets IN3 A3\n"
|
||||
"match_nets OUT3 Q3\n"
|
||||
"match_nets IN2 A2\n"
|
||||
"match_nets OUT2 Q2\n"
|
||||
"match_nets IN1 A1\n"
|
||||
"match_nets OUT1 Q1\n"
|
||||
"match_pins IN1 A1\n"
|
||||
"match_pins OUT1 Q1\n"
|
||||
"match_pins IN2 A2\n"
|
||||
"match_pins OUT2 Q2\n"
|
||||
"match_pins IN3 A3\n"
|
||||
"match_pins OUT3 Q3\n"
|
||||
"match_pins IN4 A4\n"
|
||||
"match_pins OUT4 Q4\n"
|
||||
"match_pins IN5 A5\n"
|
||||
"match_pins OUT5 Q5\n"
|
||||
"match_pins IN6 A6\n"
|
||||
"match_pins OUT6 Q6\n"
|
||||
"match_pins IN7 A7\n"
|
||||
"match_pins OUT7 Q7\n"
|
||||
"match_pins IN8 A8\n"
|
||||
"match_pins OUT8 Q8\n"
|
||||
"match_pins VDD VDD\n"
|
||||
"match_pins VSS VSS\n"
|
||||
"match_subcircuits INV8 INV8\n"
|
||||
"end_circuit INV8_WRAP INV8_WRAP MATCH\n"
|
||||
"begin_circuit TOP TOP\n"
|
||||
"match_nets VSS VSS\n"
|
||||
"match_nets VDD VDD\n"
|
||||
"match_nets IN8 A8\n"
|
||||
"match_nets OUT8 Q8\n"
|
||||
"match_nets IN7 A7\n"
|
||||
"match_nets OUT7 Q7\n"
|
||||
"match_nets IN6 A6\n"
|
||||
"match_nets OUT6 Q6\n"
|
||||
"match_nets IN5 A5\n"
|
||||
"match_nets OUT5 Q5\n"
|
||||
"match_nets IN4 A4\n"
|
||||
"match_nets OUT4 Q4\n"
|
||||
"match_nets IN3 A3\n"
|
||||
"match_nets OUT3 Q3\n"
|
||||
"match_nets IN2 A2\n"
|
||||
"match_nets OUT2 Q2\n"
|
||||
"match_nets IN1 A1\n"
|
||||
"match_nets OUT1 Q1\n"
|
||||
"match_pins IN1 A1\n"
|
||||
"match_pins OUT1 Q1\n"
|
||||
"match_pins IN2 A2\n"
|
||||
"match_pins OUT2 Q2\n"
|
||||
"match_pins IN3 A3\n"
|
||||
"match_pins OUT3 Q3\n"
|
||||
"match_pins IN4 A4\n"
|
||||
"match_pins OUT4 Q4\n"
|
||||
"match_pins IN5 A5\n"
|
||||
"match_pins OUT5 Q5\n"
|
||||
"match_pins IN6 A6\n"
|
||||
"match_pins OUT6 Q6\n"
|
||||
"match_pins IN7 A7\n"
|
||||
"match_pins OUT7 Q7\n"
|
||||
"match_pins IN8 A8\n"
|
||||
"match_pins OUT8 Q8\n"
|
||||
"match_pins VDD VDD\n"
|
||||
"match_pins VSS VSS\n"
|
||||
"match_subcircuits INV8 INV8\n"
|
||||
"end_circuit TOP TOP MATCH"
|
||||
);
|
||||
EXPECT_EQ (good, true);
|
||||
}
|
||||
|
||||
TEST(21_BusLikeAmbiguousConnections)
|
||||
|
|
@ -3539,6 +3779,7 @@ TEST(21_BusLikeAmbiguousConnections)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -3711,6 +3952,7 @@ TEST(22_NodesRemoved)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -3831,6 +4073,7 @@ TEST(23_NodesRemovedWithError)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -3930,6 +4173,7 @@ TEST(24_NodesRemovedButConnectedInOther)
|
|||
|
||||
NetlistCompareTestLogger logger;
|
||||
db::NetlistComparer comp (&logger);
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
bool good = comp.compare (&nl1, &nl2);
|
||||
|
||||
|
|
@ -4021,6 +4265,7 @@ TEST(25_JoinSymmetricNets)
|
|||
|
||||
db::NetlistComparer comp;
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NAND2"));
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
// NOTE $1 and $2 are joined because they are symmetric
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
|
|
@ -4059,6 +4304,7 @@ TEST(25b_JoinSymmetricNetsMultiple)
|
|||
|
||||
db::NetlistComparer comp;
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NAND3"));
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
nl.combine_devices ();
|
||||
|
||||
|
|
@ -4098,6 +4344,7 @@ TEST(25c_JoinSymmetricNetsMultipleMessedUp)
|
|||
|
||||
db::NetlistComparer comp;
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NOR3"));
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
nl.combine_devices ();
|
||||
|
||||
|
|
@ -4137,6 +4384,7 @@ TEST(26_JoinSymmetricNets)
|
|||
|
||||
db::NetlistComparer comp;
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("RESCUBE"));
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
"circuit RESCUBE (A=A,B=B);\n"
|
||||
|
|
@ -4181,6 +4429,7 @@ TEST(27_DontJoinSymmetricNetsWithPins)
|
|||
|
||||
db::NetlistComparer comp;
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NAND2"));
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
// NOTE $1 and $2 are NOT joined because they have pins
|
||||
EXPECT_EQ (nl.to_string (),
|
||||
|
|
@ -4213,6 +4462,8 @@ TEST(28_NoSymmetryDetectionCases)
|
|||
prep_nl (nl, nls);
|
||||
|
||||
db::NetlistComparer comp;
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
std::string sref = nl.to_string ();
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NAND2"));
|
||||
|
||||
|
|
@ -4235,6 +4486,8 @@ TEST(28_NoSymmetryDetectionCases)
|
|||
prep_nl (nl, nls);
|
||||
|
||||
db::NetlistComparer comp;
|
||||
comp.set_dont_consider_net_names (true);
|
||||
|
||||
std::string sref = nl.to_string ();
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("NAND2"));
|
||||
|
||||
|
|
@ -4264,6 +4517,7 @@ TEST(28_JoinSymmetricNets)
|
|||
prep_nl (nl, nls);
|
||||
|
||||
db::NetlistComparer comp;
|
||||
comp.set_dont_consider_net_names (true);
|
||||
comp.join_symmetric_nets (nl.circuit_by_name ("INV2LOAD"));
|
||||
|
||||
// NOTE $1 and $2 are joined because they are symmetric
|
||||
|
|
|
|||
|
|
@ -37,6 +37,15 @@ See <a href="/about/lvs_ref_netter.xml#align">Netter#align</a> for a description
|
|||
<p>
|
||||
See <a href="/about/lvs_ref_netter.xml#compare">Netter#compare</a> for a description of that function.
|
||||
</p>
|
||||
<a name="consider_net_names"/><h2>"consider_net_names" - Indicates whether the netlist comparer shall use net names</h2>
|
||||
<keyword name="consider_net_names"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>consider_net_names(f)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
See <a href="/about/lvs_ref_netter.xml#consider_net_names">Netter#consider_net_names</a> for a description of that function.
|
||||
</p>
|
||||
<a name="equivalent_pins"/><h2>"equivalent_pins" - Marks pins as equivalent</h2>
|
||||
<keyword name="equivalent_pins"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -85,6 +85,18 @@ corresponding circuits: the unpaired circuit will be flattened then.
|
|||
This method will return true, if the netlists are equivalent and false
|
||||
otherwise.
|
||||
</p>
|
||||
<a name="consider_net_names"/><h2>"consider_net_names" - Indicates whether the netlist comparer shall use net names</h2>
|
||||
<keyword name="consider_net_names"/>
|
||||
<p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>consider_net_names(f)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
If this value is set to true (the default), the netlist comparer
|
||||
will employ net names to resolve ambiguities. If set to false,
|
||||
ambiguities will be resolved based on the topology alone. Topology
|
||||
resolution is more expensive.
|
||||
</p>
|
||||
<a name="equivalent_pins"/><h2>"equivalent_pins" - Marks pins as equivalent</h2>
|
||||
<keyword name="equivalent_pins"/>
|
||||
<p>Usage:</p>
|
||||
|
|
|
|||
|
|
@ -155,6 +155,12 @@ module LVS
|
|||
# @synopsis max_depth(n)
|
||||
# See \Netter#max_depth for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name consider_net_names
|
||||
# @brief Indicates whether the netlist comparer shall use net names
|
||||
# @synopsis consider_net_names(f)
|
||||
# See \Netter#consider_net_names for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name tolerance
|
||||
# @brief Specifies compare tolerances for certain device parameters
|
||||
|
|
@ -162,7 +168,7 @@ module LVS
|
|||
# @synopsis tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance])
|
||||
# See \Netter#tolerance for a description of that function.
|
||||
|
||||
%w(schematic compare join_symmetric_nets tolerance align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity).each do |f|
|
||||
%w(schematic compare join_symmetric_nets tolerance align same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity consider_net_names).each do |f|
|
||||
eval <<"CODE"
|
||||
def #{f}(*args)
|
||||
_netter.#{f}(*args)
|
||||
|
|
|
|||
|
|
@ -631,6 +631,20 @@ module LVS
|
|||
@comparer_config << lambda { |comparer| comparer.max_branch_complexity = v }
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name consider_net_names
|
||||
# @brief Indicates whether the netlist comparer shall use net names
|
||||
# @synopsis consider_net_names(f)
|
||||
# If this value is set to true (the default), the netlist comparer
|
||||
# will employ net names to resolve ambiguities. If set to false,
|
||||
# ambiguities will be resolved based on the topology alone. Topology
|
||||
# resolution is more expensive.
|
||||
|
||||
def consider_net_names(value)
|
||||
v = ! value
|
||||
@comparer_config << lambda { |comparer| comparer.dont_consider_net_names = v }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -295,8 +295,8 @@ Z(
|
|||
Z(
|
||||
N(2 3 1)
|
||||
N(3 5 1)
|
||||
N(4 4 W)
|
||||
N(5 6 W)
|
||||
N(4 4 1)
|
||||
N(5 6 1)
|
||||
N(1 1 1)
|
||||
N(6 2 1)
|
||||
P(1 2 1)
|
||||
|
|
|
|||
|
|
@ -131,5 +131,7 @@ connect_implicit("DOESNOTEXIST", "DOESNOTEXIST")
|
|||
netlist.simplify
|
||||
align
|
||||
|
||||
consider_net_names(false)
|
||||
|
||||
compare
|
||||
|
||||
|
|
|
|||
|
|
@ -131,5 +131,7 @@ connect_implicit("DOESNOTEXIST", "DOESNOTEXIST")
|
|||
netlist.simplify
|
||||
align
|
||||
|
||||
consider_net_names(false)
|
||||
|
||||
compare
|
||||
|
||||
|
|
|
|||
|
|
@ -71,5 +71,7 @@ connect_global(ptie, "SUBSTRATE")
|
|||
netlist.simplify
|
||||
align
|
||||
|
||||
consider_net_names(false)
|
||||
|
||||
compare
|
||||
|
||||
|
|
|
|||
|
|
@ -126,5 +126,7 @@ connect_global(bulk, "SUBSTRATE")
|
|||
netlist.simplify
|
||||
align
|
||||
|
||||
consider_net_names(false)
|
||||
|
||||
compare
|
||||
|
||||
|
|
|
|||
|
|
@ -83,5 +83,7 @@ netlist.purge
|
|||
netlist.combine_devices
|
||||
netlist.purge_nets
|
||||
|
||||
consider_net_names(false)
|
||||
|
||||
compare
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue