diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 62f8d0bc3..1a734d25e 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -110,6 +110,7 @@ Ilya Barkov Iru Cai Ivan Vnučec Iztok Jeras +Jaeuk Lee Jake Merdich Jakub Michalski Jakub Wasilewski diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 349fe44da..60dbcd8f1 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -3086,6 +3086,23 @@ static inline void VL_REVCOPY_Q(VlQueue& q, const VlUnpacked& fro VL_COPY_Q(q, srcQ, lbits, srcElementBits, dstElementBits); } +// Overloads for VlQueue source -> VlUnpacked destination +template +static inline void VL_COPY_Q(VlUnpacked& q, const VlQueue& from, int lbits, + int srcElementBits, int dstElementBits) { + VlQueue tmpQ; + VL_COPY_Q(tmpQ, from, lbits, srcElementBits, dstElementBits); + for (size_t i = 0; i < N_Depth; ++i) q[i] = tmpQ.at(static_cast(i)); +} + +template +static inline void VL_REVCOPY_Q(VlUnpacked& q, const VlQueue& from, int lbits, + int srcElementBits, int dstElementBits) { + VlQueue tmpQ; + VL_REVCOPY_Q(tmpQ, from, lbits, srcElementBits, dstElementBits); + for (size_t i = 0; i < N_Depth; ++i) q[i] = tmpQ.at(static_cast(i)); +} + //====================================================================== // Expressions needing insert/select diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 4331e4015..713628fa0 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -247,6 +247,7 @@ class SliceVisitor final : public VNVisitor { const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType); if (!arrayp) return false; if (VN_IS(stp, CvtPackedToArray)) return false; + if (VN_IS(stp, CvtArrayToArray)) return false; if (VN_IS(stp, CReset)) return false; // Any isSc variables must be expanded regardless of --fno-slice diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 5eeaf2205..3a584a068 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6460,6 +6460,7 @@ class WidthVisitor final : public VNVisitor { } iterateCheckAssign(nodep, "Assign RHS", nodep->rhsp(), FINAL, lhsDTypep); + convertArrayToUnpackedAssign(nodep); // UINFOTREE(1, nodep, "", "AssignOut"); } if (VN_IS(nodep, AssignForce)) checkForceReleaseLhs(nodep, nodep->lhsp()); @@ -6582,6 +6583,30 @@ class WidthVisitor final : public VNVisitor { checkForceReleaseLhs(nodep, nodep->lhsp()); } + static void convertArrayToUnpackedAssign(AstNodeAssign* nodep) { + AstNodeDType* const lhsDTypep = nodep->lhsp()->dtypep()->skipRefp(); + if (!VN_IS(lhsDTypep, UnpackArrayDType)) return; + + AstNodeExpr* const rhsp = nodep->rhsp(); + AstNodeDType* const rhsDTypep = rhsp->dtypep()->skipRefp(); + if (!VN_IS(rhsDTypep, DynArrayDType) && !VN_IS(rhsDTypep, QueueDType)) return; + + int srcElementBits = 1; + if (const AstNodeDType* const elemDtp = rhsDTypep->subDTypep()->skipRefp()) { + srcElementBits = elemDtp->width(); + } + int dstElementBits = 1; + if (const AstNodeDType* const elemDtp = lhsDTypep->subDTypep()->skipRefp()) { + dstElementBits = elemDtp->width(); + } + + rhsp->unlinkFrBack(); + AstCvtArrayToArray* const newp = new AstCvtArrayToArray{ + rhsp->fileline(), rhsp, lhsDTypep, false, 1, dstElementBits, srcElementBits}; + newp->didWidth(true); + nodep->rhsp(newp); + } + static bool isFormatNonNumericArg(const AstNodeDType* dtypep) { dtypep = dtypep->skipRefp(); return dtypep->isString() // diff --git a/test_regress/t/t_dynarray.v b/test_regress/t/t_dynarray.v index 308f83ffa..bd9bbbf3a 100644 --- a/test_regress/t/t_dynarray.v +++ b/test_regress/t/t_dynarray.v @@ -26,6 +26,10 @@ module t ( typedef bit [7:0] byte_t; byte_t a[]; byte_t b[]; + byte_t fixed[256]; + byte_t fixed_desc[255:0]; + byte_t fixed_rev[1:256]; + byte_t q[$]; // wide data array typedef struct packed { @@ -157,6 +161,32 @@ module t ( p256.delete(); `checkh(p256.size, 0); + // Test assignment from dynamic and queue arrays to fixed unpacked arrays. + a = new[256]; + for (int j = 0; j < 256; j++) begin + a[j] = byte_t'(j + 32'ha0); + q.push_back(byte_t'(j + 32'h40)); + end + fixed = a; + `checkh(fixed[0], 8'ha0); + `checkh(fixed[255], 8'h9f); + fixed = q; + `checkh(fixed[0], 8'h40); + `checkh(fixed[255], 8'h3f); + fixed_desc = a; + `checkh(fixed_desc[255], 8'h9f); + `checkh(fixed_desc[0], 8'ha0); + fixed_desc = q; + `checkh(fixed_desc[255], 8'h3f); + `checkh(fixed_desc[0], 8'h40); + fixed_rev = a; + `checkh(fixed_rev[1], 8'ha0); + `checkh(fixed_rev[256], 8'h9f); + fixed_rev = q; + `checkh(fixed_rev[1], 8'h40); + `checkh(fixed_rev[256], 8'h3f); + q.delete(); + end $write("*-* All Finished *-*\n");