mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
This commit is contained in:
parent
175e1dde73
commit
70112438c3
@ -1344,11 +1344,54 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
UINFO(9, "created " << varp << endl);
|
||||
return newp;
|
||||
}
|
||||
AstNodeStmt* createArrayForeachLoop(FileLine* const fl, AstNodeDType* const dtypep,
|
||||
AstNodeExpr* exprp) {
|
||||
V3UniqueNames* uniqueNamep = new V3UniqueNames{"__Vrandarr"};
|
||||
AstNodeDType* tempDTypep = dtypep;
|
||||
AstVar* randLoopIndxp = nullptr;
|
||||
AstNodeStmt* stmtsp = nullptr;
|
||||
auto createLoopIndex = [&](AstNodeDType* tempDTypep) {
|
||||
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};
|
||||
return new AstForeach{fl, randLoopVarp, newRandStmtsp(fl, tempElementp, nullptr)};
|
||||
};
|
||||
AstNodeExpr* tempElementp = nullptr;
|
||||
while (VN_CAST(tempDTypep, DynArrayDType) || VN_CAST(tempDTypep, UnpackArrayDType)) {
|
||||
AstVar* const newRandLoopIndxp = createLoopIndex(tempDTypep);
|
||||
randLoopIndxp = AstNode::addNext(randLoopIndxp, newRandLoopIndxp);
|
||||
tempElementp
|
||||
= VN_CAST(tempDTypep, DynArrayDType)
|
||||
? static_cast<AstNodeExpr*>(
|
||||
new AstCMethodHard{fl, tempElementp ? tempElementp : exprp, "atWrite",
|
||||
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}})
|
||||
: static_cast<AstNodeExpr*>(
|
||||
new AstArraySel{fl, tempElementp ? tempElementp : exprp,
|
||||
new AstVarRef{fl, newRandLoopIndxp, VAccess::READ}});
|
||||
tempElementp->dtypep(tempDTypep->subDTypep());
|
||||
tempDTypep = tempDTypep->virtRefDTypep();
|
||||
}
|
||||
handleUnsupportedStruct(tempElementp);
|
||||
stmtsp = createForeachLoop(tempElementp, randLoopIndxp);
|
||||
return stmtsp;
|
||||
}
|
||||
AstNodeStmt* newRandStmtsp(FileLine* fl, AstNodeExpr* exprp, AstVar* randcVarp, int offset = 0,
|
||||
AstMemberDType* memberp = nullptr) {
|
||||
if (const auto* const structDtp
|
||||
= VN_CAST(memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp(),
|
||||
StructDType)) {
|
||||
AstNodeDType* const memberDtp
|
||||
= memberp ? memberp->subDTypep()->skipRefp() : exprp->dtypep()->skipRefp();
|
||||
if (const auto* const structDtp = VN_CAST(memberDtp, StructDType)) {
|
||||
AstNodeStmt* stmtsp = nullptr;
|
||||
if (structDtp->packed()) offset += memberp ? memberp->lsb() : 0;
|
||||
for (AstMemberDType* smemberp = structDtp->membersp(); smemberp;
|
||||
@ -1364,16 +1407,10 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
if (!structSelp->dtypep()) structSelp->dtypep(smemberp->subDTypep());
|
||||
randp = newRandStmtsp(fl, structSelp, nullptr);
|
||||
}
|
||||
if (stmtsp) {
|
||||
stmtsp->addNext(randp);
|
||||
} else {
|
||||
stmtsp = randp;
|
||||
}
|
||||
stmtsp = stmtsp ? stmtsp->addNext(randp) : randp;
|
||||
}
|
||||
return stmtsp;
|
||||
} else if (const auto* const unionDtp = VN_CAST(memberp ? memberp->subDTypep()->skipRefp()
|
||||
: exprp->dtypep()->skipRefp(),
|
||||
UnionDType)) {
|
||||
} else if (const auto* const unionDtp = VN_CAST(memberDtp, UnionDType)) {
|
||||
if (!unionDtp->packed()) {
|
||||
unionDtp->v3error("Unpacked unions shall not be declared as rand or randc."
|
||||
" (IEEE 1800-2023 18.4)");
|
||||
@ -1381,6 +1418,11 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
}
|
||||
AstMemberDType* const firstMemberp = unionDtp->membersp();
|
||||
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
|
||||
} else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) {
|
||||
return createArrayForeachLoop(fl, dynarrayDtp, exprp);
|
||||
} else if (AstUnpackArrayDType* const unpackarrayDtp
|
||||
= VN_CAST(memberDtp, UnpackArrayDType)) {
|
||||
return createArrayForeachLoop(fl, unpackarrayDtp, exprp);
|
||||
} else {
|
||||
AstNodeExpr* valp;
|
||||
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
|
||||
@ -1561,11 +1603,12 @@ class RandomizeVisitor final : public VNVisitor {
|
||||
if (memberVarp->user3()) return; // Handled in constraints
|
||||
const AstNodeDType* const dtypep = memberVarp->dtypep()->skipRefp();
|
||||
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)
|
||||
|| VN_IS(dtypep, UnionDType)) {
|
||||
|| VN_IS(dtypep, UnionDType) || VN_IS(dtypep, PackArrayDType)
|
||||
|| VN_IS(dtypep, UnpackArrayDType) || VN_IS(dtypep, DynArrayDType)) {
|
||||
AstVar* const randcVarp = newRandcVarsp(memberVarp);
|
||||
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
|
||||
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);
|
||||
basicRandomizep->addStmtsp(stmtp);
|
||||
basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp});
|
||||
} else if (const AstClassRefDType* const classRefp = VN_CAST(dtypep, ClassRefDType)) {
|
||||
if (classRefp->classp() == nodep) {
|
||||
memberVarp->v3warn(E_UNSUPPORTED,
|
||||
|
21
test_regress/t/t_randomize_array.py
Executable file
21
test_regress/t/t_randomize_array.py
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect 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('simulator')
|
||||
|
||||
if not test.have_solver:
|
||||
test.skip("No constraint solver installed")
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
145
test_regress/t/t_randomize_array.v
Executable file
145
test_regress/t/t_randomize_array.v
Executable file
@ -0,0 +1,145 @@
|
||||
// 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_packed_array_test;
|
||||
|
||||
rand bit [3:0] [2:0] [15:0] packed_array;
|
||||
function new();
|
||||
packed_array = '{default: '{default: '{default: 'h0}}};
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
`check_rand(this, this.packed_array)
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
class unconstrained_unpacked_array_test;
|
||||
|
||||
rand bit [2:0] [15:0] unpacked_array [3][5];
|
||||
function new();
|
||||
unpacked_array = '{ '{default: '{default: 'h0}},
|
||||
'{default: '{default: 'h1}},
|
||||
'{default: '{default: 'h2}}};
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
foreach (unpacked_array[i]) begin
|
||||
foreach (unpacked_array[i][j]) begin
|
||||
// At the innermost packed level, invoke check_rand
|
||||
`check_rand(this, this.unpacked_array[i][j])
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
class unconstrained_dynamic_array_test;
|
||||
|
||||
rand int dynamic_array_1d[];
|
||||
rand int dynamic_array_2d[][];
|
||||
|
||||
function new();
|
||||
// Initialize 1D dynamic array
|
||||
dynamic_array_1d = new[5];
|
||||
foreach(dynamic_array_1d[i]) begin
|
||||
dynamic_array_1d[i] = 'h0 + i;
|
||||
end
|
||||
|
||||
// Initialize 2D dynamic array
|
||||
dynamic_array_2d = new[3];
|
||||
foreach(dynamic_array_2d[i]) begin
|
||||
dynamic_array_2d[i] = new[3];
|
||||
foreach(dynamic_array_2d[i][j]) begin
|
||||
dynamic_array_2d[i][j] = 'h0 + i + j;
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
foreach (dynamic_array_1d[i]) begin
|
||||
`check_rand(this, dynamic_array_1d[i])
|
||||
end
|
||||
foreach (dynamic_array_2d[i]) begin
|
||||
foreach (dynamic_array_2d[i][j]) begin
|
||||
`check_rand(this, dynamic_array_2d[i][j])
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
class unconstrained_struct_with_array_test;
|
||||
|
||||
typedef struct {
|
||||
rand bit [7:0] byte_array[4];
|
||||
} struct_with_array_t;
|
||||
|
||||
rand struct_with_array_t struct_with_array;
|
||||
|
||||
function new();
|
||||
struct_with_array = '{'{default: 'h0}};
|
||||
endfunction
|
||||
|
||||
function void check_randomization();
|
||||
foreach (struct_with_array.byte_array[i]) begin
|
||||
`check_rand(this, struct_with_array.byte_array[i])
|
||||
end
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
||||
module t_randomize_array;
|
||||
unconstrained_packed_array_test packed_class;
|
||||
unconstrained_unpacked_array_test unpacked_class;
|
||||
unconstrained_dynamic_array_test dynamic_class;
|
||||
unconstrained_struct_with_array_test struct_with_array_class;
|
||||
|
||||
initial begin
|
||||
// Test 1: Packed Array Unconstrained Constrained Test
|
||||
packed_class = new();
|
||||
repeat(2) begin
|
||||
packed_class.check_randomization();
|
||||
end
|
||||
|
||||
// Test 2: Unpacked Array Unconstrained Constrained Test
|
||||
unpacked_class = new();
|
||||
repeat(2) begin
|
||||
unpacked_class.check_randomization();
|
||||
end
|
||||
|
||||
// Test 3: Dynamic Array Unconstrained Constrained Test
|
||||
dynamic_class = new();
|
||||
repeat(2) begin
|
||||
dynamic_class.check_randomization();
|
||||
end
|
||||
|
||||
// Test 4: Struct Containing Array Test
|
||||
|
||||
struct_with_array_class = new();
|
||||
repeat(2) begin
|
||||
struct_with_array_class.check_randomization();
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
8
test_regress/t/t_randomize_array_unsup.out
Normal file
8
test_regress/t/t_randomize_array_unsup.out
Normal file
@ -0,0 +1,8 @@
|
||||
%Error-UNSUPPORTED: t/t_randomize_array_unsup.v:28:8: Unsupported: CreateArrayForeachLoop currently does not support this data type. (Struct-Array unconstrained randomization is not fully supported)
|
||||
28 | rand simple_struct_t struct_array_2[];
|
||||
| ^~~~~~~~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_randomize_array_unsup.v:29:8: Unsupported: CreateArrayForeachLoop currently does not support this data type. (Struct-Array unconstrained randomization is not fully supported)
|
||||
29 | rand simple_struct_t struct_array_1[3];
|
||||
| ^~~~~~~~~~~~~~~
|
||||
%Error: Exiting due to
|
16
test_regress/t/t_randomize_array_unsup.py
Executable file
16
test_regress/t/t_randomize_array_unsup.py
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect 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('simulator')
|
||||
|
||||
test.compile(fails=test.vlt_all, expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
72
test_regress/t/t_randomize_array_unsup.v
Normal file
72
test_regress/t/t_randomize_array_unsup.v
Normal file
@ -0,0 +1,72 @@
|
||||
// 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
|
@ -1,5 +1,5 @@
|
||||
%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:14:32: Unsupported: randomizing this expression, treating as state
|
||||
14 | constraint dynsize { dynarr.size < 20; }
|
||||
%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:13:32: Unsupported: randomizing this expression, treating as state
|
||||
13 | constraint dynsize { dynarr.size < 20; }
|
||||
| ^~~~
|
||||
... 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.
|
||||
@ -7,16 +7,8 @@
|
||||
: ... note: In instance 't'
|
||||
8 | rand int assocarr[string];
|
||||
| ^~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:9:13: Unsupported: random member variable with type 'int$[]'
|
||||
: ... note: In instance 't'
|
||||
9 | rand int dynarr[];
|
||||
| ^~~~~~
|
||||
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:10:13: Unsupported: random member variable with type 'int$[0:4]'
|
||||
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:10:13: Unsupported: random member variable with the type of the containing class
|
||||
: ... note: In instance 't'
|
||||
10 | rand int unpackarr[5];
|
||||
| ^~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:11:13: Unsupported: random member variable with the type of the containing class
|
||||
: ... note: In instance 't'
|
||||
11 | rand Cls cls;
|
||||
10 | rand Cls cls;
|
||||
| ^~~
|
||||
%Error: Exiting due to
|
||||
|
@ -7,7 +7,6 @@
|
||||
class Cls;
|
||||
rand int assocarr[string];
|
||||
rand int dynarr[];
|
||||
rand int unpackarr[5];
|
||||
rand Cls cls;
|
||||
rand int i;
|
||||
int st;
|
||||
|
@ -21072,21 +21072,15 @@ typedef class uvm_tlm_extension_base;
|
||||
class uvm_tlm_generic_payload extends uvm_sequence_item;
|
||||
rand bit [63:0] m_address;
|
||||
rand uvm_tlm_command_e m_command;
|
||||
//TODO issue-4625 - Rand fields of dynamic array types
|
||||
//TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'byte[]'
|
||||
/*TODO rand*/ byte unsigned m_data[];
|
||||
rand byte unsigned m_data[];
|
||||
rand int unsigned m_length;
|
||||
rand uvm_tlm_response_status_e m_response_status;
|
||||
bit m_dmi;
|
||||
//TODO issue-4625 - Rand fields of dynamic array types
|
||||
//TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'byte[]'
|
||||
/*TODO rand*/ byte unsigned m_byte_enable[];
|
||||
rand byte unsigned m_byte_enable[];
|
||||
rand int unsigned m_byte_enable_length;
|
||||
rand int unsigned m_streaming_width;
|
||||
protected uvm_tlm_extension_base m_extensions [uvm_tlm_extension_base];
|
||||
//TODO issue-4625 - Rand fields of dynamic array types
|
||||
//TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'CLASSREFDTYPE 'uvm_tlm_extension_base'[]'
|
||||
local /*rand*/ uvm_tlm_extension_base m_rand_exts[];
|
||||
local rand uvm_tlm_extension_base m_rand_exts[];
|
||||
typedef uvm_object_registry#(uvm_tlm_generic_payload,"uvm_tlm_generic_payload") type_id;
|
||||
static function uvm_tlm_generic_payload type_id_create (string name="",
|
||||
uvm_component parent=null,
|
||||
|
Loading…
Reference in New Issue
Block a user