WIP: reworked log enabling in LVS, added 'no_lvs_hints' feature, updated tests

This commit is contained in:
Matthias Koefferlein 2022-08-13 18:30:02 +02:00
parent fd008b3810
commit 90df9451b6
35 changed files with 186 additions and 67 deletions

View File

@ -239,6 +239,7 @@ void std_writer_impl<Keys>::write (TokenizedOutput &stream, const db::NetlistCro
for (db::NetlistCrossReference::PerCircuitData::log_entries_const_iterator l = pcd->log_entries.begin (); l != pcd->log_entries.end (); ++l) {
TokenizedOutput (o, Keys::log_entry_key, true) << severity_to_s (l->severity) << message_to_s (l->msg);
o << endl;
}
}

View File

@ -62,6 +62,8 @@ NetlistComparer::NetlistComparer (NetlistCompareLogger *logger)
m_dont_consider_net_names = false;
m_case_sensitive = false;
m_with_log = true;
}
NetlistComparer::~NetlistComparer ()
@ -382,7 +384,7 @@ NetlistComparer::compare_impl (const db::Netlist *a, const db::Netlist *b) const
std::string msg = generate_subcircuits_not_verified_warning (ca, verified_circuits_a, cb, verified_circuits_b);
if (mp_logger->wants_log_entries ()) {
if (m_with_log) {
mp_logger->log_entry (db::NetlistCompareLogger::Error, msg);
}
@ -896,7 +898,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
// in must_match mode, check if the nets are identical
if (mp_logger) {
if (p->second && ! exact_match) {
if (mp_logger->wants_log_entries ()) {
if (m_with_log) {
mp_logger->log_entry (db::NetlistCompareLogger::Error,
tl::sprintf (tl::to_string (tr ("Nets %s are paired explicitly, but are not identical topologically")), nets2string (p->first)));
}
@ -983,6 +985,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
compare.subcircuit_equivalence = &subcircuit_equivalence;
compare.device_equivalence = &device_equivalence;
compare.logger = mp_logger;
compare.with_log = m_with_log;
compare.progress = &progress;
std::vector<NodeEdgePair> nodes, other_nodes;
@ -1085,7 +1088,7 @@ NetlistComparer::compare_circuits (const db::Circuit *c1, const db::Circuit *c2,
}
if (pass + 1 == num_passes && ! good && mp_logger && mp_logger->wants_log_entries ()) {
if (pass + 1 == num_passes && ! good && mp_logger && m_with_log) {
compare.analyze_failed_matches ();
}
@ -1211,7 +1214,7 @@ NetlistComparer::handle_pin_mismatch (const db::NetGraph &g1, const db::Circuit
} else {
if (mp_logger) {
if (mp_logger->wants_log_entries ()) {
if (m_with_log) {
analyze_pin_mismatch (pin1, c1, pin2, c2, mp_logger);
}
mp_logger->pin_mismatch (pin1, pin2);

View File

@ -100,17 +100,9 @@ public:
/**
* @brief Receives log entries for the current circuit pair
* These events are only generated when the "wants_log_entry" hint returns true.
*/
virtual void log_entry (Severity /*level*/, const std::string & /*msg*/) { }
/**
* @brief Returns a value indicating whether log entries need to be generated
* Log entries may include hints which are expensive to compute. This method tells the
* matching algorithm whether to create such entries or not.
*/
virtual bool wants_log_entries () const { return false; }
/**
* @brief Nets a and b match exactly
*/
@ -280,6 +272,24 @@ public:
return m_max_depth;
}
/**
* @brief Sets a value indicating that log messages are generated
* Log messages may be expensive to compute, hence they can be turned off.
* By default, log messages are generated.
*/
void set_with_log (bool f)
{
m_with_log = f;
}
/**
* @brief Gets a value indicating that log messages are generated
*/
bool with_log () const
{
return m_with_log;
}
/**
* @brief Sets a value indicating whether not to consider net names
* This feature is mainly intended for testing.
@ -388,6 +398,7 @@ protected:
bool handle_pin_mismatch (const NetGraph &g1, const db::Circuit *c1, const db::Pin *pin1, const NetGraph &g2, const db::Circuit *c2, const db::Pin *p2) const;
mutable NetlistCompareLogger *mp_logger;
bool m_with_log;
std::map<std::pair<const db::Circuit *, const db::Circuit *>, std::vector<std::pair<std::pair<const Net *, const Net *>, bool> > > m_same_nets;
std::unique_ptr<CircuitPinCategorizer> mp_circuit_pin_categorizer;
std::unique_ptr<DeviceCategorizer> mp_device_categorizer;

View File

@ -403,6 +403,7 @@ NetlistCompareCore::NetlistCompareCore (NetGraph *graph, NetGraph *other_graph)
dont_consider_net_names (false),
with_ambiguous (false),
logger (0),
with_log (true),
circuit_pin_mapper (0),
subcircuit_equivalence (0),
device_equivalence (0),
@ -1050,7 +1051,7 @@ NetlistCompareCore::derive_node_identities_from_ambiguity_group (const NodeRange
if (ambiguous) {
if (logger) {
if (logger->wants_log_entries ()) {
if (with_log) {
logger->log_entry (db::NetlistCompareLogger::Warning,
tl::sprintf (tl::to_string (tr ("Matching nets %s from an ambiguous group of nets")), nets2string (p->first->net (), p->second->net ())));
}
@ -1114,7 +1115,7 @@ NetlistCompareCore::derive_node_identities_from_ambiguity_group (const NodeRange
}
}
if (logger && logger->wants_log_entries () && was_ambiguous) {
if (logger && with_log && was_ambiguous) {
logger->log_entry (db::NetlistCompareLogger::Info,
tl::sprintf (tl::to_string (tr ("Matching nets %s following an ambiguous match")), nets2string (n->net (), n_other->net ())));
}
@ -1550,7 +1551,7 @@ NetlistCompareCore::derive_node_identities_from_node_set (std::vector<NodeEdgePa
}
if (max_depth != std::numeric_limits<size_t>::max() && depth > max_depth) {
if (logger->wants_log_entries ()) {
if (with_log) {
logger->log_entry (db::NetlistCompareLogger::Warning, tl::sprintf (tl::to_string (tr ("Maximum depth exhausted (max depth is %d)")), int (max_depth)));
}
if (db::NetlistCompareGlobalOptions::options ()->debug_netcompare) {
@ -1668,7 +1669,7 @@ NetlistCompareCore::derive_node_identities_from_node_set (std::vector<NodeEdgePa
} else if (max_n_branch != std::numeric_limits<size_t>::max () && double (std::max (nr->num1, nr->num2)) * double (n_branch) > double (max_n_branch)) {
if (logger->wants_log_entries ()) {
if (with_log) {
logger->log_entry (db::NetlistCompareLogger::Warning, tl::sprintf (tl::to_string (tr ("Maximum complexity exhausted (max complexity is %s, needs at least %s)")), tl::to_string (max_n_branch), tl::to_string (std::max (nr->num1, nr->num2) * n_branch)));
}
if (db::NetlistCompareGlobalOptions::options ()->debug_netcompare) {

View File

@ -96,6 +96,7 @@ public:
bool dont_consider_net_names;
bool with_ambiguous;
NetlistCompareLogger *logger;
bool with_log;
CircuitPinCategorizer *circuit_pin_mapper;
SubCircuitEquivalenceTracker *subcircuit_equivalence;
DeviceEquivalenceTracker *device_equivalence;

View File

@ -71,15 +71,27 @@ nl_compare_debug_indent (size_t depth)
return s;
}
const std::string var_sep (" \u21D4 ");
const std::string var_sep = tl::to_string (tr (" vs. "));
static std::string
expanded_name (const db::Net *a)
{
if (a == 0) {
return tl::to_string (tr ("(not connected)"));
} else {
return a->expanded_name ();
}
}
std::string
nets2string (const db::Net *a, const db::Net *b)
{
if (a->expanded_name () != b->expanded_name ()) {
return a->expanded_name () + var_sep + b->expanded_name ();
std::string na = expanded_name (a);
std::string nb = expanded_name (b);
if (na != nb) {
return na + var_sep + nb;
} else {
return a->expanded_name ();
return nb;
}
}

View File

@ -27,7 +27,6 @@ namespace db
{
NetlistCrossReference::NetlistCrossReference ()
: m_wants_log_entries (true)
{
// .. nothing yet ..
}

View File

@ -258,16 +258,6 @@ public:
gen_subcircuits (a, b, Mismatch, msg);
}
virtual bool wants_log_entries () const
{
return m_wants_log_entries;
}
void set_wants_log_entries (bool f)
{
m_wants_log_entries = f;
}
void clear ();
size_t circuit_count () const
@ -329,7 +319,6 @@ private:
std::pair<const db::Circuit *, const db::Circuit *> m_current_circuits;
PerCircuitData *mp_per_circuit_data;
PerCircuitData::log_entries_type m_other_log_entries;
bool m_wants_log_entries;
void establish_pair (const db::Circuit *a, const db::Circuit *b);
void establish_pair (const db::Net *a, const db::Net *b, Status status, const std::string &msg);

View File

@ -34,7 +34,7 @@ class GenericNetlistCompareLogger
{
public:
GenericNetlistCompareLogger ()
: db::NetlistCompareLogger (), m_wants_log (false)
: db::NetlistCompareLogger ()
{
// .. nothing yet ..
}
@ -151,21 +151,6 @@ public:
db::NetlistCompareLogger::log_entry (severity, msg);
}
virtual bool wants_log () const
{
return m_wants_log;
}
bool get_wants_log () const
{
return m_wants_log;
}
void set_wants_log (bool f)
{
m_wants_log = f;
}
virtual void match_nets (const db::Net *a, const db::Net *b)
{
if (cb_match_nets.can_issue ()) {
@ -329,7 +314,6 @@ public:
gsi::Callback cb_match_nets;
gsi::Callback cb_circuit_mismatch;
gsi::Callback cb_log_entry;
gsi::Callback cb_wants_log;
gsi::Callback cb_net_mismatch;
gsi::Callback cb_match_ambiguous_nets;
gsi::Callback cb_match_devices;
@ -344,8 +328,6 @@ public:
private:
GenericNetlistCompareLogger (const GenericNetlistCompareLogger &d);
GenericNetlistCompareLogger &operator= (const GenericNetlistCompareLogger &d);
bool m_wants_log;
};
}
@ -405,20 +387,7 @@ Class<GenericNetlistCompareLogger> decl_GenericNetlistCompareLogger (decl_dbNetl
gsi::callback ("log_entry", &GenericNetlistCompareLogger::log_entry, &GenericNetlistCompareLogger::cb_log_entry, gsi::arg ("level"), gsi::arg ("msg"),
"@brief Issues an entry for the compare log.\n"
"This method delivers a log message generated during the compare of two circuits.\n"
"It is called between of \\begin_circuit and \\end_circuit and only if \\wants_log returns true.\n"
"\n"
"This method has been added in version 0.28."
) +
gsi::method ("wants_log=", &GenericNetlistCompareLogger::set_wants_log, gsi::arg ("value"),
"@brief Sets a value indicating whether the receiver wants log messages.\n"
"Log messages may include compare hints which are expensive to compute. Hence, by default, log generation is turned off. "
"Set this attribute to true in order to receive log messages.\n"
"\n"
"This method has been added in version 0.28."
) +
gsi::method ("wants_log", &GenericNetlistCompareLogger::get_wants_log,
"@brief Gets a value indicating whether the receiver wants log messages.\n"
"See \\wants_log= for details about this flag.\n"
"It is called between of \\begin_circuit and \\end_circuit.\n"
"\n"
"This method has been added in version 0.28."
) +
@ -525,6 +494,19 @@ Class<db::NetlistComparer> decl_dbNetlistComparer ("db", "NetlistComparer",
"The logger is a delegate or event receiver which the comparer will send compare events to. "
"See the class description for more details."
) +
gsi::method ("with_log=", &db::NetlistComparer::set_with_log, gsi::arg ("flag"),
"@brief Sets a value indicating that log messages are generated.\n"
"Log messages may be expensive to compute, hence they can be turned off.\n"
"By default, log messages are generated.\n"
"\n"
"This attribute have been introduced in version 0.28.\n"
) +
gsi::method ("with_log", &db::NetlistComparer::with_log,
"@brief Gets a value indicating that log messages are generated.\n"
"See \\with_log= for details about this flag.\n"
"\n"
"This attribute have been introduced in version 0.28.\n"
) +
gsi::method ("same_nets", (void (db::NetlistComparer::*) (const db::Net *, const db::Net *, bool)) &db::NetlistComparer::same_nets, gsi::arg ("net_a"), gsi::arg ("net_b"), gsi::arg ("must_match", false),
"@brief Marks two nets as identical.\n"
"This makes a net net_a in netlist a identical to the corresponding\n"

View File

@ -90,10 +90,16 @@ module LVS
# %LVS%
# @name compare
# @brief Compares the extracted netlist vs. the schematic
# @brief Compares the extracted netlist vs. the schematic netlist
# @synopsis compare
# See \Netter#compare for a description of that function.
# %LVS%
# @name no_lvs_hints
# @brief Disables LVS hints
# @synopsis no_lvs_hints
# See \Netter#no_lvs_hints for a description of that feature.
# %LVS%
# @name join_symmetric_nets
# @brief Joins symmetric nets of selected circuits on the extracted netlist
@ -216,7 +222,7 @@ module LVS
%w(schematic compare split_gates join_symmetric_nets tolerance ignore_parameter enable_parameter disable_parameter
blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins
min_caps max_res max_depth max_branch_complexity consider_net_names lvs_data).each do |f|
min_caps max_res max_depth max_branch_complexity consider_net_names lvs_data no_lvs_hints).each do |f|
eval <<"CODE"
def #{f}(*args)
_netter.#{f}(*args)

View File

@ -499,6 +499,7 @@ CODE
def _comparer_mini
comparer = RBA::NetlistComparer::new
comparer.with_log = false
# execute the configuration commands
@comparer_miniconfig.each do |cc|
@ -518,6 +519,17 @@ CODE
end
# %LVS%
# @name no_lvs_hints
# @brief Disables LVS hints
# @synopsis no_lvs_hints
# LVS hints may be expensive to compute. Use this function to disable
# generation of LVS hints
def no_lvs_hints
@comparer_config << lambda { |comparer| comparer.with_log = false }
end
# %LVS%
# @name same_nets
# @brief Establishes an equivalence between the nets

View File

@ -645,6 +645,10 @@ xref(
)
)
circuit(RINGO RINGO nomatch
log(
entry(error description('Net $I22 is not matching any net from reference netlist'))
entry(error description('Net FB is not matching any net from reference netlist'))
)
xref(
net(8 () mismatch)
net(7 7 match)

View File

@ -645,6 +645,10 @@ xref(
)
)
circuit(RINGO RINGO nomatch
log(
entry(error description('Net $I22 is not matching any net from reference netlist'))
entry(error description('Net FB is not matching any net from reference netlist'))
)
xref(
net(8 () mismatch)
net(7 7 match)

View File

@ -645,6 +645,10 @@ xref(
)
)
circuit(RINGO RINGO nomatch
log(
entry(error description('Net $I22 is not matching any net from reference netlist'))
entry(error description('Net FB is not matching any net from reference netlist'))
)
xref(
net(8 () mismatch)
net(7 7 match)

View File

@ -645,6 +645,10 @@ xref(
)
)
circuit(RINGO RINGO nomatch
log(
entry(error description('Net $I22 is not matching any net from reference netlist'))
entry(error description('Net FB is not matching any net from reference netlist'))
)
xref(
net(8 () mismatch)
net(7 7 match)

View File

@ -447,6 +447,9 @@ xref(
)
)
circuit(testall TESTALL nomatch
log(
entry(error description('Net $5 is not matching any net from reference netlist'))
)
xref(
net(() 7 mismatch)
net(2 2 match)

View File

@ -293,6 +293,9 @@ xref(
)
)
circuit(BWBTEST BWBTEST nomatch
log(
entry(error description('No equivalent pin A from reference netlist found in netlist.\nThis is an indication that a physical connection is not made to the subcircuit.'))
)
xref(
pin(() 0 mismatch)
pin(0 1 match)

View File

@ -288,6 +288,9 @@ xref(
)
)
circuit(BWBTEST BWBTEST nomatch
log(
entry(error description('No equivalent pin A from reference netlist found in netlist.\nThis is an indication that a physical connection is not made to the subcircuit.'))
)
xref(
pin(() 0 mismatch)
pin(() 1 match)

View File

@ -450,6 +450,11 @@ xref(
)
)
circuit(testall TESTALL nomatch
log(
entry(error description('Net $10 is not matching any net from reference netlist'))
entry(error description('Net $5 is not matching any net from reference netlist'))
entry(info description('Connecting nets $10 and $5 is making a better match to net D1 from reference netlist (fuzziness 0 nodes)'))
)
xref(
net(5 () mismatch)
net(2 2 match)

View File

@ -326,6 +326,11 @@ xref(
)
)
circuit(testall TESTALL nomatch
log(
entry(error description('Net $10 is not matching any net from reference netlist'))
entry(error description('Net $5 is not matching any net from reference netlist'))
entry(info description('Connecting nets $10 and $5 is making a better match to net D1 from reference netlist (fuzziness 0 nodes)'))
)
xref(
net(5 () mismatch)
net(2 2 match)

View File

@ -446,6 +446,9 @@ xref(
)
)
circuit(testall TESTALL nomatch
log(
entry(error description('Net $2 is not matching any net from reference netlist'))
)
xref(
net(() 6 mismatch)
net(3 2 match)

View File

@ -322,6 +322,9 @@ xref(
)
)
circuit(testall TESTALL nomatch
log(
entry(error description('Net $2 is not matching any net from reference netlist'))
)
xref(
net(() 6 mismatch)
net(3 2 match)

View File

@ -181,6 +181,10 @@ xref(
)
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets 3 are paired explicitly, but are not identical topologically'))
entry(error description('Nets 4 are paired explicitly, but are not identical topologically'))
)
xref(
net(4 1 match)
net(3 2 match)

View File

@ -184,6 +184,9 @@ xref(
)
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
)
xref(
net(() 7 mismatch)
net(1 () mismatch)

View File

@ -180,6 +180,11 @@ xref(
)
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
)
xref(
net(() 5 mismatch)
net(() 7 mismatch)

View File

@ -183,6 +183,12 @@ xref(
)
)
circuit(TOP TOP nomatch
log(
entry(error description('Nets $1 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 5 are paired explicitly, but are not identical topologically'))
entry(error description('Nets 5,7 vs. (not connected) are paired explicitly, but are not identical topologically'))
entry(error description('Nets (not connected) vs. 7 are paired explicitly, but are not identical topologically'))
)
xref(
net(() 5 mismatch)
net(() 7 mismatch)

View File

@ -100,6 +100,10 @@ reference(
# Cross reference
xref(
circuit(TOP TOP match
log(
entry(warning description('Matching nets $13 vs. R1 from an ambiguous group of nets'))
entry(warning description('Matching nets $14 vs. R2 from an ambiguous group of nets'))
)
xref(
net(1 1 warning)
net(2 2 warning)

View File

@ -290,6 +290,12 @@ Z(
)
)
X(INV2 INV2 1
L(
M(W B('Matching nets Q1 from an ambiguous group of nets'))
M(W B('Matching nets Q2 from an ambiguous group of nets'))
M(I B('Matching nets A1 following an ambiguous match'))
M(I B('Matching nets A2 following an ambiguous match'))
)
Z(
N(1 3 1)
N(2 5 1)

View File

@ -290,6 +290,12 @@ Z(
)
)
X(INV2 INV2 1
L(
M(W B('Matching nets Q1 from an ambiguous group of nets'))
M(W B('Matching nets Q2 from an ambiguous group of nets'))
M(I B('Matching nets A1 following an ambiguous match'))
M(I B('Matching nets A2 following an ambiguous match'))
)
Z(
N(1 3 1)
N(2 5 1)

View File

@ -107,6 +107,10 @@ reference(
# Cross reference
xref(
circuit(Rre RRE nomatch
log(
entry(error description('Net gnd! is not matching any net from reference netlist'))
entry(error description('Net vdd! is not matching any net from reference netlist'))
)
xref(
net(() 2 mismatch)
net(() 1 mismatch)

View File

@ -377,6 +377,12 @@ reference(
# Cross reference
xref(
circuit(DINV DINV match
log(
entry(warning description('Matching nets B<1> from an ambiguous group of nets'))
entry(warning description('Matching nets B<2> from an ambiguous group of nets'))
entry(info description('Matching nets A<1> following an ambiguous match'))
entry(info description('Matching nets A<2> following an ambiguous match'))
)
xref(
net(1 1 match)
net(2 2 match)

View File

@ -417,6 +417,12 @@ Z(
)
)
X(INV2 INV2 1
L(
M(W B('Matching nets $I8 vs. 4 from an ambiguous group of nets'))
M(W B('Matching nets $I7 vs. 6 from an ambiguous group of nets'))
M(I B('Matching nets $I6 vs. 3 following an ambiguous match'))
M(I B('Matching nets $I5 vs. 5 following an ambiguous match'))
)
Z(
N(5 1 1)
N(6 2 1)
@ -435,6 +441,14 @@ Z(
)
)
X(INV3 INV3 1
L(
M(W B('Matching nets 4 from an ambiguous group of nets'))
M(W B('Matching nets 6 from an ambiguous group of nets'))
M(W B('Matching nets 8 from an ambiguous group of nets'))
M(I B('Matching nets 3 following an ambiguous match'))
M(I B('Matching nets 5 following an ambiguous match'))
M(I B('Matching nets 7 following an ambiguous match'))
)
Z(
N(7 1 1)
N(8 2 1)

View File

@ -94,4 +94,5 @@ schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
no_lvs_hints
compare

View File

@ -93,4 +93,5 @@ schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
no_lvs_hints
compare

View File

@ -88,4 +88,5 @@ schematic.simplify
# Netlist vs. netlist
align
netlist.simplify
no_lvs_hints
compare