Improve error messages on DIDNOTSETTLE, bug1556.
This commit is contained in:
parent
c1a9ada279
commit
f1b10e2b4c
|
|
@ -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.
|
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
|
=item ENDLABEL
|
||||||
|
|
||||||
Warns that a label attached to a "end"-something statement does not match
|
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
|
This error indicates that you are using a Verilog language construct
|
||||||
that is not yet supported in Verilator. See the Limitations chapter.
|
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
|
=back
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1785,7 +1785,8 @@ void Verilated::debug(int level) VL_MT_SAFE {
|
||||||
" Message prefix indicates {<thread>,<sequence_number>}.\n"););
|
" Message prefix indicates {<thread>,<sequence_number>}.\n"););
|
||||||
#else
|
#else
|
||||||
VL_PRINTF_MT("- Verilated::debug attempted,"
|
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
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1196,7 +1196,7 @@ class EmitCImp : EmitCStmts {
|
||||||
puts(")) VL_DBG_MSGF(\" CHANGE: ");
|
puts(")) VL_DBG_MSGF(\" CHANGE: ");
|
||||||
puts(protect(nodep->fileline()->filename()));
|
puts(protect(nodep->fileline()->filename()));
|
||||||
puts(":"+cvtToStr(nodep->fileline()->lineno()));
|
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) {
|
void EmitCImp::emitTextSection(AstType type) {
|
||||||
int last_line = -999;
|
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 (const AstNodeText* textp = VN_CAST(nodep, NodeText)) {
|
||||||
if (nodep->type() == type) {
|
if (nodep->type() == type) {
|
||||||
if (last_line != nodep->fileline()->lineno()) {
|
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("int __VclockLoop = 0;\n");
|
||||||
puts("QData __Vchange = 1;\n");
|
puts("QData __Vchange = 1;\n");
|
||||||
puts("do {\n");
|
puts("do {\n");
|
||||||
puts( eval_call + "\n");
|
puts( eval_call+"\n");
|
||||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||||
+")) {\n");
|
+")) {\n");
|
||||||
puts( "// About to fail, so enable debug to see what's not settling.\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( "Verilated::debug(1);\n");
|
||||||
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
||||||
puts( "Verilated::debug(__Vsaved_debug);\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 ");
|
if (initial) puts("DC ");
|
||||||
puts( "converge\");\n");
|
puts("converge\\n\"\n");
|
||||||
|
puts("\"- See DIDNOTCONVERGE in the Verilator manual\");\n");
|
||||||
puts( "} else {\n");
|
puts( "} else {\n");
|
||||||
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
puts( "__Vchange = "+protect("_change_request")+"(vlSymsp);\n");
|
||||||
puts( "}\n");
|
puts( "}\n");
|
||||||
|
|
|
||||||
|
|
@ -1960,6 +1960,7 @@ sub files_identical {
|
||||||
} @l1;
|
} @l1;
|
||||||
@l1 = map {
|
@l1 = map {
|
||||||
s/(Internal Error: [^\n]+\.cpp):[0-9]+:/$1:#:/;
|
s/(Internal Error: [^\n]+\.cpp):[0-9]+:/$1:#:/;
|
||||||
|
s/^-V\{t[0-9]+,[0-9]+\}/-V{t#,#}/; # --vlt vs --vltmt run differences
|
||||||
$_;
|
$_;
|
||||||
} @l1;
|
} @l1;
|
||||||
for (my $l=0; $l<=$#l1; ++$l) {
|
for (my $l=0; $l<=$#l1; ++$l) {
|
||||||
|
|
|
||||||
|
|
@ -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...
|
||||||
|
|
@ -17,7 +17,7 @@ compile(
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect => '%Error: \S+:\d+: Verilated model didn\'t DC converge',
|
expect_filename => $Self->{golden_filename},
|
||||||
) if $Self->{vlt_all};
|
) if $Self->{vlt_all};
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
%Error: t/t_unopt_converge.v:6: Verilated model didn't converge
|
||||||
|
Aborting...
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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...
|
||||||
|
|
@ -19,7 +19,7 @@ compile(
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect => '%Error: \S+:\d+: Verilated model didn\'t converge',
|
expect_filename => $Self->{golden_filename},
|
||||||
) if $Self->{vlt_all};
|
) if $Self->{vlt_all};
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|
|
||||||
|
|
@ -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...
|
||||||
|
|
@ -17,7 +17,7 @@ compile(
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
fails => 1,
|
fails => 1,
|
||||||
expect => '%Error: \S+:\d+: Verilated model didn\'t converge',
|
expect_filename => $Self->{golden_filename},
|
||||||
) if $Self->{vlt_all};
|
) if $Self->{vlt_all};
|
||||||
|
|
||||||
ok(1);
|
ok(1);
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,24 @@
|
||||||
-V{t0,1}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
|
-V{t#,#}- Verilated::debug is on. Message prefix indicates {<thread>,<sequence_number>}.
|
||||||
-V{t0,2}+ Vt_verilated_debug::_ctor_var_reset
|
-V{t#,#}+ Vt_verilated_debug::_ctor_var_reset
|
||||||
internalsDump:
|
internalsDump:
|
||||||
Version: Verilator ###
|
Version: Verilator ###
|
||||||
Argv: obj_vlt/t_verilated_debug/Vt_verilated_debug
|
Argv: obj_vlt/t_verilated_debug/Vt_verilated_debug
|
||||||
scopesDump:
|
scopesDump:
|
||||||
|
|
||||||
-V{t0,3}+++++TOP Evaluate Vt_verilated_debug::eval
|
-V{t#,#}+++++TOP Evaluate Vt_verilated_debug::eval
|
||||||
-V{t0,4}+ Vt_verilated_debug::_eval_debug_assertions
|
-V{t#,#}+ Vt_verilated_debug::_eval_debug_assertions
|
||||||
-V{t0,5}+ Vt_verilated_debug::_eval_initial
|
-V{t#,#}+ Vt_verilated_debug::_eval_initial
|
||||||
-V{t0,6}+ Vt_verilated_debug::_eval_settle
|
-V{t#,#}+ Vt_verilated_debug::_eval_settle
|
||||||
-V{t0,7}+ Vt_verilated_debug::_eval
|
-V{t#,#}+ Vt_verilated_debug::_eval
|
||||||
-V{t0,8}+ Vt_verilated_debug::_change_request
|
-V{t#,#}+ Vt_verilated_debug::_change_request
|
||||||
-V{t0,9}+ Clock loop
|
-V{t#,#}+ Clock loop
|
||||||
-V{t0,10}+ Vt_verilated_debug::_eval
|
-V{t#,#}+ Vt_verilated_debug::_eval
|
||||||
-V{t0,11}+ Vt_verilated_debug::_change_request
|
-V{t#,#}+ Vt_verilated_debug::_change_request
|
||||||
-V{t0,12}+++++TOP Evaluate Vt_verilated_debug::eval
|
-V{t#,#}+++++TOP Evaluate Vt_verilated_debug::eval
|
||||||
-V{t0,13}+ Vt_verilated_debug::_eval_debug_assertions
|
-V{t#,#}+ Vt_verilated_debug::_eval_debug_assertions
|
||||||
-V{t0,14}+ Clock loop
|
-V{t#,#}+ Clock loop
|
||||||
-V{t0,15}+ Vt_verilated_debug::_eval
|
-V{t#,#}+ Vt_verilated_debug::_eval
|
||||||
-V{t0,16}+ Vt_verilated_debug::_sequent__TOP__1
|
-V{t#,#}+ Vt_verilated_debug::_sequent__TOP__1
|
||||||
*-* All Finished *-*
|
*-* All Finished *-*
|
||||||
-V{t0,17}+ Vt_verilated_debug::_change_request
|
-V{t#,#}+ Vt_verilated_debug::_change_request
|
||||||
-V{t0,18}+ Vt_verilated_debug::final
|
-V{t#,#}+ Vt_verilated_debug::final
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue