diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 3477d0591..91f02aaef 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1327,7 +1327,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // Missing pin/expr? We return (pinvar, NULL) // Extra pin/expr? We clean it up - typedef std::map NameToIndex; + typedef std::map NameToIndex; NameToIndex nameToIndex; V3TaskConnects tconnects; UASSERT_OBJ(nodep->taskp(), nodep, "unlinked"); @@ -1335,16 +1335,18 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // Find ports int tpinnum = 0; AstVar* sformatp = NULL; - for (AstNode* stmtp = taskStmtsp; stmtp; stmtp=stmtp->nextp()) { + for (AstNode* stmtp = taskStmtsp; stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { tconnects.push_back(make_pair(portp, static_cast(NULL))); - nameToIndex.insert(make_pair(portp->name(), tpinnum)); // For name based connections + nameToIndex.insert( + make_pair(portp->name(), tpinnum)); // For name based connections tpinnum++; if (portp->attrSFormat()) { sformatp = portp; } else if (sformatp) { - nodep->v3error("/*verilator sformat*/ can only be applied to last argument of a function"); + portp->v3error("/*verilator sformat*/ can only be applied to last argument of " + "a function"); } } } @@ -1353,7 +1355,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // Find pins int ppinnum = 0; bool reorganize = false; - for (AstNode* nextp, *pinp = nodep->pinsp(); pinp; pinp=nextp) { + for (AstNode *nextp, *pinp = nodep->pinsp(); pinp; pinp = nextp) { nextp = pinp->nextp(); AstArg* argp = VN_CAST(pinp, Arg); UASSERT_OBJ(argp, pinp, "Non-arg under ftask reference"); @@ -1361,14 +1363,15 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // By name NameToIndex::iterator it = nameToIndex.find(argp->name()); if (it == nameToIndex.end()) { - pinp->v3error("No such argument "<prettyNameQ() - <<" in function call to "<taskp()->prettyTypeName()); + pinp->v3error("No such argument " << argp->prettyNameQ() << " in function call to " + << nodep->taskp()->prettyTypeName()); // We'll just delete it; seems less error prone than making a false argument VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp); } else { if (tconnects[it->second].second) { - pinp->v3error("Duplicate argument "<prettyNameQ() - <<" in function call to "<taskp()->prettyTypeName()); + pinp->v3error("Duplicate argument " << argp->prettyNameQ() + << " in function call to " + << nodep->taskp()->prettyTypeName()); } argp->name(""); // Can forget name as will add back in pin order tconnects[it->second].second = argp; @@ -1382,7 +1385,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) tpinnum++; } else { pinp->v3error("Too many arguments in function call to " - <taskp()->prettyTypeName()); + << nodep->taskp()->prettyTypeName()); // We'll just delete it; seems less error prone than making a false argument VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp); } @@ -1394,13 +1397,14 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) } // Connect missing ones - for (int i=0; iexprp()) { AstNode* newvaluep = NULL; if (!portp->valuep()) { - nodep->v3error("Missing argument on non-defaulted argument "<prettyNameQ() - <<" in function call to "<taskp()->prettyTypeName()); + nodep->v3error("Missing argument on non-defaulted argument " + << portp->prettyNameQ() << " in function call to " + << nodep->taskp()->prettyTypeName()); newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0); } else if (!VN_IS(portp->valuep(), Const)) { // The default value for this port might be a constant @@ -1412,11 +1416,10 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // call, or something else that only makes sense in the // domain of the function, not the callee. nodep->v3error("Unsupported: Non-constant default value in missing argument " - <prettyNameQ() - <<" in function call to "<taskp()->prettyTypeName()); + << portp->prettyNameQ() << " in function call to " + << nodep->taskp()->prettyTypeName()); newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0); - } - else { + } else { newvaluep = newvaluep->cloneTree(true); } } else { @@ -1424,7 +1427,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) } // To avoid problems with callee needing to know to deleteTree // or not, we make this into a pin - UINFO(9,"Default pin for "<fileline(), portp->name(), newvaluep); if (tconnects[i].second) { // Have a "NULL" pin already defined for it VL_DO_CLEAR(tconnects[i].second->unlinkFrBack()->deleteTree(), @@ -1433,25 +1436,30 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) tconnects[i].second = newp; reorganize = true; } - if (tconnects[i].second) { UINFO(9,"Connect "< "< NONE"< " << tconnects[i].second << endl); + } else { + UINFO(9, "Connect " << portp << " -> NONE" << endl); + } } if (reorganize) { // To simplify downstream, put argument list back into pure pinnumber ordering - while (nodep->pinsp()) nodep->pinsp()->unlinkFrBack(); // Must unlink each pin, not all pins linked together as one list - for (int i=0; ipinsp()) { + // Must unlink each pin, not all pins linked together as one list + nodep->pinsp()->unlinkFrBack(); + } + for (int i = 0; i < tpinnum; ++i) { AstArg* argp = tconnects[i].second; UASSERT_OBJ(argp, nodep, "Lost argument in func conversion"); nodep->addPinsp(argp); } } - if (debug()>=9) { + if (debug() >= 9) { nodep->dumpTree(cout, "-ftref-out: "); - for (int i=0; itaskp(), nodep, "Unlinked"); if (nodep->didWidth()) return; userIterate(nodep->taskp(), NULL); // // And do the arguments to the task/function too do { - reloop: + reloop: V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); @@ -3467,18 +3467,23 @@ private: // pointer, so need to iterate separately later if (portp->attrSFormat() && (!VN_IS(pinp, SFormatF) || pinp->nextp())) { // Not already done - UINFO(4," sformat via metacomment: "<unlinkFrBackWithNext(&handle); // Format + additional args, if any AstNode* argsp = NULL; while (AstArg* nextargp = VN_CAST(argp->nextp(), Arg)) { argsp = AstNode::addNext( - argsp, nextargp->exprp()->unlinkFrBackWithNext()); // Expression goes to SFormatF + argsp, nextargp->exprp() + ->unlinkFrBackWithNext()); // Expression goes to SFormatF nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper } string format; - if (VN_IS(pinp, Const)) format = VN_CAST(pinp, Const)->num().toString(); - else pinp->v3error("Format to $display-like function must have constant format string"); + if (VN_IS(pinp, Const)) { + format = VN_CAST(pinp, Const)->num().toString(); + } else { + pinp->v3error( + "Format to $display-like function must have constant format string"); + } VL_DO_DANGLING(pushDeletep(argp), argp); AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); if (!newp->scopeNamep() && newp->formatScopeTracking()) { @@ -3487,13 +3492,15 @@ private: 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 + } // + else if (portp->basicp() + && portp->basicp()->keyword() == AstBasicDTypeKwd::STRING && !VN_IS(pinp, CvtPackString) && !VN_IS(pinp, SFormatF) // Already generates a string && !(VN_IS(pinp, VarRef) - && VN_CAST(pinp, VarRef)->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { - UINFO(4," Add CvtPackString: "<varp()->basicp()->keyword() + == AstBasicDTypeKwd::STRING)) { + UINFO(4, " Add CvtPackString: " << pinp << endl); AstNRelinker handle; pinp->unlinkFrBack(&handle); // No next, that's the next pin AstNode* newp = new AstCvtPackString(pinp->fileline(), pinp); @@ -3507,21 +3514,19 @@ private: // Stage 2 { V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + 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 // Change data types based on above accept completion - if (portp->isDouble()) { - VL_DO_DANGLING(spliceCvtD(pinp), pinp); - } + if (portp->isDouble()) VL_DO_DANGLING(spliceCvtD(pinp), pinp); } } // Stage 3 { V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); @@ -3532,13 +3537,11 @@ private: } } // Cleanup any open arrays - if (markHasOpenArray(nodep->taskp())) { - makeOpenArrayShell(nodep); - } + if (markHasOpenArray(nodep->taskp())) makeOpenArrayShell(nodep); // Stage 4 { V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); - for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) { + for (V3TaskConnects::iterator it = tconnects.begin(); it != tconnects.end(); ++it) { AstVar* portp = it->first; AstArg* argp = it->second; AstNode* pinp = argp->exprp(); @@ -3546,16 +3549,14 @@ private: if (portp->direction() == VDirection::REF && !similarDTypeRecurse(portp->dtypep(), pinp->dtypep())) { pinp->v3error("Ref argument requires matching types;" - <<" port "<prettyNameQ() - <<" requires "<prettyTypeName() - <<" but connection is "<prettyTypeName()<<"."); - } else if (portp->isWritable() - && pinp->width() != portp->width()) { + << " port " << portp->prettyNameQ() << " requires " + << portp->prettyTypeName() << " but connection is " + << pinp->prettyTypeName() << "."); + } else if (portp->isWritable() && pinp->width() != portp->width()) { pinp->v3error("Unsupported: Function output argument " - <prettyNameQ() - <<" requires "<width() - <<" bits, but connection's "<prettyTypeName() - <<" generates "<width()<<" bits."); + << portp->prettyNameQ() << " requires " << portp->width() + << " bits, but connection's " << pinp->prettyTypeName() + << " generates " << pinp->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) } @@ -3566,6 +3567,16 @@ private: } } } + } + virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign + // Function hasn't been widthed, so make it so. + UINFO(5, " FTASKREF " << nodep << endl); + UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); + if (nodep->didWidth()) return; + userIterate(nodep->taskp(), NULL); + // And do the arguments to the task/function too + processFTaskRefArgs(nodep); nodep->didWidth(true); } virtual void visit(AstInitial* nodep) VL_OVERRIDE {