Support functions that return void.

This commit is contained in:
Stephen Williams 2013-09-18 18:48:16 -07:00
parent a9a1c50268
commit 7bc94d7810
8 changed files with 139 additions and 133 deletions

View File

@ -755,12 +755,13 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
void NetTaskDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
o << setw(ind) << "" << "task " << scope_path(scope()) << ";" << endl;
for (unsigned idx = 0 ; idx < ports_.size() ; idx += 1) {
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
const NetNet*pnet = port(idx);
o << setw(ind+4) << "";
assert(ports_[idx]);
switch (ports_[idx]->port_type()) {
assert(pnet);
switch (pnet->port_type()) {
case NetNet::PINPUT:
o << "input ";
break;
@ -774,7 +775,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
o << "NOT_A_PORT ";
break;
}
o << ports_[idx]->name() << ";" << endl;
o << pnet->name() << ";" << endl;
}
if (proc_)
@ -1129,7 +1130,7 @@ void NetFree::dump(ostream&o, unsigned ind) const
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
o << setw(ind) << "" << "function definition for " << scope_path(scope()) << endl;
if (result_sig_) {
o << setw(ind+2) << "" << "Return signal: ";
if (result_sig_->get_signed()) o << "+";
@ -1157,8 +1158,8 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
if (port(idx)->get_signed()) o << "+";
o << port(idx)->name() << endl;
}
if (statement_)
statement_->dump(o, ind+2);
if (proc_)
proc_->dump(o, ind+2);
else
o << setw(ind+2) << "" << "MISSING PROCEDURAL CODE" << endl;
}

View File

@ -200,10 +200,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
}
if (reg == 0) {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(use_scope) <<
"''" << endl;
if (use_scope->type()==NetScope::FUNC
&& use_scope->func_def()->return_sig()==0
&& use_scope->basename()==peek_tail_name(path_)) {
cerr << get_fileline() << ": error: "
<< "Cannot assign to " << path_
<< " because function " << scope_path(use_scope)
<< " is void." << endl;
} else {
cerr << get_fileline() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(use_scope) <<
"''" << endl;
}
des->errors += 1;
return 0;
}

View File

@ -582,27 +582,39 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ivl_type_t ret_type;
if (return_type_) {
ret_type = return_type_->elaborate_type(des, scope);
if (dynamic_cast<const struct void_type_t*> (return_type_)) {
ret_type = 0;
} else {
ret_type = return_type_->elaborate_type(des, scope);
ivl_assert(*this, ret_type);
}
} else {
netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
tmp->set_scalar(true);
ret_type = tmp;
}
list<netrange_t> ret_unpacked;
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
if (ret_type) {
list<netrange_t> ret_unpacked;
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type);
ret_sig->set_line(*this);
ret_sig->port_type(NetNet::POUTPUT);
} else {
ret_sig = 0;
if (debug_elaborate) {
cerr << get_fileline() << ": PFunction::elaborate_sig: "
<< "Detected that function is void." << endl;
}
}
}
vector<NetNet*>ports;
vector<NetExpr*>pdef;
elaborate_sig_ports_(des, scope, ports, pdef);
NetFuncDef*def = 0;
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports, pdef);
NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef);
assert(def);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Attach function definition to scope "

View File

@ -3381,7 +3381,19 @@ NetProc* PCallTask::elaborate_function_(Design*des, NetScope*scope) const
NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const
{
NetTaskDef*def = task->task_def();
NetBaseDef*def = 0;
if (task->type() == NetScope::TASK) {
def = task->task_def();
} else if (task->type() == NetScope::FUNC) {
NetFuncDef*tmp = task->func_def();
if (tmp->return_sig() != 0) {
cerr << get_fileline() << ": error: "
<< "Calling a non-void function as a task." << endl;
des->errors += 1;
}
def = tmp;
}
/* The caller has checked the parms_ size to make sure it
matches the task definition, so we can just use the task

View File

@ -61,21 +61,22 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Evaluate function " << scope_->basename() << endl;
<< "Evaluate function " << scope()->basename() << endl;
}
// Put the return value into the map...
LocalVar&return_var = context_map[scope_->basename()];
LocalVar&return_var = context_map[scope()->basename()];
return_var.nwords = 0;
return_var.value = 0;
// Load the input ports into the map...
ivl_assert(loc, ports_.size() == args.size());
for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
perm_string aname = ports_[idx]->name();
ivl_assert(loc, port_count() == args.size());
for (size_t idx = 0 ; idx < port_count() ; idx += 1) {
const NetNet*pnet = port(idx);
perm_string aname = pnet->name();
LocalVar&input_var = context_map[aname];
input_var.nwords = 0;
input_var.value = fix_assign_value(ports_[idx], args[idx]);
input_var.value = fix_assign_value(pnet, args[idx]);
if (debug_eval_tree) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
@ -85,26 +86,26 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
// Ask the scope to collect definitions for local values. This
// fills in the context_map with local variables held by the scope.
scope_->evaluate_function_find_locals(loc, context_map);
scope()->evaluate_function_find_locals(loc, context_map);
if (debug_eval_tree && statement_==0) {
if (debug_eval_tree && proc_==0) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Function " << scope_path(scope_)
<< "Function " << scope_path(scope())
<< " has no statement?" << endl;
}
// Perform the evaluation. Note that if there were errors
// when compiling the function definition, we may not have
// a valid statement.
bool flag = statement_ && statement_->evaluate_function(loc, context_map);
bool flag = proc_ && proc_->evaluate_function(loc, context_map);
if (debug_eval_tree && !flag) {
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "Cannot evaluate " << scope_path(scope_) << "." << endl;
<< "Cannot evaluate " << scope_path(scope()) << "." << endl;
}
// Extract the result...
ptr = context_map.find(scope_->basename());
ptr = context_map.find(scope()->basename());
NetExpr*res = ptr->second.value;
context_map.erase(ptr);
@ -127,9 +128,9 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
if (debug_eval_tree)
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
<< "disable of " << scope_path(disable)
<< " trapped in function " << scope_path(scope_)
<< " trapped in function " << scope_path(scope())
<< "." << endl;
ivl_assert(loc, disable==scope_);
ivl_assert(loc, disable==scope());
disable = 0;
}

View File

@ -2043,55 +2043,65 @@ verinum::V NetConst::value(unsigned idx) const
return value_[idx];
}
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)
NetBaseDef::NetBaseDef(NetScope*s, const vector<NetNet*>&po, const std::vector<NetExpr*>&pd)
: scope_(s), ports_(po), pdefaults_(pd)
{
proc_ = 0;
}
NetBaseDef::~NetBaseDef()
{
}
NetFuncDef::~NetFuncDef()
{
}
const NetScope* NetFuncDef::scope() const
const NetScope* NetBaseDef::scope() const
{
return scope_;
}
void NetFuncDef::set_proc(NetProc*st)
{
assert(statement_ == 0);
assert(st != 0);
statement_ = st;
}
const NetProc* NetFuncDef::proc() const
{
return statement_;
}
NetScope*NetFuncDef::scope()
NetScope*NetBaseDef::scope()
{
return scope_;
}
unsigned NetFuncDef::port_count() const
unsigned NetBaseDef::port_count() const
{
return ports_.size();
}
const NetNet* NetFuncDef::port(unsigned idx) const
NetNet* NetBaseDef::port(unsigned idx) const
{
assert(idx < ports_.size());
return ports_[idx];
}
NetExpr* NetFuncDef::port_defe(unsigned idx) const
NetExpr* NetBaseDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
void NetBaseDef::set_proc(NetProc*st)
{
assert(proc_ == 0);
assert(st != 0);
proc_ = st;
}
const NetProc* NetBaseDef::proc() const
{
return proc_;
}
NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const vector<NetNet*>&po,
const vector<NetExpr*>&pd)
: NetBaseDef(s, po, pd), result_sig_(result)
{
}
NetFuncDef::~NetFuncDef()
{
}
const NetNet* NetFuncDef::return_sig() const
{
return result_sig_;
@ -2628,7 +2638,7 @@ unsigned NetUReduce::width() const
}
NetTaskDef::NetTaskDef(NetScope*n, const vector<NetNet*>&po, const vector<NetExpr*>&pd)
: scope_(n), proc_(0), ports_(po), pdefaults_(pd)
: NetBaseDef(n, po, pd)
{
}
@ -2637,39 +2647,6 @@ NetTaskDef::~NetTaskDef()
delete proc_;
}
void NetTaskDef::set_proc(NetProc*p)
{
assert(proc_ == 0);
proc_ = p;
}
unsigned NetTaskDef::port_count() const
{
return ports_.size();
}
NetNet* NetTaskDef::port(unsigned idx) const
{
assert(idx < ports_.size());
return ports_[idx];
}
NetExpr* NetTaskDef::port_defe(unsigned idx) const
{
assert(idx < pdefaults_.size());
return pdefaults_[idx];
}
const NetScope* NetTaskDef::scope() const
{
return scope_;
}
const NetProc*NetTaskDef::proc() const
{
return proc_;
}
/*
* These are the delay_type() functions. They are used to determine
* the type of delay for the given object.

View File

@ -791,6 +791,33 @@ struct LocalVar {
};
};
class NetBaseDef {
public:
NetBaseDef(NetScope*n, const vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
virtual ~NetBaseDef();
const NetScope*scope() const;
NetScope*scope();
unsigned port_count() const;
NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
void set_proc(NetProc*p);
//const string& name() const;
const NetProc*proc() const;
private:
NetScope*scope_;
std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_;
protected:
NetProc*proc_;
};
/*
* This object type is used to contain a logical scope within a
* design. The scope doesn't represent any executable hardware, but is
@ -3212,24 +3239,13 @@ class NetFree : public NetProc {
* signals that make up its parameter list. These are all internal to
* the scope of the function.
*/
class NetFuncDef {
class NetFuncDef : public NetBaseDef {
public:
NetFuncDef(NetScope*, NetNet*result, const std::vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetFuncDef();
void set_proc(NetProc*st);
//const string name() const;
const NetProc*proc() const;
const NetScope*scope() const;
NetScope*scope();
unsigned port_count() const;
const NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
const NetNet*return_sig() const;
// When we want to evaluate the function during compile time,
@ -3241,11 +3257,7 @@ class NetFuncDef {
void dump(ostream&, unsigned ind) const;
private:
NetScope*scope_;
NetProc*statement_;
NetNet*result_sig_;
std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_;
};
/*
@ -3375,32 +3387,16 @@ class NetSTask : public NetProc {
* output and inout variables. The variables accessible as ports are
* also elaborated and accessible as ordinary reg objects.
*/
class NetTaskDef {
class NetTaskDef : public NetBaseDef {
public:
NetTaskDef(NetScope*n, const vector<NetNet*>&po,
const std::vector<NetExpr*>&pd);
~NetTaskDef();
void set_proc(NetProc*p);
//const string& name() const;
const NetScope* scope() const;
const NetProc*proc() const;
unsigned port_count() const;
NetNet*port(unsigned idx) const;
NetExpr*port_defe(unsigned idx) const;
void dump(ostream&, unsigned) const;
DelayType delay_type() const;
private:
NetScope*scope_;
NetProc*proc_;
std::vector<NetNet*>ports_;
std::vector<NetExpr*>pdefaults_; // Default expressions for ports.
private: // not implemented
NetTaskDef(const NetTaskDef&);
NetTaskDef& operator= (const NetTaskDef&);

View File

@ -121,16 +121,15 @@ bool dll_target::func_def(const NetScope*net)
is *not* correct. Someday, I'm going to have to change
this, but that will break code generators that use this
result. */
if (const NetNet*ret_sig = def->return_sig()) {
if (const NetNet*ret_sig = def->return_sig())
scop->u_.port[0] = find_signal(des_, ret_sig);
return true;
}
else
scop->u_.port[0] = 0;
cerr << "?:0" << ": internal error: "
<< "Function " << net->basename() << " has a return type"
<< " that I do not understand." << endl;
/* If there is no return value, then this is a void function. */
return true;
return false;
}
/*