Handle default arguments in class new functions.
This commit is contained in:
parent
9a116498a2
commit
16414f921f
7
PTask.h
7
PTask.h
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
38
elab_expr.cc
38
elab_expr.cc
|
|
@ -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) {
|
||||||
|
|
|
||||||
32
elab_sig.cc
32
elab_sig.cc
|
|
@ -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;
|
||||||
|
|
|
||||||
21
netlist.cc
21
netlist.cc
|
|
@ -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_;
|
||||||
|
|
|
||||||
12
netlist.h
12
netlist.h
|
|
@ -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&);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue