mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Fix pattern type matching against nested aggregates (#7304).
Fixes #7304.
This commit is contained in:
@@ -39,6 +39,7 @@ Verilator 5.053 devel
|
||||
* Optimize unnecessary per-vertex allocations in NFA lowering (#8319). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Optimize duplicate lookup in NFA property recursion guard (#8321). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Fix array slice crash when used as a bare value (#5132) (#8262). [Marco Frank]
|
||||
* Fix pattern type matching against nested aggregates (#7304).
|
||||
* Fix covergroup-internal references multi-threaded ordering (#7779) (#8255). [Matthew Ballance]
|
||||
* Fix detecting non-inlined awaits in V3Delayed.cpp (#7982). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Fix phased `solve...before` diversity (#8189) (#8194). [Aditya Shevade]
|
||||
|
||||
+5
-2
@@ -5790,7 +5790,7 @@ class WidthVisitor final : public VNVisitor {
|
||||
if (it == patmap.end()) { // Default or default_type assignment
|
||||
patp = defaultPatp_patternUOrStruct(nodep, memp, vdtypep, defaultp, dtypemap);
|
||||
pushDeletep(patp);
|
||||
patp = defaultPatp_forDType(patp, memp->virtRefDTypep());
|
||||
patp = defaultPatp_forDType(patp, memp->virtRefDTypep(), dtypemap);
|
||||
pushDeletep(patp);
|
||||
} else {
|
||||
patp = it->second; // Member assignment
|
||||
@@ -5877,7 +5877,8 @@ class WidthVisitor final : public VNVisitor {
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstPatMember* defaultPatp_forDType(AstPatMember* defaultp, AstNodeDType* elemDTypep) {
|
||||
AstPatMember* defaultPatp_forDType(AstPatMember* defaultp, AstNodeDType* elemDTypep,
|
||||
const DTypeMap& dtypemap = DTypeMap{}) {
|
||||
AstNodeExpr* const valuep = defaultp->lhssp()->cloneTree(false);
|
||||
AstNodeDType* const elemDTypeSkipRefp = elemDTypep->skipRefp();
|
||||
const AstStructDType* const structp = VN_CAST(elemDTypeSkipRefp, StructDType);
|
||||
@@ -5907,6 +5908,8 @@ class WidthVisitor final : public VNVisitor {
|
||||
AstPatMember* const nestedDefaultp
|
||||
= new AstPatMember{defaultp->fileline(), valuep, nullptr, nullptr};
|
||||
nestedDefaultp->isDefault(true);
|
||||
// Propagate the outer 'data_type: value' entries into the nested aggregate
|
||||
for (const auto& entry : dtypemap) nestedDefaultp->addNext(entry.second->cloneTree(false));
|
||||
AstPattern* const recursivePatternp = new AstPattern{defaultp->fileline(), nestedDefaultp};
|
||||
return new AstPatMember{defaultp->fileline(), recursivePatternp, nullptr, nullptr};
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator_st')
|
||||
|
||||
test.compile(verilator_flags2=['-Wno-DEPRECATED', '--structs-packed'])
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
|
||||
@@ -4,37 +4,30 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mostafa Gamal
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
/* verilator lint_off UNPACKED */
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module top();
|
||||
module t;
|
||||
|
||||
typedef struct { // IEEE 1800-2023 5.10
|
||||
typedef struct { // IEEE 1800-2023 5.10
|
||||
int a;
|
||||
shortint b;
|
||||
} ab_struct;
|
||||
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
int x;
|
||||
int y;
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
int x;
|
||||
int y;
|
||||
} st_struct;
|
||||
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
logic [7:0] a;
|
||||
bit b;
|
||||
bit signed [31:0] c;
|
||||
int s;
|
||||
} sa_struct;
|
||||
|
||||
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
int A;
|
||||
struct {
|
||||
int B, C;
|
||||
} BC1, BC2;
|
||||
struct {int B, C;} BC1, BC2;
|
||||
} DEF_struct;
|
||||
|
||||
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
typedef struct { // IEEE 1800-2023 10.9.2
|
||||
int A;
|
||||
struct {
|
||||
int B, C;
|
||||
@@ -48,137 +41,99 @@ module top();
|
||||
} BC1;
|
||||
} HIJ_struct;
|
||||
|
||||
// struct ab
|
||||
ab_struct ab;
|
||||
ab_struct abkey[1:0];
|
||||
|
||||
// struct st
|
||||
st_struct st;
|
||||
int k = 1;
|
||||
|
||||
// struct sa
|
||||
sa_struct sa;
|
||||
|
||||
// struct DEF
|
||||
DEF_struct DEF;
|
||||
|
||||
// struct HIJ
|
||||
HIJ_struct HIJ;
|
||||
|
||||
initial begin
|
||||
// struct ab
|
||||
ab = '{0, 0}; //constant member by position
|
||||
if (ab.a != 0) $stop;
|
||||
if (ab.b != 0) $stop;
|
||||
ab = '{0, 0}; //constant member by position
|
||||
`checkd(ab.a, 0);
|
||||
`checkd(ab.b, 0);
|
||||
|
||||
|
||||
ab = '{default: 0}; //default value
|
||||
if (ab.a != 0) $stop;
|
||||
if (ab.b != 0) $stop;
|
||||
ab = '{default: 0}; //default value
|
||||
`checkd(ab.a, 0);
|
||||
`checkd(ab.b, 0);
|
||||
|
||||
|
||||
ab = '{int: 1, shortint: 0}; //data type and default value
|
||||
if (ab.a != 1) $stop;
|
||||
if (ab.b != 0) $stop;
|
||||
ab = '{int : 1, shortint : 0}; //data type and default value
|
||||
`checkd(ab.a, 1);
|
||||
`checkd(ab.b, 0);
|
||||
|
||||
|
||||
abkey[1:0] = '{'{a:1, b:2}, '{int:2, shortint:3}}; // member: value & data_type: value
|
||||
if (abkey[1].a != 1) $stop;
|
||||
if (abkey[1].b != 2) $stop;
|
||||
if (abkey[0].a != 2) $stop;
|
||||
if (abkey[0].b != 3) $stop;
|
||||
abkey[1:0] = '{'{a: 1, b: 2}, '{int : 2, shortint : 3}}; // member: value & data_type: value
|
||||
`checkd(abkey[1].a, 1);
|
||||
`checkd(abkey[1].b, 2);
|
||||
`checkd(abkey[0].a, 2);
|
||||
`checkd(abkey[0].b, 3);
|
||||
|
||||
|
||||
// struct st
|
||||
st = '{1, 2+k}; //constant member by position
|
||||
if (st.x != 1) $stop;
|
||||
if (st.y != 2+k) $stop;
|
||||
st = '{1, 2 + k}; //constant member by position
|
||||
`checkd(st.x, 1);
|
||||
`checkd(st.y, 2 + k);
|
||||
|
||||
st = '{x:2, y:3+k}; //member: value
|
||||
if (st.x != 2) $stop;
|
||||
if (st.y != 3+k) $stop;
|
||||
st = '{x: 2, y: 3 + k}; //member: value
|
||||
`checkd(st.x, 2);
|
||||
`checkd(st.y, 3 + k);
|
||||
|
||||
st = '{int:2, int:3+k}; //data_type: value override
|
||||
if (st.x != 3+k) $stop;
|
||||
if (st.y != 3+k) $stop;
|
||||
|
||||
|
||||
// struct sa
|
||||
sa = '{default:'1};
|
||||
if (sa.a != '1) $stop;
|
||||
if (sa.b != '1) $stop;
|
||||
if (sa.c != '1) $stop;
|
||||
if (sa.s != '1) $stop;
|
||||
|
||||
sa = '{default:'1, int: 5};
|
||||
if (sa.a != '1) $stop;
|
||||
if (sa.b != '1) $stop;
|
||||
if (sa.c != '1) $stop;
|
||||
if (sa.s != 5) $stop;
|
||||
|
||||
|
||||
sa = '{default:'1, int: 5, b: 0};
|
||||
if (sa.a != '1) $stop;
|
||||
if (sa.b != 0) $stop;
|
||||
if (sa.c != '1) $stop;
|
||||
if (sa.s != 5) $stop;
|
||||
st = '{int : 2, int : 3 + k}; //data_type: value override
|
||||
`checkd(st.x, 3 + k);
|
||||
`checkd(st.y, 3 + k);
|
||||
|
||||
|
||||
// struct DEF
|
||||
DEF = '{A:1, BC1:'{B:2, C:3}, BC2:'{B:4,C:5}};
|
||||
if (DEF.A != 1) $stop;
|
||||
if (DEF.BC1.B != 2) $stop;
|
||||
if (DEF.BC1.C != 3) $stop;
|
||||
if (DEF.BC2.B != 4) $stop;
|
||||
if (DEF.BC2.C != 5) $stop;
|
||||
DEF = '{A: 1, BC1: '{B: 2, C: 3}, BC2: '{B: 4, C: 5}};
|
||||
`checkd(DEF.A, 1);
|
||||
`checkd(DEF.BC1.B, 2);
|
||||
`checkd(DEF.BC1.C, 3);
|
||||
`checkd(DEF.BC2.B, 4);
|
||||
`checkd(DEF.BC2.C, 5);
|
||||
|
||||
|
||||
DEF = '{int:0, BC1:'{int:10}, BC2:'{default:5}};
|
||||
if (DEF.A != 0) $stop;
|
||||
if (DEF.BC1.B != 10) $stop;
|
||||
if (DEF.BC1.C != 10) $stop;
|
||||
if (DEF.BC2.B != 5) $stop;
|
||||
if (DEF.BC2.C != 5) $stop;
|
||||
DEF = '{int : 0, BC1: '{int : 10}, BC2: '{default: 5}};
|
||||
`checkd(DEF.A, 0);
|
||||
`checkd(DEF.BC1.B, 10);
|
||||
`checkd(DEF.BC1.C, 10);
|
||||
`checkd(DEF.BC2.B, 5);
|
||||
`checkd(DEF.BC2.C, 5);
|
||||
|
||||
DEF = '{default:1, BC1:'{int:10}, BC2:'{default:5}};
|
||||
if (DEF.A != 1) $stop;
|
||||
if (DEF.BC1.B != 10) $stop;
|
||||
if (DEF.BC1.C != 10) $stop;
|
||||
if (DEF.BC2.B != 5) $stop;
|
||||
if (DEF.BC2.C != 5) $stop;
|
||||
DEF = '{default: 1, BC1: '{int : 10}, BC2: '{default: 5}};
|
||||
`checkd(DEF.A, 1);
|
||||
`checkd(DEF.BC1.B, 10);
|
||||
`checkd(DEF.BC1.C, 10);
|
||||
`checkd(DEF.BC2.B, 5);
|
||||
`checkd(DEF.BC2.C, 5);
|
||||
|
||||
DEF = '{default:10};
|
||||
if (DEF.A != 10) $stop;
|
||||
if (DEF.BC1.B != 10) $stop;
|
||||
if (DEF.BC1.C != 10) $stop;
|
||||
if (DEF.BC2.B != 10) $stop;
|
||||
if (DEF.BC2.C != 10) $stop;
|
||||
|
||||
DEF = '{int:10};
|
||||
if (DEF.A != 10) $stop;
|
||||
if (DEF.BC1.B != 10) $stop;
|
||||
if (DEF.BC1.C != 10) $stop;
|
||||
if (DEF.BC2.B != 10) $stop;
|
||||
if (DEF.BC2.C != 10) $stop;
|
||||
DEF = '{default: 10};
|
||||
`checkd(DEF.A, 10);
|
||||
`checkd(DEF.BC1.B, 10);
|
||||
`checkd(DEF.BC1.C, 10);
|
||||
`checkd(DEF.BC2.B, 10);
|
||||
`checkd(DEF.BC2.C, 10);
|
||||
|
||||
// struct HIJ
|
||||
HIJ = '{int:10, default: 5};
|
||||
if (HIJ.A != 10) $stop;
|
||||
if (HIJ.BC1.B != 10) $stop;
|
||||
if (HIJ.BC1.C != 10) $stop;
|
||||
if (HIJ.BC1.DE1.D != 10) $stop;
|
||||
if (HIJ.BC1.DE1.E != 10) $stop;
|
||||
if (HIJ.BC1.DE1.FG1.F != 10) $stop;
|
||||
if (HIJ.BC1.DE1.FG1.G != 5) $stop;
|
||||
HIJ = '{int : 10, default: 5};
|
||||
`checkd(HIJ.A, 10);
|
||||
`checkd(HIJ.BC1.B, 10);
|
||||
`checkd(HIJ.BC1.C, 10);
|
||||
`checkd(HIJ.BC1.DE1.D, 10);
|
||||
`checkd(HIJ.BC1.DE1.E, 10);
|
||||
`checkd(HIJ.BC1.DE1.FG1.F, 10);
|
||||
`checkd(HIJ.BC1.DE1.FG1.G, 5);
|
||||
|
||||
HIJ = '{shortint:10, default: 5};
|
||||
if (HIJ.A != 5) $stop;
|
||||
if (HIJ.BC1.B != 5) $stop;
|
||||
if (HIJ.BC1.C != 5) $stop;
|
||||
if (HIJ.BC1.DE1.D != 5) $stop;
|
||||
if (HIJ.BC1.DE1.E != 5) $stop;
|
||||
if (HIJ.BC1.DE1.FG1.F != 5) $stop;
|
||||
if (HIJ.BC1.DE1.FG1.G != 10) $stop;
|
||||
HIJ = '{shortint : 10, default: 5};
|
||||
`checkd(HIJ.A, 5);
|
||||
`checkd(HIJ.BC1.B, 5);
|
||||
`checkd(HIJ.BC1.C, 5);
|
||||
`checkd(HIJ.BC1.DE1.D, 5);
|
||||
`checkd(HIJ.BC1.DE1.E, 5);
|
||||
`checkd(HIJ.BC1.DE1.FG1.F, 5);
|
||||
`checkd(HIJ.BC1.DE1.FG1.G, 10);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
Reference in New Issue
Block a user