Support member functions with arguments.

This commit is contained in:
Stephen Williams 2013-03-24 11:59:33 -07:00
parent b9011d89ae
commit 64dffa5745
2 changed files with 75 additions and 48 deletions

View File

@ -816,6 +816,11 @@ class PECallFunction : public PExpr {
width_mode_t&mode); width_mode_t&mode);
unsigned test_width_method_(Design*des, NetScope*scope, unsigned test_width_method_(Design*des, NetScope*scope,
width_mode_t&mode); width_mode_t&mode);
unsigned elaborate_arguments_(Design*des, NetScope*scope,
NetFuncDef*def, bool need_const,
std::vector<NetExpr*>&parms,
unsigned parm_off) const;
}; };
/* /*

View File

@ -1848,46 +1848,9 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
done in the scope of the function call, and not the scope done in the scope of the function call, and not the scope
of the function being called. The scope of the called of the function being called. The scope of the called
function is elaborated when the definition is elaborated. */ function is elaborated when the definition is elaborated. */
unsigned parm_errors = elaborate_arguments_(des, scope,
unsigned parm_errors = 0; def, need_const,
unsigned missing_parms = 0; parms, 0);
for (unsigned idx = 0 ; idx < parms.size() ; idx += 1) {
PExpr*tmp = parms_[idx];
if (tmp) {
parms[idx] = elaborate_rval_expr(des, scope,
def->port(idx)->data_type(),
(unsigned)def->port(idx)->vector_width(),
tmp, need_const);
if (parms[idx] == 0) {
parm_errors += 1;
continue;
}
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[idx])) {
cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user "
"function argument." << endl;
des->errors += 1;
}
if (debug_elaborate)
cerr << get_fileline() << ": debug:"
<< " function " << path_
<< " arg " << (idx+1)
<< " argwid=" << parms[idx]->expr_width()
<< ": " << *parms[idx] << endl;
} else {
missing_parms += 1;
parms[idx] = 0;
}
}
if (missing_parms > 0) {
cerr << get_fileline() << ": error: The function " << path_
<< " has been called with empty parameters." << endl;
cerr << get_fileline() << ": : Verilog doesn't allow "
<< "passing empty parameters to functions." << endl;
des->errors += 1;
}
if (need_const && !dscope->is_const_func()) { if (need_const && !dscope->is_const_func()) {
@ -1909,7 +1872,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
if (missing_parms || parm_errors) if (parm_errors)
return 0; return 0;
/* Look for the return value signal for the called /* Look for the return value signal for the called
@ -1938,6 +1901,67 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
/*
* Elaborate the arguments of a function or method. The parms vector
* is where to place the elaborated expressions, so it an output. The
* parm_off is where in the parms vector to start writing
* arguments. This value is normally 0, but is 1 if this is a method
* so that parms[0] can hold the "this" argument. In this latter case,
* def->port(0) will be the "this" argument and should be skipped.
*/
unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
NetFuncDef*def, bool need_const,
vector<NetExpr*>&parms,
unsigned parm_off) const
{
unsigned parm_errors = 0;
unsigned missing_parms = 0;
const unsigned parm_count = parms.size() - parm_off;
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
unsigned pidx = idx + parm_off;
PExpr*tmp = parms_[idx];
if (tmp) {
parms[pidx] = elaborate_rval_expr(des, scope,
def->port(pidx)->data_type(),
(unsigned)def->port(pidx)->vector_width(),
tmp, need_const);
if (parms[pidx] == 0) {
parm_errors += 1;
continue;
}
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[pidx])) {
cerr << evt->get_fileline() << ": error: An event '"
<< evt->event()->name() << "' can not be a user "
"function argument." << endl;
des->errors += 1;
}
if (debug_elaborate)
cerr << get_fileline() << ": debug:"
<< " function " << path_
<< " arg " << (idx+1)
<< " argwid=" << parms[pidx]->expr_width()
<< ": " << *parms[idx] << endl;
} else {
missing_parms += 1;
parms[pidx] = 0;
}
}
if (missing_parms > 0) {
cerr << get_fileline() << ": error: The function " << path_
<< " has been called with empty parameters." << endl;
cerr << get_fileline() << ": : Verilog doesn't allow "
<< "passing empty parameters to functions." << endl;
parm_errors += 1;
des->errors += 1;
}
return parm_errors;
}
NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
unsigned expr_wid) const unsigned expr_wid) const
{ {
@ -2021,6 +2045,9 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
return 0; return 0;
} }
NetFuncDef*def = func->func_def();
ivl_assert(*this, def);
NetNet*res = func->find_signal(func->basename()); NetNet*res = func->find_signal(func->basename());
ivl_assert(*this, res); ivl_assert(*this, res);
@ -2030,13 +2057,8 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
ethis->set_line(*this); ethis->set_line(*this);
parms.push_back(ethis); parms.push_back(ethis);
if (parms_.size() > 0) { parms.resize(1 + parms_.size());
cerr << get_fileline() << ": sorry: " elaborate_arguments_(des, scope, def, false, parms, 1);
<< "Arguments (" << parms_.size() << ")"
<< " to function method " << func->basename()
<< " not supported." << endl;
des->errors += 1;
}
NetESignal*eres = new NetESignal(res); NetESignal*eres = new NetESignal(res);
NetEUFunc*call = new NetEUFunc(scope, func, eres, parms, false); NetEUFunc*call = new NetEUFunc(scope, func, eres, parms, false);