Addressing review comments

- Renamed the command line option to specify the array limit size
  - Added a new test to test the command line option
  - Fixed the existing test to verify all the supported operators
This commit is contained in:
Rahul Behl 2026-02-13 12:25:26 +05:30
parent 92ff52f16e
commit b88fc74c57
7 changed files with 118 additions and 76 deletions

View File

@ -1825,7 +1825,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-U", CbPartialMatch, &V3PreShell::undef);
DECL_OPTION("-underline-zero", OnOff, &m_underlineZero).undocumented(); // Deprecated
DECL_OPTION("-no-unlimited-stack", CbCall, []() {}); // Processed only in bin/verilator shell
DECL_OPTION("-constraint-with-limit", Set, &m_constraintWithLimit).undocumented();
DECL_OPTION("-constraint-array-limit", Set, &m_constraintArrayLimit).undocumented();
DECL_OPTION("-unroll-count", Set, &m_unrollCount).undocumented(); // Optimization tweak
DECL_OPTION("-unroll-limit", Set, &m_unrollLimit);
DECL_OPTION("-unroll-stmts", Set, &m_unrollStmts).undocumented(); // Optimization tweak

View File

@ -352,7 +352,7 @@ private:
int m_unrollCount = 64; // main switch: --unroll-count
int m_unrollLimit = 16384; // main switch: --unroll-limit
int m_unrollStmts = 30000; // main switch: --unroll-stmts
int m_constraintWithLimit = 64; // main switch: --constraint-with-limit
int m_constraintArrayLimit = 64; // main switch: --constraint-array-limit
int m_verilateJobs = -1; // main switch: --verilate-jobs
int m_compLimitBlocks = 0; // compiler selection; number of nested blocks
@ -636,7 +636,7 @@ public:
int unrollCount() const { return m_unrollCount; }
int unrollLimit() const { return m_unrollLimit; }
int unrollStmts() const { return m_unrollStmts; }
int constraintWithLimit() const { return m_constraintWithLimit; }
int constraintArrayLimit() const { return m_constraintArrayLimit; }
int verilateJobs() const { return m_verilateJobs; }
int compLimitBlocks() const { return m_compLimitBlocks; }

View File

@ -1513,11 +1513,11 @@ class ConstraintExprVisitor final : public VNVisitor {
if (AstUnpackArrayDType* const adtypep
= VN_CAST(nodep->fromp()->dtypep()->skipRefp(), UnpackArrayDType)) {
const int arraySize = adtypep->elementsConst();
if (arraySize > v3Global.opt.constraintWithLimit()) {
if (arraySize > v3Global.opt.constraintArrayLimit()) {
nodep->v3warn(CONSTRAINTIGN, "Constraint array reduction ignored (array size "
+ cvtToStr(arraySize)
+ " exceeds --constraint-with-limit of "
+ cvtToStr(v3Global.opt.constraintWithLimit())
+ " exceeds --constraint-array-limit of "
+ cvtToStr(v3Global.opt.constraintArrayLimit())
+ "), treating as state");
nodep->user1(false);
if (editFormat(nodep)) return;

View File

@ -0,0 +1,6 @@
%Warning-CONSTRAINTIGN: t/t_constraint_array_limit.v:15:12: Constraint array reduction ignored (array size 100 exceeds --constraint-array-limit of 64), treating as state
15 | data.sum() with (item) < 1000;
| ^~~
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expectations definition
#
# Copyright 2024 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=test.vlt_all, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,38 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Ravi Behl.
// SPDX-License-Identifier: CC0-1.0
// Test that array reduction constraints are ignored when array size exceeds --constraint-array-limit
`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);
class Packet;
rand int data[100]; // Array size 100 > default limit of 64
constraint c {
data.sum() with (item) < 1000; // This should be ignored due to array size
}
function void verify();
int i;
i = randomize();
`checkd(i, 1);
endfunction
endclass
module t;
initial begin
Packet p;
int success_count;
p = new;
// Try randomization -- should fail with a warning
p.verify();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -5,6 +5,8 @@
// SPDX-License-Identifier: CC0-1.0
// Test case for array reduction methods with 'with' clause in constraints (issue #6455)
`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);
class test_sum;
rand byte array[5];
@ -20,14 +22,18 @@ class test_sum;
}
}
function bit verify();
function void verify();
int count_map[byte];
int repeated_count = 0;
int i;
i = randomize();
`checkd(i, 1);
// Count occurrences
foreach (array[i]) begin
if (!count_map.exists(array[i])) count_map[array[i]] = 0;
count_map[array[i]]++;
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
@ -36,22 +42,20 @@ class test_sum;
if (repeated_count != 3) begin
$display("%%Error: sum test - repeated_value=%0d appears %0d times, expected 3",
repeated_value, repeated_count);
return 0;
$stop;
end
end else begin
$display("%%Error: sum test - repeated_value=%0d doesn't appear in array", repeated_value);
return 0;
$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]);
return 0;
$stop;
end
end
return 1;
endfunction
endclass
@ -65,28 +69,30 @@ class test_product;
array.sum() with (int'(item != 0)) >= 2;
}
function bit verify();
function void verify();
int prod = 1;
int nonzero_count = 0;
int i;
foreach (array[i]) begin
if (array[i] != 0) begin
prod *= array[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);
return 0;
$stop;
end
if (nonzero_count < 2) begin
$display("%%Error: product test - only %0d non-zero elements", nonzero_count);
return 0;
$stop;
end
return 1;
endfunction
endclass
@ -98,19 +104,21 @@ class test_and;
array.and() with (item & 8'hF0) == 8'h50;
}
function bit verify();
function void verify();
bit [7:0] result = 8'hFF;
int i;
foreach (array[i]) begin
result &= (array[i] & 8'hF0);
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);
return 0;
$stop;
end
return 1;
endfunction
endclass
@ -124,19 +132,21 @@ class test_or;
array.sum() with (int'((item & 8'h08) != 0)) >= 1;
}
function bit verify();
function void verify();
bit [7:0] result = 8'h00;
int i;
foreach (array[i]) begin
result |= (array[i] & 8'h08);
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);
return 0;
$stop;
end
return 1;
endfunction
endclass
@ -150,19 +160,21 @@ class test_xor;
array.sum() with (int'(item != 0)) >= 2;
}
function bit verify();
function void verify();
bit [7:0] result = 8'h00;
int i;
foreach (array[i]) begin
result ^= array[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");
return 0;
$stop;
end
return 1;
endfunction
endclass
@ -176,57 +188,27 @@ module t;
initial begin
// Test sum
sum_inst = new();
repeat (3) begin
if (sum_inst.randomize() == 0) begin
$display("%%Error: Failed to randomize sum test");
$stop;
end
if (!sum_inst.verify()) $stop;
end
repeat (20) sum_inst.verify();
$display("sum test PASSED");
// Test product
product_inst = new();
repeat (3) begin
if (product_inst.randomize() == 0) begin
$display("%%Error: Failed to randomize product test");
$stop;
end
if (!product_inst.verify()) $stop;
end
repeat (20) product_inst.verify();
$display("product test PASSED");
// Test and
and_inst = new();
repeat (3) begin
if (and_inst.randomize() == 0) begin
$display("%%Error: Failed to randomize and test");
$stop;
end
if (!and_inst.verify()) $stop;
end
repeat (20) and_inst.verify();
$display("and test PASSED");
// Test or
or_inst = new();
repeat (3) begin
if (or_inst.randomize() == 0) begin
$display("%%Error: Failed to randomize or test");
$stop;
end
if (!or_inst.verify()) $stop;
end
repeat (20) or_inst.verify();
$display("or test PASSED");
// Test xor
xor_inst = new();
repeat (3) begin
if (xor_inst.randomize() == 0) begin
$display("%%Error: Failed to randomize xor test");
$stop;
end
if (!xor_inst.verify()) $stop;
end
repeat (20) xor_inst.verify();
$display("xor test PASSED");
$write("*-* All Finished *-*\n");