Support force assignments to array elements of real type (#7048)
This commit is contained in:
parent
e5ad9b3a4b
commit
258629634c
|
|
@ -574,6 +574,7 @@ public:
|
|||
|| m_e == LONGINT || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64
|
||||
|| m_e == TIME);
|
||||
}
|
||||
bool isBit() const { return m_e == BIT; }
|
||||
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
||||
return (m_e == LOGIC || m_e == BIT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -459,6 +459,7 @@ public:
|
|||
return m.m_keyword;
|
||||
}
|
||||
bool isBitLogic() const { return keyword().isBitLogic(); }
|
||||
bool isBit() const { return keyword().isBit(); }
|
||||
bool isCHandle() const VL_MT_STABLE { return keyword().isCHandle(); }
|
||||
bool isDouble() const VL_MT_STABLE { return keyword().isDouble(); }
|
||||
bool isEvent() const VL_MT_STABLE { return keyword() == VBasicDTypeKwd::EVENT; }
|
||||
|
|
|
|||
|
|
@ -1778,6 +1778,15 @@ public:
|
|||
addAttrsp(attrsp);
|
||||
dtypep(nullptr); // V3Width will resolve
|
||||
}
|
||||
AstTypedef(FileLine* fl, const string& name, AstNodeDType* dtp, bool underClass)
|
||||
: ASTGEN_SUPER_Typedef(fl)
|
||||
, m_name{name}
|
||||
, m_declTokenNum{fl->tokenNum()}
|
||||
, m_isHideLocal{false}
|
||||
, m_isHideProtected{false}
|
||||
, m_isUnderClass{underClass} {
|
||||
dtypep(dtp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstTypedef;
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
|
|
|
|||
118
src/V3Force.cpp
118
src/V3Force.cpp
|
|
@ -241,6 +241,7 @@ public:
|
|||
|
||||
private:
|
||||
// NODE STATE
|
||||
// AstNodeDType::user1p -> AstNodeDType*, dtype created for __En variables
|
||||
// AstVar::user1p -> ForceComponentsVar* instance (via m_forceComponentsVar)
|
||||
// AstVarScope::user1p -> ForceComponentsVarScope* instance (via m_forceComponentsVarScope)
|
||||
// AstVarRef::user2 -> Flag indicating not to replace reference
|
||||
|
|
@ -264,7 +265,7 @@ private:
|
|||
if (const AstUnpackArrayDType* const udtp = VN_CAST(dtp, UnpackArrayDType)) {
|
||||
const size_t elemsInSubDType = checkIfDTypeSupportedRecurse(udtp->subDTypep(), varp);
|
||||
return udtp->elementsConst() * elemsInSubDType;
|
||||
} else if (const AstNodeUOrStructDType* const sdtp = VN_CAST(dtp, NodeUOrStructDType)) {
|
||||
} else if (const AstStructDType* const sdtp = VN_CAST(dtp, StructDType)) {
|
||||
size_t elemCount = 0;
|
||||
for (const AstMemberDType* mdtp = sdtp->membersp(); mdtp;
|
||||
mdtp = VN_AS(mdtp->nextp(), MemberDType)) {
|
||||
|
|
@ -287,26 +288,117 @@ private:
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
static AstNodeDType* getEnVarpDTypep(const AstVar* const varp) {
|
||||
static AstNodeDType* getEnVarpDTypep(AstVar* const varp) {
|
||||
AstNodeDType* const origDTypep = varp->dtypep()->skipRefp();
|
||||
if (origDTypep->user1p()) return VN_AS(origDTypep->user1p(), NodeDType);
|
||||
const size_t unpackElemNum = checkIfDTypeSupportedRecurse(origDTypep, varp);
|
||||
if (unpackElemNum > ELEMENTS_MAX) {
|
||||
varp->v3warn(E_UNSUPPORTED, "Unsupported: Force of variable with "
|
||||
">= "
|
||||
<< ELEMENTS_MAX << " unpacked elements");
|
||||
}
|
||||
if (VN_IS(origDTypep, UnpackArrayDType)) {
|
||||
return origDTypep;
|
||||
} else if (VN_IS(origDTypep, BasicDType)) {
|
||||
return isRangedDType(varp) ? origDTypep : varp->findBitDType();
|
||||
} else if (VN_IS(origDTypep, PackArrayDType)) {
|
||||
return origDTypep;
|
||||
} else if (VN_IS(origDTypep, NodeUOrStructDType)) {
|
||||
return origDTypep;
|
||||
} else {
|
||||
varp->v3fatalSrc("Unsupported: Force of variable of unhandled data type");
|
||||
return origDTypep;
|
||||
}
|
||||
return getEnVarpDTypeRecursep(varp, origDTypep);
|
||||
}
|
||||
static AstNodeDType* getEnVarpDTypeRecursep(AstVar* const varp, AstNodeDType* const dtypep) {
|
||||
if (dtypep->user1p()) return VN_AS(dtypep->user1p(), NodeDType);
|
||||
if (AstNodeArrayDType* const arrp = VN_CAST(dtypep, NodeArrayDType)) {
|
||||
AstNodeDType* const subDTypep = arrp->subDTypep()->skipRefp();
|
||||
AstNodeDType* const enSubDTypep = getEnVarpDTypeRecursep(varp, subDTypep);
|
||||
if (subDTypep != enSubDTypep) {
|
||||
AstNodeArrayDType* enArrp;
|
||||
if (VN_IS(arrp, UnpackArrayDType)) {
|
||||
enArrp = new AstUnpackArrayDType{arrp->fileline(), enSubDTypep,
|
||||
arrp->rangep()->cloneTree(false)};
|
||||
} else if (VN_IS(arrp, PackArrayDType)) {
|
||||
enArrp = new AstPackArrayDType{arrp->fileline(), enSubDTypep,
|
||||
arrp->rangep()->cloneTree(false)};
|
||||
} else {
|
||||
varp->v3fatalSrc("Unsupported: Force of variable of unhandled data type");
|
||||
return dtypep;
|
||||
}
|
||||
dtypep->user1p(enArrp);
|
||||
v3Global.rootp()->typeTablep()->addTypesp(enArrp);
|
||||
return enArrp;
|
||||
} else {
|
||||
dtypep->user1p(dtypep);
|
||||
return dtypep;
|
||||
}
|
||||
} else if (AstBasicDType* const basicp = VN_CAST(dtypep, BasicDType)) {
|
||||
if (basicp->isBit()) {
|
||||
dtypep->user1p(dtypep);
|
||||
return dtypep;
|
||||
} else {
|
||||
AstNodeDType* const bitDtp = varp->findBitRangeDType(
|
||||
basicp->declRange(), basicp->elements(), VSigning::UNSIGNED);
|
||||
dtypep->user1p(bitDtp);
|
||||
return bitDtp;
|
||||
}
|
||||
} else if (AstNodeUOrStructDType* const structp = VN_CAST(dtypep, NodeUOrStructDType)) {
|
||||
std::vector<AstMemberDType*> enMemberDTypes;
|
||||
bool changed = false;
|
||||
for (AstMemberDType* mdtp = structp->membersp(); mdtp;
|
||||
mdtp = VN_AS(mdtp->nextp(), MemberDType)) {
|
||||
AstNodeDType* const subMdtp = mdtp->subDTypep()->skipRefp();
|
||||
AstNodeDType* const enSubMdtp = getEnVarpDTypeRecursep(varp, subMdtp);
|
||||
if (subMdtp != enSubMdtp) {
|
||||
changed = true;
|
||||
AstMemberDType* const enMdtp
|
||||
= new AstMemberDType{mdtp->fileline(), mdtp->name(), enSubMdtp};
|
||||
enMdtp->dtypep(enSubMdtp);
|
||||
enMemberDTypes.push_back(enMdtp);
|
||||
} else {
|
||||
enMemberDTypes.push_back(mdtp->cloneTreePure(false));
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
const bool packed = structp->packed();
|
||||
AstNodeUOrStructDType* enStructp;
|
||||
if (VN_IS(structp, StructDType)) {
|
||||
enStructp = new AstStructDType{structp->fileline(),
|
||||
packed ? VSigning::SIGNED : VSigning::NOSIGN};
|
||||
} else if (VN_IS(structp, UnionDType) && packed) {
|
||||
const AstUnionDType* const unionp = VN_AS(structp, UnionDType);
|
||||
enStructp = new AstUnionDType{unionp->fileline(), unionp->isSoft(),
|
||||
unionp->isTagged(), VSigning::SIGNED};
|
||||
} else {
|
||||
varp->v3fatalSrc("Unsupported: Force of variable of unhandled data type");
|
||||
return dtypep;
|
||||
}
|
||||
int width = 0;
|
||||
if (packed) {
|
||||
for (const auto& memberp : enMemberDTypes) {
|
||||
enStructp->addMembersp(memberp);
|
||||
const int memberWidth = memberp->width();
|
||||
if (VN_IS(structp, StructDType)) {
|
||||
width += memberWidth;
|
||||
} else {
|
||||
width = std::max(width, memberWidth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& memberp : enMemberDTypes) enStructp->addMembersp(memberp);
|
||||
width = 1;
|
||||
}
|
||||
v3Global.rootp()->typeTablep()->addTypesp(enStructp);
|
||||
enStructp->name(structp->name() + "__VforceEn_t");
|
||||
enStructp->dtypep(enStructp);
|
||||
enStructp->widthForce(width, width);
|
||||
enStructp->classOrPackagep(structp->classOrPackagep());
|
||||
dtypep->user1p(enStructp);
|
||||
AstTypedef* const typedefp
|
||||
= new AstTypedef{enStructp->fileline(), enStructp->name(), enStructp,
|
||||
VN_IS(enStructp->classOrPackagep(), Class)};
|
||||
varp->addNextHere(typedefp);
|
||||
return enStructp;
|
||||
} else {
|
||||
for (const auto& memberp : enMemberDTypes) memberp->deleteTree();
|
||||
dtypep->user1p(dtypep);
|
||||
return dtypep;
|
||||
}
|
||||
}
|
||||
varp->v3fatalSrc("Unsupported: Force of variable of unhandled data type");
|
||||
return dtypep;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ module t (
|
|||
int int_arr[-1:2][1][3];
|
||||
bit [5:0] bit_arr[5];
|
||||
union_t union_arr[4];
|
||||
real real_arr[2][1][3];
|
||||
|
||||
assign bit_arr[2][3] = 1;
|
||||
|
||||
|
|
@ -35,18 +36,21 @@ module t (
|
|||
logic_arr[0][2][-4] <= 1;
|
||||
int_arr[0][0][2] <= 1;
|
||||
union_arr[1].x <= 1;
|
||||
real_arr[0][0][1] <= 1;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
`checkh(logic_arr[0][2][-4], 1);
|
||||
`checkh(int_arr[0][0][2], 1);
|
||||
`checkh(bit_arr[2][3], 1);
|
||||
`checkh(union_arr[1].x, 1);
|
||||
`checkr(real_arr[0][0][1], 1);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force logic_arr[0][2][-4] = 0;
|
||||
force int_arr[0][0][2] = 0;
|
||||
force bit_arr[2][3] = 0;
|
||||
force union_arr[1].y = 2;
|
||||
force real_arr[0][0][1] = 0;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkh(logic_arr[0][2][-4], 0);
|
||||
|
|
@ -56,11 +60,14 @@ module t (
|
|||
`checkh(bit_arr[2][3], 0);
|
||||
`checkh(union_arr[1].x, 2);
|
||||
union_arr[1].x <= 3;
|
||||
`checkr(real_arr[0][0][1], 0);
|
||||
real_arr[0][0][1] <= 2;
|
||||
end
|
||||
else if (cyc == 4) begin
|
||||
`checkh(logic_arr[0][2][-4], 0);
|
||||
`checkh(int_arr[0][0][2], 0);
|
||||
`checkh(union_arr[1].y, 2);
|
||||
`checkr(real_arr[0][0][1], 0);
|
||||
end
|
||||
else if (cyc == 5) begin
|
||||
release logic_arr[0][2][-4];
|
||||
|
|
@ -68,6 +75,7 @@ module t (
|
|||
release bit_arr[2][3];
|
||||
`checkh(bit_arr[2][3], 1);
|
||||
release union_arr[1].x;
|
||||
release real_arr[0][0][1];
|
||||
end
|
||||
else if (cyc == 6) begin
|
||||
`checkh(logic_arr[0][2][-4], 0);
|
||||
|
|
@ -77,11 +85,14 @@ module t (
|
|||
`checkh(bit_arr[2][3], 1);
|
||||
`checkh(union_arr[1].x, 2);
|
||||
union_arr[1].y <= 4;
|
||||
`checkr(real_arr[0][0][1], 0);
|
||||
real_arr[0][0][1] <= 3;
|
||||
end
|
||||
else if (cyc == 7) begin
|
||||
`checkh(logic_arr[0][2][-4], 1);
|
||||
`checkh(int_arr[0][0][2], 1);
|
||||
`checkh(union_arr[1].x, 4);
|
||||
`checkr(real_arr[0][0][1], 3);
|
||||
end
|
||||
else if (cyc == 8) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
|
|
|||
|
|
@ -16,10 +16,16 @@ module t (
|
|||
|
||||
integer cyc = 0;
|
||||
|
||||
typedef struct packed {
|
||||
bit a;
|
||||
bit b;
|
||||
} packed_t;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
logic y;
|
||||
int arr[5];
|
||||
packed_t pt;
|
||||
} struct_t;
|
||||
|
||||
struct_t s_array[3];
|
||||
|
|
@ -32,16 +38,19 @@ module t (
|
|||
s_array[1].x = 1;
|
||||
s_array[1].arr[2] = 1;
|
||||
my_struct.x <= 1;
|
||||
my_struct.pt.b <= 1;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(s_array[1].arr[2], 1);
|
||||
`checkh(my_struct.x, 1);
|
||||
`checkh(my_struct.pt.b, 1);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force s_array[1].x = 0;
|
||||
force s_array[1].arr[2] = 2;
|
||||
force my_struct.x = 0;
|
||||
force my_struct.pt.b = 0;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkh(s_array[1].x, 0);
|
||||
|
|
@ -50,16 +59,20 @@ module t (
|
|||
s_array[1].arr[2] = 3;
|
||||
`checkh(my_struct.x, 0);
|
||||
my_struct.x <= 1;
|
||||
`checkh(my_struct.pt.b, 0);
|
||||
my_struct.pt.b <= 1;
|
||||
end
|
||||
else if (cyc == 4) begin
|
||||
`checkh(s_array[1].x, 0);
|
||||
`checkh(s_array[1].arr[2], 2);
|
||||
`checkh(my_struct.x, 0);
|
||||
`checkh(my_struct.pt.b, 0);
|
||||
end
|
||||
else if (cyc == 5) begin
|
||||
release s_array[1].x;
|
||||
release s_array[1].arr[2];
|
||||
release my_struct.x;
|
||||
release my_struct.pt.b;
|
||||
end
|
||||
else if (cyc == 6) begin
|
||||
`checkh(s_array[1].x, 0);
|
||||
|
|
@ -68,11 +81,14 @@ module t (
|
|||
s_array[1].arr[2] = 4;
|
||||
`checkh(my_struct.x, 0);
|
||||
my_struct.x <= 1;
|
||||
`checkh(my_struct.pt.b, 0);
|
||||
my_struct.pt.b <= 1;
|
||||
end
|
||||
else if (cyc == 7) begin
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(s_array[1].arr[2], 4);
|
||||
`checkh(my_struct.x, 1);
|
||||
`checkh(my_struct.pt.b, 1);
|
||||
end
|
||||
else if (cyc == 8) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:22:7: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
22 | bit big_array[40][40][40];
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:26:7: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
26 | bit big_array[40][40][40];
|
||||
| ^~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:21:12: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
21 | struct_t s_array[3000];
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:25:12: Unsupported: Force of variable with >= 1000 unpacked elements
|
||||
25 | struct_t s_array[3000];
|
||||
| ^~~~~~~
|
||||
%Error: Exiting due to
|
||||
%Error-UNSUPPORTED: t/t_force_unpacked_unsup.v:27:11: Forcing variable of unsupported type: REFDTYPE 'union_t'
|
||||
27 | union_t my_union;
|
||||
| ^~~~~~~~
|
||||
%Error: Internal Error: t/t_force_unpacked_unsup.v:27:11: ../V3Force.cpp:#: Unsupported: Force of variable of unhandled data type
|
||||
27 | union_t my_union;
|
||||
| ^~~~~~~~
|
||||
... This fatal error may be caused by the earlier error(s); resolve those first.
|
||||
|
|
|
|||
|
|
@ -17,59 +17,63 @@ module t (
|
|||
integer cyc = 0;
|
||||
|
||||
typedef struct {int x;} struct_t;
|
||||
typedef union {
|
||||
int x;
|
||||
logic y;
|
||||
} union_t;
|
||||
|
||||
struct_t s_array[3000];
|
||||
bit big_array[40][40][40];
|
||||
real r_array[2];
|
||||
union_t my_union;
|
||||
|
||||
// Test loop
|
||||
always @(posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 0) begin
|
||||
r_array[0] <= 1;
|
||||
big_array[1][2][3] <= 1;
|
||||
s_array[1].x <= 1;
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 1) begin
|
||||
`checkr(r_array[0], 1);
|
||||
`checkr(big_array[1][2][3], 1);
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(my_union.x, 1);
|
||||
end
|
||||
else if (cyc == 2) begin
|
||||
force r_array[0] = 0;
|
||||
force big_array[1][2][3] = 0;
|
||||
force s_array[1].x = 0;
|
||||
force my_union.x = 0;
|
||||
end
|
||||
else if (cyc == 3) begin
|
||||
`checkr(r_array[0], 0);
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
r_array[0] <= 1;
|
||||
big_array[1][2][3] <= 1;
|
||||
`checkh(s_array[1].x, 0);
|
||||
s_array[1].x <= 1;
|
||||
`checkh(my_union.x, 0);
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 4) begin
|
||||
`checkr(r_array[0], 0);
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
`checkh(s_array[1].x, 0);
|
||||
`checkh(my_union.x, 0);
|
||||
end
|
||||
else if (cyc == 5) begin
|
||||
release r_array[0];
|
||||
release big_array[1][2][3];
|
||||
release s_array[1].x;
|
||||
release my_union.x;
|
||||
end
|
||||
else if (cyc == 6) begin
|
||||
`checkr(r_array[0], 0);
|
||||
`checkr(big_array[1][2][3], 0);
|
||||
r_array[0] <= 1;
|
||||
big_array[1][2][3] <= 1;
|
||||
`checkh(s_array[1].x, 0);
|
||||
s_array[1].x <= 1;
|
||||
`checkh(my_union.x, 0);
|
||||
my_union.x <= 1;
|
||||
end
|
||||
else if (cyc == 7) begin
|
||||
`checkr(r_array[0], 1);
|
||||
`checkr(big_array[1][2][3], 1);
|
||||
`checkh(s_array[1].x, 1);
|
||||
`checkh(my_union.x, 1);
|
||||
end
|
||||
else if (cyc == 8) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
|
|
|||
Loading…
Reference in New Issue