Add +verilator+error+limit to see more assertion errors.

This commit is contained in:
Wilson Snyder 2019-11-16 18:25:47 -05:00
parent 8ebe86e54b
commit d480c2f033
11 changed files with 127 additions and 29 deletions

View File

@ -4,7 +4,9 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.023 devel
**** Support $rewind and $ungetc.
*** Add +verilator+error+limit to see more assertion errors. [Peter Monsson]
*** Support $rewind and $ungetc.
**** Add -Wpedantic for compliance testing.

View File

@ -795,8 +795,10 @@ will also go to standard out.
=item --error-limit I<value>
After this number of errors are encountered, exit. Warnings are not
counted in this limit. Defaults to 50.
After this number of errors are encountered during Verilator run, exit.
Warnings are not counted in this limit. Defaults to 50.
Does not affect runtime errors, for those see +verilator+error+limit.
=item --exe
@ -1701,11 +1703,16 @@ may skip over all +verilator arguments when parsing its command line.
=item +verilator+debug
Enable debugging. Equivalent to +verilator+debugi+4.
Enable runtime debugging. Equivalent to +verilator+debugi+4.
=item +verilator+debugi+I<value>
Enable debugging at the provided level.
Enable runtime debugging at the provided level.
=item +verilator+error+limit+I<value>
Set number of non-fatal errors (e.g. assertion failures) before exiting
simulation. Defaults to 1.
=item +verilator+help
@ -1713,20 +1720,20 @@ Display help and exit.
=item +verilator+prof+threads+file+I<filename>
When using --prof-threads, the filename to dump to. Defaults to
When using --prof-threads at runtime, the filename to dump to. Defaults to
"profile_threads.dat".
=item +verilator+prof+threads+start+I<value>
When using --prof-threads, Verilator will wait until $time is at this
value, then start the profiling warmup, then capturing. Generally this
When using --prof-threads at runtime, Verilator will wait until $time is at
this value, then start the profiling warmup, then capturing. Generally this
should be set to some time that is well within the normal operation of the
simulation, i.e. outside of reset. If 0, the dump is disabled. Defaults to
1.
=item +verilator+prof+threads+window+I<value>
When using --prof-threads, after $time reaches
When using --prof-threads at runtime, after $time reaches
+verilator+prof+threads+start, Verilator will warm up the profiling for
this number of eval() calls, then will capture the profiling of this number
of eval() calls. Defaults to 2, which makes sense for a
@ -1735,14 +1742,15 @@ posedge eval() and one negedge eval().
=item +verilator+rand+reset+I<value>
When a model was Verilated using "-x-initial unique", sets the
When a model was Verilated using "-x-initial unique", sets the runtime
initialization technique. 0 = Reset to zeros. 1 = Reset to all-ones. 2 =
Randomize. See L</"Unknown states">.
=item +verilator+seed+I<value>
For $random and "-x-initial unique", set the random seed value. If zero or
not specified picks a value from the system random number generator.
For $random and "-x-initial unique", set the runtime random seed value. If
zero or not specified picks a value from the system random number
generator.
=item +verilator+V

View File

@ -71,6 +71,8 @@ VerilatedImp VerilatedImp::s_s;
//===========================================================================
// User definable functions
// Note a TODO is a future version of the API will pass a structure so that
// the calling arguments allow for extension
#ifndef VL_USER_FINISH ///< Define this to override this function
void vl_finish(const char* filename, int linenum, const char* hier) VL_MT_UNSAFE {
@ -109,6 +111,16 @@ void vl_fatal(const char* filename, int linenum, const char* hier, const char* m
}
#endif
//===========================================================================
// Error handline
void vl_stop_maybe(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_UNSAFE {
Verilated::errorCountInc();
if (!maybe || Verilated::errorCount() >= Verilated::errorLimit()) {
vl_stop(filename, linenum, hier);
}
}
//===========================================================================
// Wrapper to call certain functions via messages when multithreaded
@ -122,13 +134,13 @@ void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAF
#endif
}
void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE {
void VL_STOP_MT(const char* filename, int linenum, const char* hier, bool maybe) VL_MT_SAFE {
#ifdef VL_THREADED
VerilatedThreadMsgQueue::post(VerilatedMsg([=](){
vl_stop(filename, linenum, hier);
vl_stop_maybe(filename, linenum, hier, maybe);
}));
#else
vl_stop(filename, linenum, hier);
vl_stop_maybe(filename, linenum, hier, maybe);
#endif
}
@ -215,13 +227,15 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
// Overall class init
Verilated::Serialized::Serialized() {
s_randReset = 0;
s_randSeed = 0;
s_debug = 0;
s_calcUnusedSigs = false;
s_gotFinish = false;
s_assertOn = true;
s_fatalOnVpiError = true; // retains old default behaviour
s_errorCount = 0;
s_errorLimit = 1;
s_randReset = 0;
s_randSeed = 0;
}
Verilated::NonSerialized::NonSerialized() {
@ -1802,6 +1816,18 @@ void Verilated::calcUnusedSigs(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_calcUnusedSigs = flag;
}
void Verilated::errorCount(int val) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_errorCount = val;
}
void Verilated::errorCountInc() VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
++s_s.s_errorCount;
}
void Verilated::errorLimit(int val) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_errorLimit = val;
}
void Verilated::gotFinish(bool flag) VL_MT_SAFE {
VerilatedLockGuard lock(m_mutex);
s_s.s_gotFinish = flag;
@ -1991,6 +2017,9 @@ void VerilatedImp::commandArgVl(const std::string& arg) {
else if (commandArgVlValue(arg, "+verilator+debugi+", value/*ref*/)) {
Verilated::debug(atoi(value.c_str()));
}
else if (commandArgVlValue(arg, "+verilator+error+limit+", value/*ref*/)) {
Verilated::errorLimit(atoi(value.c_str()));
}
else if (arg == "+verilator+help") {
versionDump();
VL_PRINTF_MT("For help, please see 'verilator --help'\n");

View File

@ -355,6 +355,8 @@ class Verilated {
bool s_assertOn; ///< Assertions are enabled
bool s_fatalOnVpiError; ///< Stop on vpi error/unsupported
// Slow path
int s_errorCount; ///< Number of errors
int s_errorLimit; ///< Stop on error number
int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
int s_randSeed; ///< Random seed: 0=random
Serialized();
@ -427,6 +429,13 @@ public:
static void calcUnusedSigs(bool flag) VL_MT_SAFE;
static bool calcUnusedSigs() VL_MT_SAFE { ///< Return calcUnusedSigs value
return s_s.s_calcUnusedSigs; }
/// Current number of errors/assertions
static void errorCount(int val) VL_MT_SAFE;
static void errorCountInc() VL_MT_SAFE;
static int errorCount() VL_MT_SAFE { return s_s.s_errorCount; }
/// Set number of errors/assertions before stop
static void errorLimit(int val) VL_MT_SAFE;
static int errorLimit() VL_MT_SAFE { return s_s.s_errorLimit; }
/// Did the simulation $finish?
static void gotFinish(bool flag) VL_MT_SAFE;
static bool gotFinish() VL_MT_SAFE { return s_s.s_gotFinish; } ///< Return if got a $finish
@ -565,7 +574,8 @@ extern void vl_fatal(const char* filename, int linenum, const char* hier,
/// Multithread safe wrapper for calls to $finish
extern void VL_FINISH_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE;
/// Multithread safe wrapper for calls to $stop
extern void VL_STOP_MT(const char* filename, int linenum, const char* hier) VL_MT_SAFE;
extern void VL_STOP_MT(const char* filename, int linenum, const char* hier,
bool maybe = false) VL_MT_SAFE;
/// Multithread safe wrapper to call for a couple of fatal messages
extern void VL_FATAL_MT(const char* filename, int linenum, const char* hier,
const char* msg) VL_MT_SAFE;

View File

@ -94,7 +94,7 @@ private:
AstDisplayType::DT_ERROR, message, NULL, NULL);
AstNode* bodysp = dispp;
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
bodysp->addNext(new AstStop(nodep->fileline()));
bodysp->addNext(new AstStop(nodep->fileline(), true));
return bodysp;
}

View File

@ -3584,9 +3584,11 @@ public:
};
class AstStop : public AstNodeStmt {
bool m_maybe; // Maybe stop, maybe not based on error count
public:
explicit AstStop(FileLine* fl)
: AstNodeStmt(fl) {}
explicit AstStop(FileLine* fl, bool maybe)
: AstNodeStmt(fl)
, m_maybe(maybe) {}
ASTNODE_NODE_FUNCS(Stop)
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
@ -3597,6 +3599,7 @@ public:
virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); }
virtual bool same(const AstNode* samep) const {
return fileline() == samep->fileline(); }
bool maybe() const { return m_maybe; }
};
class AstFinish : public AstNodeStmt {

View File

@ -532,7 +532,9 @@ public:
putsQuoted(protect(nodep->fileline()->filename()));
puts(", ");
puts(cvtToStr(nodep->fileline()->lineno()));
puts(", \"\");\n");
puts(", \"\"");
if (nodep->maybe()) puts(", true");
puts(");\n");
}
virtual void visit(AstFinish* nodep) {
puts("VL_FINISH_MT(");

View File

@ -106,7 +106,7 @@ public:
}
AstDisplay* createDisplayError(FileLine* fileline) {
AstDisplay* nodep = new AstDisplay(fileline,AstDisplayType::DT_ERROR, "", NULL,NULL);
nodep->addNext(new AstStop(fileline));
nodep->addNext(new AstStop(fileline, true));
return nodep;
}
AstNode* createGatePin(AstNode* exprp) {
@ -2850,8 +2850,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); }
| yD_FINISH parenE { $$ = new AstFinish($1); }
| yD_FINISH '(' expr ')' { $$ = new AstFinish($1); DEL($3); }
| yD_STOP parenE { $$ = new AstStop($1); }
| yD_STOP '(' expr ')' { $$ = new AstStop($1); DEL($3); }
| yD_STOP parenE { $$ = new AstStop($1, false); }
| yD_STOP '(' expr ')' { $$ = new AstStop($1, false); DEL($3); }
//
| yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
@ -2868,10 +2868,10 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, NULL); }
| yD_WARNING '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, $3); }
| yD_ERROR parenE { $$ = GRAMMARP->createDisplayError($1); }
| yD_ERROR '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, NULL, $3); $$->addNext(new AstStop($1)); }
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1)); }
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1)); DEL($3); }
| yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1)); DEL($3); }
| yD_ERROR '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, NULL, $3); $$->addNext(new AstStop($1, true)); }
| yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); }
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); DEL($3); }
| yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1, false)); DEL($3); }
//
| yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); }
| yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); }

View File

@ -0,0 +1,5 @@
[0] %Error: t_runflag_errlimit.v:8: Assertion failed in top.t: One
[0] %Error: t_runflag_errlimit.v:9: Assertion failed in top.t: Two
[0] %Error: t_runflag_errlimit.v:10: Assertion failed in top.t: Three
%Error: t/t_runflag_errlimit.v:10: Verilog $stop
Aborting...

View File

@ -0,0 +1,23 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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(vlt_all => 1);
compile(
);
execute(
all_run_flags => ["+verilator+error+limit+3"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,16 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2019 by Wilson Snyder.
module t;
initial begin
$error("One");
$error("Two");
$error("Three");
$error("Four");
$error("Five");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule