parent
f6532728f6
commit
3b6674386c
|
|
@ -258,6 +258,7 @@ Vassilis Papaefstathiou
|
|||
Veripool API Bot
|
||||
Victor Besyakov
|
||||
Vito Gamberini
|
||||
Wei-Lun Chiu
|
||||
William D. Jones
|
||||
Wilson Snyder
|
||||
Xi Zhang
|
||||
|
|
|
|||
|
|
@ -1123,6 +1123,16 @@ List Of Warnings
|
|||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: INSIDETRUE
|
||||
|
||||
Warns that an ``inside`` expression contains a range with unbounded
|
||||
values on both sides (``[$:$]``), which is always true. This is likely
|
||||
a coding mistake.
|
||||
|
||||
Ignoring this warning will only suppress the lint check; it will
|
||||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: LATCH
|
||||
|
||||
.. TODO better example
|
||||
|
|
|
|||
|
|
@ -356,6 +356,34 @@ const char* AstExecGraph::broken() const {
|
|||
|
||||
AstNodeExpr* AstInsideRange::newAndFromInside(AstNodeExpr* exprp, AstNodeExpr* lhsp,
|
||||
AstNodeExpr* rhsp) {
|
||||
const bool lhsUnbounded = VN_IS(lhsp, Unbounded);
|
||||
const bool rhsUnbounded = VN_IS(rhsp, Unbounded);
|
||||
|
||||
if (lhsUnbounded && rhsUnbounded) {
|
||||
fileline()->v3warn(INSIDETRUE,
|
||||
"Unbounded on both sides of inside range [$:$] is always true");
|
||||
VL_DO_DANGLING(exprp->deleteTree(), exprp);
|
||||
VL_DO_DANGLING(lhsp->deleteTree(), lhsp);
|
||||
VL_DO_DANGLING(rhsp->deleteTree(), rhsp);
|
||||
return new AstConst{fileline(), AstConst::BitTrue{}};
|
||||
}
|
||||
|
||||
if (lhsUnbounded) {
|
||||
// [$:N] - only check expr <= rhs
|
||||
// Use exprp directly (not cloned) so ExprStmt side effects are preserved
|
||||
VL_DO_DANGLING(lhsp->deleteTree(), lhsp);
|
||||
AstNodeExpr* const bp = new AstLte{fileline(), exprp, rhsp};
|
||||
bp->fileline()->modifyWarnOff(V3ErrorCode::CMPCONST, true);
|
||||
return bp;
|
||||
} else if (rhsUnbounded) {
|
||||
// [N:$] - only check expr >= lhs
|
||||
VL_DO_DANGLING(rhsp->deleteTree(), rhsp);
|
||||
AstNodeExpr* const ap = new AstGte{fileline(), exprp, lhsp};
|
||||
ap->fileline()->modifyWarnOff(V3ErrorCode::UNSIGNED, true);
|
||||
return ap;
|
||||
}
|
||||
|
||||
// Normal case: [N:M] - check expr >= lhs && expr <= rhs
|
||||
AstNodeExpr* const ap = new AstGte{fileline(), exprp, lhsp};
|
||||
AstNodeExpr* lteLhsp;
|
||||
if (const AstExprStmt* const exprStmt = VN_CAST(exprp, ExprStmt)) {
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ public:
|
|||
INFINITELOOP, // Infinite loop
|
||||
INITIALDLY, // Initial delayed statement
|
||||
INSECURE, // Insecure options
|
||||
INSIDETRUE, // Inside range is always true
|
||||
LATCH, // Latch detected outside of always_latch block
|
||||
LITENDIAN, // Little endian, renamed to ASCRANGE
|
||||
MINTYPMAXDLY, // Unsupported: min/typ/max delay expressions
|
||||
|
|
@ -224,7 +225,8 @@ public:
|
|||
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "FUNCTIMECTL",
|
||||
"GENCLK", "GENUNNAMED", "HIERBLOCK", "HIERPARAM", "IFDEPTH", "IGNOREDRETURN",
|
||||
"IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH",
|
||||
"INFINITELOOP", "INITIALDLY", "INSECURE", "LATCH", "LITENDIAN", "MINTYPMAXDLY",
|
||||
"INFINITELOOP", "INITIALDLY", "INSECURE", "INSIDETRUE", "LATCH", "LITENDIAN",
|
||||
"MINTYPMAXDLY",
|
||||
"MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT",
|
||||
"NOLATCH", "NONSTD", "NORETURN", "NULLPORT", "PARAMNODEFAULT", "PINCONNECTEMPTY",
|
||||
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT",
|
||||
|
|
|
|||
|
|
@ -1624,6 +1624,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
nodep->dtypeSetSigned32(); // Used in int context
|
||||
if (VN_IS(nodep->backp(), IsUnbounded)) return; // Ok, leave
|
||||
if (VN_IS(nodep->backp(), BracketArrayDType)) return; // Ok, leave
|
||||
if (VN_IS(nodep->backp(), InsideRange)) return; // Ok, leave
|
||||
if (const auto* const varp = VN_CAST(nodep->backp(), Var)) {
|
||||
if (varp->isParam()) return; // Ok, leave
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2026 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
test.execute()
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// DESCRIPTION: Verilator: Test for unbounded '$' in inside range
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_inside_unbounded;
|
||||
initial begin
|
||||
int value;
|
||||
|
||||
// Test [$:100] - should match minimum to 100
|
||||
value = 50;
|
||||
if (!(value inside {[$:100]})) $stop;
|
||||
|
||||
value = 100;
|
||||
if (!(value inside {[$:100]})) $stop;
|
||||
|
||||
value = 101;
|
||||
if (value inside {[$:100]}) $stop; // Should NOT match
|
||||
|
||||
// Test [0:$] - should match 0 to maximum
|
||||
value = 50;
|
||||
if (!(value inside {[0:$]})) $stop;
|
||||
|
||||
value = 0;
|
||||
if (!(value inside {[0:$]})) $stop;
|
||||
|
||||
// Test [100:$] - should match 100 to maximum
|
||||
value = 100;
|
||||
if (!(value inside {[100:$]})) $stop;
|
||||
|
||||
value = 200;
|
||||
if (!(value inside {[100:$]})) $stop;
|
||||
|
||||
value = 50;
|
||||
if (value inside {[100:$]}) $stop; // Should NOT match
|
||||
|
||||
// Test mixed with other ranges
|
||||
value = 5;
|
||||
if (!(value inside {[$:10], [90:$]})) $stop;
|
||||
|
||||
value = 95;
|
||||
if (!(value inside {[$:10], [90:$]})) $stop;
|
||||
|
||||
value = 50;
|
||||
if (value inside {[$:10], [90:$]}) $stop; // Should NOT match
|
||||
|
||||
// Test with function
|
||||
if (!(get_value(50) inside {[$:100]})) $stop;
|
||||
if (!(get_value(50) inside {[0:$]})) $stop;
|
||||
if (get_value(50) inside {[100:$]}) $stop; // Should NOT match
|
||||
|
||||
// Test with increment
|
||||
value = 49;
|
||||
if (!(++value inside {[$:100]})) $stop; // value becomes 50
|
||||
if (value != 50) $stop;
|
||||
|
||||
value = -1;
|
||||
if (!(++value inside {[0:$]})) $stop; // value becomes 0
|
||||
if (value != 0) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
function int get_value(int v);
|
||||
return v;
|
||||
endfunction
|
||||
|
||||
// Use volatile-like behavior to prevent compile-time optimization
|
||||
int runtime_val;
|
||||
function int get_runtime_value(int v);
|
||||
`ifdef VERILATOR
|
||||
runtime_val = $c32(v);
|
||||
`else
|
||||
runtime_val = v;
|
||||
`endif
|
||||
return runtime_val;
|
||||
endfunction
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
%Warning-INSIDETRUE: t/t_inside_unbounded_bad.v:12:23: Unbounded on both sides of inside range [$:$] is always true
|
||||
12 | if (value inside {[$:$]}) $display("PASS");
|
||||
| ^
|
||||
... For warning description see https://verilator.org/warn/INSIDETRUE?v=latest
|
||||
... Use "/* verilator lint_off INSIDETRUE */" and lint_on around source to disable this message.
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2026 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// DESCRIPTION: Verilator: Test for unsupported [$:$] in inside range
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_inside_unbounded_bad;
|
||||
initial begin
|
||||
int value;
|
||||
value = 50;
|
||||
// [$:$] should warn - always true
|
||||
if (value inside {[$:$]}) $display("PASS");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2026 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(v_flags2=['-Wno-INSIDETRUE'])
|
||||
test.execute()
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// DESCRIPTION: Verilator: Test for [$:$] with warning suppressed
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2026.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_inside_unbounded_nowarn;
|
||||
initial begin
|
||||
int value;
|
||||
value = 50;
|
||||
// [$:$] is always true - warning suppressed with -Wno-INSIDETRUE
|
||||
if (!(value inside {[$:$]})) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue