parent
b0c475205b
commit
df5f95a5bd
110
src/V3Width.cpp
110
src/V3Width.cpp
|
|
@ -209,6 +209,7 @@ private:
|
||||||
// TYPES
|
// TYPES
|
||||||
using TableMap = std::map<std::pair<const AstNodeDType*, VAttrType>, AstVar*>;
|
using TableMap = std::map<std::pair<const AstNodeDType*, VAttrType>, AstVar*>;
|
||||||
using PatVecMap = std::map<int, AstPatMember*>;
|
using PatVecMap = std::map<int, AstPatMember*>;
|
||||||
|
using DTypeMap = std::map<const std::string, AstPatMember*>;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
WidthVP* m_vup = nullptr; // Current node state
|
WidthVP* m_vup = nullptr; // Current node state
|
||||||
|
|
@ -3564,11 +3565,9 @@ private:
|
||||||
// which member each AstPatMember corresponds to before we can
|
// which member each AstPatMember corresponds to before we can
|
||||||
// determine the dtypep for that PatMember's value, and then
|
// determine the dtypep for that PatMember's value, and then
|
||||||
// width the initial value appropriately.
|
// width the initial value appropriately.
|
||||||
using PatMap = std::map<const AstMemberDType*, AstPatMember*>; // Store member: value
|
using PatMap = std::map<const AstMemberDType*, AstPatMember*>;
|
||||||
using DTypeMap
|
PatMap patmap; // Store member: value
|
||||||
= std::map<const std::string, AstPatMember*>; // Store data_type: default_value
|
DTypeMap dtypemap; // Store data_type: default_value
|
||||||
PatMap patmap;
|
|
||||||
DTypeMap dtypemap;
|
|
||||||
{
|
{
|
||||||
const AstMemberDType* memp = vdtypep->membersp();
|
const AstMemberDType* memp = vdtypep->membersp();
|
||||||
AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember);
|
AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember);
|
||||||
|
|
@ -3631,44 +3630,23 @@ private:
|
||||||
for (AstMemberDType* memp = vdtypep->membersp(); memp;
|
for (AstMemberDType* memp = vdtypep->membersp(); memp;
|
||||||
memp = VN_AS(memp->nextp(), MemberDType)) {
|
memp = VN_AS(memp->nextp(), MemberDType)) {
|
||||||
const auto it = patmap.find(memp);
|
const auto it = patmap.find(memp);
|
||||||
AstPatMember* newpatp = nullptr;
|
|
||||||
AstPatMember* patp = nullptr;
|
AstPatMember* patp = nullptr;
|
||||||
if (it == patmap.end()) {
|
if (it == patmap.end()) {
|
||||||
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName();
|
// default or deafult_type assignment
|
||||||
const auto it2 = dtypemap.find(memp_DType);
|
if (AstNodeUOrStructDType* const memp_nested_vdtypep
|
||||||
if (it2 != dtypemap.end()) {
|
= VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) {
|
||||||
// default_value for data_type
|
newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp, newp,
|
||||||
patp = it2->second;
|
nodep, dtypemap);
|
||||||
newpatp = patp->cloneTree(false);
|
|
||||||
patp = newpatp;
|
|
||||||
} else if (defaultp) {
|
|
||||||
// default_value for any unassigned member yet
|
|
||||||
newpatp = defaultp->cloneTree(false);
|
|
||||||
patp = newpatp;
|
|
||||||
} else {
|
} else {
|
||||||
if (!VN_IS(vdtypep, UnionDType)) {
|
patp = Defaultpatp_patternUOrStruct(nodep, memp, patp, vdtypep, defaultp,
|
||||||
nodep->v3error("Assignment pattern missed initializing elements: "
|
dtypemap);
|
||||||
<< memp->virtRefDTypep()->prettyDTypeName() << " "
|
newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep);
|
||||||
<< memp->prettyName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// member assignment
|
||||||
patp = it->second;
|
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) {
|
if (newp) {
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
|
|
@ -3677,6 +3655,66 @@ private:
|
||||||
}
|
}
|
||||||
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
|
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) {
|
void patternArray(AstPattern* nodep, AstNodeArrayDType* arrayDtp, AstPatMember* defaultp) {
|
||||||
const VNumRange range = arrayDtp->declRange();
|
const VNumRange range = arrayDtp->declRange();
|
||||||
PatVecMap patmap = patVectorMap(nodep, range);
|
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
|
// // id/*member*/ is part of constExpr below
|
||||||
//UNSUP constExpr { $$ = $1; }
|
//UNSUP constExpr { $$ = $1; }
|
||||||
// // IEEE: assignment_pattern_key
|
// // IEEE: assignment_pattern_key
|
||||||
//UNSUP simple_type { $1->v3error("Unsupported: '{} with data type as key"); $$ = $1; }
|
|
||||||
// // simple_type reference looks like constExpr
|
|
||||||
// // Verilator:
|
// // Verilator:
|
||||||
// // The above expressions cause problems because "foo" may be
|
// // The above expressions cause problems because "foo" may be
|
||||||
// // a constant identifier (if array) or a reference to the
|
// // 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
|
: ... In instance t
|
||||||
38 | test_out <= '{'0, '0};
|
38 | test_out <= '{'0, '0};
|
||||||
| ^~
|
| ^~
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,20 @@ module top();
|
||||||
} DEF_struct;
|
} 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
|
// struct ab
|
||||||
ab_struct ab;
|
ab_struct ab;
|
||||||
ab_struct abkey[1:0];
|
ab_struct abkey[1:0];
|
||||||
|
|
@ -48,6 +62,9 @@ module top();
|
||||||
// struct DEF
|
// struct DEF
|
||||||
DEF_struct DEF;
|
DEF_struct DEF;
|
||||||
|
|
||||||
|
// struct HIJ
|
||||||
|
HIJ_struct HIJ;
|
||||||
|
|
||||||
initial begin;
|
initial begin;
|
||||||
// struct ab
|
// struct ab
|
||||||
ab = '{0, 0}; //constant member by position
|
ab = '{0, 0}; //constant member by position
|
||||||
|
|
@ -130,6 +147,39 @@ module top();
|
||||||
if (DEF.BC2.B != 5) $stop;
|
if (DEF.BC2.B != 5) $stop;
|
||||||
if (DEF.BC2.C != 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");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue