Handle recursive functions and arbitrary function

references to other functions, properly pass
 function parameters and save function results.
This commit is contained in:
steve 1999-09-01 20:46:19 +00:00
parent 5ee83fce70
commit 9f7eb4a935
6 changed files with 204 additions and 51 deletions

12
PTask.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: PTask.h,v 1.4 1999/08/25 22:22:41 steve Exp $" #ident "$Id: PTask.h,v 1.5 1999/09/01 20:46:19 steve Exp $"
#endif #endif
# include "LineInfo.h" # include "LineInfo.h"
@ -63,7 +63,10 @@ class PFunction : public LineInfo {
void set_output(PWire*); void set_output(PWire*);
virtual void elaborate(Design *des, const string &path) const; /* Functions are elaborated in 2 passes. */
virtual void elaborate_1(Design *des, const string &path) const;
virtual void elaborate_2(Design *des, const string &path) const;
void dump(ostream&, unsigned) const; void dump(ostream&, unsigned) const;
private: private:
@ -74,6 +77,11 @@ class PFunction : public LineInfo {
/* /*
* $Log: PTask.h,v $ * $Log: PTask.h,v $
* Revision 1.5 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.4 1999/08/25 22:22:41 steve * Revision 1.4 1999/08/25 22:22:41 steve
* elaborate some aspects of functions. * elaborate some aspects of functions.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: design_dump.cc,v 1.36 1999/08/31 22:38:29 steve Exp $" #ident "$Id: design_dump.cc,v 1.37 1999/09/01 20:46:19 steve Exp $"
#endif #endif
/* /*
@ -427,7 +427,10 @@ void NetForever::dump(ostream&o, unsigned ind) const
void NetFuncDef::dump(ostream&o, unsigned ind) const void NetFuncDef::dump(ostream&o, unsigned ind) const
{ {
o << setw(ind) << "" << "function " << name_ << endl; o << setw(ind) << "" << "function " << name_ << endl;
statement_->dump(o, ind+2); if (statement_)
statement_->dump(o, ind+2);
else
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
} }
void NetPDelay::dump(ostream&o, unsigned ind) const void NetPDelay::dump(ostream&o, unsigned ind) const
@ -719,6 +722,11 @@ void Design::dump(ostream&o) const
/* /*
* $Log: design_dump.cc,v $ * $Log: design_dump.cc,v $
* Revision 1.37 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.36 1999/08/31 22:38:29 steve * Revision 1.36 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions. * Elaborate and emit to vvm procedural functions.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.74 1999/08/31 22:38:29 steve Exp $" #ident "$Id: elaborate.cc,v 1.75 1999/09/01 20:46:19 steve Exp $"
#endif #endif
/* /*
@ -736,7 +736,13 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path,
NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const
{ {
string myname = path+"."+name_; string myname = path+"."+name_;
NetFuncDef*def = des->find_function(myname); NetFuncDef*def = des->find_function(path, name_);
if (def == 0) {
cerr << get_line() << ": No function " << name_ <<
" in this context (" << path << ")." << endl;
des->errors += 1;
return 0;
}
assert(def); assert(def);
svector<NetExpr*> parms (parms_.count()); svector<NetExpr*> parms (parms_.count());
@ -745,7 +751,17 @@ NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const
parms[idx] = tmp; parms[idx] = tmp;
} }
NetNet*res = des->find_signal(myname, name_); /* Look for the return value signal for the called function in
the context of the function definition, not my context. */
NetNet*res = des->find_signal(def->name(), name_);
if (res == 0) {
cerr << get_line() << ": INTERNAL ERROR: Unable to locate "
"function return value for " << name_ << " in " <<
def->name() << "." << endl;
des->errors += 1;
return 0;
}
assert(res); assert(res);
NetESignal*eres = new NetESignal(res); NetESignal*eres = new NetESignal(res);
assert(eres); assert(eres);
@ -1887,16 +1903,16 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
return top; return top;
} }
void PFunction::elaborate(Design*des, const string&path) const /*
* Elaborating function definitions takes 2 passes. The first creates
* the NetFuncDef object and attaches the ports to it. The second pass
* (elaborate_2) elaborates the statement that is contained
* within. These passes are needed because the statement may invoke
* the function itself (or other functions) so can't be elaborated
* until all the functions are partially elaborated.
*/
void PFunction::elaborate_1(Design*des, const string&path) const
{ {
NetProc*st = statement_->elaborate(des, path);
if (st == 0) {
cerr << statement_->get_line() << ": Unable to elaborate "
"statement in function " << path << " at " << get_line()
<< "." << endl;
return;
}
/* Translate the wires that are ports to NetNet pointers by /* Translate the wires that are ports to NetNet pointers by
presuming that the name is already elaborated, and look it presuming that the name is already elaborated, and look it
up in the design. Then save that pointer for later use by up in the design. Then save that pointer for later use by
@ -1910,11 +1926,26 @@ void PFunction::elaborate(Design*des, const string&path) const
ports[idx+1] = tmp; ports[idx+1] = tmp;
} }
NetFuncDef*def = new NetFuncDef(path, ports);
NetFuncDef*def = new NetFuncDef(path, st, ports);
des->add_function(path, def); des->add_function(path, def);
} }
void PFunction::elaborate_2(Design*des, const string&path) const
{
NetFuncDef*def = des->find_function(path);
assert(def);
NetProc*st = statement_->elaborate(des, path);
if (st == 0) {
cerr << statement_->get_line() << ": Unable to elaborate "
"statement in function " << path << "." << endl;
des->errors += 1;
return;
}
def->set_proc(st);
}
NetProc* PRepeat::elaborate(Design*des, const string&path) const NetProc* PRepeat::elaborate(Design*des, const string&path) const
{ {
NetExpr*expr = expr_->elaborate_expr(des, path); NetExpr*expr = expr_->elaborate_expr(des, path);
@ -2036,10 +2067,17 @@ bool Module::elaborate(Design*des, const string&path, svector<PExpr*>*overrides_
// Elaborate functions. // Elaborate functions.
typedef map<string,PFunction*>::const_iterator mfunc_it_t; typedef map<string,PFunction*>::const_iterator mfunc_it_t;
for (mfunc_it_t cur = funcs_.begin() for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) { ; cur != funcs_.end() ; cur ++) {
string pname = path + "." + (*cur).first; string pname = path + "." + (*cur).first;
(*cur).second->elaborate(des, pname); (*cur).second->elaborate_1(des, pname);
}
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
string pname = path + "." + (*cur).first;
(*cur).second->elaborate_2(des, pname);
} }
// Elaborate the task definitions. This is done before the // Elaborate the task definitions. This is done before the
@ -2127,6 +2165,11 @@ Design* elaborate(const map<string,Module*>&modules,
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.75 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.74 1999/08/31 22:38:29 steve * Revision 1.74 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions. * Elaborate and emit to vvm procedural functions.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.54 1999/08/31 22:38:29 steve Exp $" #ident "$Id: netlist.cc,v 1.55 1999/09/01 20:46:19 steve Exp $"
#endif #endif
# include <cassert> # include <cassert>
@ -482,8 +482,8 @@ NetProc* NetCondit::else_clause()
return else_; return else_;
} }
NetFuncDef::NetFuncDef(const string&n, NetProc*st, const svector<NetNet*>&po) NetFuncDef::NetFuncDef(const string&n, const svector<NetNet*>&po)
: name_(n), statement_(st), ports_(po) : name_(n), statement_(0), ports_(po)
{ {
} }
@ -496,11 +496,29 @@ const string& NetFuncDef::name() const
return name_; return name_;
} }
void NetFuncDef::set_proc(NetProc*st)
{
assert(statement_ == 0);
assert(st != 0);
statement_ = st;
}
const NetProc* NetFuncDef::proc() const const NetProc* NetFuncDef::proc() const
{ {
return statement_; return statement_;
} }
unsigned NetFuncDef::port_count() const
{
return ports_.count();
}
const NetNet* NetFuncDef::port(unsigned idx) const
{
assert(idx < ports_.count());
return ports_[idx];
}
NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe) NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe)
: NetNode(ev, wid), sref<NetPEvent,NetNEvent>(pe), edge_(e) : NetNode(ev, wid), sref<NetPEvent,NetNEvent>(pe), edge_(e)
{ {
@ -560,6 +578,7 @@ const NetExpr* NetSTask::parm(unsigned idx) const
NetEUFunc::NetEUFunc(NetFuncDef*def, NetESignal*res, svector<NetExpr*>&p) NetEUFunc::NetEUFunc(NetFuncDef*def, NetESignal*res, svector<NetExpr*>&p)
: func_(def), result_(res), parms_(p) : func_(def), result_(res), parms_(p)
{ {
expr_width(result_->expr_width());
} }
NetEUFunc::~NetEUFunc() NetEUFunc::~NetEUFunc()
@ -578,6 +597,22 @@ const NetESignal*NetEUFunc::result() const
return result_; return result_;
} }
unsigned NetEUFunc::parm_count() const
{
return parms_.count();
}
const NetExpr* NetEUFunc::parm(unsigned idx) const
{
assert(idx < parms_.count());
return parms_[idx];
}
const NetFuncDef* NetEUFunc::definition() const
{
return func_;
}
/* /*
* XXXX FIX ME: For now, just take whatever the caller says as my * XXXX FIX ME: For now, just take whatever the caller says as my
* width. What I really need to do is note the width of the output * width. What I really need to do is note the width of the output
@ -1501,13 +1536,31 @@ void Design::add_function(const string&key, NetFuncDef*def)
funcs_[key] = def; funcs_[key] = def;
} }
NetFuncDef* Design::find_function(const string&path, const string&name)
{
string root = path;
for (;;) {
string key = root + "." + name;
map<string,NetFuncDef*>::const_iterator cur = funcs_.find(key);
if (cur != funcs_.end())
return (*cur).second;
unsigned pos = root.rfind('.');
if (pos > root.length())
break;
root = root.substr(0, pos);
}
return 0;
}
NetFuncDef* Design::find_function(const string&key) NetFuncDef* Design::find_function(const string&key)
{ {
map<string,NetFuncDef*>::const_iterator cur = funcs_.find(key); map<string,NetFuncDef*>::const_iterator cur = funcs_.find(key);
if (cur == funcs_.end()) if (cur != funcs_.end())
return 0; return (*cur).second;
return 0;
return (*cur).second;
} }
void Design::add_task(const string&key, NetTaskDef*def) void Design::add_task(const string&key, NetTaskDef*def)
@ -1642,6 +1695,11 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/* /*
* $Log: netlist.cc,v $ * $Log: netlist.cc,v $
* Revision 1.55 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.54 1999/08/31 22:38:29 steve * Revision 1.54 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions. * Elaborate and emit to vvm procedural functions.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: netlist.h,v 1.58 1999/08/31 22:38:29 steve Exp $" #ident "$Id: netlist.h,v 1.59 1999/09/01 20:46:19 steve Exp $"
#endif #endif
/* /*
@ -768,12 +768,17 @@ class NetForever : public NetProc {
class NetFuncDef { class NetFuncDef {
public: public:
NetFuncDef(const string&, NetProc*st, const svector<NetNet*>&po); NetFuncDef(const string&, const svector<NetNet*>&po);
~NetFuncDef(); ~NetFuncDef();
void set_proc(NetProc*st);
const string& name() const; const string& name() const;
const NetProc*proc() const; const NetProc*proc() const;
unsigned port_count() const;
const NetNet*port(unsigned idx) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
private: private:
@ -951,6 +956,10 @@ class NetEUFunc : public NetExpr {
const string& name() const; const string& name() const;
const NetESignal*result() const; const NetESignal*result() const;
unsigned parm_count() const;
const NetExpr* parm(unsigned idx) const;
const NetFuncDef* definition() const;
virtual bool set_width(unsigned); virtual bool set_width(unsigned);
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
@ -1402,7 +1411,8 @@ class Design {
// Functions // Functions
void add_function(const string&n, NetFuncDef*); void add_function(const string&n, NetFuncDef*);
NetFuncDef* find_function(const string&key); NetFuncDef* find_function(const string&path, const string&key);
NetFuncDef* find_function(const string&path);
// Tasks // Tasks
void add_task(const string&n, NetTaskDef*); void add_task(const string&n, NetTaskDef*);
@ -1508,6 +1518,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.59 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.58 1999/08/31 22:38:29 steve * Revision 1.58 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions. * Elaborate and emit to vvm procedural functions.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.36 1999/08/31 22:38:29 steve Exp $" #ident "$Id: t-vvm.cc,v 1.37 1999/09/01 20:46:19 steve Exp $"
#endif #endif
# include <iostream> # include <iostream>
@ -206,11 +206,38 @@ void vvm_proc_rval::expr_subsignal(const NetESubSignal*sig)
result = val; result = val;
} }
/*
* A function call is handled by assigning the parameters from the
* input expressions, then calling the function. After the function
* returns, copy the result into a temporary variable.
*
* Function calls are different from tasks in this regard--tasks had
* all this assigning arranged during elaboration. For functions, we
* must do it ourselves.
*/
void vvm_proc_rval::expr_ufunc(const NetEUFunc*expr) void vvm_proc_rval::expr_ufunc(const NetEUFunc*expr)
{ {
string name = mangle(expr->name()); const NetFuncDef*def = expr->definition();
os_ << " " << name << "(sim_);" << endl; const unsigned pcnt = expr->parm_count();
result = mangle(expr->result()->name()) + "_bits"; assert(pcnt == (def->port_count()-1));
/* Scan the parameter expressions, and assign the values to
the parameter port register. */
for (unsigned idx = 0 ; idx < pcnt ; idx += 1) {
expr->parm(idx)->expr_scan(this);
os_ << " " << mangle(def->port(idx+1)->name()) <<
"_bits = " << result << ";" << endl;
}
/* Make the function call. */
os_ << " " << mangle(expr->name()) << "(sim_);" << endl;
/* Save the return value in a temporary. */
result = make_temp();
string rbits = mangle(expr->result()->name()) + "_bits";
os_ << " vvm_bitset_t<" << expr->expr_width() << "> " <<
result << " = " << rbits << ";" << endl;
} }
void vvm_proc_rval::expr_unary(const NetEUnary*expr) void vvm_proc_rval::expr_unary(const NetEUnary*expr)
@ -537,10 +564,13 @@ void target_vvm::func_def(ostream&os, const NetFuncDef*def)
thread_step_ = 0; thread_step_ = 0;
const string name = mangle(def->name()); const string name = mangle(def->name());
os << "// Function " << def->name() << endl; os << "// Function " << def->name() << endl;
os << "static void " << name << "(vvm_simulation*sim_)" << endl; os << "static void " << name << "(vvm_simulation*);" << endl;
os << "{" << endl;
def->proc()->emit_proc(os, this); delayed << "// Function " << def->name() << endl;
os << "}" << endl; delayed << "static void " << name << "(vvm_simulation*sim_)" << endl;
delayed << "{" << endl;
def->proc()->emit_proc(delayed, this);
delayed << "}" << endl;
} }
/* /*
@ -1191,19 +1221,6 @@ void target_vvm::proc_stask(ostream&os, const NetSTask*net)
{ {
string ptmp = make_temp(); string ptmp = make_temp();
#if 0
os << " struct __vpiHandle " << ptmp << "[" <<
net->nparms() << "];" << endl;
for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1)
if (net->parm(idx)) {
string val = emit_parm_rval(os, net->parm(idx));
os << " vvm_make_vpi_parm(&" << ptmp << "["
<< idx << "], " << val << ");" << endl;
} else {
os << " vvm_make_vpi_parm(&" << ptmp << "["
<< idx << "]);" << endl;
}
#else
os << " vpiHandle " << ptmp << "[" << net->nparms() << os << " vpiHandle " << ptmp << "[" << net->nparms() <<
"];" << endl; "];" << endl;
for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) { for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) {
@ -1221,7 +1238,6 @@ void target_vvm::proc_stask(ostream&os, const NetSTask*net)
os << " " << ptmp << "[" << idx << "] = " << val << ";" os << " " << ptmp << "[" << idx << "] = " << val << ";"
<< endl; << endl;
} }
#endif
os << " vvm_calltask(sim_, \"" << net->name() << "\", " << os << " vvm_calltask(sim_, \"" << net->name() << "\", " <<
net->nparms() << ", " << ptmp << ");" << endl; net->nparms() << ", " << ptmp << ");" << endl;
@ -1385,6 +1401,11 @@ extern const struct target tgt_vvm = {
}; };
/* /*
* $Log: t-vvm.cc,v $ * $Log: t-vvm.cc,v $
* Revision 1.37 1999/09/01 20:46:19 steve
* Handle recursive functions and arbitrary function
* references to other functions, properly pass
* function parameters and save function results.
*
* Revision 1.36 1999/08/31 22:38:29 steve * Revision 1.36 1999/08/31 22:38:29 steve
* Elaborate and emit to vvm procedural functions. * Elaborate and emit to vvm procedural functions.
* *