// DESCRIPTION: Verilator: Verilog Test module // // This file ONLY is placed under the Creative Commons Public Domain. // SPDX-FileCopyrightText: 2026 by Wilson Snyder and Contributors // SPDX-License-Identifier: CC0-1.0 // Test case for array reduction methods with 'with' clause in constraints (issue #6455) // 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 class test_sum; rand byte array[5]; rand byte repeated_value; constraint c { // Ensure exactly 3 occurrences of repeated_value using sum array.sum() with (int'(item == repeated_value)) == 3; // All other values should appear exactly once foreach (array[i]) { array[i] != repeated_value -> array.sum() with (int'(item == array[i])) == 1; } } function void verify(); int count_map[byte]; int repeated_count = 0; int i; i = randomize(); `checkd(i, 1); // Count occurrences foreach (array[idx]) begin if (!count_map.exists(array[idx])) count_map[array[idx]] = 0; count_map[array[idx]]++; end // Check repeated_value appears exactly 3 times if (count_map.exists(repeated_value)) begin repeated_count = count_map[repeated_value]; if (repeated_count != 3) begin $display("%%Error: sum test - repeated_value=%0d appears %0d times, expected 3", repeated_value, repeated_count); $stop; end end else begin $display("%%Error: sum test - repeated_value=%0d doesn't appear in array", repeated_value); $stop; end // Check all other values appear exactly once foreach (count_map[val]) begin if (val != repeated_value && count_map[val] != 1) begin $display("%%Error: sum test - value=%0d appears %0d times, expected 1", val, count_map[val]); $stop; end end endfunction endclass class test_product; rand bit [3:0] array[4]; constraint c { // Product of non-zero elements should be <= 100 array.product() with (item != 0 ? int'(item) : 1) <= 100; // At least 2 non-zero elements array.sum() with (int'(item != 0)) >= 2; } function void verify(); int prod = 1; int nonzero_count = 0; int i; i = randomize(); `checkd(i, 1); foreach (array[idx]) begin if (array[idx] != 0) begin prod *= array[idx]; nonzero_count++; end end if (prod > 100) begin $display("%%Error: product test - product %0d > 100", prod); $stop; end if (nonzero_count < 2) begin $display("%%Error: product test - only %0d non-zero elements", nonzero_count); $stop; end endfunction endclass class test_and; rand bit [7:0] array[3]; constraint c { // AND of all elements with a mask should equal specific value array.and() with (item & 8'hF0) == 8'h50; } function void verify(); bit [7:0] result = 8'hFF; int i; i = randomize(); `checkd(i, 1); foreach (array[idx]) begin result &= (array[idx] & 8'hF0); end if (result != 8'h50) begin $display("%%Error: and test - result 0x%0h != 0x50", result); $stop; end endfunction endclass class test_or; rand bit [7:0] array[3]; constraint c { // OR of specific bits should set bit 3 (array.or() with (item & 8'h08)) == 8'h08; // At least one element has bit 3 set array.sum() with (int'((item & 8'h08) != 0)) >= 1; } function void verify(); bit [7:0] result = 8'h00; int i; i = randomize(); `checkd(i, 1); foreach (array[idx]) begin result |= (array[idx] & 8'h08); end if (result != 8'h08) begin $display("%%Error: or test - result 0x%0h != 0x08", result); $stop; end endfunction endclass class test_xor; rand bit [7:0] array[4]; constraint c { // XOR of all elements should be non-zero (parity check) array.xor() with (item) != 0; // Ensure some variation array.sum() with (int'(item != 0)) >= 2; } function void verify(); bit [7:0] result = 8'h00; int i; i = randomize(); `checkd(i, 1); foreach (array[idx]) begin result ^= array[idx]; end if (result == 0) begin $display("%%Error: xor test - result is 0"); $stop; end endfunction endclass module t; test_sum sum_inst; test_product product_inst; test_and and_inst; test_or or_inst; test_xor xor_inst; initial begin // Test sum sum_inst = new(); repeat (20) sum_inst.verify(); $display("sum test PASSED"); // Test product product_inst = new(); repeat (20) product_inst.verify(); $display("product test PASSED"); // Test and and_inst = new(); repeat (20) and_inst.verify(); $display("and test PASSED"); // Test or or_inst = new(); repeat (20) or_inst.verify(); $display("or test PASSED"); // Test xor xor_inst = new(); repeat (20) xor_inst.verify(); $display("xor test PASSED"); $write("*-* All Finished *-*\n"); $finish; end endmodule