mirror of https://github.com/KLayout/klayout.git
WIP: some refactoring, debugging output for netlist compare
Abstraction: a central getenv() feature to wrap all the system-specific things Netlist compare debug and options can be enabled through environment variables: KLAYOUT_NETLIST_COMPARE_DEBUG_NETCOMPARE=1: print netlist compare debug info KLAYOUT_NETLIST_COMPARE_DEBUG_NETGRAPH=1: print net grapg KLAYOUT_NETLIST_COMPARE_CASE_SENSITIVE=1: make netlist compare case sensitive
This commit is contained in:
parent
99f22c3221
commit
58de38739a
|
|
@ -27,20 +27,49 @@
|
|||
#include "tlTimer.h"
|
||||
#include "tlEquivalenceClusters.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// verbose debug output
|
||||
// TODO: make this a feature?
|
||||
// #define PRINT_DEBUG_NETCOMPARE
|
||||
namespace {
|
||||
|
||||
// verbose net graph output
|
||||
// TODO: make this a feature?
|
||||
// #define PRINT_DEBUG_NETGRAPH
|
||||
struct GlobalCompareOptions
|
||||
{
|
||||
GlobalCompareOptions ()
|
||||
{
|
||||
m_is_initialized = false;
|
||||
}
|
||||
|
||||
// Add this define for case insensitive compare
|
||||
// (applies to circuits, device classes)
|
||||
#define COMPARE_CASE_INSENSITIVE
|
||||
void ensure_initialized ()
|
||||
{
|
||||
if (! m_is_initialized) {
|
||||
// $KLAYOUT_NETLIST_COMPARE_DEBUG_NETCOMPARE
|
||||
debug_netcompare = tl::app_flag ("netlist-compare-debug-netcompare");
|
||||
// $KLAYOUT_NETLIST_COMPARE_DEBUG_NETGRAPH
|
||||
debug_netgraph = tl::app_flag ("netlist-compare-debug-netgraph");
|
||||
// $KLAYOUT_NETLIST_COMPARE_CASE_SENSITIVE
|
||||
compare_case_sensitive = tl::app_flag ("netlist-compare-case-sensitive");
|
||||
m_is_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool debug_netcompare;
|
||||
bool debug_netgraph;
|
||||
bool compare_case_sensitive;
|
||||
|
||||
private:
|
||||
bool m_is_initialized;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static GlobalCompareOptions *options ()
|
||||
{
|
||||
// TODO: thread safe?
|
||||
static GlobalCompareOptions s_options;
|
||||
s_options.ensure_initialized ();
|
||||
return &s_options;
|
||||
}
|
||||
|
||||
// A constant indicating a failed match
|
||||
const size_t failed_match = std::numeric_limits<size_t>::max ();
|
||||
|
|
@ -63,28 +92,25 @@ namespace db
|
|||
static int name_compare (const std::string &n1, const std::string &n2)
|
||||
{
|
||||
// TODO: unicode support?
|
||||
#if defined(COMPARE_CASE_INSENSITIVE)
|
||||
if (options ()->compare_case_sensitive) {
|
||||
return strcmp (n1.c_str (), n2.c_str ());
|
||||
} else {
|
||||
#if defined(_WIN32)
|
||||
return _stricmp (n1.c_str (), n2.c_str ());
|
||||
return _stricmp (n1.c_str (), n2.c_str ());
|
||||
#else
|
||||
return strcasecmp (n1.c_str (), n2.c_str ());
|
||||
#endif
|
||||
#else
|
||||
return strcmp (n1.c_str (), n2.c_str ());
|
||||
return strcasecmp (n1.c_str (), n2.c_str ());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(COMPARE_CASE_INSENSITIVE)
|
||||
static std::string normalize_name (const std::string &n)
|
||||
static inline std::string normalize_name (const std::string &n)
|
||||
{
|
||||
return tl::to_upper_case (n);
|
||||
if (options ()->compare_case_sensitive) {
|
||||
return n;
|
||||
} else {
|
||||
return tl::to_upper_case (n);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline const std::string &normalize_name (const std::string &n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// DeviceCompare definition and implementation
|
||||
|
|
@ -1515,11 +1541,12 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci
|
|||
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
||||
i->apply_net_index (m_net_index);
|
||||
}
|
||||
#if defined(PRINT_DEBUG_NETGRAPH)
|
||||
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
||||
tl::info << i->to_string () << tl::noendl;
|
||||
|
||||
if (options ()->debug_netgraph) {
|
||||
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
||||
tl::info << i->to_string () << tl::noendl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// create subcircuit virtual nodes
|
||||
|
||||
|
|
@ -1543,11 +1570,12 @@ NetGraph::build (const db::Circuit *c, DeviceCategorizer &device_categorizer, Ci
|
|||
for (std::map<const db::SubCircuit *, NetGraphNode>::iterator i = m_virtual_nodes.begin (); i != m_virtual_nodes.end (); ++i) {
|
||||
i->second.apply_net_index (m_net_index);
|
||||
}
|
||||
#if defined(PRINT_DEBUG_NETGRAPH)
|
||||
for (std::map<const db::SubCircuit *, NetGraphNode>::iterator i = m_virtual_nodes.begin (); i != m_virtual_nodes.end (); ++i) {
|
||||
tl::info << i->second.to_string () << tl::noendl;
|
||||
|
||||
if (options ()->debug_netgraph) {
|
||||
for (std::map<const db::SubCircuit *, NetGraphNode>::iterator i = m_virtual_nodes.begin (); i != m_virtual_nodes.end (); ++i) {
|
||||
tl::info << i->second.to_string () << tl::noendl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
@ -1560,34 +1588,48 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
|
||||
std::vector<const NetGraphNode *> other_nodes;
|
||||
other_nodes.reserve (ee - e);
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "consider transitions:";
|
||||
#endif
|
||||
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 defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "here: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
||||
tl::info << indent(depth) << " " << t->to_string();
|
||||
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 << "";
|
||||
}
|
||||
#endif
|
||||
nodes.push_back (nn);
|
||||
}
|
||||
}
|
||||
|
||||
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 defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
|
||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
||||
tl::info << indent(depth) << " " << t->to_string();
|
||||
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 << "";
|
||||
}
|
||||
#endif
|
||||
other_nodes.push_back (nn);
|
||||
}
|
||||
}
|
||||
|
|
@ -1604,9 +1646,9 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
if (tentative) {
|
||||
|
||||
if (nodes.size () != other_nodes.size ()) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected branch.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -1614,9 +1656,9 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
if (nodes.size () > 1 || other_nodes.size () > 1) {
|
||||
for (size_t i = 0; i < nodes.size (); ++i) {
|
||||
if (! (*nodes[i] == *other_nodes[i])) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected branch.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
}
|
||||
|
|
@ -1631,9 +1673,9 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
|
||||
if (bt_count == failed_match) {
|
||||
if (tentative) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected branch.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected branch.";
|
||||
}
|
||||
return bt_count;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1642,11 +1684,11 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
|||
|
||||
}
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
if (! new_nodes) {
|
||||
tl::info << indent(depth) << "! no updates.";
|
||||
if (options ()->debug_netcompare) {
|
||||
if (! new_nodes) {
|
||||
tl::info << indent(depth) << "=> no updates.";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return new_nodes;
|
||||
}
|
||||
|
||||
|
|
@ -1671,13 +1713,13 @@ 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 defined(PRINT_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 ();
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t new_nodes = 0;
|
||||
|
||||
|
|
@ -1722,9 +1764,9 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
|
||||
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);
|
||||
if (bt_count == failed_match) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected pair.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair.";
|
||||
}
|
||||
return bt_count;
|
||||
} else {
|
||||
new_nodes += bt_count;
|
||||
|
|
@ -1733,9 +1775,9 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
} 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 defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -1758,9 +1800,9 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
|
||||
NetGraphNode::edge_iterator e = n->find_edge (e_other->first);
|
||||
if (e == n->end ()) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -1770,11 +1812,11 @@ NetGraph::derive_node_identities (size_t net_index, size_t depth, size_t n_branc
|
|||
|
||||
}
|
||||
|
||||
#if defined(PRINT_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";
|
||||
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";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return new_nodes;
|
||||
}
|
||||
|
|
@ -1855,17 +1897,18 @@ 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<const NetGraphNode *> &nodes, std::vector<const NetGraphNode *> &other_nodes, size_t depth, size_t n_branch, TentativeNodeMapping *tentative, bool with_ambiguous, CompareData *data)
|
||||
{
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
std::string indent_s = indent (depth);
|
||||
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||
#endif
|
||||
std::string indent_s;
|
||||
if (options ()->debug_netcompare) {
|
||||
indent_s = indent (depth);
|
||||
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||
}
|
||||
|
||||
size_t new_nodes = 0;
|
||||
|
||||
if (depth > data->max_depth) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -1881,9 +1924,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->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
|
||||
|
|
@ -2030,9 +2073,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
// their names differ -> this favors net matching by name
|
||||
|
||||
if (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||
}
|
||||
return failed_match;
|
||||
}
|
||||
|
||||
|
|
@ -2044,9 +2087,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||
}
|
||||
if (data->logger && ! tentative) {
|
||||
if (! (node (ni) == data->other->node (other_ni))) {
|
||||
// this is a mismatch, but we continue with this
|
||||
|
|
@ -2086,16 +2129,16 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
|
||||
} else if (nr->num * n_branch > data->max_n_branch) {
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
||||
}
|
||||
return failed_match;
|
||||
|
||||
} else {
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
||||
}
|
||||
|
||||
// sort the ambiguity group such that net names match best
|
||||
|
||||
|
|
@ -2152,16 +2195,16 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni);
|
||||
|
||||
// try this candidate in tentative mode
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
||||
}
|
||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
||||
|
||||
if (bt_count != failed_match) {
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "match found";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "match found";
|
||||
}
|
||||
// we have a match ...
|
||||
|
||||
if (any) {
|
||||
|
|
@ -2185,9 +2228,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
}
|
||||
|
||||
if (! any && tentative) {
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "mismatch.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "mismatch.";
|
||||
}
|
||||
// a mismatch - stop here.
|
||||
return failed_match;
|
||||
}
|
||||
|
|
@ -2207,13 +2250,13 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
|
||||
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||
|
||||
#if defined(PRINT_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 (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 ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (data->logger) {
|
||||
bool ambiguous = equivalent_other_nodes.has_attribute (p->second);
|
||||
if (ambiguous) {
|
||||
|
|
@ -2249,9 +2292,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
|||
|
||||
}
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2516,9 +2559,9 @@ 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 defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name ();
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name ();
|
||||
}
|
||||
if (mp_logger) {
|
||||
mp_logger->begin_circuit (ca, cb);
|
||||
}
|
||||
|
|
@ -2835,9 +2878,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
g2.identify (ni2, ni1);
|
||||
}
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
int iter = 0;
|
||||
#endif
|
||||
|
||||
// two passes: one without ambiguities, the second one with
|
||||
|
||||
|
|
@ -2845,20 +2886,20 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
|
||||
for (int pass = 0; pass < 2; ++pass) {
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
if (pass > 0) {
|
||||
tl::info << "including ambiguous nodes now.";
|
||||
if (options ()->debug_netcompare) {
|
||||
if (pass > 0) {
|
||||
tl::info << "including ambiguous nodes now.";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
good = true;
|
||||
while (true) {
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
++iter;
|
||||
tl::info << "new compare iteration #" << iter;
|
||||
tl::info << "deducing from present nodes ...";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "new compare iteration #" << iter;
|
||||
tl::info << "deducing from present nodes ...";
|
||||
}
|
||||
|
||||
size_t new_identities = 0;
|
||||
|
||||
|
|
@ -2877,18 +2918,18 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
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) {
|
||||
new_identities += ni;
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << ni << " new identities.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << ni << " new identities.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << "checking topological identity ...";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << "checking topological identity ...";
|
||||
}
|
||||
|
||||
// derive new identities through topology: first collect all nets with the same topological signature
|
||||
|
||||
|
|
@ -2934,9 +2975,9 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
|
|||
size_t ni = g1.derive_node_identities_from_node_set (nodes, other_nodes, 0, 1, 0 /*not tentative*/, pass > 0 /*with ambiguities*/, &data);
|
||||
if (ni > 0 && ni != failed_match) {
|
||||
new_identities += ni;
|
||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
||||
tl::info << ni << " new identities.";
|
||||
#endif
|
||||
if (options ()->debug_netcompare) {
|
||||
tl::info << ni << " new identities.";
|
||||
}
|
||||
}
|
||||
|
||||
if (new_identities == 0) {
|
||||
|
|
|
|||
|
|
@ -1283,14 +1283,6 @@ ApplicationBase::get_config_names () const
|
|||
return names;
|
||||
}
|
||||
|
||||
bool
|
||||
ApplicationBase::special_app_flag (const std::string &name)
|
||||
{
|
||||
// TODO: some more elaborate scheme?
|
||||
const char *env = getenv (("KLAYOUT_" + name).c_str ());
|
||||
return (env && *env);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// GuiApplication implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -198,16 +198,6 @@ public:
|
|||
*/
|
||||
std::vector<std::string> get_config_names () const;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the give special application flag is set
|
||||
*
|
||||
* Special application flags are ways to introduce debug or flags for special
|
||||
* use cases. Such flags have a name and currently are controlled externally by
|
||||
* an environment variable called "KLAYOUT_x" where x is the name. If that
|
||||
* variable is set and the value is non-empty, the flag is regarded set.
|
||||
*/
|
||||
bool special_app_flag (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Return a reference to the Ruby interpreter
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "laySystemPaths.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlString.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
|
@ -31,32 +32,17 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#elif __APPLE__
|
||||
# include <libproc.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
std::string
|
||||
get_appdata_path ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wchar_t *env = _wgetenv (L"KLAYOUT_HOME");
|
||||
if (env) {
|
||||
return tl::to_string (QString ((const QChar *) env));
|
||||
if (tl::has_env ("KLAYOUT_HOME")) {
|
||||
return tl::get_env ("KLAYOUT_HOME");
|
||||
}
|
||||
#else
|
||||
char *env = getenv ("KLAYOUT_HOME");
|
||||
if (env) {
|
||||
return (tl::system_to_string (env));
|
||||
}
|
||||
#endif
|
||||
|
||||
QDir appdata_dir = QDir::homePath ();
|
||||
QString appdata_folder;
|
||||
|
|
@ -138,23 +124,14 @@ get_klayout_path ()
|
|||
|
||||
// generate the klayout path: the first component is always the appdata path
|
||||
klayout_path.push_back (get_appdata_path ());
|
||||
#ifdef _WIN32
|
||||
wchar_t *env = _wgetenv (L"KLAYOUT_PATH");
|
||||
if (env) {
|
||||
split_path (tl::to_string (QString ((const QChar *) env)), klayout_path);
|
||||
|
||||
std::string env = tl::get_env ("KLAYOUT_PATH");
|
||||
if (! env.empty ()) {
|
||||
split_path (env, klayout_path);
|
||||
} else {
|
||||
get_other_system_paths (klayout_path);
|
||||
klayout_path.push_back (tl::get_inst_path ());
|
||||
}
|
||||
#else
|
||||
char *env = getenv ("KLAYOUT_PATH");
|
||||
if (env) {
|
||||
split_path (tl::system_to_string (env), klayout_path);
|
||||
} else {
|
||||
get_other_system_paths (klayout_path);
|
||||
klayout_path.push_back (tl::get_inst_path ());
|
||||
}
|
||||
#endif
|
||||
|
||||
return klayout_path;
|
||||
|
||||
|
|
@ -164,23 +141,7 @@ get_klayout_path ()
|
|||
std::string
|
||||
salt_mine_url ()
|
||||
{
|
||||
const std::string default_url ("http://sami.klayout.org/repository.xml");
|
||||
|
||||
#ifdef _WIN32
|
||||
wchar_t *env = _wgetenv (L"KLAYOUT_SALT_MINE");
|
||||
if (env) {
|
||||
return tl::to_string (QString ((const QChar *) env));
|
||||
} else {
|
||||
return default_url;
|
||||
}
|
||||
#else
|
||||
char *env = getenv ("KLAYOUT_SALT_MINE");
|
||||
if (env) {
|
||||
return (tl::system_to_string (env));
|
||||
} else {
|
||||
return default_url;
|
||||
}
|
||||
#endif
|
||||
return tl::get_env ("KLAYOUT_SALT_MINE", "http://sami.klayout.org/repository.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "tlTimer.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlThreadedWorkers.h"
|
||||
#include "tlEnv.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "tlMath.h"
|
||||
#include "layCellView.h"
|
||||
|
|
@ -1085,7 +1086,7 @@ XORToolDialog::run_xor ()
|
|||
|
||||
bool summarize = mp_ui->summarize_cb->isChecked ();
|
||||
// TODO: make this a user interface feature later
|
||||
bool process_el = lay::ApplicationBase::instance ()->special_app_flag ("ALWAYS_DO_XOR");
|
||||
bool process_el = tl::app_flag ("always-do-xor");
|
||||
|
||||
int cv_index_a = mp_ui->layouta->current_cv_index ();
|
||||
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ SOURCES = \
|
|||
tlList.cc \
|
||||
tlEquivalenceClusters.cc \
|
||||
tlUniqueName.cc \
|
||||
tlRecipe.cc
|
||||
tlRecipe.cc \
|
||||
tlEnv.cc
|
||||
|
||||
HEADERS = \
|
||||
tlAlgorithm.h \
|
||||
|
|
@ -103,7 +104,8 @@ HEADERS = \
|
|||
tlEquivalenceClusters.h \
|
||||
tlUniqueName.h \
|
||||
tlRecipe.h \
|
||||
tlSelect.h
|
||||
tlSelect.h \
|
||||
tlEnv.h
|
||||
|
||||
equals(HAVE_CURL, "1") {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "tlEnv.h"
|
||||
#include "tlString.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#elif __APPLE__
|
||||
# include <libproc.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
std::string get_env (const std::string &name, const std::string &def_value)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::wstring wname = tl::to_wstring (name);
|
||||
wchar_t *env = _wgetenv (wname.c_str ());
|
||||
if (env) {
|
||||
return tl::to_string (QString ((const QChar *) env));
|
||||
} else {
|
||||
return def_value;
|
||||
}
|
||||
#else
|
||||
char *env = getenv (name.c_str ());
|
||||
if (env) {
|
||||
return tl::system_to_string (env);
|
||||
} else {
|
||||
return def_value;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool has_env (const std::string &name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::wstring wname = tl::to_wstring (name);
|
||||
wchar_t *env = _wgetenv (wname.c_str ());
|
||||
return env != 0;
|
||||
#else
|
||||
char *env = getenv (name.c_str ());
|
||||
return env != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool app_flag (const std::string &name)
|
||||
{
|
||||
std::string env_name = std::string ("KLAYOUT_") + tl::replaced (tl::to_upper_case (name), "-", "_");
|
||||
|
||||
int v = 0;
|
||||
std::string vs = get_env (env_name);
|
||||
tl::Extractor ex (vs.c_str ());
|
||||
return ex.try_read (v) && v != 0;
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_tlAppFlags
|
||||
#define HDR_tlAppFlags
|
||||
|
||||
#include "tlCommon.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Gets the value for the given environment variable
|
||||
*
|
||||
* If the environment variable is not set, the default value will be returned.
|
||||
*/
|
||||
std::string TL_PUBLIC get_env (const std::string &name, const std::string &def_value = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Gets the value if the given environment variable is set
|
||||
*/
|
||||
bool TL_PUBLIC has_env (const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets an application flag with the given name
|
||||
*
|
||||
* This feature is supposed to deliver special flags for debugging etc.
|
||||
* By using a central access point for these settings, it will be easy to provide
|
||||
* different implementations later.
|
||||
*
|
||||
* Currently, application flags are derived by checking whether a corresponding
|
||||
* environment variable exists. Names like "a-b" are translated into "KLAYOUT_A_B"
|
||||
* for the environment variable.
|
||||
*
|
||||
* If the corresponding variable exists and does not have a value of "0", true
|
||||
* is returned from this function.
|
||||
*/
|
||||
bool TL_PUBLIC app_flag (const std::string &name);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "tlString.h"
|
||||
#include "tlGlobPattern.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
|
@ -35,7 +36,6 @@
|
|||
#define _USE_MATH_DEFINES // for MSVC
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// Suggestions for further functions:
|
||||
|
|
@ -2800,9 +2800,9 @@ env_f (const ExpressionParserContext &context, tl::Variant &out, const std::vect
|
|||
throw EvalError (tl::to_string (tr ("'env' function expects exactly two arguments")), context);
|
||||
}
|
||||
|
||||
const char *env = getenv (vv [0].to_string ());
|
||||
if (env) {
|
||||
out = env;
|
||||
const char *vn = vv [0].to_string ();
|
||||
if (tl::has_env (vn)) {
|
||||
out = tl::get_env (vn);
|
||||
} else {
|
||||
out = tl::Variant ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,12 @@
|
|||
|
||||
#include "tlLog.h"
|
||||
#include "tlString.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#if !defined(_MSC_VER)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -42,21 +38,9 @@ namespace tl
|
|||
|
||||
static int default_verbosity ()
|
||||
{
|
||||
const char *verbosity_str = 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
const wchar_t *verbosity_wstr = _wgetenv (L"KLAYOUT_VERBOSITY");
|
||||
std::string vs;
|
||||
if (verbosity_wstr) {
|
||||
vs = tl::to_string (std::wstring (verbosity_wstr));
|
||||
verbosity_str = vs.c_str ();
|
||||
}
|
||||
#else
|
||||
verbosity_str = getenv ("KLAYOUT_VERBOSITY");
|
||||
#endif
|
||||
|
||||
int verbosity = 0;
|
||||
if (verbosity_str) {
|
||||
std::string verbosity_str = tl::get_env ("KLAYOUT_VERBOSITY");
|
||||
if (! verbosity_str.empty ()) {
|
||||
try {
|
||||
tl::from_string (verbosity_str, verbosity);
|
||||
} catch (...) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "tlFileUtils.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
|
@ -85,8 +86,8 @@ void set_debug_mode (bool f)
|
|||
|
||||
std::string testsrc ()
|
||||
{
|
||||
const char *ts = getenv ("TESTSRC");
|
||||
if (! ts) {
|
||||
std::string ts = tl::get_env ("TESTSRC");
|
||||
if (ts.empty ()) {
|
||||
throw tl::Exception ("TESTSRC undefined");
|
||||
}
|
||||
return ts;
|
||||
|
|
@ -104,8 +105,8 @@ std::string testsrc_private ()
|
|||
std::string testtmp ()
|
||||
{
|
||||
// Ensures the test temp directory is present
|
||||
const char *tt = getenv ("TESTTMP");
|
||||
if (! tt) {
|
||||
std::string tt = tl::get_env ("TESTTMP");
|
||||
if (tt.empty ()) {
|
||||
throw tl::Exception ("TESTTMP undefined");
|
||||
}
|
||||
return tt;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
#include "tlExpression.h"
|
||||
#include "tlVariantUserClasses.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlEnv.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#define _USE_MATH_DEFINES // for MSVC
|
||||
#include <math.h>
|
||||
|
||||
|
|
@ -834,7 +834,7 @@ TEST(6)
|
|||
v = e.parse ("env('HJASK')").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("nil"));
|
||||
v = e.parse ("env('PATH')").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string (getenv ("PATH")));
|
||||
EXPECT_EQ (v.to_string (), tl::get_env ("PATH"));
|
||||
v = e.parse ("absolute_path('./x.gds')").execute ();
|
||||
// EXPECT_EQ (v.to_string (), std::string ()); // not universal
|
||||
v = e.parse ("absolute_file_path('./x.gds')").execute ();
|
||||
|
|
|
|||
Loading…
Reference in New Issue