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 "tlTimer.h"
|
||||||
#include "tlEquivalenceClusters.h"
|
#include "tlEquivalenceClusters.h"
|
||||||
#include "tlLog.h"
|
#include "tlLog.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
// verbose debug output
|
namespace {
|
||||||
// TODO: make this a feature?
|
|
||||||
// #define PRINT_DEBUG_NETCOMPARE
|
|
||||||
|
|
||||||
// verbose net graph output
|
struct GlobalCompareOptions
|
||||||
// TODO: make this a feature?
|
{
|
||||||
// #define PRINT_DEBUG_NETGRAPH
|
GlobalCompareOptions ()
|
||||||
|
{
|
||||||
|
m_is_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Add this define for case insensitive compare
|
void ensure_initialized ()
|
||||||
// (applies to circuits, device classes)
|
{
|
||||||
#define COMPARE_CASE_INSENSITIVE
|
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
|
// A constant indicating a failed match
|
||||||
const size_t failed_match = std::numeric_limits<size_t>::max ();
|
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)
|
static int name_compare (const std::string &n1, const std::string &n2)
|
||||||
{
|
{
|
||||||
// TODO: unicode support?
|
// 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)
|
#if defined(_WIN32)
|
||||||
return _stricmp (n1.c_str (), n2.c_str ());
|
return _stricmp (n1.c_str (), n2.c_str ());
|
||||||
#else
|
#else
|
||||||
return strcasecmp (n1.c_str (), n2.c_str ());
|
return strcasecmp (n1.c_str (), n2.c_str ());
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
return strcmp (n1.c_str (), n2.c_str ());
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(COMPARE_CASE_INSENSITIVE)
|
static inline std::string normalize_name (const std::string &n)
|
||||||
static 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
|
// 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) {
|
for (std::vector<NetGraphNode>::iterator i = m_nodes.begin (); i != m_nodes.end (); ++i) {
|
||||||
i->apply_net_index (m_net_index);
|
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) {
|
if (options ()->debug_netgraph) {
|
||||||
tl::info << i->to_string () << tl::noendl;
|
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
|
// 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) {
|
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);
|
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) {
|
if (options ()->debug_netgraph) {
|
||||||
tl::info << i->second.to_string () << tl::noendl;
|
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
|
size_t
|
||||||
|
|
@ -1560,34 +1588,48 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
|
|
||||||
std::vector<const NetGraphNode *> other_nodes;
|
std::vector<const NetGraphNode *> other_nodes;
|
||||||
other_nodes.reserve (ee - e);
|
other_nodes.reserve (ee - e);
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "consider transitions:";
|
tl::info << indent(depth) << "considering transitions:";
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
for (NetGraphNode::edge_iterator i = e; i != ee; ++i) {
|
for (NetGraphNode::edge_iterator i = e; i != ee; ++i) {
|
||||||
if (i->second.first != net_index) {
|
if (i->second.first != net_index) {
|
||||||
const NetGraphNode *nn = &node (i->second.first);
|
const NetGraphNode *nn = &node (i->second.first);
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "here: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
|
if (first) {
|
||||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
tl::info << indent (depth) << " here: " << (node (net_index).net () ? node (net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||||
tl::info << indent(depth) << " " << t->to_string();
|
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);
|
nodes.push_back (nn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! nodes.empty ()) { // if non-ambiguous, non-assigned
|
if (! nodes.empty ()) { // if non-ambiguous, non-assigned
|
||||||
|
|
||||||
|
first = true;
|
||||||
|
|
||||||
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
|
for (NetGraphNode::edge_iterator i = e_other; i != ee_other; ++i) {
|
||||||
if (i->second.first != other_net_index) {
|
if (i->second.first != other_net_index) {
|
||||||
const NetGraphNode *nn = &data->other->node (i->second.first);
|
const NetGraphNode *nn = &data->other->node (i->second.first);
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "there: " << (nn->net() ? nn->net()->expanded_name().c_str() : "(null)") << " via";
|
if (first) {
|
||||||
for (std::vector<NetGraphNode::Transition>::const_iterator t = i->first.begin (); t != i->first.end(); ++t) {
|
tl::info << indent (depth) << " there: " << (data->other->node (other_net_index).net () ? data->other->node (other_net_index).net ()->expanded_name ().c_str () : "(null)") << " ->";
|
||||||
tl::info << indent(depth) << " " << t->to_string();
|
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);
|
other_nodes.push_back (nn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1604,9 +1646,9 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
if (tentative) {
|
if (tentative) {
|
||||||
|
|
||||||
if (nodes.size () != other_nodes.size ()) {
|
if (nodes.size () != other_nodes.size ()) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected branch.";
|
tl::info << indent(depth) << "=> rejected branch.";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
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) {
|
if (nodes.size () > 1 || other_nodes.size () > 1) {
|
||||||
for (size_t i = 0; i < nodes.size (); ++i) {
|
for (size_t i = 0; i < nodes.size (); ++i) {
|
||||||
if (! (*nodes[i] == *other_nodes[i])) {
|
if (! (*nodes[i] == *other_nodes[i])) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected branch.";
|
tl::info << indent(depth) << "=> rejected branch.";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
return failed_match;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1631,9 +1673,9 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
|
|
||||||
if (bt_count == failed_match) {
|
if (bt_count == failed_match) {
|
||||||
if (tentative) {
|
if (tentative) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected branch.";
|
tl::info << indent(depth) << "=> rejected branch.";
|
||||||
#endif
|
}
|
||||||
return bt_count;
|
return bt_count;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1642,11 +1684,11 @@ NetGraph::derive_node_identities_for_edges (NetGraphNode::edge_iterator e, NetGr
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
if (! new_nodes) {
|
if (! new_nodes) {
|
||||||
tl::info << indent(depth) << "! no updates.";
|
tl::info << indent(depth) << "=> no updates.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return new_nodes;
|
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 ();
|
size_t other_net_index = n->other_net_index ();
|
||||||
NetGraphNode *n_other = & data->other->node (other_net_index);
|
NetGraphNode *n_other = & data->other->node (other_net_index);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
if (! tentative) {
|
if (! tentative) {
|
||||||
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
tl::info << indent(depth) << "deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||||
} else {
|
} else {
|
||||||
tl::info << indent(depth) << "tentatively deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
tl::info << indent(depth) << "tentatively deducing from pair: " << n->net ()->expanded_name () << " vs. " << n_other->net ()->expanded_name ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t new_nodes = 0;
|
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);
|
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 (bt_count == failed_match) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected pair.";
|
tl::info << indent(depth) << "=> rejected pair.";
|
||||||
#endif
|
}
|
||||||
return bt_count;
|
return bt_count;
|
||||||
} else {
|
} else {
|
||||||
new_nodes += bt_count;
|
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) {
|
} else if (tentative) {
|
||||||
// in tentative mode an exact match is required: no having the same edges for a node disqualifies the node
|
// in tentative mode an exact match is required: no having the same edges for a node disqualifies the node
|
||||||
// as matching.
|
// as matching.
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
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);
|
NetGraphNode::edge_iterator e = n->find_edge (e_other->first);
|
||||||
if (e == n->end ()) {
|
if (e == n->end ()) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent(depth) << "! rejected pair for missing edge.";
|
tl::info << indent(depth) << "=> rejected pair for missing edge.";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
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 (options ()->debug_netcompare) {
|
||||||
if (! tentative && new_nodes > 0) {
|
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";
|
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;
|
return new_nodes;
|
||||||
}
|
}
|
||||||
|
|
@ -1855,17 +1897,18 @@ static bool net_names_are_different (const db::Net *a, const db::Net *b)
|
||||||
size_t
|
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)
|
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;
|
||||||
std::string indent_s = indent (depth);
|
if (options ()->debug_netcompare) {
|
||||||
indent_s += "*" + tl::to_string (n_branch) + " ";
|
indent_s = indent (depth);
|
||||||
#endif
|
indent_s += "*" + tl::to_string (n_branch) + " ";
|
||||||
|
}
|
||||||
|
|
||||||
size_t new_nodes = 0;
|
size_t new_nodes = 0;
|
||||||
|
|
||||||
if (depth > data->max_depth) {
|
if (depth > data->max_depth) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
tl::info << indent_s << "max. depth exhausted (" << depth + 1 << ">" << data->max_depth << ")";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
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);
|
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match (singular): " << nodes.front ()->net ()->expanded_name () << " vs. " << other_nodes.front ()->net ()->expanded_name ();
|
||||||
#endif
|
}
|
||||||
if (data->logger && ! tentative) {
|
if (data->logger && ! tentative) {
|
||||||
if (! (node (ni) == data->other->node (other_ni))) {
|
if (! (node (ni) == data->other->node (other_ni))) {
|
||||||
// this is a mismatch but we continue, because that is the only candidate
|
// 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
|
// 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 (tentative && ! data->dont_consider_net_names && net_names_are_different ((*nr->n1)->net (), (*nr->n2)->net ())) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
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 ();
|
tl::info << indent_s << "rejecting pair as names are not identical: " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
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);
|
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match (singular): " << (*nr->n1)->net ()->expanded_name () << " vs. " << (*nr->n2)->net ()->expanded_name ();
|
||||||
#endif
|
}
|
||||||
if (data->logger && ! tentative) {
|
if (data->logger && ! tentative) {
|
||||||
if (! (node (ni) == data->other->node (other_ni))) {
|
if (! (node (ni) == data->other->node (other_ni))) {
|
||||||
// this is a mismatch, but we continue with this
|
// 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) {
|
} else if (nr->num * n_branch > data->max_n_branch) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
tl::info << indent_s << "max. complexity exhausted (" << nr->num << "*" << n_branch << ">" << data->max_n_branch << ") - mismatch.";
|
||||||
#endif
|
}
|
||||||
return failed_match;
|
return failed_match;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
tl::info << indent_s << "analyzing ambiguity group with " << nr->num << " members";
|
||||||
#endif
|
}
|
||||||
|
|
||||||
// sort the ambiguity group such that net names match best
|
// 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);
|
TentativeNodeMapping::map_pair_from_unknown (&tn, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
// try this candidate in tentative mode
|
// try this candidate in tentative mode
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
tl::info << indent_s << "trying in tentative mode: " << (*i1)->net ()->expanded_name () << " vs. " << (*i2)->net ()->expanded_name ();
|
||||||
#endif
|
}
|
||||||
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
size_t bt_count = derive_node_identities (ni, depth + 1, nr->num * n_branch, &tn, with_ambiguous, data);
|
||||||
|
|
||||||
if (bt_count != failed_match) {
|
if (bt_count != failed_match) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "match found";
|
tl::info << indent_s << "match found";
|
||||||
#endif
|
}
|
||||||
// we have a match ...
|
// we have a match ...
|
||||||
|
|
||||||
if (any) {
|
if (any) {
|
||||||
|
|
@ -2185,9 +2228,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! any && tentative) {
|
if (! any && tentative) {
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "mismatch.";
|
tl::info << indent_s << "mismatch.";
|
||||||
#endif
|
}
|
||||||
// a mismatch - stop here.
|
// a mismatch - stop here.
|
||||||
return failed_match;
|
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);
|
TentativeNodeMapping::map_pair (tentative, this, ni, data->other, other_ni);
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
if (equivalent_other_nodes.has_attribute (p->second)) {
|
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 ();
|
tl::info << indent_s << "deduced ambiguous match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||||
} else {
|
} else {
|
||||||
tl::info << indent_s << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
tl::info << indent_s << "deduced match: " << p->first->net ()->expanded_name () << " vs. " << p->second->net ()->expanded_name ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (data->logger) {
|
if (data->logger) {
|
||||||
bool ambiguous = equivalent_other_nodes.has_attribute (p->second);
|
bool ambiguous = equivalent_other_nodes.has_attribute (p->second);
|
||||||
if (ambiguous) {
|
if (ambiguous) {
|
||||||
|
|
@ -2249,9 +2292,9 @@ NetGraph::derive_node_identities_from_node_set (std::vector<const NetGraphNode *
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
tl::info << indent_s << "finished analysis of ambiguity group with " << nr->num << " members";
|
||||||
#endif
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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 (all_subcircuits_verified (ca, verified_circuits_a) && all_subcircuits_verified (cb, verified_circuits_b)) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name ();
|
tl::info << "treating circuit: " << ca->name () << " vs. " << cb->name ();
|
||||||
#endif
|
}
|
||||||
if (mp_logger) {
|
if (mp_logger) {
|
||||||
mp_logger->begin_circuit (ca, cb);
|
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);
|
g2.identify (ni2, ni1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
// two passes: one without ambiguities, the second one with
|
// 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) {
|
for (int pass = 0; pass < 2; ++pass) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
if (pass > 0) {
|
if (pass > 0) {
|
||||||
tl::info << "including ambiguous nodes now.";
|
tl::info << "including ambiguous nodes now.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
good = true;
|
good = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
|
||||||
++iter;
|
++iter;
|
||||||
tl::info << "new compare iteration #" << iter;
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << "deducing from present nodes ...";
|
tl::info << "new compare iteration #" << iter;
|
||||||
#endif
|
tl::info << "deducing from present nodes ...";
|
||||||
|
}
|
||||||
|
|
||||||
size_t new_identities = 0;
|
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);
|
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) {
|
if (ni > 0 && ni != failed_match) {
|
||||||
new_identities += ni;
|
new_identities += ni;
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << ni << " new identities.";
|
tl::info << ni << " new identities.";
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << "checking topological identity ...";
|
tl::info << "checking topological identity ...";
|
||||||
#endif
|
}
|
||||||
|
|
||||||
// derive new identities through topology: first collect all nets with the same topological signature
|
// 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);
|
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) {
|
if (ni > 0 && ni != failed_match) {
|
||||||
new_identities += ni;
|
new_identities += ni;
|
||||||
#if defined(PRINT_DEBUG_NETCOMPARE)
|
if (options ()->debug_netcompare) {
|
||||||
tl::info << ni << " new identities.";
|
tl::info << ni << " new identities.";
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_identities == 0) {
|
if (new_identities == 0) {
|
||||||
|
|
|
||||||
|
|
@ -1283,14 +1283,6 @@ ApplicationBase::get_config_names () const
|
||||||
return names;
|
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
|
// GuiApplication implementation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,16 +198,6 @@ public:
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> get_config_names () const;
|
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
|
* @brief Return a reference to the Ruby interpreter
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "laySystemPaths.h"
|
#include "laySystemPaths.h"
|
||||||
#include "tlFileUtils.h"
|
#include "tlFileUtils.h"
|
||||||
#include "tlString.h"
|
#include "tlString.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
@ -31,32 +32,17 @@
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#elif __APPLE__
|
|
||||||
# include <libproc.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
#else
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace lay
|
namespace lay
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
get_appdata_path ()
|
get_appdata_path ()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
if (tl::has_env ("KLAYOUT_HOME")) {
|
||||||
wchar_t *env = _wgetenv (L"KLAYOUT_HOME");
|
return tl::get_env ("KLAYOUT_HOME");
|
||||||
if (env) {
|
|
||||||
return tl::to_string (QString ((const QChar *) env));
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
char *env = getenv ("KLAYOUT_HOME");
|
|
||||||
if (env) {
|
|
||||||
return (tl::system_to_string (env));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QDir appdata_dir = QDir::homePath ();
|
QDir appdata_dir = QDir::homePath ();
|
||||||
QString appdata_folder;
|
QString appdata_folder;
|
||||||
|
|
@ -138,23 +124,14 @@ get_klayout_path ()
|
||||||
|
|
||||||
// generate the klayout path: the first component is always the appdata path
|
// generate the klayout path: the first component is always the appdata path
|
||||||
klayout_path.push_back (get_appdata_path ());
|
klayout_path.push_back (get_appdata_path ());
|
||||||
#ifdef _WIN32
|
|
||||||
wchar_t *env = _wgetenv (L"KLAYOUT_PATH");
|
std::string env = tl::get_env ("KLAYOUT_PATH");
|
||||||
if (env) {
|
if (! env.empty ()) {
|
||||||
split_path (tl::to_string (QString ((const QChar *) env)), klayout_path);
|
split_path (env, klayout_path);
|
||||||
} else {
|
} else {
|
||||||
get_other_system_paths (klayout_path);
|
get_other_system_paths (klayout_path);
|
||||||
klayout_path.push_back (tl::get_inst_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;
|
return klayout_path;
|
||||||
|
|
||||||
|
|
@ -164,23 +141,7 @@ get_klayout_path ()
|
||||||
std::string
|
std::string
|
||||||
salt_mine_url ()
|
salt_mine_url ()
|
||||||
{
|
{
|
||||||
const std::string default_url ("http://sami.klayout.org/repository.xml");
|
return tl::get_env ("KLAYOUT_SALT_MINE", "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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "tlTimer.h"
|
#include "tlTimer.h"
|
||||||
#include "tlProgress.h"
|
#include "tlProgress.h"
|
||||||
#include "tlThreadedWorkers.h"
|
#include "tlThreadedWorkers.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
#include "tlExceptions.h"
|
#include "tlExceptions.h"
|
||||||
#include "tlMath.h"
|
#include "tlMath.h"
|
||||||
#include "layCellView.h"
|
#include "layCellView.h"
|
||||||
|
|
@ -1085,7 +1086,7 @@ XORToolDialog::run_xor ()
|
||||||
|
|
||||||
bool summarize = mp_ui->summarize_cb->isChecked ();
|
bool summarize = mp_ui->summarize_cb->isChecked ();
|
||||||
// TODO: make this a user interface feature later
|
// 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_a = mp_ui->layouta->current_cv_index ();
|
||||||
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
int cv_index_b = mp_ui->layoutb->current_cv_index ();
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ SOURCES = \
|
||||||
tlList.cc \
|
tlList.cc \
|
||||||
tlEquivalenceClusters.cc \
|
tlEquivalenceClusters.cc \
|
||||||
tlUniqueName.cc \
|
tlUniqueName.cc \
|
||||||
tlRecipe.cc
|
tlRecipe.cc \
|
||||||
|
tlEnv.cc
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
tlAlgorithm.h \
|
tlAlgorithm.h \
|
||||||
|
|
@ -103,7 +104,8 @@ HEADERS = \
|
||||||
tlEquivalenceClusters.h \
|
tlEquivalenceClusters.h \
|
||||||
tlUniqueName.h \
|
tlUniqueName.h \
|
||||||
tlRecipe.h \
|
tlRecipe.h \
|
||||||
tlSelect.h
|
tlSelect.h \
|
||||||
|
tlEnv.h
|
||||||
|
|
||||||
equals(HAVE_CURL, "1") {
|
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 "tlString.h"
|
||||||
#include "tlGlobPattern.h"
|
#include "tlGlobPattern.h"
|
||||||
#include "tlFileUtils.h"
|
#include "tlFileUtils.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -35,7 +36,6 @@
|
||||||
#define _USE_MATH_DEFINES // for MSVC
|
#define _USE_MATH_DEFINES // for MSVC
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
// Suggestions for further functions:
|
// 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);
|
throw EvalError (tl::to_string (tr ("'env' function expects exactly two arguments")), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *env = getenv (vv [0].to_string ());
|
const char *vn = vv [0].to_string ();
|
||||||
if (env) {
|
if (tl::has_env (vn)) {
|
||||||
out = env;
|
out = tl::get_env (vn);
|
||||||
} else {
|
} else {
|
||||||
out = tl::Variant ();
|
out = tl::Variant ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,12 @@
|
||||||
|
|
||||||
#include "tlLog.h"
|
#include "tlLog.h"
|
||||||
#include "tlString.h"
|
#include "tlString.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace tl
|
namespace tl
|
||||||
{
|
{
|
||||||
|
|
@ -42,21 +38,9 @@ namespace tl
|
||||||
|
|
||||||
static int default_verbosity ()
|
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;
|
int verbosity = 0;
|
||||||
if (verbosity_str) {
|
std::string verbosity_str = tl::get_env ("KLAYOUT_VERBOSITY");
|
||||||
|
if (! verbosity_str.empty ()) {
|
||||||
try {
|
try {
|
||||||
tl::from_string (verbosity_str, verbosity);
|
tl::from_string (verbosity_str, verbosity);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "tlFileUtils.h"
|
#include "tlFileUtils.h"
|
||||||
#include "tlTimer.h"
|
#include "tlTimer.h"
|
||||||
#include "tlStream.h"
|
#include "tlStream.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
@ -85,8 +86,8 @@ void set_debug_mode (bool f)
|
||||||
|
|
||||||
std::string testsrc ()
|
std::string testsrc ()
|
||||||
{
|
{
|
||||||
const char *ts = getenv ("TESTSRC");
|
std::string ts = tl::get_env ("TESTSRC");
|
||||||
if (! ts) {
|
if (ts.empty ()) {
|
||||||
throw tl::Exception ("TESTSRC undefined");
|
throw tl::Exception ("TESTSRC undefined");
|
||||||
}
|
}
|
||||||
return ts;
|
return ts;
|
||||||
|
|
@ -104,8 +105,8 @@ std::string testsrc_private ()
|
||||||
std::string testtmp ()
|
std::string testtmp ()
|
||||||
{
|
{
|
||||||
// Ensures the test temp directory is present
|
// Ensures the test temp directory is present
|
||||||
const char *tt = getenv ("TESTTMP");
|
std::string tt = tl::get_env ("TESTTMP");
|
||||||
if (! tt) {
|
if (tt.empty ()) {
|
||||||
throw tl::Exception ("TESTTMP undefined");
|
throw tl::Exception ("TESTTMP undefined");
|
||||||
}
|
}
|
||||||
return tt;
|
return tt;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@
|
||||||
#include "tlExpression.h"
|
#include "tlExpression.h"
|
||||||
#include "tlVariantUserClasses.h"
|
#include "tlVariantUserClasses.h"
|
||||||
#include "tlUnitTest.h"
|
#include "tlUnitTest.h"
|
||||||
|
#include "tlEnv.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#define _USE_MATH_DEFINES // for MSVC
|
#define _USE_MATH_DEFINES // for MSVC
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
@ -834,7 +834,7 @@ TEST(6)
|
||||||
v = e.parse ("env('HJASK')").execute ();
|
v = e.parse ("env('HJASK')").execute ();
|
||||||
EXPECT_EQ (v.to_string (), std::string ("nil"));
|
EXPECT_EQ (v.to_string (), std::string ("nil"));
|
||||||
v = e.parse ("env('PATH')").execute ();
|
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 ();
|
v = e.parse ("absolute_path('./x.gds')").execute ();
|
||||||
// EXPECT_EQ (v.to_string (), std::string ()); // not universal
|
// EXPECT_EQ (v.to_string (), std::string ()); // not universal
|
||||||
v = e.parse ("absolute_file_path('./x.gds')").execute ();
|
v = e.parse ("absolute_file_path('./x.gds')").execute ();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue