parent
b0c475205b
commit
df5f95a5bd
110
src/V3Width.cpp
110
src/V3Width.cpp
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
| ^~
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue