Fix multidim dynamic array elements passed to ref argument (#7023)

This commit is contained in:
Ryszard Rozak 2026-02-10 08:46:04 +01:00 committed by GitHub
parent a660fa54a7
commit 6303eb45ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 116 additions and 39 deletions

View File

@ -508,6 +508,16 @@ class TaskVisitor final : public VNVisitor {
return assp;
}
void changeAtWriteRecurse(AstNodeExpr* const exprp) {
// Change nested at methods to writable variant
if (AstCMethodHard* const cMethodp = VN_CAST(exprp, CMethodHard)) {
if (cMethodp->method() == VCMethod::ARRAY_AT) {
cMethodp->method(VCMethod::ARRAY_AT_WRITE);
}
changeAtWriteRecurse(cMethodp->fromp());
}
}
void connectPort(AstVar* portp, AstArg* argp, const string& namePrefix, AstNode* beginp,
bool inlineTask) {
AstNodeExpr* const pinp = argp->exprp();
@ -538,10 +548,7 @@ class TaskVisitor final : public VNVisitor {
refArgOk = cMethodp->method() == VCMethod::DYN_AT_WRITE_APPEND
|| cMethodp->method() == VCMethod::DYN_AT_WRITE_APPEND_BACK;
} else {
if (cMethodp->method() == VCMethod::ARRAY_AT) {
// Change the method to writable variant
cMethodp->method(VCMethod::ARRAY_AT_WRITE);
}
changeAtWriteRecurse(cMethodp);
refArgOk = cMethodp->method() == VCMethod::ARRAY_AT_WRITE;
}
}

View File

@ -28,10 +28,16 @@ class Cls;
endfunction
endclass
typedef struct {
MyInt arr[2][][$];
} struct_t;
module t;
int a, b;
int arr[1];
int dyn_arr[];
int dyn_arr_2d[][];
struct_t st;
Cls cls;
MyInt mi;
initial begin
@ -64,6 +70,25 @@ module t;
`checkh(dyn_arr[1], 2);
`checkh(b, 5);
dyn_arr_2d = new[2];
dyn_arr_2d[0] = new[4];
dyn_arr_2d[0][1] = 10;
b = get_val_set_5(dyn_arr_2d[0][1]);
`checkh(dyn_arr_2d[0][1], 5);
`checkh(b, 10);
b = cls.get_val_set_2(dyn_arr_2d[0][1]);
`checkh(dyn_arr_2d[0][1], 2);
`checkh(b, 5);
st.arr[1] = new[3];
st.arr[1][2][0] = new(10);
b = get_val_set_5(st.arr[1][2][0].x);
`checkh(st.arr[1][2][0].x, 5);
`checkh(b, 10);
b = cls.get_val_set_2(st.arr[1][2][0].x);
`checkh(st.arr[1][2][0].x, 2);
`checkh(b, 5);
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -5,49 +5,94 @@
// SPDX-License-Identifier: CC0-1.0
class external_cl;
int x;
int y;
int x;
int y;
logic [7:0] dyn[][];
function new();
x = 0;
y = 0;
endfunction
function new();
x = 0;
y = 0;
dyn = new[4];
foreach (dyn[i]) dyn[i] = new[1];
endfunction
endclass
module t;
initial begin
int a, b;
automatic int limit = 10;
external_cl obj;
initial begin
int a, b;
automatic int limit = 10;
external_cl obj;
// Test 1: Basic std::randomize with 'with' clause
if (std::randomize(a, b) with { 2 < a; a < 7; b < a; } != 1) $stop;
if (!(2 < a && a < 7 && b < a)) $stop;
$display("Test 1 passed: a=%0d, b=%0d", a, b);
// Test 1: Basic std::randomize with 'with' clause
if (std::randomize(
a, b
) with {
2 < a;
a < 7;
b < a;
} != 1)
$stop;
if (!(2 < a && a < 7 && b < a)) $stop;
$display("Test 1 passed: a=%0d, b=%0d", a, b);
// Test 2: Local variable and class member with mutual constraints
obj = new;
if (std::randomize(a, obj.x) with { a > 10; a < 20; obj.x > a; obj.x < a + 5; } != 1) $stop;
if (!(a > 10 && a < 20 && obj.x > a && obj.x < a + 5)) $stop;
$display("Test 2 passed: a=%0d, obj.x=%0d (obj.x between a+1 and a+4)", a, obj.x);
// Test 2: Local variable and class member with mutual constraints
obj = new;
if (std::randomize(
a, obj.x
) with {
a > 10;
a < 20;
obj.x > a;
obj.x < a + 5;
} != 1)
$stop;
if (!(a > 10 && a < 20 && obj.x > a && obj.x < a + 5)) $stop;
$display("Test 2 passed: a=%0d, obj.x=%0d (obj.x between a+1 and a+4)", a, obj.x);
// Test 3: Reference external variable in constraint
if (std::randomize(a) with { a > 0; a < limit; } != 1) $stop;
if (!(a > 0 && a < limit)) $stop;
$display("Test 3 passed: a=%0d, limit=%0d", a, limit);
// Test 3: Reference external variable in constraint
if (std::randomize(
a
) with {
a > 0;
a < limit;
} != 1)
$stop;
if (!(a > 0 && a < limit)) $stop;
$display("Test 3 passed: a=%0d, limit=%0d", a, limit);
// Test 4: Randomize class member variables
obj = new;
if (std::randomize(obj.x, obj.y) with { obj.x > 5; obj.x < 20; obj.y == obj.x + 1; } != 1) $stop;
if (!(obj.x > 5 && obj.x < 20 && obj.y == obj.x + 1)) $stop;
$display("Test 4 passed: obj.x=%0d, obj.y=%0d", obj.x, obj.y);
// Test 4: Randomize class member variables
obj = new;
if (std::randomize(
obj.x, obj.y
) with {
obj.x > 5;
obj.x < 20;
obj.y == obj.x + 1;
} != 1)
$stop;
if (!(obj.x > 5 && obj.x < 20 && obj.y == obj.x + 1)) $stop;
$display("Test 4 passed: obj.x=%0d, obj.y=%0d", obj.x, obj.y);
// Test 5: Multiple class members and local variable
if (std::randomize(a, obj.x, obj.y) with { a > 0; a < 5; obj.x > a; obj.y > obj.x; obj.y < a + 10; } != 1) $stop;
if (!(a > 0 && a < 5 && obj.x > a && obj.y > obj.x && obj.y < a + 10)) $stop;
$display("Test 5 passed: a=%0d, obj.x=%0d, obj.y=%0d", a, obj.x, obj.y);
// Test 5: Multiple class members and local variable
if (std::randomize(
a, obj.x, obj.y
) with {
a > 0;
a < 5;
obj.x > a;
obj.y > obj.x;
obj.y < a + 10;
} != 1)
$stop;
if (!(a > 0 && a < 5 && obj.x > a && obj.y > obj.x && obj.y < a + 10)) $stop;
$display("Test 5 passed: a=%0d, obj.x=%0d, obj.y=%0d", a, obj.x, obj.y);
$write("*-* All Finished *-*\n");
$finish;
end
// Test 6: Member of 2D array
assert (std::randomize(obj.dyn[2][0]) with {obj.dyn[2][0] inside {[1 : 10]};} == 1);
if (!(obj.dyn[2][0] inside {[1 : 10]})) $stop;
$display("Test 6 passed: obj.dyn[2][0]=%0d", obj.dyn[2][0]);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule