Fix multidim dynamic array elements passed to ref argument (#7023)
This commit is contained in:
parent
a660fa54a7
commit
6303eb45ce
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue