Support calling system functions as tasks, bug1285.

This commit is contained in:
Wilson Snyder 2018-03-08 23:40:19 -05:00
parent 86fe6ac3a8
commit 22ff760f0b
7 changed files with 53 additions and 4 deletions

View File

@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
**** Fix GCC 8.0 issues, bug1273.
**** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard]

View File

@ -2594,6 +2594,26 @@ public:
void lhsp(AstNode* nodep) { setOp3p(nodep); }
};
class AstSysFuncAsTask : public AstNodeStmt {
// Call what is normally a system function (with a return) in a non-return context
// Parents: stmtlist
// Children: a system function
public:
AstSysFuncAsTask(FileLine* fileline, AstNode* exprsp)
: AstNodeStmt (fileline) { addNOp1p(exprsp); }
ASTNODE_NODE_FUNCS(SysFuncAsTask)
virtual string verilogKwd() const { return ""; }
virtual bool isGateOptimizable() const { return true; }
virtual bool isPredictOptimizable() const { return true; }
virtual bool isPure() const { return true; }
virtual bool isOutputter() const { return false; }
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(const AstNode* samep) const { return true; }
AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval
void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval
};
class AstSysIgnore : public AstNodeStmt {
// Parents: stmtlist
// Children: varrefs or exprs

View File

@ -374,6 +374,11 @@ public:
puts(")); }\n");
}
}
virtual void visit(AstSysFuncAsTask* nodep) {
if (!nodep->lhsp()->isWide()) puts("(void)");
nodep->lhsp()->iterateAndNext(*this);
if (!nodep->lhsp()->isWide()) puts(";");
}
virtual void visit(AstSystemT* nodep) {
puts("(void)VL_SYSTEM_I");
emitIQW(nodep->lhsp());

View File

@ -278,6 +278,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateAndNext(*this); }
puts(");\n");
}
virtual void visit(AstSysFuncAsTask* nodep) {
nodep->lhsp()->iterateAndNext(*this);
puts(";\n");
}
virtual void visit(AstSysIgnore* nodep) {
putfs(nodep,nodep->verilogKwd());
putbs(" (");

View File

@ -2188,6 +2188,10 @@ private:
nodep->dtypeSetSigned32(); // Spec says integer return
}
}
virtual void visit(AstSysFuncAsTask* nodep) {
assertAtStatement(nodep);
userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p());
}
virtual void visit(AstSystemT* nodep) {
assertAtStatement(nodep);
userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p());

View File

@ -2663,6 +2663,8 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yaD_DPI '(' exprList ')' { $$ = new AstTaskRef($2,*$1,$3); GRAMMARP->argWrapList($$->castTaskRef()); }
//
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); }
//
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
| yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); }
| yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); }
@ -2673,7 +2675,6 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
//
| yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); }
//
| yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,NULL,NULL); }
| yD_DISPLAY '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,NULL,$3); }
@ -2698,6 +2699,9 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_READMEMH '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); }
| yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
| yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
//
// Any system function as a task
| system_f_call_or_t { $$ = new AstSysFuncAsTask($<fl>1, $1); }
;
system_f_call<nodep>: // IEEE: system_tf_call (as func)
@ -2707,7 +2711,14 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); GRAMMARP->argWrapList($$->castFuncRef()); }
//
| yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
//
| system_f_call_or_t { $$ = $1; }
;
system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
yD_ACOS '(' expr ')' { $$ = new AstAcosD($1,$3); }
| yD_ACOSH '(' expr ')' { $$ = new AstAcoshD($1,$3); }
| yD_ASIN '(' expr ')' { $$ = new AstAsinD($1,$3); }
| yD_ASINH '(' expr ')' { $$ = new AstAsinhD($1,$3); }
@ -2717,7 +2728,6 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_BITS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3); }
| yD_BITS '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_BITS,$3,$5); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); }
@ -2762,7 +2772,6 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
| yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); }
| yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); }
| yD_TESTPLUSARGS '(' str ')' { $$ = new AstTestPlusArgs($1,*$3); }

View File

@ -45,6 +45,11 @@ module t;
$display("str='%s'",sv_str);
if (sv_str != "T=1234") $stop;
sv_str = "none";
$value$plusargs("IN%s", sv_str);
$display("str='%s'",sv_str);
if (sv_str != "T=1234") $stop;
p_in = "IN%s";
`ifdef VERILATOR
p_in = $c(p_in); // Prevent constant propagation