From d5f7878eb4b059a10baf7128063dabaf4c6d65b3 Mon Sep 17 00:00:00 2001 From: Aditya Shevade Date: Sun, 23 Aug 2026 04:47:43 -0700 Subject: [PATCH] Fix internal error on an enum literal inside a `with` lambda body (#8190) (#8193) --- docs/CONTRIBUTORS | 1 + src/V3Randomize.cpp | 4 ++ .../t/t_constraint_enum_lambda_arg.py | 21 ++++++ test_regress/t/t_constraint_enum_lambda_arg.v | 72 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100755 test_regress/t/t_constraint_enum_lambda_arg.py create mode 100644 test_regress/t/t_constraint_enum_lambda_arg.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 1672555b0..c9f8bde1a 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -11,6 +11,7 @@ Please see the Verilator manual for 200+ additional contributors. Thanks to all. 404allen404 Adam Bagley Adam Kostrzewski +Aditya Shevade Adrian Sampson Adrien Le Masle أحمد المحمودي (Ahmed El-Mahmoudy) diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 7089d4e95..93e9d434a 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -36,6 +36,7 @@ #include "V3Randomize.h" #include "V3Ast.h" +#include "V3Const.h" #include "V3Error.h" #include "V3FileLine.h" #include "V3Global.h" @@ -2852,6 +2853,9 @@ class ConstraintExprVisitor final : public VNVisitor { } VL_DO_DANGLING(elemSelp->deleteTree(), elemSelp); + // enum-literal folding pass already ran -- re-fold the literals. + perElemExprp = V3Const::constifyEdit(perElemExprp); + perElemExprp->foreach([&](AstNode* nodep) { // Don't mark loop variable references as randomizable if (!VN_IS(nodep, Const)) { diff --git a/test_regress/t/t_constraint_enum_lambda_arg.py b/test_regress/t/t_constraint_enum_lambda_arg.py new file mode 100755 index 000000000..db1adb3f9 --- /dev/null +++ b/test_regress/t/t_constraint_enum_lambda_arg.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_constraint_enum_lambda_arg.v b/test_regress/t/t_constraint_enum_lambda_arg.v new file mode 100644 index 000000000..c3c3a6ad7 --- /dev/null +++ b/test_regress/t/t_constraint_enum_lambda_arg.v @@ -0,0 +1,72 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Aditya Shevade +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +// verilog_format: on + +typedef enum bit [1:0] { + READ, + WRITE, + FLUSH, + INVALID +} cmd_e; + +class EnumLambdaArg; + rand cmd_e items[8]; + constraint c_count { + items.sum() with (item == WRITE ? 1 : 0) == 3; + } +endclass + +// Same shape, but the enum lives in a struct field reached via the lambda +// argument (item.kind), not the array element itself. +typedef struct { + cmd_e kind; +} entry_t; +class StructFieldEnumLambdaArg; + rand entry_t items[8]; + constraint c_find { + // verilator lint_off CONSTRAINTIGN + items.find(item) with (item.kind == WRITE).size() >= 0; + // verilator lint_on CONSTRAINTIGN + } +endclass + +// Same shape, but via a locator method (find()) instead of a reduction +// (sum()) -- both take a with (...) lambda body the same way. +class EnumLambdaArgFind; + rand cmd_e items[8]; + constraint c_find { + // find() with (...) inside a constraint is separately unsupported + // (CONSTRAINTIGN, fatal by default) -- suppressed here since this + // test is only about the enum literal not crashing the compiler. + // verilator lint_off CONSTRAINTIGN + items.find(item) with (item == WRITE).size() >= 0; + // verilator lint_on CONSTRAINTIGN + } +endclass + +module t; + initial begin + automatic EnumLambdaArg obj = new(); + automatic StructFieldEnumLambdaArg sobj = new(); + automatic EnumLambdaArgFind fobj = new(); + int ok; + repeat (5) begin + ok = obj.randomize(); + `checkd(ok, 1); + ok = sobj.randomize(); + `checkd(ok, 1); + ok = fobj.randomize(); + `checkd(ok, 1); + end + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule