Improve error messages on DIDNOTSETTLE, bug1556.

This commit is contained in:
Wilson Snyder 2019-11-06 19:47:34 -05:00
parent c1a9ada279
commit f1b10e2b4c
13 changed files with 114 additions and 63 deletions

View File

@ -3847,6 +3847,43 @@ as an unpacked struct or a large unpacked array. This typically occurs when
The solution is to break the loop, as described for UNOPTFLAT.
=item DIDNOTCONVERGE
Error at runtime when model did not properly settle.
Verilator sometimes has to evaluate combinatorial logic multiple times,
usually around code where a UNOPTFLAT warning was issued, but disabled.
For example:
always_comb b = ~a;
always_comb a = b
This code will toggle forever, and thus to prevent an infinite loop, the
executable will give the didn't converge error.
To debug this, first is to review any UNOPTFLAT warnings that were ignored.
Though typically it is safe to ignore UNOPTFLAT (at a performance cost), at
the time of issuing a UNOPTFLAT Verilator didn't know if they would
eventually converge and assumed the would.
Next, run Verilator with --prof-cfuncs. Run make on the generated files
with "CPP_FLAGS=-DVL_DEBUG", to allow enabling runtime debug messages.
Rerun the test. Now just before the convergence error you should see
additional output similar to this:
CHANGE: filename.v:1: b
CHANGE: filename.v:2: a
This means that signal b and signal a keep changing, inspect the code that
modifies these signals. Note if many signals are getting printed then most
likely all of them are oscillating. It may also be that e.g. "a" may be
oscillating, then "a" feeds signal "c" which then is also reported as
oscillating.
Finally, rare, more difficult cases can be debugged like a "C" program;
either enter GDB and use its tracing facilities, or edit the generated C++
code to add appropriate prints to see what is going on.
=item ENDLABEL
Warns that a label attached to a "end"-something statement does not match
@ -4378,42 +4415,6 @@ warnings or errors, submit a bug report.
This error indicates that you are using a Verilog language construct
that is not yet supported in Verilator. See the Limitations chapter.
=item Verilated model didn't converge
Verilator sometimes has to evaluate combinatorial logic multiple times,
usually around code where a UNOPTFLAT warning was issued, but disabled.
For example:
always @ (a) b=~a;
always @ (b) a=b
will toggle forever and thus the executable will give the didn't converge
error to prevent an infinite loop.
To debug this, first is to review any UNOPTFLAT warnings that were ignored,
though typically these can be ignored (at a performance cost), convergence
issues can also be flagged with this warning as Verilator didn't know if
they would eventually converge.
Next, run Verilator with --prof-cfuncs. Run make on the generated
files with "OPT=-DVL_DEBUG". Then call Verilated::debug(1) in your
main.cpp.
This will cause each change in a variable to print a message. Near the
bottom you'll see the variables that causes the problem. For the program
above:
CHANGE: filename.v:1: b
CHANGE: filename.v:2: a
If many signals are getting printed then most likely each are oscillating
(or there is a bug). It may also be that e.g. "a" may be oscillating, then
"a" feeds signal "c" which then is also reported as oscillating.
Finally, rare more difficult cases can be debugged like a "C" program;
either enter GDB and use its tracing facilities, or edit the generated C++
code to add appropriate prints to see what is going on.
=back

View File

@ -1785,7 +1785,8 @@ void Verilated::debug(int level) VL_MT_SAFE {
" Message prefix indicates {<thread>,<sequence_number>}.\n"););
#else
VL_PRINTF_MT("- Verilated::debug attempted,"
" but compiled without VL_DEBUG, so messages suppressed.\n");
" but compiled without VL_DEBUG, so messages suppressed.\n"
"- Suggest remake using 'make ... CPPFLAGS=-DVL_DEBUG'\n");
#endif
}
}

View File

@ -1196,7 +1196,7 @@ class EmitCImp : EmitCStmts {
puts(")) VL_DBG_MSGF(\" CHANGE: ");
puts(protect(nodep->fileline()->filename()));
puts(":"+cvtToStr(nodep->fileline()->lineno()));
puts(": "+varname+"\\n\"); );\n");
puts(varname+"\\n\"); );\n");
}
}
}
@ -2056,7 +2056,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
void EmitCImp::emitTextSection(AstType type) {
int last_line = -999;
for (AstNode* nodep = m_modp->stmtsp(); nodep != NULL; nodep = nodep->nextp()) {
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
if (const AstNodeText* textp = VN_CAST(nodep, NodeText)) {
if (nodep->type() == type) {
if (last_line != nodep->fileline()->lineno()) {
@ -2131,7 +2131,7 @@ void EmitCImp::emitSettleLoop(const std::string& eval_call, bool initial) {
puts("int __VclockLoop = 0;\n");
puts("QData __Vchange = 1;\n");
puts("do {\n");
puts( eval_call + "\n");
puts( eval_call+"\n");
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
+")) {\n");
puts( "// About to fail, so enable debug to see what's not settling.\n");
@ -2140,9 +2140,15 @@ void EmitCImp::emitSettleLoop(const std::string& eval_call, bool initial) {
puts( "Verilated::debug(1);\n");
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
puts( "Verilated::debug(__Vsaved_debug);\n");
puts( "VL_FATAL_MT(__FILE__, __LINE__, __FILE__, \"Verilated model didn't ");
puts( "VL_FATAL_MT(");
putsQuoted(protect(m_modp->fileline()->filename()));
puts(", ");
puts(cvtToStr(m_modp->fileline()->lineno()));
puts(", \"\",\n");
puts("\"Verilated model didn't ");
if (initial) puts("DC ");
puts( "converge\");\n");
puts("converge\\n\"\n");
puts("\"- See DIDNOTCONVERGE in the Verilator manual\");\n");
puts( "} else {\n");
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
puts( "}\n");

View File

@ -1960,6 +1960,7 @@ sub files_identical {
} @l1;
@l1 = map {
s/(Internal Error: [^\n]+\.cpp):[0-9]+:/$1:#:/;
s/^-V\{t[0-9]+,[0-9]+\}/-V{t#,#}/; # --vlt vs --vltmt run differences
$_;
} @l1;
for (my $l=0; $l<=$#l1; ++$l) {

View File

@ -0,0 +1,5 @@
-V{t#,#}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
-V{t#,#}+ Vt_unopt_converge_initial_run_bad::_change_request
-V{t#,#} CHANGE: t/t_unopt_converge_initial.v:18: x
%Error: t/t_unopt_converge_initial.v:6: Verilated model didn't DC converge
Aborting...

View File

@ -17,7 +17,7 @@ compile(
execute(
fails => 1,
expect => '%Error: \S+:\d+: Verilated model didn\'t DC converge',
expect_filename => $Self->{golden_filename},
) if $Self->{vlt_all};
ok(1);

View File

@ -0,0 +1,2 @@
%Error: t/t_unopt_converge.v:6: Verilated model didn't converge
Aborting...

View File

@ -0,0 +1,25 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
scenarios(simulator => 1);
top_filename("t/t_unopt_converge.v");
compile(
v_flags2 => ['+define+ALLOW_UNOPT'],
make_flags => 'CPPFLAGS_ADD=-UVL_DEBUG',
);
execute(
fails => 1,
expect_filename => $Self->{golden_filename},
) if $Self->{vlt_all};
ok(1);
1;

View File

@ -0,0 +1,5 @@
-V{t#,#}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
-V{t#,#}+ Vt_unopt_converge_print_bad::_change_request
-V{t#,#} CHANGE: t/t_unopt_converge.v:18: x
%Error: t/t_unopt_converge.v:6: Verilated model didn't converge
Aborting...

View File

@ -19,7 +19,7 @@ compile(
execute(
fails => 1,
expect => '%Error: \S+:\d+: Verilated model didn\'t converge',
expect_filename => $Self->{golden_filename},
) if $Self->{vlt_all};
ok(1);

View File

@ -0,0 +1,5 @@
-V{t#,#}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
-V{t#,#}+ Vt_unopt_converge_run_bad::_change_request
-V{t#,#} CHANGE: t/t_unopt_converge.v:18: x
%Error: t/t_unopt_converge.v:6: Verilated model didn't converge
Aborting...

View File

@ -17,7 +17,7 @@ compile(
execute(
fails => 1,
expect => '%Error: \S+:\d+: Verilated model didn\'t converge',
expect_filename => $Self->{golden_filename},
) if $Self->{vlt_all};
ok(1);

View File

@ -1,24 +1,24 @@
-V{t0,1}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
-V{t0,2}+ Vt_verilated_debug::_ctor_var_reset
-V{t#,#}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
-V{t#,#}+ Vt_verilated_debug::_ctor_var_reset
internalsDump:
Version: Verilator ###
Argv: obj_vlt/t_verilated_debug/Vt_verilated_debug
scopesDump:
-V{t0,3}+++++TOP Evaluate Vt_verilated_debug::eval
-V{t0,4}+ Vt_verilated_debug::_eval_debug_assertions
-V{t0,5}+ Vt_verilated_debug::_eval_initial
-V{t0,6}+ Vt_verilated_debug::_eval_settle
-V{t0,7}+ Vt_verilated_debug::_eval
-V{t0,8}+ Vt_verilated_debug::_change_request
-V{t0,9}+ Clock loop
-V{t0,10}+ Vt_verilated_debug::_eval
-V{t0,11}+ Vt_verilated_debug::_change_request
-V{t0,12}+++++TOP Evaluate Vt_verilated_debug::eval
-V{t0,13}+ Vt_verilated_debug::_eval_debug_assertions
-V{t0,14}+ Clock loop
-V{t0,15}+ Vt_verilated_debug::_eval
-V{t0,16}+ Vt_verilated_debug::_sequent__TOP__1
-V{t#,#}+++++TOP Evaluate Vt_verilated_debug::eval
-V{t#,#}+ Vt_verilated_debug::_eval_debug_assertions
-V{t#,#}+ Vt_verilated_debug::_eval_initial
-V{t#,#}+ Vt_verilated_debug::_eval_settle
-V{t#,#}+ Vt_verilated_debug::_eval
-V{t#,#}+ Vt_verilated_debug::_change_request
-V{t#,#}+ Clock loop
-V{t#,#}+ Vt_verilated_debug::_eval
-V{t#,#}+ Vt_verilated_debug::_change_request
-V{t#,#}+++++TOP Evaluate Vt_verilated_debug::eval
-V{t#,#}+ Vt_verilated_debug::_eval_debug_assertions
-V{t#,#}+ Clock loop
-V{t#,#}+ Vt_verilated_debug::_eval
-V{t#,#}+ Vt_verilated_debug::_sequent__TOP__1
*-* All Finished *-*
-V{t0,17}+ Vt_verilated_debug::_change_request
-V{t0,18}+ Vt_verilated_debug::final
-V{t#,#}+ Vt_verilated_debug::_change_request
-V{t#,#}+ Vt_verilated_debug::final