diff --git a/Changes b/Changes index 23fb8fa80..304f6200c 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ Verilator 5.009 devel * Add --public-depth to force public to a certain instance depth (#3952). [Andrew Nolte] * Add --public-params flag (#3990). [Andrew Nolte] +* Add CONSTRAINTIGN warning when constraint ignored. * Add STATICVAR warning and convert to automatic (#4018) (#4027) (#4030). [Ryszard Rozak, Antmicro Ltd] * Support class extends of package::class. * Support class srandom and class random stability. diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index fe406c8a2..1a754c8f6 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -396,6 +396,16 @@ List Of Warnings simulators. +.. option:: CONSTRAINTIGN + + Warns that Verilator does not support :code:`constraint`, + :code:`constraint_mode`, or :code:`rand_mode`, and the construct was are + ignored. + + Ignoring this warning may make Verilator randomize() simulations differ + from other simulators. + + .. option:: CONTASSREG .. TODO better example diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 277d6988b..232d4ebca 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -3188,7 +3188,7 @@ private: void visit(AstStmtExpr* nodep) override { iterateChildren(nodep); - if (!nodep->exprp()) { + if (!nodep->exprp() || VN_IS(nodep->exprp(), Const)) { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; } diff --git a/src/V3Error.h b/src/V3Error.h index b63dfdf2d..ddff5baf2 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -88,6 +88,7 @@ public: CMPCONST, // Comparison is constant due to limited range COLONPLUS, // :+ instead of +: COMBDLY, // Combinatorial delayed assignment + CONSTRAINTIGN, // Constraint ignored CONTASSREG, // Continuous assignment on reg DECLFILENAME, // Declaration doesn't match filename DEFPARAM, // Style: Defparam @@ -187,7 +188,7 @@ public: "ALWCOMBORDER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA", - "CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG", + "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG", "DECLFILENAME", "DEFPARAM", "DEPRECATED", "ENCAPSULATED", "ENDLABEL", "ENUMVALUE", "EOFNEWLINE", "GENCLK", "HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 5bec957ad..bb5e25edb 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2829,7 +2829,9 @@ private: AstBasicDType* const basicp = fromDtp ? fromDtp->basicp() : nullptr; UINFO(9, " from dt " << fromDtp << endl); userIterate(fromDtp, WidthVP{SELF, BOTH}.p()); - if (AstEnumDType* const adtypep = VN_CAST(fromDtp, EnumDType)) { + if (nodep->name() == "rand_mode") { + methodCallRandMode(nodep); + } else if (AstEnumDType* const adtypep = VN_CAST(fromDtp, EnumDType)) { methodCallEnum(nodep, adtypep); } else if (AstAssocArrayDType* const adtypep = VN_CAST(fromDtp, AssocArrayDType)) { methodCallAssoc(nodep, adtypep); @@ -2843,6 +2845,8 @@ private: methodCallClass(nodep, adtypep); } else if (AstUnpackArrayDType* const adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { methodCallUnpack(nodep, adtypep); + } else if (basicp && nodep->name() == "constraint_mode") { + methodCallConstraint(nodep, basicp); } else if (basicp && basicp->isEvent()) { methodCallEvent(nodep, basicp); } else if (basicp && basicp->isString()) { @@ -3533,6 +3537,26 @@ private: } nodep->dtypeSetSigned32(); // Guess on error } + void methodCallConstraint(AstMethodCall* nodep, AstBasicDType*) { + // Method call on constraint (currently hacked as just a var) + if (nodep->name() == "constraint_mode") { + methodOkArguments(nodep, 0, 1); + nodep->v3warn(CONSTRAINTIGN, "constraint_mode ignored (unsupported)"); + // Constraints ignored, so we just return "OFF" + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else { + nodep->v3fatalSrc("Unknown built-in constraint method " << nodep->prettyNameQ()); + } + } + void methodCallRandMode(AstMethodCall* nodep) { + // Method call on constraint (currently hacked as just a var) + methodOkArguments(nodep, 0, 1); + nodep->v3warn(CONSTRAINTIGN, "rand_mode ignored (unsupported)"); + // Disables ignored, so we just return "ON" + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitTrue{}}); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } void methodCallUnpack(AstMethodCall* nodep, AstUnpackArrayDType* adtypep) { enum : uint8_t { UNKNOWN = 0, diff --git a/src/verilog.y b/src/verilog.y index eb06172e6..571f51876 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -6992,9 +6992,13 @@ class_constraint: // ==IEEE: class_constraint // // IEEE: constraint_declaration // // UNSUP: We have the unsupported warning on the randomize() call, so don't bother on // // constraint blocks. When we support randomize we need to make AST nodes for below rules - constraintStaticE yCONSTRAINT idAny constraint_block { $$ = nullptr; /*UNSUP*/ } + constraintStaticE yCONSTRAINT idAny constraint_block + { // Variable so we can link and later ignore constraint_mode() methods + $$ = new AstVar{$3, VVarType::MEMBER, *$3, VFlagBitPacked{}, 1}; + $2->v3warn(CONSTRAINTIGN, "Constraint ignored (unsupported)"); } // // IEEE: constraint_prototype + constraint_prototype_qualifier - | constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; } + | constraintStaticE yCONSTRAINT idAny ';' + { $$ = nullptr; } | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern constraint"); } | yPURE constraintStaticE yCONSTRAINT idAny ';' diff --git a/test_regress/t/t_constraint.pl b/test_regress/t/t_constraint.pl new file mode 100755 index 000000000..11d21fc86 --- /dev/null +++ b/test_regress/t/t_constraint.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 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 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ['-Wno-CONSTRAINTIGN'], + ); + +execute( + check_finished => 1, + ); + + +ok(1); +1; diff --git a/test_regress/t/t_constraint.v b/test_regress/t/t_constraint.v new file mode 100644 index 000000000..59dea5195 --- /dev/null +++ b/test_regress/t/t_constraint.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Packet; + rand int one; + + constraint a { one > 0 && one < 2; } + +endclass + +module t (/*AUTOARG*/); + + Packet p; + + int v; + + initial begin + p = new; + v = p.randomize(); + if (v != 1) $stop; +`ifndef VERILATOR + if (p.one != 1) $stop; +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_mode.pl b/test_regress/t/t_constraint_mode.pl new file mode 100755 index 000000000..11d21fc86 --- /dev/null +++ b/test_regress/t/t_constraint_mode.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 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 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ['-Wno-CONSTRAINTIGN'], + ); + +execute( + check_finished => 1, + ); + + +ok(1); +1; diff --git a/test_regress/t/t_constraint_mode.v b/test_regress/t/t_constraint_mode.v new file mode 100644 index 000000000..6d18156bc --- /dev/null +++ b/test_regress/t/t_constraint_mode.v @@ -0,0 +1,59 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Packet; + rand int one; + + constraint a { one > 0 && one < 2; } + + task test1; + // TODO Verilator ignores this setting currently, always returning 1 (rand on) + one.rand_mode(0); + one.rand_mode(1); + if (one.rand_mode() != 1) $stop; + + // TODO Verilator ignores this setting currently, always returning 0 (constraint off) + a.constraint_mode(1); + a.constraint_mode(0); + if (a.constraint_mode() != 0) $stop; + endtask + +endclass + +module t (/*AUTOARG*/); + + Packet p; + + int v; + + initial begin + p = new; + v = p.randomize(); + if (v != 1) $stop; +`ifndef VERILATOR + if (p.one != 1) $stop; +`endif + + // TODO Verilator ignores this setting currently, always returning 1 (rand on) + p.one.rand_mode(0); + p.one.rand_mode(1); + if (p.one.rand_mode() != 1) $stop; + + // TODO Verilator ignores this setting currently, always returning 0 (constraint off) + p.a.constraint_mode(1); + p.a.constraint_mode(0); + if (p.a.constraint_mode() != 0) $stop; + + p.test1(); + + // TODO test can't redefine constraint_mode + // TODO test can't redefine rand_mode + // TODO test can't call constraint_mode on non-constraint + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_mode_warn_bad.out b/test_regress/t/t_constraint_mode_warn_bad.out new file mode 100644 index 000000000..478853c43 --- /dev/null +++ b/test_regress/t/t_constraint_mode_warn_bad.out @@ -0,0 +1,54 @@ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:10:4: Constraint ignored (unsupported) + 10 | constraint a { one > 0 && one < 2; } + | ^~~~~~~~~~ + ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest + ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:14:11: rand_mode ignored (unsupported) + : ... In instance t + 14 | one.rand_mode(0); + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:15:11: rand_mode ignored (unsupported) + : ... In instance t + 15 | one.rand_mode(1); + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:16:15: rand_mode ignored (unsupported) + : ... In instance t + 16 | if (one.rand_mode() != 1) $stop; + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:19:9: constraint_mode ignored (unsupported) + : ... In instance t + 19 | a.constraint_mode(1); + | ^~~~~~~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:20:9: constraint_mode ignored (unsupported) + : ... In instance t + 20 | a.constraint_mode(0); + | ^~~~~~~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:21:13: constraint_mode ignored (unsupported) + : ... In instance t + 21 | if (a.constraint_mode() != 0) $stop; + | ^~~~~~~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:41:13: rand_mode ignored (unsupported) + : ... In instance t + 41 | p.one.rand_mode(0); + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:42:13: rand_mode ignored (unsupported) + : ... In instance t + 42 | p.one.rand_mode(1); + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:43:17: rand_mode ignored (unsupported) + : ... In instance t + 43 | if (p.one.rand_mode() != 1) $stop; + | ^~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:46:11: constraint_mode ignored (unsupported) + : ... In instance t + 46 | p.a.constraint_mode(1); + | ^~~~~~~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:47:11: constraint_mode ignored (unsupported) + : ... In instance t + 47 | p.a.constraint_mode(0); + | ^~~~~~~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_constraint_mode.v:48:15: constraint_mode ignored (unsupported) + : ... In instance t + 48 | if (p.a.constraint_mode() != 0) $stop; + | ^~~~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_mode_warn_bad.pl b/test_regress/t/t_constraint_mode_warn_bad.pl new file mode 100755 index 000000000..96addf7c7 --- /dev/null +++ b/test_regress/t/t_constraint_mode_warn_bad.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 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 + +scenarios(vlt => 1); + +top_filename("t/t_constraint_mode.v"); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_randomize.out b/test_regress/t/t_randomize.out index 334f02e8a..82e50c3f1 100644 --- a/test_regress/t/t_randomize.out +++ b/test_regress/t/t_randomize.out @@ -2,12 +2,31 @@ 11 | extern constraint ex; | ^~~~~~ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Warning-CONSTRAINTIGN: t/t_randomize.v:13:4: Constraint ignored (unsupported) + 13 | constraint a { header > 0 && header < 1000; } + | ^~~~~~~~~~ + ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. +%Warning-CONSTRAINTIGN: t/t_randomize.v:14:4: Constraint ignored (unsupported) + 14 | constraint b { + | ^~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_randomize.v:19:4: Constraint ignored (unsupported) + 19 | constraint c { + | ^~~~~~~~~~ +%Warning-CONSTRAINTIGN: t/t_randomize.v:23:4: Constraint ignored (unsupported) + 23 | constraint d { + | ^~~~~~~~~~ %Error-UNSUPPORTED: t/t_randomize.v:29:29: Unsupported: solve before 29 | constraint order { solve length before header; } | ^~~~~~ +%Warning-CONSTRAINTIGN: t/t_randomize.v:29:4: Constraint ignored (unsupported) + 29 | constraint order { solve length before header; } + | ^~~~~~~~~~ %Error-UNSUPPORTED: t/t_randomize.v:32:9: Unsupported: dist 32 | x dist { [100:102] :/ 1, 200 := 2, 300 := 5, 400}; | ^~~~ +%Warning-CONSTRAINTIGN: t/t_randomize.v:30:4: Constraint ignored (unsupported) + 30 | constraint dis { + | ^~~~~~~~~~ %Error-UNSUPPORTED: t/t_randomize.v:37:1: Unsupported: extern constraint 37 | constraint Packet::ex { header > 0 }; | ^~~~~~~~~~