diff --git a/include/verilated_random.h b/include/verilated_random.h index 964898713..bbcd3ba16 100644 --- a/include/verilated_random.h +++ b/include/verilated_random.h @@ -692,9 +692,6 @@ public: // Light wrapper for RNG used by std::randomize() to support scope-level randomization. class VlStdRandomizer final : public VlRandomizer { - // MEMBERS - VlRNG m_rng; // Random number generator - public: // CONSTRUCTORS VlStdRandomizer() = default; @@ -705,7 +702,7 @@ private: template typename std::enable_if::value, bool>::type basicStdRandomizationImpl(T& value, size_t width) { - VL_RANDOM_RNG_W(m_rng, width, value); + VL_RANDOM_RNG_W(VlProcess::currentRng(), width, value); // Mask off garbage bits in last word const int words = VL_WORDS_I(width); const int bitsInLastWord = width & VL_SIZEBITS_I; @@ -718,9 +715,9 @@ private: typename std::enable_if::value, bool>::type basicStdRandomizationImpl(T& value, size_t width) { if (width <= 32) { - value = VL_MASK_I(width) & VL_RANDOM_RNG_I(m_rng); + value = VL_MASK_I(width) & VL_RANDOM_RNG_I(VlProcess::currentRng()); } else { - value = VL_MASK_Q(width) & VL_RANDOM_RNG_Q(m_rng); + value = VL_MASK_Q(width) & VL_RANDOM_RNG_Q(VlProcess::currentRng()); } return true; } @@ -755,7 +752,7 @@ public: } return true; } - bool next() { return VlRandomizer::next(m_rng); } + bool next() { return VlRandomizer::next(VlProcess::currentRng()); } }; #endif // Guard diff --git a/test_regress/t/t_std_randomize_process_seed.py b/test_regress/t/t_std_randomize_process_seed.py new file mode 100755 index 000000000..22bb2884a --- /dev/null +++ b/test_regress/t/t_std_randomize_process_seed.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: std::randomize follows process RNG seeding +# +# 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") + +v_flags = ["+define+TEST_CONSTRAINT_SOLVER"] if test.have_solver else [] + +test.compile(v_flags2=v_flags, verilator_flags2=["--timing"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_std_randomize_process_seed.v b/test_regress/t/t_std_randomize_process_seed.v new file mode 100644 index 000000000..0424df65b --- /dev/null +++ b/test_regress/t/t_std_randomize_process_seed.v @@ -0,0 +1,67 @@ +// DESCRIPTION: Verilator: std::randomize follows process RNG seeding +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// 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); +`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__, `__LINE__, (gotv), (expv)); `stop; end while (0); +// verilog_format: on + +module t; + typedef bit [94:0] wide_t; + + task automatic sample_after_process_seed(input int seed, output int scalar_values[4], + output wide_t wide_values[4]); + process p; + p = process::self(); + p.srandom(seed); + foreach (scalar_values[i]) begin + `checkd(std::randomize(scalar_values[i]), 1); + `checkd(std::randomize(wide_values[i]), 1); + end + endtask + +`ifdef TEST_CONSTRAINT_SOLVER + task automatic sample_with_after_process_seed(input int seed, output int values[4]); + process p; + p = process::self(); + p.srandom(seed); + foreach (values[i]) begin + `checkd(std::randomize(values[i]) with {values[i] inside {[32'h1000_0000 : 32'h7fff_ffff]};}, + 1); + end + endtask +`endif + + initial begin + int scalar_first[4]; + int scalar_second[4]; + wide_t wide_first[4]; + wide_t wide_second[4]; +`ifdef TEST_CONSTRAINT_SOLVER + int constrained_first[4]; + int constrained_second[4]; +`endif + + sample_after_process_seed(32'h1357_2468, scalar_first, wide_first); + sample_after_process_seed(32'h1357_2468, scalar_second, wide_second); + + foreach (scalar_first[i]) begin + `checkd(scalar_second[i], scalar_first[i]); + `checkh(wide_second[i], wide_first[i]); + end + +`ifdef TEST_CONSTRAINT_SOLVER + sample_with_after_process_seed(32'h1357_2468, constrained_first); + sample_with_after_process_seed(32'h1357_2468, constrained_second); + + foreach (constrained_first[i]) `checkd(constrained_second[i], constrained_first[i]); +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule