mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
parent
eeef5ab4de
commit
7b431b37c7
@ -82,6 +82,7 @@ Michaël Lefebvre
|
||||
Mike Popoloski
|
||||
Miodrag Milanović
|
||||
Morten Borup Petersen
|
||||
Mostafa Gamal
|
||||
Nandu Raj
|
||||
Nathan Kohagen
|
||||
Nathan Myers
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
| ^~
|
||||
|
21
test_regress/t/t_structu_dataType_assignment.pl
Normal file
21
test_regress/t/t_structu_dataType_assignment.pl
Normal 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;
|
137
test_regress/t/t_structu_dataType_assignment.v
Normal file
137
test_regress/t/t_structu_dataType_assignment.v
Normal 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
|
5
test_regress/t/t_structu_dataType_assignment_bad.out
Normal file
5
test_regress/t/t_structu_dataType_assignment_bad.out
Normal 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
|
21
test_regress/t/t_structu_dataType_assignment_bad.pl
Executable file
21
test_regress/t/t_structu_dataType_assignment_bad.pl
Executable 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;
|
21
test_regress/t/t_structu_dataType_assignment_bad.v
Normal file
21
test_regress/t/t_structu_dataType_assignment_bad.v
Normal 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
|
Loading…
Reference in New Issue
Block a user