Fix nested default assignment for struct pattern (#3511) (#3524)

This commit is contained in:
Mostafa Gamal 2022-08-12 12:55:07 +02:00 committed by GitHub
parent b0c475205b
commit df5f95a5bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 39 deletions

View File

@ -209,6 +209,7 @@ private:
// TYPES
using TableMap = std::map<std::pair<const AstNodeDType*, VAttrType>, AstVar*>;
using PatVecMap = std::map<int, AstPatMember*>;
using DTypeMap = std::map<const std::string, AstPatMember*>;
// STATE
WidthVP* m_vup = nullptr; // Current node state
@ -3564,11 +3565,9 @@ 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*>; // Store member: value
using DTypeMap
= std::map<const std::string, AstPatMember*>; // Store data_type: default_value
PatMap patmap;
DTypeMap dtypemap;
using PatMap = std::map<const AstMemberDType*, AstPatMember*>;
PatMap patmap; // Store member: value
DTypeMap dtypemap; // Store data_type: default_value
{
const AstMemberDType* memp = vdtypep->membersp();
AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember);
@ -3631,44 +3630,23 @@ private:
for (AstMemberDType* memp = vdtypep->membersp(); memp;
memp = VN_AS(memp->nextp(), MemberDType)) {
const auto it = patmap.find(memp);
AstPatMember* newpatp = nullptr;
AstPatMember* patp = nullptr;
if (it == patmap.end()) {
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;
// default or deafult_type assignment
if (AstNodeUOrStructDType* const memp_nested_vdtypep
= VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) {
newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp, newp,
nodep, dtypemap);
} else {
if (!VN_IS(vdtypep, UnionDType)) {
nodep->v3error("Assignment pattern missed initializing elements: "
<< memp->virtRefDTypep()->prettyDTypeName() << " "
<< memp->prettyName());
}
patp = Defaultpatp_patternUOrStruct(nodep, memp, patp, vdtypep, defaultp,
dtypemap);
newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep);
}
} else {
// member assignment
patp = it->second;
newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep);
}
if (patp) {
// Determine initial values
patp->dtypep(memp);
AstNode* const valuep = patternMemberValueIterate(patp);
if (!newp) {
newp = valuep;
} else {
AstConcat* const concatp = new AstConcat(patp->fileline(), newp, valuep);
newp = concatp;
newp->dtypeSetLogicSized(concatp->lhsp()->width() + concatp->rhsp()->width(),
nodep->dtypep()->numeric());
}
}
if (newpatp) VL_DO_DANGLING(pushDeletep(newpatp), newpatp);
}
if (newp) {
nodep->replaceWith(newp);
@ -3677,6 +3655,66 @@ private:
}
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
}
AstNode* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, AstNode* newp,
AstPattern* nodep, DTypeMap dtypemap) {
AstPatMember* patp = nullptr;
for (AstMemberDType* memp_nested = memp_vdtypep->membersp(); memp_nested;
memp_nested = VN_AS(memp_nested->nextp(), MemberDType)) {
if (AstNodeUOrStructDType* const memp_multinested_vdtypep
= VN_CAST(memp_nested->virtRefDTypep(), NodeUOrStructDType)) {
// When unpacked struct/union is supported this if will need some additional conditions
newp = nestedvalueConcat_patternUOrStruct(memp_multinested_vdtypep, defaultp, newp,
nodep, dtypemap);
} else {
patp = Defaultpatp_patternUOrStruct(nodep, memp_nested, patp, memp_vdtypep,
defaultp, dtypemap);
newp = valueConcat_patternUOrStruct(patp, newp, memp_nested, nodep);
}
}
return newp;
}
AstPatMember* Defaultpatp_patternUOrStruct(AstPattern* nodep, AstMemberDType* memp,
AstPatMember* patp,
AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, DTypeMap dtypemap) {
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName();
const auto it = dtypemap.find(memp_DType);
if (it != dtypemap.end()) {
// default_value for data_type
patp = it->second->cloneTree(false);
} else if (defaultp) {
// default_value for any unmatched member yet
patp = defaultp->cloneTree(false);
} else {
if (!VN_IS(memp_vdtypep, UnionDType)) {
nodep->v3error("Assignment pattern missed initializing elements: "
<< memp->virtRefDTypep()->prettyDTypeNameQ() << " "
<< memp->prettyNameQ());
}
}
return patp;
}
AstNode* valueConcat_patternUOrStruct(AstPatMember* patp, AstNode* newp, AstMemberDType* memp,
AstPattern* nodep) {
if (patp) {
patp->dtypep(memp);
AstNode* const valuep = patternMemberValueIterate(patp);
if (!newp) {
newp = valuep;
} else {
AstConcat* const concatp = new AstConcat{patp->fileline(), newp, valuep};
newp = concatp;
newp->dtypeSetLogicSized(concatp->lhsp()->width() + concatp->rhsp()->width(),
nodep->dtypep()->numeric());
}
}
return newp;
}
void patternArray(AstPattern* nodep, AstNodeArrayDType* arrayDtp, AstPatMember* defaultp) {
const VNumRange range = arrayDtp->declRange();
PatVecMap patmap = patVectorMap(nodep, range);

View File

@ -3532,8 +3532,6 @@ patternKey<nodep>: // IEEE: merge structure_pattern_key, array_patt
// // id/*member*/ is part of constExpr below
//UNSUP constExpr { $$ = $1; }
// // IEEE: assignment_pattern_key
//UNSUP simple_type { $1->v3error("Unsupported: '{} with data type as key"); $$ = $1; }
// // simple_type reference looks like constExpr
// // Verilator:
// // The above expressions cause problems because "foo" may be
// // a constant identifier (if array) or a reference to the

View File

@ -1,4 +1,4 @@
%Error: t/t_array_list_bad.v:38:25: Assignment pattern missed initializing elements: logic 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

@ -34,6 +34,20 @@ module top();
} DEF_struct;
typedef struct { // IEEE 1800-2017 SV CH:10.9.2
int A;
struct {
int B, C;
struct{
int D, E;
struct{
int F;
shortint G;
} FG1;
} DE1;
} BC1;
} HIJ_struct;
// struct ab
ab_struct ab;
ab_struct abkey[1:0];
@ -48,6 +62,9 @@ module top();
// struct DEF
DEF_struct DEF;
// struct HIJ
HIJ_struct HIJ;
initial begin;
// struct ab
ab = '{0, 0}; //constant member by position
@ -130,6 +147,39 @@ module top();
if (DEF.BC2.B != 5) $stop;
if (DEF.BC2.C != 5) $stop;
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;
// 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 = '{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;
$write("*-* All Finished *-*\n");
$finish;
end