Internals: Support linking recursive function calls (but not later stages)
This commit is contained in:
parent
4d1f4bbf49
commit
b989ac6db5
|
|
@ -2750,6 +2750,7 @@ private:
|
|||
bool m_isHideProtected : 1; // Verilog protected
|
||||
bool m_pure : 1; // DPI import pure (vs. virtual pure)
|
||||
bool m_pureVirtual : 1; // Pure virtual
|
||||
bool m_recursive : 1; // Recusive or part of recursion
|
||||
bool m_underGenerate : 1; // Under generate (for warning)
|
||||
bool m_virtual : 1; // Virtual method in class
|
||||
VLifetime m_lifetime; // Lifetime
|
||||
|
|
@ -2774,6 +2775,7 @@ protected:
|
|||
, m_isHideProtected{false}
|
||||
, m_pure{false}
|
||||
, m_pureVirtual{false}
|
||||
, m_recursive{false}
|
||||
, m_underGenerate{false}
|
||||
, m_virtual{false} {
|
||||
addNOp3p(stmtsp);
|
||||
|
|
@ -2843,6 +2845,8 @@ public:
|
|||
bool pure() const { return m_pure; }
|
||||
void pureVirtual(bool flag) { m_pureVirtual = flag; }
|
||||
bool pureVirtual() const { return m_pureVirtual; }
|
||||
void recursive(bool flag) { m_recursive = flag; }
|
||||
bool recursive() const { return m_recursive; }
|
||||
void underGenerate(bool flag) { m_underGenerate = flag; }
|
||||
bool underGenerate() const { return m_underGenerate; }
|
||||
void isVirtual(bool flag) { m_virtual = flag; }
|
||||
|
|
|
|||
|
|
@ -1802,12 +1802,13 @@ void AstNodeFTaskRef::dump(std::ostream& str) const {
|
|||
void AstNodeFTask::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (classMethod()) str << " [METHOD]";
|
||||
if (taskPublic()) str << " [PUBLIC]";
|
||||
if (prototype()) str << " [PROTOTYPE]";
|
||||
if (dpiImport()) str << " [DPII]";
|
||||
if (dpiExport()) str << " [DPIX]";
|
||||
if (dpiImport()) str << " [DPII]";
|
||||
if (dpiOpenChild()) str << " [DPIOPENCHILD]";
|
||||
if (dpiOpenParent()) str << " [DPIOPENPARENT]";
|
||||
if (prototype()) str << " [PROTOTYPE]";
|
||||
if (recursive()) str << " [RECURSIVE]";
|
||||
if (taskPublic()) str << " [PUBLIC]";
|
||||
if ((dpiImport() || dpiExport()) && cname() != name()) str << " [c=" << cname() << "]";
|
||||
}
|
||||
void AstNodeBlock::dump(std::ostream& str) const {
|
||||
|
|
|
|||
|
|
@ -1860,7 +1860,7 @@ private:
|
|||
VSymEnt* m_pinSymp = nullptr; // SymEnt for pin lookups
|
||||
const AstCell* m_cellp = nullptr; // Current cell
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
const AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
int m_modportNum = 0; // Uniqueify modport numbers
|
||||
|
||||
struct DotStates {
|
||||
|
|
@ -2748,8 +2748,11 @@ private:
|
|||
if (foundp) {
|
||||
if (VN_IS(foundp->nodep(), Var) && m_ds.m_dotText == "" && m_ftaskp
|
||||
&& m_ftaskp->name() == foundp->nodep()->name()) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Recursive function call "
|
||||
<< nodep->prettyNameQ());
|
||||
// This is a recursive reference to the function itself, not to the var
|
||||
nodep->taskp(m_ftaskp);
|
||||
nodep->classOrPackagep(foundp->classOrPackagep());
|
||||
UINFO(7, " Resolved recursive " << nodep
|
||||
<< endl); // Also prints taskp
|
||||
} else {
|
||||
nodep->v3error("Found definition of '"
|
||||
<< m_ds.m_dotText << (m_ds.m_dotText == "" ? "" : ".")
|
||||
|
|
|
|||
|
|
@ -977,6 +977,13 @@ private:
|
|||
VL_DANGLING(funcp); // Make sure we've sized the function
|
||||
funcp = nodep->taskp();
|
||||
UASSERT_OBJ(funcp, nodep, "Not linked");
|
||||
if (funcp->recursive()) {
|
||||
// Because we attach values to nodes rather then making a stack, this is a mess
|
||||
// When we do support this, we need a stack depth limit of 1K or something,
|
||||
// and the t_func_recurse_param_bad.v test should check that limit's error message
|
||||
clearOptimizable(funcp, "Unsupported: Recursive constant functions");
|
||||
return;
|
||||
}
|
||||
// Apply function call values to function
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
|
||||
// Must do this in two steps, eval all params, then apply them
|
||||
|
|
|
|||
|
|
@ -4538,8 +4538,10 @@ private:
|
|||
// Grab width from the output variable (if it's a function)
|
||||
if (nodep->didWidth()) return;
|
||||
if (nodep->doingWidth()) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Recursive function or task call");
|
||||
nodep->dtypeSetBit();
|
||||
UINFO(5, "Recursive function or task call: " << nodep);
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Recursive function or task call: "
|
||||
<< nodep->prettyNameQ());
|
||||
nodep->recursive(true);
|
||||
nodep->didWidth(true);
|
||||
return;
|
||||
}
|
||||
|
|
@ -4554,7 +4556,8 @@ private:
|
|||
// Would use user1 etc, but V3Width called from too many places to spend a user
|
||||
nodep->doingWidth(true);
|
||||
m_ftaskp = nodep;
|
||||
userIterateChildren(nodep, nullptr);
|
||||
// First width the function variable, as if is a recursive function we need data type
|
||||
if (nodep->fvarp()) userIterate(nodep->fvarp(), nullptr);
|
||||
if (nodep->isConstructor()) {
|
||||
// Pretend it's void so less special casing needed when look at dtypes
|
||||
nodep->dtypeSetVoid();
|
||||
|
|
@ -4563,6 +4566,7 @@ private:
|
|||
UASSERT_OBJ(m_funcp, nodep, "FTask with function variable, but isn't a function");
|
||||
nodep->dtypeFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
|
||||
}
|
||||
userIterateChildren(nodep, nullptr);
|
||||
nodep->didWidth(true);
|
||||
nodep->doingWidth(false);
|
||||
m_funcp = nullptr;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
%Error-UNSUPPORTED: t/t_func_recurse.v:12:31: Unsupported: Recursive function call 'recurse_self'
|
||||
12 | else recurse_self = i + recurse_self(i - 1) * 2;
|
||||
| ^~~~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_func_recurse.v:9:27: Unsupported: Recursive function or task call: 'recurse_self'
|
||||
: ... In instance t
|
||||
9 | function automatic int recurse_self;
|
||||
| ^~~~~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%Error-UNSUPPORTED: t/t_func_recurse2.v:9:27: Unsupported: Recursive function or task call
|
||||
%Error-UNSUPPORTED: t/t_func_recurse2.v:9:27: Unsupported: Recursive function or task call: 'recurse_1'
|
||||
: ... In instance t
|
||||
9 | function automatic int recurse_1;
|
||||
| ^~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
%Error-UNSUPPORTED: t/t_func_recurse_param.v:12:31: Unsupported: Recursive function call 'recurse_self'
|
||||
12 | else recurse_self = i + recurse_self(i - 1) * 2;
|
||||
| ^~~~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_func_recurse_param.v:9:27: Unsupported: Recursive function or task call: 'recurse_self'
|
||||
: ... In instance t
|
||||
9 | function automatic int recurse_self;
|
||||
| ^~~~~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: t/t_func_recurse_param.v:15:26: Expecting expression to be constant, but can't determine constant for FUNCREF 'recurse_self'
|
||||
: ... In instance t
|
||||
t/t_func_recurse_param.v:9:27: ... Location of non-constant FUNC 'recurse_self': Unsupported: Recursive constant functions
|
||||
15 | localparam int ZERO = recurse_self(0);
|
||||
| ^~~~~~~~~~~~
|
||||
%Error: t/t_func_recurse_param.v:16:28: Expecting expression to be constant, but can't determine constant for FUNCREF 'recurse_self'
|
||||
: ... In instance t
|
||||
t/t_func_recurse_param.v:9:27: ... Location of non-constant FUNC 'recurse_self': Unsupported: Recursive constant functions
|
||||
16 | localparam int ELEVEN = recurse_self(3);
|
||||
| ^~~~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
%Error-UNSUPPORTED: t/t_func_recurse_param_bad.v:12:31: Unsupported: Recursive function call 'recurse_self'
|
||||
12 | else recurse_self = i + recurse_self(i - 1) * 2;
|
||||
| ^~~~~~~~~~~~
|
||||
%Error-UNSUPPORTED: t/t_func_recurse_param_bad.v:9:27: Unsupported: Recursive function or task call: 'recurse_self'
|
||||
: ... In instance t
|
||||
9 | function automatic int recurse_self;
|
||||
| ^~~~~~~~~~~~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: t/t_func_recurse_param_bad.v:15:26: Expecting expression to be constant, but can't determine constant for FUNCREF 'recurse_self'
|
||||
: ... In instance t
|
||||
t/t_func_recurse_param_bad.v:9:27: ... Location of non-constant FUNC 'recurse_self': Unsupported: Recursive constant functions
|
||||
15 | localparam int HUGE = recurse_self(10000);
|
||||
| ^~~~~~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
Loading…
Reference in New Issue