From 22dc437dbb78b0f61a8b56d4d7abed5f848ca520 Mon Sep 17 00:00:00 2001 From: Yilou Wang Date: Wed, 11 Feb 2026 03:24:25 +0100 Subject: [PATCH] Support std::randomize() for queue, dynamic array, and associative array variables (#7044) --- include/verilated_random.h | 17 ++++++ test_regress/t/t_std_randomize_assoc.py | 21 ++++++++ test_regress/t/t_std_randomize_assoc.v | 48 +++++++++++++++++ test_regress/t/t_std_randomize_queue.py | 21 ++++++++ test_regress/t/t_std_randomize_queue.v | 70 +++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100755 test_regress/t/t_std_randomize_assoc.py create mode 100644 test_regress/t/t_std_randomize_assoc.v create mode 100755 test_regress/t/t_std_randomize_queue.py create mode 100644 test_regress/t/t_std_randomize_queue.v diff --git a/include/verilated_random.h b/include/verilated_random.h index 0d4c84fbd..c37fbec33 100644 --- a/include/verilated_random.h +++ b/include/verilated_random.h @@ -641,6 +641,23 @@ public: for (size_t i = 0; i < N_Depth; ++i) { basicStdRandomization(value.operator[](i), width); } return true; } + + // Queue/dynamic array randomization + template + bool basicStdRandomization(VlQueue& value, size_t width) { + for (int i = 0; i < value.size(); ++i) { basicStdRandomization(value.atWrite(i), width); } + return true; + } + + // Associative array randomization + template + bool basicStdRandomization(VlAssocArray& value, size_t width) { + T_Key key; + for (int exists = value.first(key); exists; exists = value.next(key)) { + basicStdRandomization(value.at(key), width); + } + return true; + } bool next() { return VlRandomizer::next(m_rng); } }; diff --git a/test_regress/t/t_std_randomize_assoc.py b/test_regress/t/t_std_randomize_assoc.py new file mode 100755 index 000000000..db1adb3f9 --- /dev/null +++ b/test_regress/t/t_std_randomize_assoc.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_std_randomize_assoc.v b/test_regress/t/t_std_randomize_assoc.v new file mode 100644 index 000000000..4ce121f55 --- /dev/null +++ b/test_regress/t/t_std_randomize_assoc.v @@ -0,0 +1,48 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 PlanV GmbH +// SPDX-License-Identifier: CC0-1.0 + +// Test std::randomize() with associative array variables + +`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); + +module t_std_randomize_assoc; + + // Associative array variables + int assoc_int [int]; + bit [7:0] assoc_byte [string]; + + initial begin + // Test 1: std::randomize with int-keyed associative array (no constraints) + assoc_int[0] = 0; + assoc_int[1] = 0; + assoc_int[2] = 0; + `checkd(std::randomize(assoc_int), 1); + + // Test 2: std::randomize with string-keyed associative array + assoc_byte["a"] = 0; + assoc_byte["b"] = 0; + assoc_byte["c"] = 0; + `checkd(std::randomize(assoc_byte), 1); + + // Test 3: Multiple randomizations produce different values + begin + automatic int non_zero = 0; + repeat (5) begin + assoc_int[0] = 0; + assoc_int[1] = 0; + `checkd(std::randomize(assoc_int), 1); + if (assoc_int[0] != 0) non_zero++; + if (assoc_int[1] != 0) non_zero++; + end + // With 10 random int values, expect most non-zero + if (non_zero < 7) `stop; + end + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_std_randomize_queue.py b/test_regress/t/t_std_randomize_queue.py new file mode 100755 index 000000000..db1adb3f9 --- /dev/null +++ b/test_regress/t/t_std_randomize_queue.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_std_randomize_queue.v b/test_regress/t/t_std_randomize_queue.v new file mode 100644 index 000000000..7c5a04fcb --- /dev/null +++ b/test_regress/t/t_std_randomize_queue.v @@ -0,0 +1,70 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 PlanV GmbH +// SPDX-License-Identifier: CC0-1.0 + +// Test std::randomize() with queue and dynamic array variables + +`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); + +module t_std_randomize_queue; + + // Queue variables + bit [7:0] q8 [$]; + bit [31:0] q32 [$]; + + // Dynamic array variables + bit [7:0] dyn8 []; + + int i; + + initial begin + // Test 1: std::randomize with queue (no constraints) + q8 = {8'd0, 8'd0, 8'd0}; + `checkd(std::randomize(q8), 1); + + // Test 2: std::randomize with queue and constraints + q8 = {8'd0, 8'd0, 8'd0, 8'd0}; + `checkd(std::randomize(q8) with { + foreach (q8[j]) q8[j] > 8'd10 && q8[j] < 8'd100; + }, 1); + foreach (q8[j]) begin + if (q8[j] <= 8'd10 || q8[j] >= 8'd100) `stop; + end + + // Test 3: std::randomize with 32-bit queue + q32 = {32'd0, 32'd0, 32'd0}; + `checkd(std::randomize(q32) with { + foreach (q32[k]) q32[k] < 32'd1000; + }, 1); + foreach (q32[k]) begin + if (q32[k] >= 32'd1000) `stop; + end + + // Test 4: std::randomize with dynamic array + dyn8 = new[3]; + `checkd(std::randomize(dyn8) with { + foreach (dyn8[m]) dyn8[m] inside {[1:50]}; + }, 1); + foreach (dyn8[m]) begin + if (dyn8[m] < 1 || dyn8[m] > 50) `stop; + end + + // Test 5: Multiple randomizations produce different values + q8 = {8'd0, 8'd0, 8'd0}; + begin + automatic int non_zero = 0; + repeat (5) begin + `checkd(std::randomize(q8), 1); + foreach (q8[n]) if (q8[n] != 0) non_zero++; + end + // With 15 random 8-bit values, expect most non-zero + if (non_zero < 10) `stop; + end + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule