From 37a931feb4b12526fd8c0b7eadf27f8cd3a780b3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 16 Dec 2017 15:46:21 -0500 Subject: [PATCH] Internals: Refactor some V3Task code in prep for openarrays. No functional change intended. --- src/V3Task.cpp | 139 +++++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 61 deletions(-) diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 3fd0c67fb..b6d3f617d 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -305,7 +305,7 @@ private: IM_AFTER, // Pointing at last inserted stmt, insert after IM_WHILE_PRECOND // Pointing to for loop, add to body end }; - typedef map > DpiNames; + typedef std::map > DpiNames; // STATE TaskStateVisitor* m_statep; // Common state between visitors @@ -677,7 +677,7 @@ private: return newp; } - AstCFunc* makeDpiExportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { + void makeDpiExportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { AstCFunc* dpip = new AstCFunc(nodep->fileline(), nodep->cname(), m_scopep, @@ -771,10 +771,10 @@ private: string stmt = "return "+rtnvarp->name()+";\n"; dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); } - return dpip; + makePortList(nodep, rtnvarp, dpip); } - AstCFunc* makeDpiImportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { + void makeDpiImportWrapper(AstNodeFTask* nodep, AstVar* rtnvarp) { if (nodep->cname() != AstNode::prettyName(nodep->cname())) { nodep->v3error("DPI function has illegal characters in C identifier name: "<cname())); } @@ -793,7 +793,46 @@ private: dpip->dpiImport (true); // Add DPI reference to top, since it's a global function m_topScopep->scopep()->addActivep(dpip); - return dpip; + makePortList(nodep, rtnvarp, dpip); + } + + bool duplicatedDpiProto(AstNodeFTask* nodep, string dpiproto) { + // Only create one DPI extern for each specified cname, + // as it's legal for the user to attach multiple tasks to one dpi cname + DpiNames::iterator iter = m_dpiNames.find(nodep->cname()); + if (iter == m_dpiNames.end()) { + m_dpiNames.insert(make_pair(nodep->cname(), make_pair(nodep, dpiproto))); + return false; + } + else if (iter->second.second != dpiproto) { + nodep->v3error("Duplicate declaration of DPI function with different formal arguments: "<prettyName()<warnMore()<<"... New prototype: "<second.first->warnMore()<<"... Original prototype: "<second.second); + return true; + } + else { + return true; + } + } + + void makePortList(AstNodeFTask* nodep, AstVar* rtnvarp, AstCFunc* dpip) { + // Copy nodep's list of function I/O to the new dpip c function + for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { + if (AstVar* portp = stmtp->castVar()) { + if (portp->isIO()) { + // Move it to new function + AstVar* newPortp = portp->cloneTree(false); + newPortp->funcLocal(true); + dpip->addArgsp(newPortp); + if (!portp->basicp()) { + portp->v3error("Unsupported: DPI argument of type "<basicp()->prettyTypeName()<warnMore()<<"... For best portability, use bit, byte, int, or longint"); + // We don't warn on logic either, although the 4-stateness is lost. + // That's what other simulators do. + } + } + } + } } void bodyDpiImportFunc(AstNodeFTask* nodep, AstVarScope* rtnvscp, AstCFunc* cfuncp) { @@ -858,30 +897,43 @@ private: // should the type of the function be bool/uint32/64 etc (based on lookup) or IData? AstNode::user2ClearTree(); AstVar* rtnvarp = NULL; - AstVarScope* rtnvscp = NULL; if (nodep->isFunction()) { - AstVar* portp = NULL; - if (NULL!=(portp = nodep->fvarp()->castVar())) { - if (!portp->isFuncReturn()) nodep->v3error("Not marked as function return var"); - if (portp->isWide()) nodep->v3error("Unsupported: Public functions with return > 64 bits wide. (Make it a output instead.)"); - if (ftaskNoInline || nodep->dpiExport()) portp->funcReturn(false); // Converting return to 'outputs' - if ((nodep->dpiImport() || nodep->dpiExport()) - && portp->dtypep()->basicp() - && portp->dtypep()->basicp()->keyword().isDpiUnreturnable()) { - portp->v3error("DPI function may not return type "<basicp()->prettyTypeName() - <<" (IEEE 2012 35.5.5)"); - } - portp->unlinkFrBack(); - rtnvarp = portp; - rtnvarp->funcLocal(true); - rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name - rtnvscp = new AstVarScope (rtnvarp->fileline(), m_scopep, rtnvarp); - m_scopep->addVarp(rtnvscp); - rtnvarp->user2p(rtnvscp); - } else { - nodep->v3fatalSrc("function without function output variable"); + AstVar* portp = nodep->fvarp()->castVar(); + if (!portp) nodep->v3fatalSrc("function without function output variable"); + if (!portp->isFuncReturn()) nodep->v3error("Not marked as function return var"); + if (portp->isWide()) nodep->v3error("Unsupported: Public functions with return > 64 bits wide. (Make it a output instead.)"); + if (ftaskNoInline || nodep->dpiExport()) portp->funcReturn(false); // Converting return to 'outputs' + if ((nodep->dpiImport() || nodep->dpiExport()) + && portp->dtypep()->basicp() + && portp->dtypep()->basicp()->keyword().isDpiUnreturnable()) { + portp->v3error("DPI function may not return type "<basicp()->prettyTypeName() + <<" (IEEE 2012 35.5.5)"); } + portp->unlinkFrBack(); + rtnvarp = portp; + rtnvarp->funcLocal(true); + rtnvarp->name(rtnvarp->name()+"__Vfuncrtn"); // Avoid conflict with DPI function name } + + if (nodep->dpiImport()) { + string dpiproto = dpiprotoName(nodep, rtnvarp); + if (!duplicatedDpiProto(nodep, dpiproto)) { + makeDpiImportWrapper(nodep, rtnvarp); + } + } else if (nodep->dpiExport()) { + string dpiproto = dpiprotoName(nodep, rtnvarp); + if (!duplicatedDpiProto(nodep, dpiproto)) { + makeDpiExportWrapper(nodep, rtnvarp); + } + } + + AstVarScope* rtnvscp = NULL; + if (rtnvarp) { + rtnvscp = new AstVarScope (rtnvarp->fileline(), m_scopep, rtnvarp); + m_scopep->addVarp(rtnvscp); + rtnvarp->user2p(rtnvscp); + } + string prefix = ""; if (nodep->dpiImport()) prefix = "__Vdpiimwrap_"; else if (nodep->dpiExport()) prefix = "__Vdpiexp_"; @@ -935,32 +987,6 @@ private: cfuncp->addInitsp(snp); } - AstCFunc* dpip = NULL; - string dpiproto; - if (nodep->dpiImport() || nodep->dpiExport()) { - dpiproto = dpiprotoName(nodep, rtnvarp); - - // Only create one DPI extern for each specified cname, - // as it's legal for the user to attach multiple tasks to one dpi cname - DpiNames::iterator iter = m_dpiNames.find(nodep->cname()); - if (iter == m_dpiNames.end()) { - // m_dpiNames insert below - if (nodep->dpiImport()) { - dpip = makeDpiImportWrapper(nodep, rtnvarp); - } else if (nodep->dpiExport()) { - dpip = makeDpiExportWrapper(nodep, rtnvarp); - cfuncp->addInitsp(new AstComment(dpip->fileline(), (string)("Function called from: ")+dpip->cname())); - } - - m_dpiNames.insert(make_pair(nodep->cname(), make_pair(dpip, dpiproto))); - } - else if (iter->second.second != dpiproto) { - nodep->v3error("Duplicate declaration of DPI function with different formal arguments: "<prettyName()<warnMore()<<"... New prototype: "<second.first->warnMore()<<"... Original prototype: "<second.second); - } - } - // Create list of arguments and move to function for (AstNode* nextp, *stmtp = nodep->stmtsp(); stmtp; stmtp=nextp) { nextp = stmtp->nextp(); @@ -970,15 +996,6 @@ private: portp->unlinkFrBack(); portp->funcLocal(true); cfuncp->addArgsp(portp); - if (dpip) { - dpip->addArgsp(portp->cloneTree(false)); - if (!portp->basicp()) { - portp->v3error("Unsupported: DPI argument of type "<basicp()->prettyTypeName()<warnMore()<<"... For best portability, use bit, byte, int, or longint"); - // We don't warn on logic either, although the 4-stateness is lost. - // That's what other simulators do. - } - } } else { // "Normal" variable, mark inside function portp->funcLocal(true);