mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add +verilator+error+limit to see more assertion errors.
This commit is contained in:
parent
8ebe86e54b
commit
d480c2f033
4
Changes
4
Changes
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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(");
|
||||
|
@ -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); }
|
||||
|
5
test_regress/t/t_runflag_errlimit.out
Normal file
5
test_regress/t/t_runflag_errlimit.out
Normal 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...
|
23
test_regress/t/t_runflag_errlimit.pl
Executable file
23
test_regress/t/t_runflag_errlimit.pl
Executable 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;
|
16
test_regress/t/t_runflag_errlimit.v
Normal file
16
test_regress/t/t_runflag_errlimit.v
Normal 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
|
Loading…
Reference in New Issue
Block a user