From 9a2a5d3155049f74514642a3513c7be1ae6023c0 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 16 Dec 2017 09:36:07 -0500 Subject: [PATCH] Internals: Unroll V3Width task processing, in prep for openarrays. No functional change intended. --- src/V3Width.cpp | 153 ++++++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 64 deletions(-) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6601f8575..5ef692af6 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2396,78 +2396,103 @@ private: userIterate(nodep->taskp(), NULL); // // And do the arguments to the task/function too - for (int accept_mode=0; accept_mode<3; accept_mode++) { // Avoid duplicate code; just do inner stuff several times - reloop: + do { + reloop: + V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); + for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + AstVar* portp = it->first; + AstArg* argp = it->second; + AstNode* pinp = argp->exprp(); + if (!pinp) continue; // Argument error we'll find later + // Prelim may cause the node to get replaced; we've lost our + // pointer, so need to iterate separately later + if (portp->attrSFormat() + && (!pinp->castSFormatF() || pinp->nextp())) { // Not already done + UINFO(4," sformat via metacomment: "<unlinkFrBackWithNext(&handle); // Format + additional args, if any + AstNode* argsp = NULL; + while (AstArg* nextargp = argp->nextp()->castArg()) { + argsp = AstNode::addNext(argsp, nextargp->exprp()->unlinkFrBackWithNext()); // Expression goes to SFormatF + nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper + } + string format; + if (pinp->castConst()) format = pinp->castConst()->num().toString(); + else pinp->v3error("Format to $display-like function must have constant format string"); + pushDeletep(argp); VL_DANGLING(argp); + AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); + if (!newp->scopeNamep() && newp->formatScopeTracking()) { + newp->scopeNamep(new AstScopeName(newp->fileline())); + } + handle.relink(new AstArg(newp->fileline(), "", newp)); + // Connection list is now incorrect (has extra args in it). + goto reloop; // so exit early; next loop will correct it + } + else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING + && !pinp->castCvtPackString() + && !pinp->castSFormatF() // Already generates a string + && !(pinp->castVarRef() && pinp->castVarRef()->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { + UINFO(4," Add CvtPackString: "<unlinkFrBack(&handle); // No next, that's the next pin + AstNode* newp = new AstCvtPackString(pinp->fileline(), pinp); + handle.relink(newp); + pinp = newp; + } + // AstPattern requires assignments to pass datatype on PRELIM + userIterate(pinp, WidthVP(portp->dtypep(),PRELIM).p()); VL_DANGLING(pinp); + } + } while (0); + // Stage 2 + { V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); - if (pinp!=NULL) { // Else argument error we'll find later - if (accept_mode==0) { - // Prelim may cause the node to get replaced; we've lost our - // pointer, so need to iterate separately later - if (portp->attrSFormat() - && (!pinp->castSFormatF() || pinp->nextp())) { // Not already done - UINFO(4," sformat via metacomment: "<unlinkFrBackWithNext(&handle); // Format + additional args, if any - AstNode* argsp = NULL; - while (AstArg* nextargp = argp->nextp()->castArg()) { - argsp = AstNode::addNext(argsp, nextargp->exprp()->unlinkFrBackWithNext()); // Expression goes to SFormatF - nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper - } - string format; - if (pinp->castConst()) format = pinp->castConst()->num().toString(); - else pinp->v3error("Format to $display-like function must have constant format string"); - pushDeletep(argp); VL_DANGLING(argp); - AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); - if (!newp->scopeNamep() && newp->formatScopeTracking()) { - newp->scopeNamep(new AstScopeName(newp->fileline())); - } - handle.relink(new AstArg(newp->fileline(), "", newp)); - // Connection list is now incorrect (has extra args in it). - goto reloop; // so exit early; next loop will correct it - } - else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING - && !pinp->castCvtPackString() - && !pinp->castSFormatF() // Already generates a string - && !(pinp->castVarRef() && pinp->castVarRef()->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { - UINFO(4," Add CvtPackString: "<unlinkFrBack(&handle); // No next, that's the next pin - AstNode* newp = new AstCvtPackString(pinp->fileline(), pinp); - handle.relink(newp); - pinp = newp; - } - // AstPattern requires assignments to pass datatype on PRELIM - userIterate(pinp, WidthVP(portp->dtypep(),PRELIM).p()); VL_DANGLING(pinp); - } else if (accept_mode==1) { - // Change data types based on above accept completion - if (portp->isDouble()) { - spliceCvtD(pinp); VL_DANGLING(pinp); - } - } else if (accept_mode==2) { - // Do PRELIM again, because above accept may have exited early due to node replacement - userIterate(pinp, WidthVP(portp->dtypep(),PRELIM).p()); - if ((portp->isOutput() || portp->isInout()) - && pinp->width() != portp->width()) { - pinp->v3error("Unsupported: Function output argument '"<prettyName()<<"'" - <<" requires "<width() - <<" bits, but connection's "<prettyTypeName() - <<" generates "<width()<<" bits."); - // otherwise would need some mess to force both sides to proper size - // (get an ASSIGN with EXTEND on the lhs instead of rhs) - } - if (!portp->basicp() || portp->basicp()->isOpaque()) { - userIterate(pinp, WidthVP(portp->dtypep(),FINAL).p()); - } else { - iterateCheckAssign(nodep,"Function Argument",pinp,FINAL,portp->dtypep()); - } - } + if (!pinp) continue; // Argument error we'll find later + // Change data types based on above accept completion + if (portp->isDouble()) { + spliceCvtD(pinp); VL_DANGLING(pinp); } } } + // Stage 3 + { + V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); + for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + AstVar* portp = it->first; + AstArg* argp = it->second; + AstNode* pinp = argp->exprp(); + if (!pinp) continue; // Argument error we'll find later + // Do PRELIM again, because above accept may have exited early due to node replacement + userIterate(pinp, WidthVP(portp->dtypep(),PRELIM).p()); + } + } + // Stage 4 + { + V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); + for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + AstVar* portp = it->first; + AstArg* argp = it->second; + AstNode* pinp = argp->exprp(); + if (!pinp) continue; // Argument error we'll find later + if ((portp->isOutput() || portp->isInout()) + && pinp->width() != portp->width()) { + pinp->v3error("Unsupported: Function output argument '"<prettyName()<<"'" + <<" requires "<width() + <<" bits, but connection's "<prettyTypeName() + <<" generates "<width()<<" bits."); + // otherwise would need some mess to force both sides to proper size + // (get an ASSIGN with EXTEND on the lhs instead of rhs) + } + if (!portp->basicp() || portp->basicp()->isOpaque()) { + userIterate(pinp, WidthVP(portp->dtypep(),FINAL).p()); + } else { + iterateCheckAssign(nodep,"Function Argument",pinp,FINAL,portp->dtypep()); + } + } + } nodep->didWidth(true); } virtual void visit(AstInitial* nodep) {