Handle default arguments in class new functions.

This commit is contained in:
Stephen Williams 2013-09-14 19:54:35 -07:00
parent 9a116498a2
commit 16414f921f
5 changed files with 86 additions and 32 deletions

View File

@ -26,6 +26,7 @@
# include <vector> # include <vector>
# include <list> # include <list>
class Design; class Design;
class NetExpr;
class NetNet; class NetNet;
class NetScope; class NetScope;
class PWire; class PWire;
@ -48,8 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
inline class_type_t* method_of() const { return this_type_; } inline class_type_t* method_of() const { return this_type_; }
protected: protected:
// Elaborate the ports list. Write into the ports vector the
// NetNet pointers for the ports, and write into the pdefs the
// default value expressions, if any.
void elaborate_sig_ports_(Design*des, NetScope*scope, void elaborate_sig_ports_(Design*des, NetScope*scope,
std::vector<NetNet*>&ports) const; std::vector<NetNet*>&ports,
std::vector<NetExpr*>&pdefs) const;
void dump_ports_(std::ostream&out, unsigned ind) const; void dump_ports_(std::ostream&out, unsigned ind) const;

View File

@ -4586,37 +4586,53 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
NetFuncDef*def = new_scope->func_def(); NetFuncDef*def = new_scope->func_def();
ivl_assert(*this, def); ivl_assert(*this, def);
if ((parms_.size()+1) != def->port_count()) { // Are there too many arguments passed to the function. If so,
// generate an error message. The case of too few arguments
// will be handled below, when we run out of arguments.
if ((parms_.size()+1) > def->port_count()) {
cerr << get_fileline() << ": error: Parm count mismatch" cerr << get_fileline() << ": error: Parm count mismatch"
<< " passing " << parms_.size() << " arguments " << " passing " << parms_.size() << " arguments "
<< " to constructor expecting " << (def->port_count()-1) << " to constructor expecting " << (def->port_count()-1)
<< " arguments." << endl; << " arguments." << endl;
des->errors += 1; des->errors += 1;
return obj;
} }
vector<NetExpr*> parms (1 + parms_.size()); vector<NetExpr*> parms (def->port_count());
parms[0] = obj; parms[0] = obj;
int missing_parms = 0; int missing_parms = 0;
int parm_errors = 0; int parm_errors = 0;
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
PExpr*tmp = parms_[idx]; // While there are default arguments, check them.
size_t pidx = idx + 1; if (idx <= parms_.size()) {
PExpr*tmp = parms_[idx-1];
if (tmp == 0) { if (tmp == 0) {
parms[pidx] = 0; parms[idx] = 0;
missing_parms += 1; missing_parms += 1;
continue; continue;
} }
parms[pidx] = elaborate_rval_expr(des, scope, def->port(pidx)->data_type(), parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->data_type(),
def->port(pidx)->vector_width(), def->port(idx)->vector_width(),
tmp, false); tmp, false);
if (parms[pidx] == 0) { if (parms[idx] == 0)
parm_errors += 1; parm_errors += 1;
continue; continue;
} }
// Ran out of explicit arguments. Is there a default
// argument we can use?
if (NetExpr*tmp = def->port_defe(idx)) {
parms[idx] = tmp;
continue;
}
// If we run out of passed expressions, and there is no
// default value for this port, then we will need to
// report an error that we are missing parameters.
missing_parms += 1;
parms[idx] = 0;
} }
if (missing_parms > 0) { if (missing_parms > 0) {

View File

@ -596,10 +596,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
} }
vector<NetNet*>ports; vector<NetNet*>ports;
elaborate_sig_ports_(des, scope, ports); vector<NetExpr*>pdef;
elaborate_sig_ports_(des, scope, ports, pdef);
NetFuncDef*def = 0; NetFuncDef*def = 0;
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports); if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports, pdef);
assert(def); assert(def);
if (debug_elaborate) if (debug_elaborate)
@ -630,8 +631,9 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
elaborate_sig_wires_(des, scope); elaborate_sig_wires_(des, scope);
vector<NetNet*>ports; vector<NetNet*>ports;
elaborate_sig_ports_(des, scope, ports); vector<NetExpr*>pdefs;
NetTaskDef*def = new NetTaskDef(scope, ports); elaborate_sig_ports_(des, scope, ports, pdefs);
NetTaskDef*def = new NetTaskDef(scope, ports, pdefs);
scope->set_task_def(def); scope->set_task_def(def);
// Look for further signals in the sub-statement // Look for further signals in the sub-statement
@ -640,10 +642,11 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
} }
void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope, void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
vector<NetNet*>&ports) const vector<NetNet*>&ports, vector<NetExpr*>&pdefs) const
{ {
if (ports_ == 0) { if (ports_ == 0) {
ports.clear(); ports.clear();
pdefs.clear();
/* Make sure the function has at least one input /* Make sure the function has at least one input
port. If it fails this test, print an error port. If it fails this test, print an error
@ -661,13 +664,16 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
} }
ports.resize(ports_->size()); ports.resize(ports_->size());
pdefs.resize(ports_->size());
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) { for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
perm_string port_name = ports_->at(idx).port->basename(); perm_string port_name = ports_->at(idx).port->basename();
ports[idx] = 0; ports[idx] = 0;
pdefs[idx] = 0;
NetNet*tmp = scope->find_signal(port_name); NetNet*tmp = scope->find_signal(port_name);
NetExpr*tmp_def = 0;
if (tmp == 0) { if (tmp == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
<< "task/function " << scope_path(scope) << "task/function " << scope_path(scope)
@ -678,12 +684,19 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
continue; continue;
} }
// If the port has a default expression that can be used
// as a value when the caller doesn't bind, then
// elaborate that expression here. This expression
// should evaluate down do a constant.
if (ports_->at(idx).defe != 0) { if (ports_->at(idx).defe != 0) {
cerr << get_fileline() << ": sorry: " tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, -1, true);
<< "task/function default port expressions not supported." if (tmp_def==0) {
<< endl; cerr << get_fileline() << ": error: Unable to evaluate "
<< *ports_->at(idx).defe
<< " as a port default (constant) expression." << endl;
des->errors += 1; des->errors += 1;
} }
}
if (tmp->port_type() == NetNet::NOT_A_PORT) { if (tmp->port_type() == NetNet::NOT_A_PORT) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
@ -696,11 +709,12 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
} }
ports[idx] = tmp; ports[idx] = tmp;
pdefs[idx] = tmp_def;
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) { if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
cerr << tmp->get_fileline() << ": error: " cerr << tmp->get_fileline() << ": error: "
<< "Function " << scope_path(scope) << "Function " << scope_path(scope)
<< " port " << port_name << " port " << port_name
<< " is not an inputport." << endl; << " is not an input port." << endl;
cerr << tmp->get_fileline() << ": : " cerr << tmp->get_fileline() << ": : "
<< "Function arguments must be input ports." << endl; << "Function arguments must be input ports." << endl;
des->errors += 1; des->errors += 1;

View File

@ -2043,8 +2043,9 @@ verinum::V NetConst::value(unsigned idx) const
return value_[idx]; return value_[idx];
} }
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po) NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po,
: scope_(s), statement_(0), result_sig_(result), ports_(po) const vector<NetExpr*>&pd)
: scope_(s), statement_(0), result_sig_(result), ports_(po), pdefaults_(pd)
{ {
} }
@ -2085,6 +2086,12 @@ const NetNet* NetFuncDef::port(unsigned idx) const
return ports_[idx]; return ports_[idx];
} }
NetExpr* NetFuncDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
const NetNet* NetFuncDef::return_sig() const const NetNet* NetFuncDef::return_sig() const
{ {
return result_sig_; return result_sig_;
@ -2620,8 +2627,8 @@ unsigned NetUReduce::width() const
return width_; return width_;
} }
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po) NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
: scope_(n), proc_(0), ports_(po) : scope_(n), proc_(0), ports_(po), pdefaults_(pd)
{ {
} }
@ -2647,6 +2654,12 @@ NetNet* NetTaskDef::port(unsigned idx) const
return ports_[idx]; return ports_[idx];
} }
NetExpr* NetTaskDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
const NetScope* NetTaskDef::scope() const const NetScope* NetTaskDef::scope() const
{ {
return scope_; return scope_;

View File

@ -3215,7 +3215,8 @@ class NetFree : public NetProc {
class NetFuncDef { class NetFuncDef {
public: public:
NetFuncDef(NetScope*, NetNet*result, const std::vector<NetNet*>&po); NetFuncDef(NetScope*, NetNet*result, const std::vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetFuncDef(); ~NetFuncDef();
void set_proc(NetProc*st); void set_proc(NetProc*st);
@ -3227,6 +3228,7 @@ class NetFuncDef {
unsigned port_count() const; unsigned port_count() const;
const NetNet*port(unsigned idx) const; const NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
const NetNet*return_sig() const; const NetNet*return_sig() const;
@ -3243,6 +3245,7 @@ class NetFuncDef {
NetProc*statement_; NetProc*statement_;
NetNet*result_sig_; NetNet*result_sig_;
std::vector<NetNet*>ports_; std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_;
}; };
/* /*
@ -3375,7 +3378,8 @@ class NetSTask : public NetProc {
class NetTaskDef { class NetTaskDef {
public: public:
NetTaskDef(NetScope*n, const vector<NetNet*>&po); NetTaskDef(NetScope*n, const vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetTaskDef(); ~NetTaskDef();
void set_proc(NetProc*p); void set_proc(NetProc*p);
@ -3386,6 +3390,7 @@ class NetTaskDef {
unsigned port_count() const; unsigned port_count() const;
NetNet*port(unsigned idx) const; NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
void dump(ostream&, unsigned) const; void dump(ostream&, unsigned) const;
DelayType delay_type() const; DelayType delay_type() const;
@ -3393,7 +3398,8 @@ class NetTaskDef {
private: private:
NetScope*scope_; NetScope*scope_;
NetProc*proc_; NetProc*proc_;
vector<NetNet*>ports_; std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_; // Default expressions for ports.
private: // not implemented private: // not implemented
NetTaskDef(const NetTaskDef&); NetTaskDef(const NetTaskDef&);