Support functions that return void.
This commit is contained in:
parent
a9a1c50268
commit
7bc94d7810
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
16
elab_lval.cc
16
elab_lval.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
28
elab_sig.cc
28
elab_sig.cc
|
|
@ -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 "
|
||||
|
|
|
|||
14
elaborate.cc
14
elaborate.cc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
93
netlist.cc
93
netlist.cc
|
|
@ -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.
|
||||
|
|
|
|||
62
netlist.h
62
netlist.h
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue