Fix array reduction in constraints crashing with class inheritance (#7226) (#7263)

This commit is contained in:
Yilou Wang 2026-03-16 21:36:48 +01:00 committed by GitHub
parent e5d0b89bfc
commit bf792f1809
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 100 additions and 5 deletions

View File

@ -2368,9 +2368,8 @@ class ConstraintExprVisitor final : public VNVisitor {
const std::string smtArrayName = arrVarp->name();
AstNodeDType* elemDtp = arrVarp->dtypep()->skipRefp()->subDTypep();
const int elemWidth = elemDtp->width();
AstNodeModule* const classModulep = m_classp
? static_cast<AstNodeModule*>(m_classp)
: VN_AS(m_genp->user2p(), NodeModule);
AstNodeModule* const arrModulep = VN_AS(arrVarp->user2p(), NodeModule);
AstNodeModule* const genModulep = VN_AS(m_genp->user2p(), NodeModule);
arrVarp->user3(true);
// Create variable name using AstSFormatF
@ -2379,7 +2378,7 @@ class ConstraintExprVisitor final : public VNVisitor {
// Create array element reference: array.atWrite(index)
AstCMethodHard* const atWritep = new AstCMethodHard{
fl, new AstVarRef{fl, classModulep, arrVarp, VAccess::READWRITE},
fl, new AstVarRef{fl, arrModulep, arrVarp, VAccess::READWRITE},
VCMethod::ARRAY_AT_WRITE, new AstVarRef{fl, loopVarp, VAccess::READ}};
atWritep->dtypeFrom(elemDtp);
@ -2392,7 +2391,7 @@ class ConstraintExprVisitor final : public VNVisitor {
// Create write_var method call: gen.write_var(arrElement, width, name, 0)
AstCMethodHard* const writeVarp = new AstCMethodHard{
fl, new AstVarRef{fl, classModulep, m_genp, VAccess::READWRITE},
fl, new AstVarRef{fl, genModulep, m_genp, VAccess::READWRITE},
VCMethod::RANDOMIZER_WRITE_VAR, atWritep};
writeVarp->addPinsp(new AstConst{fl, AstConst::WidthedValue{}, 64,
static_cast<uint32_t>(elemWidth)});

View File

@ -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()

View File

@ -0,0 +1,75 @@
// 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 array reduction methods in constraints with class inheritance (issue #7226)
// The bug was that .sum() in a constraint crashed with "Can't locate varref scope"
// when the class extends another class.
// 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
class Base;
rand int base_val;
constraint c_base {base_val inside {[1:100]};}
endclass
// Derived class with dynamic array and .sum() constraint -- the crash scenario
class Derived extends Base;
rand int arr[];
constraint c_size {arr.size() == 4;}
constraint c_sum {arr.sum() == 200;}
function new();
arr = new[4];
endfunction
endclass
// Multi-level inheritance: ensure deeper hierarchies also work
class GrandChild extends Derived;
rand bit [7:0] extra[3];
constraint c_extra_or {extra.or() != 0;}
endclass
module t;
initial begin
static Derived d = new();
static GrandChild g = new();
int sum_check;
// Test single-level inheritance with .sum()
repeat (5) begin
`checkd(d.randomize(), 1)
`checkd(d.arr.size(), 4)
sum_check = 0;
foreach (d.arr[i]) sum_check += d.arr[i];
`checkd(sum_check, 200)
`checkd(d.base_val inside {[1:100]}, 1)
end
// Test multi-level inheritance with reduction on fixed array
repeat (5) begin
bit [7:0] or_check;
`checkd(g.randomize(), 1)
`checkd(g.arr.size(), 4)
sum_check = 0;
foreach (g.arr[i]) sum_check += g.arr[i];
`checkd(sum_check, 200)
or_check = 0;
foreach (g.extra[i]) or_check |= g.extra[i];
if (or_check == 0) begin
$write("%%Error: %s:%0d: extra.or() should be nonzero\n", `__FILE__, `__LINE__);
`stop;
end
`checkd(g.base_val inside {[1:100]}, 1)
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule