diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 77e232945..0b003034b 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -82,6 +82,7 @@ Michaël Lefebvre Mike Popoloski Miodrag Milanović Morten Borup Petersen +Mostafa Gamal Nandu Raj Nathan Kohagen Nathan Myers diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 446f20ed8..9ce0b5b4c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3559,50 +3559,67 @@ private: // which member each AstPatMember corresponds to before we can // determine the dtypep for that PatMember's value, and then // width the initial value appropriately. - using PatMap = std::map; + using PatMap = std::map; // Store member: value + using DTypeMap = std::map; // Store data_type: default_value PatMap patmap; + DTypeMap dtypemap; { const AstMemberDType* memp = vdtypep->membersp(); AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); - for (; memp || patp;) { + while (patp) { do { - if (patp) { - if (patp->keyp()) { - if (const AstText* textp = VN_CAST(patp->keyp(), Text)) { - memp = vdtypep->findMember(textp->text()); - if (!memp) { - patp->keyp()->v3error("Assignment pattern key '" - << textp->text() - << "' not found as member"); - break; - } + if (patp->keyp()) { + // '{member:value} or '{data_type: default_value} + if (const AstText* textp = VN_CAST(patp->keyp(), Text)) { + // member: value + memp = vdtypep->findMember(textp->text()); + if (!memp) { + patp->keyp()->v3error("Assignment pattern key '" + << textp->text() + << "' not found as member"); + break; } else { - patp->keyp()->v3error( - "Assignment pattern key not supported/understood: " - << patp->keyp()->prettyTypeName()); + const std::pair ret = patmap.emplace(memp, patp); + if (!ret.second) { + patp->v3error("Assignment pattern contains duplicate entry: " + << VN_AS(patp->keyp(), Text)->text()); + } + memp = VN_AS(memp->nextp(), MemberDType); } } + else if (const AstNodeDType* nodedtypep = VN_CAST(patp->keyp(), NodeDType)){ + // data_type: default_value + const string dtype = nodedtypep->dtypep()->prettyDTypeName(); + auto it = dtypemap.find(dtype); + if (it == dtypemap.end()) { + dtypemap.emplace(dtype, patp); + } + else { + // Override stored default_value + it->second = patp->cloneTree(false); + } + } + else { + // Undefined pattern + patp->keyp()->v3error( + "Assignment pattern key not supported/understood: " + << patp->keyp()->prettyTypeName()); + } } - if (memp && !patp) { - // Missing init elements, warn below - memp = nullptr; - patp = nullptr; - break; - } else if (!memp && patp) { - patp->v3error("Assignment pattern contains too many elements"); - memp = nullptr; - patp = nullptr; - break; - } else { - const std::pair ret = patmap.emplace(memp, patp); - if (!ret.second) { - patp->v3error("Assignment pattern contains duplicate entry: " - << VN_AS(patp->keyp(), Text)->text()); + else{ + // constant expr + if (memp) { + const std::pair ret = patmap.emplace(memp, patp); + if (!ret.second) { + patp->v3error("Assignment pattern contains duplicate entry: " + << VN_AS(patp->keyp(), Text)->text()); + } + memp = VN_AS(memp->nextp(), MemberDType); } } } while (false); + // Next - if (memp) memp = VN_AS(memp->nextp(), MemberDType); if (patp) patp = VN_AS(patp->nextp(), PatMember); } } @@ -3613,13 +3630,24 @@ private: AstPatMember* newpatp = nullptr; AstPatMember* patp = nullptr; if (it == patmap.end()) { - if (defaultp) { + const string memp_DType = memp->virtRefDTypep()->prettyDTypeName(); + const auto it2 = dtypemap.find(memp_DType); + if (it2 != dtypemap.end()) { + // default_value for data_type + patp = it2->second; + newpatp = patp->cloneTree(false); + patp = newpatp; + } + else if (defaultp) { + // default_value for any unassigned member yet newpatp = defaultp->cloneTree(false); patp = newpatp; } else { if (!VN_IS(vdtypep, UnionDType)) { nodep->v3error("Assignment pattern missed initializing elements: " - << memp->prettyTypeName()); + << memp->virtRefDTypep()->prettyDTypeName() + << " " + << memp->prettyName()); } } } else { diff --git a/src/verilog.y b/src/verilog.y index 82faf4a7d..79daad950 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3544,6 +3544,7 @@ patternKey: // IEEE: merge structure_pattern_key, array_patt | yaFLOATNUM { $$ = new AstConst($1,AstConst::RealDouble(),$1); } | id { $$ = new AstText($1,*$1); } | strAsInt { $$ = $1; } + | simple_type { $$ = $1; } ; assignment_pattern: // ==IEEE: assignment_pattern diff --git a/test_regress/t/t_array_list_bad.out b/test_regress/t/t_array_list_bad.out index edf0db3e8..0eeb8a06f 100644 --- a/test_regress/t/t_array_list_bad.out +++ b/test_regress/t/t_array_list_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_array_list_bad.v:38:25: Assignment pattern missed initializing elements: MEMBERDTYPE 't3' +%Error: t/t_array_list_bad.v:38:25: Assignment pattern missed initializing elements: logic t3 : ... In instance t 38 | test_out <= '{'0, '0}; | ^~ diff --git a/test_regress/t/t_structu_dataType_assignment.pl b/test_regress/t/t_structu_dataType_assignment.pl new file mode 100644 index 000000000..2cb5eeaff --- /dev/null +++ b/test_regress/t/t_structu_dataType_assignment.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2021 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( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_structu_dataType_assignment.v b/test_regress/t/t_structu_dataType_assignment.v new file mode 100644 index 000000000..2962a6e78 --- /dev/null +++ b/test_regress/t/t_structu_dataType_assignment.v @@ -0,0 +1,137 @@ +// DESCRIPTION: Verilator: Verilog Test module for specialized type default values +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Mostafa Gamal. +// SPDX-License-Identifier: CC0-1.0 + +/* verilator lint_off UNPACKED */ + +module top(); + + typedef struct { // IEEE 1800-2017 SV CH:5.10 + int a; + shortint b; + } ab_struct; + + typedef struct { // IEEE 1800-2017 SV CH:10.9.2 + int x; + int y; + } st_struct; + + typedef struct { // IEEE 1800-2017 SV CH:10.9.2 + logic [7:0] a; + bit b; + bit signed [31:0] c; + int s; + } sa_struct; + + + typedef struct { // IEEE 1800-2017 SV CH:10.9.2 + int A; + struct { + int B, C; + } BC1, BC2; + } DEF_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; + + initial begin; + // struct ab + ab = '{0, 0}; //constant member by position + if (ab.a != 0) $stop; + if (ab.b != 0) $stop; + + + ab = '{default: 0}; //default value + if (ab.a != 0) $stop; + if (ab.b != 0) $stop; + + + ab = '{int: 1, shortint: 0}; //data type and default value + if (ab.a != 1) $stop; + if (ab.b != 0) $stop; + + + 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; + + + // struct st + st = '{1, 2+k}; //constant member by position + if (st.x != 1) $stop; + if (st.y != 2+k) $stop; + + st = '{x:2, y:3+k}; //member: value + if (st.x != 2) $stop; + if (st.y != 3+k) $stop; + + 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; + + + // 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 = '{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 = '{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; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_structu_dataType_assignment_bad.out b/test_regress/t/t_structu_dataType_assignment_bad.out new file mode 100644 index 000000000..1b430ffd4 --- /dev/null +++ b/test_regress/t/t_structu_dataType_assignment_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_structu_dataType_assignment_bad.v:19:26: Assignment pattern key not supported/understood: CONST '?32?sh1' + : ... In instance top + 19 | DEF_struct DEF_bad = '{1: 5, default: 10}; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_structu_dataType_assignment_bad.pl b/test_regress/t/t_structu_dataType_assignment_bad.pl new file mode 100755 index 000000000..bec0388e9 --- /dev/null +++ b/test_regress/t/t_structu_dataType_assignment_bad.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2021 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; diff --git a/test_regress/t/t_structu_dataType_assignment_bad.v b/test_regress/t/t_structu_dataType_assignment_bad.v new file mode 100644 index 000000000..6ab523bbf --- /dev/null +++ b/test_regress/t/t_structu_dataType_assignment_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module for specialized type default values +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Mostafa Gamal. +// SPDX-License-Identifier: CC0-1.0 + +/* verilator lint_off UNPACKED */ + +module top(); + + + typedef struct { // IEEE 1800-2017 SV CH:10.9.2 + int A; + struct { + int B, C; + } BC1, BC2; + } DEF_struct; + + DEF_struct DEF_bad = '{1: 5, default: 10}; + +endmodule