Support elaboration assertions, bug973.

This commit is contained in:
Wilson Snyder 2015-10-23 18:13:25 -04:00
parent 040b1b06d5
commit 4fde6ee7af
8 changed files with 152 additions and 8 deletions

View File

@ -11,6 +11,8 @@ indicates the contributor was also the author of the fix; Thanks!
** Support $sformatf, bug977. [Johan Bjork]
*** Support elaboration assertions, bug973. [Johan Bjork]
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
**** Fix very long module names, bug937. [Todd Strader]

View File

@ -3340,6 +3340,10 @@ with "unused" in the name, or put the appropriate lint_off around the wire.
Having unused signals in one place makes it easy to find what is unused,
and reduces the number of lint_off pragmas, reducing bugs.
=item USERINFO, USERWARN, USERERROR, USERFATAL
A SystemVerilog elaboration-time assertion print was executed.
=item VARHIDDEN
Warns that a task, function, or begin/end block is declaring a variable by

View File

@ -96,6 +96,10 @@ public:
UNPACKED, // Unsupported unpacked
UNSIGNED, // Comparison is constant due to unsigned arithmetic
UNUSED, // No receivers
USERERROR, // Elaboration time $error
USERFATAL, // Elaboration time $fatal
USERINFO, // Elaboration time $info
USERWARN, // Elaboration time $warning
VARHIDDEN, // Hiding variable
WIDTH, // Width mismatch
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
@ -132,6 +136,7 @@ public:
"REALCVT", "REDEFMACRO",
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNPACKED", "UNSIGNED", "UNUSED",
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
" MAX"
};

View File

@ -343,13 +343,6 @@ private:
virtual void visit(AstDisplay* nodep, AstNUser* vup) {
nodep->iterateChildren(*this);
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef());
if (!m_assertp
&& (nodep->displayType() == AstDisplayType::DT_INFO
|| nodep->displayType() == AstDisplayType::DT_WARNING
|| nodep->displayType() == AstDisplayType::DT_ERROR
|| nodep->displayType() == AstDisplayType::DT_FATAL)) {
nodep->v3error(nodep->verilogKwd()+" only allowed under an assertion.");
}
}
virtual void visit(AstUdpTable* nodep, AstNUser*) {

View File

@ -580,6 +580,7 @@ private:
}
}
virtual void visit(AstStop* nodep, AstNUser*) {
if (jumpingOver(nodep)) return;
if (m_params) { // This message seems better than an obscure $stop
// The spec says $stop is just ignored, it seems evil to ignore assertions
clearOptimizable(nodep,"$stop executed during function constification; maybe indicates assertion firing");
@ -695,9 +696,78 @@ private:
if (!m_params) { badNodeType(nodep); return; }
}
virtual void visit(AstSFormatF *nodep, AstNUser *) {
if (jumpingOver(nodep)) return;
nodep->iterateChildren(*this);
if (m_params) {
AstNode* nextArgp = nodep->exprsp();
string result = "";
string format = nodep->text();
string::const_iterator pos = format.begin();
bool inPct = false;
for (; pos != format.end(); ++pos) {
if (!inPct && pos[0] == '%') {
inPct = true;
} else if (!inPct) { // Normal text
result += *pos;
} else { // Format character
AstNode* argp = nextArgp;
inPct = false;
nextArgp = nextArgp->nextp();
if (V3Number::displayedFmtLegal(tolower(pos[0]))) {
V3Number* nump = fetchNumberNull(argp);
if (!nump) {
clearOptimizable(nodep, "Argument for $display like statement is not constant");
break;
}
string format = string("%") + pos[0];
result += nump->displayed(format);
} else {
switch (tolower(pos[0])) {
case '%':
result += "%";
break;
default:
clearOptimizable(nodep, "Unknown $display-like format code.");
break;
}
}
}
}
nodep->text(result);
}
}
virtual void visit(AstDisplay *nodep, AstNUser *) {
if (jumpingOver(nodep)) return;
nodep->iterateChildren(*this);
if (m_params) {
switch (nodep->displayType()) {
case AstDisplayType::DT_DISPLAY: // FALLTHRU
case AstDisplayType::DT_INFO:
v3warn(USERINFO, nodep->fmtp()->text());
break;
case AstDisplayType::DT_ERROR:
v3warn(USERERROR, nodep->fmtp()->text());
break;
case AstDisplayType::DT_WARNING:
v3warn(USERWARN, nodep->fmtp()->text());
break;
case AstDisplayType::DT_FATAL:
v3warn(USERFATAL, nodep->fmtp()->text());
break;
case AstDisplayType::DT_WRITE: // FALLTHRU
default:
clearOptimizable(nodep, "Unexpected display type");
}
}
}
// default
// These types are definately not reducable
// AstCoverInc, AstDisplay, AstArraySel, AstStop, AstFinish,
// AstCoverInc, AstArraySel, AstFinish,
// AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt
virtual void visit(AstNode* nodep, AstNUser*) {
if (jumpingOver(nodep)) return;

18
test_regress/t/t_assert_elab.pl Executable file
View File

@ -0,0 +1,18 @@
#!/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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,24 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2015 by Johan Bjork.
module t;
localparam str = "string";
function logic checkParameter(input logic [8:0] N);
if (N == 1)
return 0;
$fatal(1, "Parameter %d is invalid...%s and %s", N, str, "constant both work");
endfunction
`ifdef FAILING_ASSERTIONS
localparam x = checkParameter(5);
`else
localparam x = checkParameter(1);
`endif
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,28 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
top_filename("t/t_assert_elab.v");
unlink("$Self->{obj_dir}/t_assert_elab_bad.log");
compile (
v_flags2 => ['+define+FAILING_ASSERTIONS',
$Self->{v3}?'--assert':($Self->{nc}?'+assert':'')],
fails => 1,
);
execute (
fails => $Self->{vlt},
);
file_grep ("$Self->{obj_dir}/vlt_compile.log",
qr/%Warning-USERFATAL: Parameter 5 is invalid...string and constant both work/);
ok(1);
1;