Support unconstrained randomization for unions (#5395) (#5396)

This commit is contained in:
Yilou Wang 2024-08-26 17:04:45 +02:00 committed by GitHub
parent 4e86e60491
commit c4cb26fa9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 274 additions and 19 deletions

View File

@ -215,6 +215,7 @@ Wilson Snyder
Xi Zhang
Yan Xu
Yangyu Chen
Yilou Wang
Yinan Xu
Yoda Lee
Yossi Nivin

View File

@ -1319,6 +1319,16 @@ class RandomizeVisitor final : public VNVisitor {
}
}
return stmtsp;
} else if (const auto* const unionDtp = VN_CAST(memberp ? memberp->subDTypep()->skipRefp()
: exprp->dtypep()->skipRefp(),
UnionDType)) {
if (!unionDtp->packed()) {
unionDtp->v3error("Unpacked unions shall not be declared as rand or randc."
" (IEEE 1800-2023 18.4)");
return nullptr;
}
AstMemberDType* const firstMemberp = unionDtp->membersp();
return newRandStmtsp(fl, exprp, nullptr, offset, firstMemberp);
} else {
AstNodeExpr* valp;
if (AstEnumDType* const enumDtp = VN_CAST(memberp ? memberp->subDTypep()->subDTypep()
@ -1498,7 +1508,8 @@ 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)) {
if (VN_IS(dtypep, BasicDType) || VN_IS(dtypep, StructDType)
|| VN_IS(dtypep, UnionDType)) {
AstVar* const randcVarp = newRandcVarsp(memberVarp);
AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE};
AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp);

View File

@ -1,21 +1,17 @@
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:19:25: Unsupported: random member variable with type 'int$[]'
19 | constraint dynsize { dynarr.size < 20; }
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14:25: Unsupported: random member variable with type 'int$[]'
14 | constraint dynsize { dynarr.size < 20; }
| ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variable with type 'int$[string]'
: ... note: In instance 't'
12 | rand int assocarr[string];
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:8:13: Unsupported: random member variable with type 'int$[string]'
: ... note: In instance 't'
8 | rand int assocarr[string];
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:14: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 type 'int$[0:4]'
: ... note: In instance 't'
14 | rand int unpackarr[5];
10 | rand int unpackarr[5];
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variable with type 'union{}$unit::Union'
%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'
15 | rand Union uni;
| ^~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:16:13: Unsupported: random member variable with the type of the containing class
: ... note: In instance 't'
16 | rand Cls cls;
11 | rand Cls cls;
| ^~~
%Error: Exiting due to

View File

@ -4,15 +4,10 @@
// any use, without warranty, 2020 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
typedef union packed {
int x;
} Union;
class Cls;
rand int assocarr[string];
rand int dynarr[];
rand int unpackarr[5];
rand Union uni;
rand Cls cls;
rand int i;
int st;

View File

@ -0,0 +1,25 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
scenarios(simulator => 1);
if (!$Self->have_solver) {
skip("No constraint solver installed");
} else {
compile(
);
execute(
check_finished => 1,
);
}
ok(1);
1;

View File

@ -0,0 +1,168 @@
// 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
typedef union packed {
int int_value;
bit [31:0] bits;
} SimpleUnion;
typedef struct packed {
rand bit [3:0] field_a;
rand bit [7:0] field_b;
} PackedStruct;
typedef union packed {
PackedStruct struct_fields;
bit [11:0] inner_bits;
} StructInUnion;
typedef union packed {
StructInUnion inner_union;
bit [11:0] outer_bits;
} UnionInUnion;
// SimpleUnion Constrained Test Class
class SimpleUnionConstrainedTest;
rand SimpleUnion union_instance;
function new();
union_instance.bits = 32'b0;
endfunction
constraint union_constraint {
union_instance.bits[11:0] inside {[0:4095]};
}
endclass
// SimpleUnion Unconstrained Test Class
class SimpleUnionUnconstrainedTest;
rand SimpleUnion union_instance;
function new();
union_instance.bits = 32'b0;
endfunction
endclass
// StructInUnion Constrained Test Class
class StructInUnionConstrainedTest;
rand StructInUnion union_instance;
function new();
union_instance.inner_bits = 12'b0;
endfunction
constraint union_constraint {
union_instance.inner_bits inside {[0:4095]};
}
endclass
// StructInUnion Unconstrained Test Class
class StructInUnionUnconstrainedTest;
rand StructInUnion union_instance;
function new();
union_instance.inner_bits = 12'b0;
endfunction
endclass
// UnionInUnion Constrained Test Class
class UnionInUnionConstrainedTest;
rand UnionInUnion union_instance;
function new();
union_instance.outer_bits = 12'b0;
endfunction
constraint union_constraint {
union_instance.outer_bits inside {[0:4095]};
}
endclass
// UnionInUnion Unconstrained Test Class
class UnionInUnionUnconstrainedTest;
rand UnionInUnion union_instance;
function new();
union_instance.outer_bits = 12'b0;
endfunction
endclass
// Top-Level Test Module
module t_randomize_union;
// Instances of each test class
SimpleUnionConstrainedTest test_simple_union_constrained;
SimpleUnionUnconstrainedTest test_simple_union_unconstrained;
StructInUnionConstrainedTest test_struct_in_union_constrained;
StructInUnionUnconstrainedTest test_struct_in_union_unconstrained;
UnionInUnionConstrainedTest test_union_in_union_constrained;
UnionInUnionUnconstrainedTest test_union_in_union_unconstrained;
initial begin
// Test 1: SimpleUnion Constrained Test
test_simple_union_constrained = new();
$display("\n--- Test 1: SimpleUnion Constrained Test ---");
repeat(10) begin
int success;
success = test_simple_union_constrained.randomize();
if (success != 1) $stop;
$display("SimpleUnion (Constrained): int_value: %b, bits: %b", test_simple_union_constrained.union_instance.int_value, test_simple_union_constrained.union_instance.bits);
end
// Test 2: SimpleUnion Unconstrained Test
test_simple_union_unconstrained = new();
$display("\n--- Test 2: SimpleUnion Unconstrained Test ---");
repeat(10) begin
int success;
success = test_simple_union_unconstrained.randomize();
if (success != 1) $stop;
$display("SimpleUnion (Unconstrained): int_value: %b, bits: %b", test_simple_union_unconstrained.union_instance.int_value, test_simple_union_unconstrained.union_instance.bits);
end
// Test 3: StructInUnion Constrained Test
test_struct_in_union_constrained = new();
$display("\n--- Test 3: StructInUnion Constrained Test ---");
repeat(10) begin
int success;
success = test_struct_in_union_constrained.randomize();
if (success != 1) $stop;
$display("StructInUnion (Constrained): struct.a: %b, struct.b: %b, inner_bits: %b", test_struct_in_union_constrained.union_instance.struct_fields.field_a, test_struct_in_union_constrained.union_instance.struct_fields.field_b, test_struct_in_union_constrained.union_instance.inner_bits);
end
// Test 4: StructInUnion Unconstrained Test
test_struct_in_union_unconstrained = new();
$display("\n--- Test 4: StructInUnion Unconstrained Test ---");
repeat(10) begin
int success;
success = test_struct_in_union_unconstrained.randomize();
if (success != 1) $stop;
$display("StructInUnion (Unconstrained): struct.a: %b, struct.b: %b, inner_bits: %b", test_struct_in_union_unconstrained.union_instance.struct_fields.field_a, test_struct_in_union_unconstrained.union_instance.struct_fields.field_b, test_struct_in_union_unconstrained.union_instance.inner_bits);
end
// Test 5: UnionInUnion Constrained Test
test_union_in_union_constrained = new();
$display("\n--- Test 5: UnionInUnion Constrained Test ---");
repeat(10) begin
int success;
success = test_union_in_union_constrained.randomize();
if (success != 1) $stop;
$display("UnionInUnion (Constrained): outer_bits: %b, inner_union.struct: %b, b: %b", test_union_in_union_constrained.union_instance.outer_bits, test_union_in_union_constrained.union_instance.inner_union.struct_fields.field_a, test_union_in_union_constrained.union_instance.inner_union.struct_fields.field_b);
end
// Test 6: UnionInUnion Unconstrained Test
test_union_in_union_unconstrained = new();
$display("\n--- Test 6: UnionInUnion Unconstrained Test ---");
repeat(10) begin
int success;
success = test_union_in_union_unconstrained.randomize();
if (success != 1) $stop;
$display("UnionInUnion (Unconstrained): outer_bits: %b, inner_union.struct: %b, inner_union.inner_bits: %b", test_union_in_union_unconstrained.union_instance.outer_bits, test_union_in_union_unconstrained.union_instance.inner_union.struct_fields, test_union_in_union_unconstrained.union_instance.inner_union.inner_bits);
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,4 @@
%Error: t/t_randomize_union_bad.v:7:9: Unpacked unions shall not be declared as rand or randc. (IEEE 1800-2023 18.4)
7 | typedef union {
| ^~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
scenarios(simulator => 1);
compile(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,36 @@
// 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
typedef union {
int int_value;
bit [31:0] bits;
} UnpackedUnion;
class UnpackedUnionErrorTest;
rand UnpackedUnion union_instance;
function new();
union_instance.bits = 32'b0;
endfunction
endclass
module t_randomize_union_bad;
UnpackedUnionErrorTest test_unpacked_union;
initial begin
test_unpacked_union = new();
repeat(10) begin
int success;
success = test_unpacked_union.randomize();
if (success != 1) $stop;
$display("UnpackedUnion: int_value: %b, bits: %b", test_unpacked_union.union_instance.int_value, test_unpacked_union.union_instance.bits);
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule