mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
parent
76fe224e7c
commit
8c3cc3af8f
@ -1390,15 +1390,6 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
|
||||
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
|
||||
};
|
||||
auto handleUnsupportedStruct = [&](AstNodeExpr* tempElementp) {
|
||||
if (VN_IS(tempElementp->dtypep()->skipRefp(), StructDType)) {
|
||||
tempElementp->dtypep()->v3warn(
|
||||
E_UNSUPPORTED,
|
||||
"Unsupported: CreateArrayForeachLoop currently does not support "
|
||||
"this data type. (Struct-Array unconstrained "
|
||||
"randomization is not fully supported)");
|
||||
}
|
||||
};
|
||||
auto createForeachLoop = [&](AstNodeExpr* tempElementp, AstVar* randLoopIndxp) {
|
||||
AstSelLoopVars* const randLoopVarp
|
||||
= new AstSelLoopVars{fl, exprp->cloneTree(false), randLoopIndxp};
|
||||
@ -1422,7 +1413,6 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
tempElementp->dtypep(tempDTypep->subDTypep());
|
||||
tempDTypep = tempDTypep->virtRefDTypep();
|
||||
}
|
||||
handleUnsupportedStruct(tempElementp);
|
||||
stmtsp = createForeachLoop(tempElementp, randLoopIndxp);
|
||||
return stmtsp;
|
||||
}
|
||||
|
@ -119,6 +119,28 @@ class UnknownVisitor final : public VNVisitor {
|
||||
= new AstVar{fl, VVarType::MODULETEMP, m_lvboundNames.get(prep), prep->dtypep()};
|
||||
m_modp->addStmtsp(varp);
|
||||
AstNode* const abovep = prep->backp(); // Grab above point before we replace 'prep'
|
||||
AstNode* currentStmtp = abovep;
|
||||
while (currentStmtp && !VN_IS(currentStmtp, NodeStmt))
|
||||
currentStmtp = currentStmtp->backp();
|
||||
VNRelinker linkContext;
|
||||
currentStmtp = currentStmtp->unlinkFrBackWithNext(&linkContext);
|
||||
AstNodeExpr* const selExprp = prep->cloneTree(true);
|
||||
AstNodeExpr* currentExprp = selExprp;
|
||||
while (AstNodeExpr* itrSelExprp = VN_AS(currentExprp->op1p(), NodeExpr)) {
|
||||
if (AstVarRef* const selRefp = VN_CAST(itrSelExprp, VarRef)) {
|
||||
// Mark the variable reference as READ access to avoid assignment issues
|
||||
selRefp->access(VAccess::READ);
|
||||
break;
|
||||
}
|
||||
currentExprp = itrSelExprp;
|
||||
}
|
||||
// Before assigning the value to the temporary variable, first assign the current array
|
||||
// element to it. This ensures any field modifications happen on the correct instance
|
||||
// and prevents overwriting other fields.
|
||||
AstNode* const newAssignp
|
||||
= new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, selExprp};
|
||||
newAssignp->addNextStmt(currentStmtp, newAssignp);
|
||||
linkContext.relink(newAssignp);
|
||||
prep->replaceWith(new AstVarRef{fl, varp, VAccess::WRITE});
|
||||
if (m_timingControlp) m_timingControlp->unlinkFrBack();
|
||||
AstIf* const newp = new AstIf{
|
||||
|
@ -106,6 +106,37 @@ class unconstrained_struct_with_array_test;
|
||||
|
||||
endclass
|
||||
|
||||
class unconstrained_struct_array_test;
|
||||
|
||||
typedef struct {
|
||||
rand int field_a;
|
||||
rand int field_b;
|
||||
} simple_struct_t;
|
||||
rand simple_struct_t struct_array_1[3]; // Unpacked array
|
||||
rand simple_struct_t struct_array_2[][]; // Dynamic array
|
||||
|
||||
function new();
|
||||
struct_array_1 = '{'{default: 0}, '{default: 1}, '{default: 2}};
|
||||
|
||||
struct_array_2 = new[3];
|
||||
foreach (struct_array_2[i]) begin
|
||||
struct_array_2[i] = new[4];
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
foreach (struct_array_1[i]) begin
|
||||
`check_rand(this, struct_array_1[i].field_a)
|
||||
`check_rand(this, struct_array_1[i].field_b)
|
||||
end
|
||||
foreach (struct_array_2[i, j]) begin
|
||||
`check_rand(this, struct_array_2[i][j].field_a)
|
||||
`check_rand(this, struct_array_2[i][j].field_b)
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
class unconstrained_associative_array_test;
|
||||
|
||||
rand int associative_array_1d[string];
|
||||
@ -172,6 +203,7 @@ module t_randomize_array;
|
||||
unconstrained_unpacked_array_test unpacked_class;
|
||||
unconstrained_dynamic_array_test dynamic_class;
|
||||
unconstrained_struct_with_array_test struct_with_array_class;
|
||||
unconstrained_struct_array_test struct_array_class;
|
||||
unconstrained_associative_array_test associative_array_class;
|
||||
unconstrained_queue_test queue_class;
|
||||
|
||||
@ -200,6 +232,11 @@ module t_randomize_array;
|
||||
struct_with_array_class.check_randomization();
|
||||
end
|
||||
|
||||
struct_array_class = new();
|
||||
repeat(2) begin
|
||||
struct_array_class.check_randomization();
|
||||
end
|
||||
|
||||
// Test 5: Associative Array Unconstrained Test
|
||||
associative_array_class = new();
|
||||
repeat(2) begin
|
||||
|
@ -1,72 +0,0 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define check_rand(cl, field) \
|
||||
begin \
|
||||
longint prev_result; \
|
||||
int ok = 0; \
|
||||
for (int i = 0; i < 10; i++) begin \
|
||||
longint result; \
|
||||
void'(cl.randomize()); \
|
||||
result = longint'(field); \
|
||||
if (i > 0 && result != prev_result) ok = 1; \
|
||||
prev_result = result; \
|
||||
end \
|
||||
if (ok != 1) $stop; \
|
||||
end
|
||||
|
||||
class unconstrained_struct_array_test;
|
||||
|
||||
typedef struct {
|
||||
rand int field_a;
|
||||
rand int field_b;
|
||||
} simple_struct_t;
|
||||
|
||||
rand simple_struct_t struct_array_2[]; // Dynamic array
|
||||
rand simple_struct_t struct_array_1[3]; // Unpacked array
|
||||
|
||||
|
||||
function new();
|
||||
struct_array_1 = '{'{default: 0}, '{default: 1}, '{default: 2}};
|
||||
|
||||
struct_array_2 = new[3];
|
||||
foreach (struct_array_2[i]) begin
|
||||
struct_array_2[i].field_a = i;
|
||||
struct_array_2[i].field_b = i + 1;
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
foreach (struct_array_1[i]) begin
|
||||
`check_rand(this, struct_array_1[i].field_a)
|
||||
`check_rand(this, struct_array_1[i].field_b)
|
||||
end
|
||||
|
||||
foreach (struct_array_2[i]) begin
|
||||
`check_rand(this, struct_array_2[i].field_a)
|
||||
`check_rand(this, struct_array_2[i].field_b)
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
module t_randomize_array_unsup;
|
||||
|
||||
unconstrained_struct_array_test struct_array_class;
|
||||
|
||||
initial begin
|
||||
|
||||
// Test: Struct Array Unconstrained Constrained Test
|
||||
struct_array_class = new();
|
||||
repeat(2) begin
|
||||
struct_array_class.check_randomization();
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
@ -11,6 +11,8 @@ import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
52
test_regress/t/t_struct_array_assignment.v
Executable file
52
test_regress/t/t_struct_array_assignment.v
Executable file
@ -0,0 +1,52 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2024 by PlanV GmbH.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class unconstrained_struct_array_test;
|
||||
|
||||
typedef struct {
|
||||
int field_a;
|
||||
int field_b;
|
||||
int field_c;
|
||||
} simple_struct_t;
|
||||
|
||||
simple_struct_t struct_array[3]; // Unpacked array
|
||||
|
||||
function new();
|
||||
// Initialize struct_array
|
||||
struct_array = '{'{default: 0}, '{default: 1}, '{default: 2}};
|
||||
endfunction
|
||||
|
||||
// Self-check function to validate the array contents
|
||||
function void self_test();
|
||||
foreach (struct_array[i]) begin
|
||||
if (struct_array[i].field_a != i) $stop;
|
||||
if (struct_array[i].field_b != i + 1) $stop;
|
||||
if (struct_array[i].field_c != i + 2) $stop;
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
module t_struct_array_assignment;
|
||||
unconstrained_struct_array_test cl;
|
||||
|
||||
initial begin
|
||||
|
||||
cl = new();
|
||||
|
||||
foreach(cl.struct_array[i]) begin
|
||||
cl.struct_array[i].field_a = i;
|
||||
cl.struct_array[i].field_b = i + 1;
|
||||
cl.struct_array[i].field_c = i + 2;
|
||||
end
|
||||
|
||||
cl.self_test();
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user