Internals: clang-format and refactor taskref pin handling.

This commit is contained in:
Wilson Snyder 2020-04-12 08:26:14 -04:00
parent ea3acc2d3a
commit 1e2d73fc80
2 changed files with 75 additions and 56 deletions

View File

@ -1339,12 +1339,14 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
if (AstVar* portp = VN_CAST(stmtp, Var)) { if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO()) { if (portp->isIO()) {
tconnects.push_back(make_pair(portp, static_cast<AstArg*>(NULL))); tconnects.push_back(make_pair(portp, static_cast<AstArg*>(NULL)));
nameToIndex.insert(make_pair(portp->name(), tpinnum)); // For name based connections nameToIndex.insert(
make_pair(portp->name(), tpinnum)); // For name based connections
tpinnum++; tpinnum++;
if (portp->attrSFormat()) { if (portp->attrSFormat()) {
sformatp = portp; sformatp = portp;
} else if (sformatp) { } 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");
} }
} }
} }
@ -1361,14 +1363,15 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
// By name // By name
NameToIndex::iterator it = nameToIndex.find(argp->name()); NameToIndex::iterator it = nameToIndex.find(argp->name());
if (it == nameToIndex.end()) { if (it == nameToIndex.end()) {
pinp->v3error("No such argument "<<argp->prettyNameQ() pinp->v3error("No such argument " << argp->prettyNameQ() << " in function call to "
<<" in function call to "<<nodep->taskp()->prettyTypeName()); << nodep->taskp()->prettyTypeName());
// We'll just delete it; seems less error prone than making a false argument // We'll just delete it; seems less error prone than making a false argument
VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp); VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp);
} else { } else {
if (tconnects[it->second].second) { if (tconnects[it->second].second) {
pinp->v3error("Duplicate argument " << argp->prettyNameQ() pinp->v3error("Duplicate argument " << argp->prettyNameQ()
<<" in function call to "<<nodep->taskp()->prettyTypeName()); << " in function call to "
<< nodep->taskp()->prettyTypeName());
} }
argp->name(""); // Can forget name as will add back in pin order argp->name(""); // Can forget name as will add back in pin order
tconnects[it->second].second = argp; tconnects[it->second].second = argp;
@ -1399,8 +1402,9 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
if (!tconnects[i].second || !tconnects[i].second->exprp()) { if (!tconnects[i].second || !tconnects[i].second->exprp()) {
AstNode* newvaluep = NULL; AstNode* newvaluep = NULL;
if (!portp->valuep()) { if (!portp->valuep()) {
nodep->v3error("Missing argument on non-defaulted argument "<<portp->prettyNameQ() nodep->v3error("Missing argument on non-defaulted argument "
<<" in function call to "<<nodep->taskp()->prettyTypeName()); << portp->prettyNameQ() << " in function call to "
<< nodep->taskp()->prettyTypeName());
newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0); newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0);
} else if (!VN_IS(portp->valuep(), Const)) { } else if (!VN_IS(portp->valuep(), Const)) {
// The default value for this port might be a constant // 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 // call, or something else that only makes sense in the
// domain of the function, not the callee. // domain of the function, not the callee.
nodep->v3error("Unsupported: Non-constant default value in missing argument " nodep->v3error("Unsupported: Non-constant default value in missing argument "
<<portp->prettyNameQ() << portp->prettyNameQ() << " in function call to "
<<" in function call to "<<nodep->taskp()->prettyTypeName()); << nodep->taskp()->prettyTypeName());
newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0); newvaluep = new AstConst(nodep->fileline(), AstConst::Unsized32(), 0);
} } else {
else {
newvaluep = newvaluep->cloneTree(true); newvaluep = newvaluep->cloneTree(true);
} }
} else { } else {
@ -1433,14 +1436,19 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp)
tconnects[i].second = newp; tconnects[i].second = newp;
reorganize = true; reorganize = true;
} }
if (tconnects[i].second) { UINFO(9,"Connect "<<portp if (tconnects[i].second) {
<<" -> "<<tconnects[i].second<<endl); } UINFO(9, "Connect " << portp << " -> " << tconnects[i].second << endl);
else { UINFO(9,"Connect "<<portp<<" -> NONE"<<endl); } } else {
UINFO(9, "Connect " << portp << " -> NONE" << endl);
}
} }
if (reorganize) { if (reorganize) {
// To simplify downstream, put argument list back into pure pinnumber ordering // 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 while (nodep->pinsp()) {
// Must unlink each pin, not all pins linked together as one list
nodep->pinsp()->unlinkFrBack();
}
for (int i = 0; i < tpinnum; ++i) { for (int i = 0; i < tpinnum; ++i) {
AstArg* argp = tconnects[i].second; AstArg* argp = tconnects[i].second;
UASSERT_OBJ(argp, nodep, "Lost argument in func conversion"); UASSERT_OBJ(argp, nodep, "Lost argument in func conversion");

View File

@ -3446,7 +3446,7 @@ private:
nodep->dtypeFrom(nodep->taskp()); nodep->dtypeFrom(nodep->taskp());
//if (debug()) nodep->dumpTree(cout, " FuncOut: "); //if (debug()) nodep->dumpTree(cout, " FuncOut: ");
} }
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { void processFTaskRefArgs(AstNodeFTaskRef* nodep) {
// For arguments, is assignment-like context; see IEEE rules in AstNodeAssign // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign
// Function hasn't been widthed, so make it so. // Function hasn't been widthed, so make it so.
UINFO(5, " FTASKREF " << nodep << endl); UINFO(5, " FTASKREF " << nodep << endl);
@ -3473,12 +3473,17 @@ private:
AstNode* argsp = NULL; AstNode* argsp = NULL;
while (AstArg* nextargp = VN_CAST(argp->nextp(), Arg)) { while (AstArg* nextargp = VN_CAST(argp->nextp(), Arg)) {
argsp = AstNode::addNext( 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 nextargp->unlinkFrBack()->deleteTree(); // Remove the call's Arg wrapper
} }
string format; string format;
if (VN_IS(pinp, Const)) format = VN_CAST(pinp, Const)->num().toString(); if (VN_IS(pinp, Const)) {
else pinp->v3error("Format to $display-like function must have constant format string"); 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); VL_DO_DANGLING(pushDeletep(argp), argp);
AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp); AstSFormatF* newp = new AstSFormatF(nodep->fileline(), format, false, argsp);
if (!newp->scopeNamep() && newp->formatScopeTracking()) { if (!newp->scopeNamep() && newp->formatScopeTracking()) {
@ -3487,12 +3492,14 @@ private:
handle.relink(new AstArg(newp->fileline(), "", newp)); handle.relink(new AstArg(newp->fileline(), "", newp));
// Connection list is now incorrect (has extra args in it). // Connection list is now incorrect (has extra args in it).
goto reloop; // so exit early; next loop will correct 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, CvtPackString)
&& !VN_IS(pinp, SFormatF) // Already generates a string && !VN_IS(pinp, SFormatF) // Already generates a string
&& !(VN_IS(pinp, VarRef) && !(VN_IS(pinp, VarRef)
&& VN_CAST(pinp, VarRef)->varp()->basicp()->keyword()==AstBasicDTypeKwd::STRING)) { && VN_CAST(pinp, VarRef)->varp()->basicp()->keyword()
== AstBasicDTypeKwd::STRING)) {
UINFO(4, " Add CvtPackString: " << pinp << endl); UINFO(4, " Add CvtPackString: " << pinp << endl);
AstNRelinker handle; AstNRelinker handle;
pinp->unlinkFrBack(&handle); // No next, that's the next pin pinp->unlinkFrBack(&handle); // No next, that's the next pin
@ -3513,9 +3520,7 @@ private:
AstNode* pinp = argp->exprp(); AstNode* pinp = argp->exprp();
if (!pinp) continue; // Argument error we'll find later if (!pinp) continue; // Argument error we'll find later
// Change data types based on above accept completion // Change data types based on above accept completion
if (portp->isDouble()) { if (portp->isDouble()) VL_DO_DANGLING(spliceCvtD(pinp), pinp);
VL_DO_DANGLING(spliceCvtD(pinp), pinp);
}
} }
} }
// Stage 3 // Stage 3
@ -3532,9 +3537,7 @@ private:
} }
} }
// Cleanup any open arrays // Cleanup any open arrays
if (markHasOpenArray(nodep->taskp())) { if (markHasOpenArray(nodep->taskp())) makeOpenArrayShell(nodep);
makeOpenArrayShell(nodep);
}
// Stage 4 // Stage 4
{ {
V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp()); V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
@ -3546,14 +3549,12 @@ private:
if (portp->direction() == VDirection::REF if (portp->direction() == VDirection::REF
&& !similarDTypeRecurse(portp->dtypep(), pinp->dtypep())) { && !similarDTypeRecurse(portp->dtypep(), pinp->dtypep())) {
pinp->v3error("Ref argument requires matching types;" pinp->v3error("Ref argument requires matching types;"
<<" port "<<portp->prettyNameQ() << " port " << portp->prettyNameQ() << " requires "
<<" requires "<<portp->prettyTypeName() << portp->prettyTypeName() << " but connection is "
<<" but connection is "<<pinp->prettyTypeName()<<"."); << pinp->prettyTypeName() << ".");
} else if (portp->isWritable() } else if (portp->isWritable() && pinp->width() != portp->width()) {
&& pinp->width() != portp->width()) {
pinp->v3error("Unsupported: Function output argument " pinp->v3error("Unsupported: Function output argument "
<<portp->prettyNameQ() << portp->prettyNameQ() << " requires " << portp->width()
<<" requires "<<portp->width()
<< " bits, but connection's " << pinp->prettyTypeName() << " bits, but connection's " << pinp->prettyTypeName()
<< " generates " << pinp->width() << " bits."); << " generates " << pinp->width() << " bits.");
// otherwise would need some mess to force both sides to proper size // otherwise would need some mess to force both sides to proper size
@ -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); nodep->didWidth(true);
} }
virtual void visit(AstInitial* nodep) VL_OVERRIDE { virtual void visit(AstInitial* nodep) VL_OVERRIDE {