From 6e7b07c794fe67b06eab52666ff1c570baa5f7fe Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 8 Nov 2020 18:58:31 -0500 Subject: [PATCH] Internals: Prep for #2597. No functional change intended --- src/V3Width.cpp | 70 ++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6b797d7ad..6555db0f0 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1709,39 +1709,7 @@ private: width = 1; } userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); - AstBasicDType* underDtp = VN_CAST(nodep->lhsp()->dtypep(), BasicDType); - if (!underDtp) underDtp = nodep->lhsp()->dtypep()->basicp(); - if (!underDtp) { - nodep->v3warn(E_UNSUPPORTED, - "Unsupported: Size-changing cast on non-basic data type"); - underDtp = VN_CAST(nodep->findLogicBoolDType(), BasicDType); - } - // A cast propagates its size to the lower expression and is included in the maximum - // width, so 23'(1'b1 + 1'b1) uses 23-bit math, but 1'(2'h2 * 2'h1) uses two-bit math. - // However the output width is exactly that requested. - // So two steps, first do the calculation's width (max of the two widths) - { - int calcWidth = std::max(width, underDtp->width()); - AstNodeDType* calcDtp - = (underDtp->isFourstate() - ? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric()) - : nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric())); - nodep->dtypep(calcDtp); - // We ignore warnings as that is sort of the point of a cast - iterateCheck(nodep, "Cast expr", nodep->lhsp(), CONTEXT, FINAL, calcDtp, - EXTEND_EXP, false); - } - // if (debug()) nodep->dumpTree(cout, " CastSizeClc: "); - // Next step, make the proper output width - { - AstNodeDType* outDtp - = (underDtp->isFourstate() - ? nodep->findLogicDType(width, width, underDtp->numeric()) - : nodep->findBitDType(width, width, underDtp->numeric())); - nodep->dtypep(outDtp); - // We ignore warnings as that is sort of the point of a cast - widthCheckSized(nodep, "Cast expr", nodep->lhsp(), outDtp, EXTEND_EXP, false); - } + castSized(nodep, nodep->lhsp(), width); // lhsp may change } if (m_vup->final()) { // CastSize not needed once sizes determined @@ -1751,6 +1719,42 @@ private: } // if (debug()) nodep->dumpTree(cout, " CastSizeOut: "); } + void castSized(AstNode* nodep, AstNode* underp, int width) { + AstBasicDType* underDtp = VN_CAST(underp->dtypep(), BasicDType); + if (!underDtp) underDtp = underp->dtypep()->basicp(); + if (!underDtp) { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: Size-changing cast on non-basic data type"); + underDtp = VN_CAST(nodep->findLogicBoolDType(), BasicDType); + } + UASSERT_OBJ(underp == nodep->op1p(), nodep, "Assuming op1 is cast value"); + // A cast propagates its size to the lower expression and is included in the maximum + // width, so 23'(1'b1 + 1'b1) uses 23-bit math, but 1'(2'h2 * 2'h1) uses two-bit math. + // However the output width is exactly that requested. + // So two steps, first do the calculation's width (max of the two widths) + { + int calcWidth = std::max(width, underDtp->width()); + AstNodeDType* calcDtp + = (underDtp->isFourstate() + ? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric()) + : nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric())); + nodep->dtypep(calcDtp); + // We ignore warnings as that is sort of the point of a cast + iterateCheck(nodep, "Cast expr", underp, CONTEXT, FINAL, calcDtp, EXTEND_EXP, false); + VL_DANGLING(underp); + underp = nodep->op1p(); // Above asserts that op1 was underp pre-relink + } + // if (debug()) nodep->dumpTree(cout, " CastSizeClc: "); + // Next step, make the proper output width + { + AstNodeDType* outDtp = (underDtp->isFourstate() + ? nodep->findLogicDType(width, width, underDtp->numeric()) + : nodep->findBitDType(width, width, underDtp->numeric())); + nodep->dtypep(outDtp); + // We ignore warnings as that is sort of the point of a cast + widthCheckSized(nodep, "Cast expr", underp, outDtp, EXTEND_EXP, false); + VL_DANGLING(underp); + } + } virtual void visit(AstVar* nodep) override { // if (debug()) nodep->dumpTree(cout, " InitPre: "); // Must have deterministic constant width