diff --git a/Changes b/Changes index 492673d4c..9102be2c4 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/src/V3Width.cpp b/src/V3Width.cpp index c5c03da1a..7e0099b87 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -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}; } diff --git a/test_regress/t/t_structu_dataType_assignment.py b/test_regress/t/t_structu_dataType_assignment.py index 4a044903a..1a93d5310 100755 --- a/test_regress/t/t_structu_dataType_assignment.py +++ b/test_regress/t/t_structu_dataType_assignment.py @@ -11,7 +11,7 @@ import vltest_bootstrap test.scenarios('simulator_st') -test.compile(verilator_flags2=['-Wno-DEPRECATED', '--structs-packed']) +test.compile() test.execute() diff --git a/test_regress/t/t_structu_dataType_assignment.v b/test_regress/t/t_structu_dataType_assignment.v index 667c5f70c..93005bab3 100644 --- a/test_regress/t/t_structu_dataType_assignment.v +++ b/test_regress/t/t_structu_dataType_assignment.v @@ -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;