Fix struct pattern assignment (#2328) (#3517).

This commit is contained in:
Mostafa Gamal 2022-07-25 23:46:22 +02:00 committed by GitHub
parent eeef5ab4de
commit 7b431b37c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 269 additions and 34 deletions

View File

@ -82,6 +82,7 @@ Michaël Lefebvre
Mike Popoloski
Miodrag Milanović
Morten Borup Petersen
Mostafa Gamal
Nandu Raj
Nathan Kohagen
Nathan Myers

View File

@ -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<const AstMemberDType*, AstPatMember*>;
using PatMap = std::map<const AstMemberDType*, AstPatMember*>; // Store member: value
using DTypeMap = std::map<const std::string, AstPatMember*>; // 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<PatMap::iterator, bool> 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<PatMap::iterator, bool> 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<PatMap::iterator, bool> 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 {

View File

@ -3544,6 +3544,7 @@ patternKey<nodep>: // IEEE: merge structure_pattern_key, array_patt
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
| id { $$ = new AstText($<fl>1,*$1); }
| strAsInt { $$ = $1; }
| simple_type { $$ = $1; }
;
assignment_pattern<patternp>: // ==IEEE: assignment_pattern

View File

@ -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};
| ^~

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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