mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Add assertions on 'unique if', bug725.
This commit is contained in:
parent
55bb766c15
commit
8d8c5da812
2
Changes
2
Changes
@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
*** Add --no-trace-params.
|
||||
|
||||
*** Add assertions on 'unique if', bug725. [Jeff Bush]
|
||||
|
||||
**** Documentation fixes, bug723. [Glen Gibb]
|
||||
|
||||
**** Fix tracing of package variables and real arrays.
|
||||
|
@ -1991,9 +1991,8 @@ appropriate code to detect failing cases at runtime and print an "Assertion
|
||||
failed" error message.
|
||||
|
||||
Verilator likewise also asserts any "unique" or "priority" SystemVerilog
|
||||
keywords on case statements. However, "unique if" and "priority if" are
|
||||
currently simply ignored.
|
||||
|
||||
keywords on case statement, as well as "unique" on if statements.
|
||||
However, "priority if" is currently simply ignored.
|
||||
|
||||
=head1 LANGUAGE EXTENSIONS
|
||||
|
||||
|
@ -174,6 +174,61 @@ private:
|
||||
// Bye
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstIf* nodep, AstNUser*) {
|
||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
AstNodeIf* ifp = nodep;
|
||||
AstNode* propp = NULL;
|
||||
bool hasDefaultElse = false;
|
||||
do {
|
||||
// If this statement ends with 'else if', then nextIf will point to the
|
||||
// nextIf statement. Otherwise it will be null.
|
||||
AstNodeIf* nextifp = dynamic_cast<AstNodeIf*>(ifp->elsesp());
|
||||
|
||||
// Recurse into the true case.
|
||||
ifp->ifsp()->iterateChildren(*this);
|
||||
|
||||
// If the last else is not an else if, recurse into that too.
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
ifp->elsesp()->iterateChildren(*this);
|
||||
}
|
||||
|
||||
// Build a bitmask of the true predicates
|
||||
AstNode* predp = ifp->condp()->cloneTree(false);
|
||||
if (propp) {
|
||||
propp = new AstConcat(nodep->fileline(), predp, propp);
|
||||
} else {
|
||||
propp = predp;
|
||||
}
|
||||
|
||||
// Record if this ends with an 'else' that does not have an if
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
hasDefaultElse = true;
|
||||
}
|
||||
|
||||
ifp = nextifp;
|
||||
} while (ifp);
|
||||
|
||||
AstNode *newifp = nodep->cloneTree(false);
|
||||
bool allow_none = nodep->unique0Pragma();
|
||||
|
||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||
// predicates evaluates to true.
|
||||
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
||||
AstIf* checkifp = new AstIf (nodep->fileline(),
|
||||
new AstLogNot (nodep->fileline(), ohot),
|
||||
newFireAssert(nodep, "'unique if' statement violated"),
|
||||
newifp);
|
||||
checkifp->branchPred(AstBranchPred::BP_UNLIKELY);
|
||||
nodep->replaceWith(checkifp);
|
||||
pushDeletep(nodep);
|
||||
} else {
|
||||
nodep->ifsp()->iterateChildren(*this);
|
||||
nodep->elsesp()->iterateChildren(*this);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS //========== Case assertions
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
|
20
test_regress/t/t_uniqueif.pl
Executable file
20
test_regress/t/t_uniqueif.pl
Executable file
@ -0,0 +1,20 @@
|
||||
#!/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.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
111
test_regress/t/t_uniqueif.v
Normal file
111
test_regress/t/t_uniqueif.v
Normal file
@ -0,0 +1,111 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2007 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
integer cyc=1;
|
||||
integer a, b, c, d, e, f, g, h, i, j, k, l;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
|
||||
//====================
|
||||
// Positive test cases
|
||||
//====================
|
||||
|
||||
// Single if, which is untrue sometimes
|
||||
unique0 if (cyc > 5)
|
||||
a <= 17;
|
||||
|
||||
// single if with else
|
||||
unique0 if (cyc < 3)
|
||||
b <= 17;
|
||||
else
|
||||
b <= 19;
|
||||
|
||||
// multi if, some cases may not be true
|
||||
unique0 if (cyc < 3)
|
||||
c <= 17;
|
||||
else if (cyc > 3)
|
||||
c <= 19;
|
||||
|
||||
// multi if with else, else clause hit in some cases
|
||||
unique0 if (cyc < 3)
|
||||
d <= 17;
|
||||
else if (cyc > 3)
|
||||
d <= 19;
|
||||
else
|
||||
d <= 21;
|
||||
|
||||
// single if with else
|
||||
unique if (cyc < 3)
|
||||
f <= 17;
|
||||
else
|
||||
f <= 19;
|
||||
|
||||
// multi if
|
||||
unique if (cyc < 3)
|
||||
g <= 17;
|
||||
else if (cyc >= 3)
|
||||
g <= 19;
|
||||
|
||||
// multi if with else, else clause hit in some cases
|
||||
unique if (cyc < 3)
|
||||
h <= 17;
|
||||
else if (cyc > 3)
|
||||
h <= 19;
|
||||
else
|
||||
h <= 21;
|
||||
|
||||
//====================
|
||||
// Negative test cases
|
||||
//====================
|
||||
`ifdef FAILING_ASSERTION1
|
||||
$display("testing fail 1: %d", cyc);
|
||||
// multi if, multiple cases true
|
||||
unique0 if (cyc < 3)
|
||||
i <= 17;
|
||||
else if (cyc < 5)
|
||||
i <= 19;
|
||||
`endif
|
||||
|
||||
`ifdef FAILING_ASSERTION2
|
||||
// multi if, multiple cases true
|
||||
unique if (cyc < 3)
|
||||
j <= 17;
|
||||
else if (cyc < 5)
|
||||
j <= 19;
|
||||
`endif
|
||||
|
||||
`ifdef FAILING_ASSERTION3
|
||||
// multi if, no cases true
|
||||
unique if (cyc > 1000)
|
||||
k <= 17;
|
||||
else if (cyc > 2000)
|
||||
k <= 19;
|
||||
`endif
|
||||
|
||||
`ifdef FAILING_ASSERTION4
|
||||
// Single if, which is untrue sometimes.
|
||||
// The LRM states: "A software tool shall also issue an error if it determines that no condition'
|
||||
// is true, or it is possible that no condition is true, and the final if does not have a
|
||||
// corresponding else." In this case, the final if is the only if, but I think the clause
|
||||
// still applies.
|
||||
unique if (cyc > 5)
|
||||
l <= 17;
|
||||
`endif
|
||||
|
||||
|
||||
if (cyc==10) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
28
test_regress/t/t_uniqueif_fail1.pl
Executable file
28
test_regress/t/t_uniqueif_fail1.pl
Executable 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_uniqueif.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+FAILING_ASSERTION1'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
fails => $Self->{nc},
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_uniqueif_fail2.pl
Executable file
28
test_regress/t/t_uniqueif_fail2.pl
Executable 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_uniqueif.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+FAILING_ASSERTION2'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
fails => $Self->{nc},
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_uniqueif_fail3.pl
Executable file
28
test_regress/t/t_uniqueif_fail3.pl
Executable 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_uniqueif.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+FAILING_ASSERTION3'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
fails => $Self->{nc},
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
28
test_regress/t/t_uniqueif_fail4.pl
Executable file
28
test_regress/t/t_uniqueif_fail4.pl
Executable 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_uniqueif.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => ['+define+FAILING_ASSERTION4'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
fails => $Self->{nc},
|
||||
);
|
||||
|
||||
execute (
|
||||
fails => $Self->{vlt},
|
||||
expect=>
|
||||
'.*%Error: t_uniqueif.v:\d+: Assertion failed in top.v: \'unique if\' statement violated
|
||||
%Error: t/t_uniqueif.v:\d+: Verilog \$stop
|
||||
.*',
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
Loading…
Reference in New Issue
Block a user