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 <list>
|
||||
class Design;
|
||||
class NetExpr;
|
||||
class NetNet;
|
||||
class NetScope;
|
||||
class PWire;
|
||||
|
|
@ -48,8 +49,12 @@ class PTaskFunc : public PScope, public LineInfo {
|
|||
inline class_type_t* method_of() const { return this_type_; }
|
||||
|
||||
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,
|
||||
std::vector<NetNet*>&ports) const;
|
||||
std::vector<NetNet*>&ports,
|
||||
std::vector<NetExpr*>&pdefs) const;
|
||||
|
||||
void dump_ports_(std::ostream&out, unsigned ind) const;
|
||||
|
||||
|
|
|
|||
44
elab_expr.cc
44
elab_expr.cc
|
|
@ -4586,37 +4586,53 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
|||
NetFuncDef*def = new_scope->func_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"
|
||||
<< " passing " << parms_.size() << " arguments "
|
||||
<< " to constructor expecting " << (def->port_count()-1)
|
||||
<< " arguments." << endl;
|
||||
des->errors += 1;
|
||||
return obj;
|
||||
}
|
||||
|
||||
vector<NetExpr*> parms (1 + parms_.size());
|
||||
vector<NetExpr*> parms (def->port_count());
|
||||
parms[0] = obj;
|
||||
|
||||
int missing_parms = 0;
|
||||
int parm_errors = 0;
|
||||
for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
size_t pidx = idx + 1;
|
||||
for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
|
||||
// While there are default arguments, check them.
|
||||
if (idx <= parms_.size()) {
|
||||
PExpr*tmp = parms_[idx-1];
|
||||
if (tmp == 0) {
|
||||
parms[idx] = 0;
|
||||
missing_parms += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
parms[idx] = elaborate_rval_expr(des, scope, def->port(idx)->data_type(),
|
||||
def->port(idx)->vector_width(),
|
||||
tmp, false);
|
||||
if (parms[idx] == 0)
|
||||
parm_errors += 1;
|
||||
|
||||
if (tmp == 0) {
|
||||
parms[pidx] = 0;
|
||||
missing_parms += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
parms[pidx] = elaborate_rval_expr(des, scope, def->port(pidx)->data_type(),
|
||||
def->port(pidx)->vector_width(),
|
||||
tmp, false);
|
||||
if (parms[pidx] == 0) {
|
||||
parm_errors += 1;
|
||||
// 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) {
|
||||
|
|
|
|||
34
elab_sig.cc
34
elab_sig.cc
|
|
@ -596,10 +596,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
vector<NetNet*>ports;
|
||||
elaborate_sig_ports_(des, scope, ports);
|
||||
vector<NetExpr*>pdef;
|
||||
elaborate_sig_ports_(des, scope, ports, pdef);
|
||||
|
||||
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);
|
||||
if (debug_elaborate)
|
||||
|
|
@ -630,8 +631,9 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
vector<NetNet*>ports;
|
||||
elaborate_sig_ports_(des, scope, ports);
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
vector<NetExpr*>pdefs;
|
||||
elaborate_sig_ports_(des, scope, ports, pdefs);
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports, pdefs);
|
||||
scope->set_task_def(def);
|
||||
|
||||
// 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,
|
||||
vector<NetNet*>&ports) const
|
||||
vector<NetNet*>&ports, vector<NetExpr*>&pdefs) const
|
||||
{
|
||||
if (ports_ == 0) {
|
||||
ports.clear();
|
||||
pdefs.clear();
|
||||
|
||||
/* Make sure the function has at least one input
|
||||
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());
|
||||
pdefs.resize(ports_->size());
|
||||
|
||||
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
|
||||
|
||||
perm_string port_name = ports_->at(idx).port->basename();
|
||||
|
||||
ports[idx] = 0;
|
||||
pdefs[idx] = 0;
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
NetExpr*tmp_def = 0;
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "task/function " << scope_path(scope)
|
||||
|
|
@ -678,11 +684,18 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
|||
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) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "task/function default port expressions not supported."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, -1, true);
|
||||
if (tmp_def==0) {
|
||||
cerr << get_fileline() << ": error: Unable to evaluate "
|
||||
<< *ports_->at(idx).defe
|
||||
<< " as a port default (constant) expression." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
|
|
@ -696,11 +709,12 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
pdefs[idx] = tmp_def;
|
||||
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Function " << scope_path(scope)
|
||||
<< " port " << port_name
|
||||
<< " is not an inputport." << endl;
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : "
|
||||
<< "Function arguments must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
|
|
|
|||
21
netlist.cc
21
netlist.cc
|
|
@ -2043,8 +2043,9 @@ verinum::V NetConst::value(unsigned idx) const
|
|||
return value_[idx];
|
||||
}
|
||||
|
||||
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po)
|
||||
: scope_(s), statement_(0), result_sig_(result), ports_(po)
|
||||
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&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];
|
||||
}
|
||||
|
||||
NetExpr* NetFuncDef::port_defe(unsigned idx) const
|
||||
{
|
||||
assert(idx < pdefaults_.size());
|
||||
return pdefaults_[idx];
|
||||
}
|
||||
|
||||
const NetNet* NetFuncDef::return_sig() const
|
||||
{
|
||||
return result_sig_;
|
||||
|
|
@ -2620,8 +2627,8 @@ unsigned NetUReduce::width() const
|
|||
return width_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po)
|
||||
: scope_(n), proc_(0), ports_(po)
|
||||
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
|
||||
: scope_(n), proc_(0), ports_(po), pdefaults_(pd)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -2647,6 +2654,12 @@ NetNet* NetTaskDef::port(unsigned idx) const
|
|||
return ports_[idx];
|
||||
}
|
||||
|
||||
NetExpr* NetTaskDef::port_defe(unsigned idx) const
|
||||
{
|
||||
assert(idx < pdefaults_.size());
|
||||
return pdefaults_[idx];
|
||||
}
|
||||
|
||||
const NetScope* NetTaskDef::scope() const
|
||||
{
|
||||
return scope_;
|
||||
|
|
|
|||
12
netlist.h
12
netlist.h
|
|
@ -3215,7 +3215,8 @@ class NetFree : public NetProc {
|
|||
class NetFuncDef {
|
||||
|
||||
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();
|
||||
|
||||
void set_proc(NetProc*st);
|
||||
|
|
@ -3227,6 +3228,7 @@ class NetFuncDef {
|
|||
|
||||
unsigned port_count() const;
|
||||
const NetNet*port(unsigned idx) const;
|
||||
NetExpr*port_defe(unsigned idx) const;
|
||||
|
||||
const NetNet*return_sig() const;
|
||||
|
||||
|
|
@ -3243,6 +3245,7 @@ class NetFuncDef {
|
|||
NetProc*statement_;
|
||||
NetNet*result_sig_;
|
||||
std::vector<NetNet*>ports_;
|
||||
std::vector<NetExpr*>pdefaults_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -3375,7 +3378,8 @@ class NetSTask : public NetProc {
|
|||
class NetTaskDef {
|
||||
|
||||
public:
|
||||
NetTaskDef(NetScope*n, const vector<NetNet*>&po);
|
||||
NetTaskDef(NetScope*n, const vector<NetNet*>&po,
|
||||
const std::vector<NetExpr*>&pd);
|
||||
~NetTaskDef();
|
||||
|
||||
void set_proc(NetProc*p);
|
||||
|
|
@ -3386,6 +3390,7 @@ class NetTaskDef {
|
|||
|
||||
unsigned port_count() const;
|
||||
NetNet*port(unsigned idx) const;
|
||||
NetExpr*port_defe(unsigned idx) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
DelayType delay_type() const;
|
||||
|
|
@ -3393,7 +3398,8 @@ class NetTaskDef {
|
|||
private:
|
||||
NetScope*scope_;
|
||||
NetProc*proc_;
|
||||
vector<NetNet*>ports_;
|
||||
std::vector<NetNet*>ports_;
|
||||
std::vector<NetExpr*>pdefaults_; // Default expressions for ports.
|
||||
|
||||
private: // not implemented
|
||||
NetTaskDef(const NetTaskDef&);
|
||||
|
|
|
|||
Loading…
Reference in New Issue