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 $sformatf, bug977. [Johan Bjork]
*** Support elaboration assertions, bug973. [Johan Bjork]
**** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader] **** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader]
**** Fix very long module names, bug937. [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, Having unused signals in one place makes it easy to find what is unused,
and reduces the number of lint_off pragmas, reducing bugs. 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 =item VARHIDDEN
Warns that a task, function, or begin/end block is declaring a variable by Warns that a task, function, or begin/end block is declaring a variable by

View File

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

View File

@ -343,13 +343,6 @@ private:
virtual void visit(AstDisplay* nodep, AstNUser* vup) { virtual void visit(AstDisplay* nodep, AstNUser* vup) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
if (nodep->filep()) expectDescriptor(nodep, nodep->filep()->castNodeVarRef()); 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*) { virtual void visit(AstUdpTable* nodep, AstNUser*) {

View File

@ -580,6 +580,7 @@ private:
} }
} }
virtual void visit(AstStop* nodep, AstNUser*) { virtual void visit(AstStop* nodep, AstNUser*) {
if (jumpingOver(nodep)) return;
if (m_params) { // This message seems better than an obscure $stop if (m_params) { // This message seems better than an obscure $stop
// The spec says $stop is just ignored, it seems evil to ignore assertions // The spec says $stop is just ignored, it seems evil to ignore assertions
clearOptimizable(nodep,"$stop executed during function constification; maybe indicates assertion firing"); clearOptimizable(nodep,"$stop executed during function constification; maybe indicates assertion firing");
@ -695,9 +696,78 @@ private:
if (!m_params) { badNodeType(nodep); return; } 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 // default
// These types are definately not reducable // These types are definately not reducable
// AstCoverInc, AstDisplay, AstArraySel, AstStop, AstFinish, // AstCoverInc, AstArraySel, AstFinish,
// AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt // AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt
virtual void visit(AstNode* nodep, AstNUser*) { virtual void visit(AstNode* nodep, AstNUser*) {
if (jumpingOver(nodep)) return; 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;