From 0d1f036f17449bb0857f2707551a9731d6c8eda4 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 6 Sep 2025 08:24:19 -0400 Subject: [PATCH] Add error on non-packed struct randc (#5999). --- Changes | 1 + src/V3Randomize.cpp | 11 ++++++++--- test_regress/t/t_randomize_unpacked_bad.out | 5 +++++ test_regress/t/t_randomize_unpacked_bad.py | 16 ++++++++++++++++ test_regress/t/t_randomize_unpacked_bad.v | 18 ++++++++++++++++++ 5 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test_regress/t/t_randomize_unpacked_bad.out create mode 100755 test_regress/t/t_randomize_unpacked_bad.py create mode 100644 test_regress/t/t_randomize_unpacked_bad.v diff --git a/Changes b/Changes index a0ab32e4d..e998f6257 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,7 @@ Verilator 5.041 devel **Other:** +* Add error on non-packed struct randc (#5999). [Seth Pellegrino] * Improve automatic selection of logic for DFG synthesis (#6370). [Geza Lore] * Improve `covergroup with function sample` handling (#6387). [Jakub Wasilewski] * Optimize dead functions without references (#6380). [Artur Bieniek, Antmicro Ltd.] diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 87d610dec..bb5e1aca2 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -1602,9 +1602,7 @@ class RandomizeVisitor final : public VNVisitor { if (AstEnumDType* const enumDtp = VN_CAST(varp->dtypep()->skipRefToEnump(), EnumDType)) { items = static_cast(enumDtp->itemCount()); - } else { - AstBasicDType* const basicp = varp->dtypep()->skipRefp()->basicp(); - UASSERT_OBJ(basicp, varp, "Unexpected randc variable dtype"); + } else if (AstBasicDType* const basicp = varp->dtypep()->skipRefp()->basicp()) { if (basicp->width() > 32) { varp->v3error("Maximum implemented width for randc is 32 bits, " << varp->prettyNameQ() << " is " << basicp->width() << " bits"); @@ -1612,6 +1610,13 @@ class RandomizeVisitor final : public VNVisitor { return nullptr; } items = 1ULL << basicp->width(); + } else if (AstStructDType* const dtp = VN_CAST(varp->dtypep()->skipRefp(), StructDType)) { + UASSERT_OBJ(!dtp->packed(), dtp, "skipRef should have hidden packed before got here"); + dtp->v3error("Unpacked structs shall not be declared as randc" + " (IEEE 1800-2023 18.4)"); + return nullptr; + } else { + varp->v3fatalSrc("Unexpected randc variable dtype"); } AstCDType* newdtp = findVlRandCDType(varp->fileline(), items); AstVar* newp diff --git a/test_regress/t/t_randomize_unpacked_bad.out b/test_regress/t/t_randomize_unpacked_bad.out new file mode 100644 index 000000000..aca911dad --- /dev/null +++ b/test_regress/t/t_randomize_unpacked_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_randomize_unpacked_bad.v:8:9: Unpacked structs shall not be declared as randc (IEEE 1800-2023 18.4) + 8 | randc struct {logic m_x;} s; + | ^~~~~~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: Exiting due to diff --git a/test_regress/t/t_randomize_unpacked_bad.py b/test_regress/t/t_randomize_unpacked_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_randomize_unpacked_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_randomize_unpacked_bad.v b/test_regress/t/t_randomize_unpacked_bad.v new file mode 100644 index 000000000..d6a85358a --- /dev/null +++ b/test_regress/t/t_randomize_unpacked_bad.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class ex; + randc struct {logic m_x;} s; // <--- Bad: randc illegal on unpacked struct + + randc struct packed {logic m_x;} p_s; // Ok +endclass : ex + +module foo; + initial begin + ex e; + void'(e.randomize()); + end +endmodule