Handle recursive functions and arbitrary function
references to other functions, properly pass function parameters and save function results.
This commit is contained in:
parent
5ee83fce70
commit
9f7eb4a935
12
PTask.h
12
PTask.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "LineInfo.h"
|
||||
|
|
@ -63,7 +63,10 @@ class PFunction : public LineInfo {
|
|||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -74,6 +77,11 @@ class PFunction : public LineInfo {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -427,7 +427,10 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
|||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function " << name_ << endl;
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
|
||||
}
|
||||
|
||||
void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
|
|
@ -719,6 +722,11 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
|
|
|
|||
73
elaborate.cc
73
elaborate.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -736,7 +736,13 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path,
|
|||
NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
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);
|
||||
svector<NetExpr*> parms (parms_.count());
|
||||
|
||||
|
|
@ -745,7 +751,17 @@ NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
|||
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);
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
assert(eres);
|
||||
|
|
@ -1887,16 +1903,16 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
|||
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
|
||||
presuming that the name is already elaborated, and look it
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
NetFuncDef*def = new NetFuncDef(path, st, ports);
|
||||
NetFuncDef*def = new NetFuncDef(path, ports);
|
||||
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
|
||||
{
|
||||
NetExpr*expr = expr_->elaborate_expr(des, path);
|
||||
|
|
@ -2036,10 +2067,17 @@ bool Module::elaborate(Design*des, const string&path, svector<PExpr*>*overrides_
|
|||
|
||||
// Elaborate functions.
|
||||
typedef map<string,PFunction*>::const_iterator mfunc_it_t;
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
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
|
||||
|
|
@ -2127,6 +2165,11 @@ Design* elaborate(const map<string,Module*>&modules,
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
|
|
|
|||
70
netlist.cc
70
netlist.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -482,8 +482,8 @@ NetProc* NetCondit::else_clause()
|
|||
return else_;
|
||||
}
|
||||
|
||||
NetFuncDef::NetFuncDef(const string&n, NetProc*st, const svector<NetNet*>&po)
|
||||
: name_(n), statement_(st), ports_(po)
|
||||
NetFuncDef::NetFuncDef(const string&n, const svector<NetNet*>&po)
|
||||
: name_(n), statement_(0), ports_(po)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -496,11 +496,29 @@ const string& NetFuncDef::name() const
|
|||
return name_;
|
||||
}
|
||||
|
||||
void NetFuncDef::set_proc(NetProc*st)
|
||||
{
|
||||
assert(statement_ == 0);
|
||||
assert(st != 0);
|
||||
statement_ = st;
|
||||
}
|
||||
|
||||
const NetProc* NetFuncDef::proc() const
|
||||
{
|
||||
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)
|
||||
: 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)
|
||||
: func_(def), result_(res), parms_(p)
|
||||
{
|
||||
expr_width(result_->expr_width());
|
||||
}
|
||||
|
||||
NetEUFunc::~NetEUFunc()
|
||||
|
|
@ -578,6 +597,22 @@ const NetESignal*NetEUFunc::result() const
|
|||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
map<string,NetFuncDef*>::const_iterator cur = funcs_.find(key);
|
||||
if (cur == funcs_.end())
|
||||
return 0;
|
||||
|
||||
if (cur != funcs_.end())
|
||||
return (*cur).second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 $
|
||||
* 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
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
|
|
|
|||
21
netlist.h
21
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -768,12 +768,17 @@ class NetForever : public NetProc {
|
|||
class NetFuncDef {
|
||||
|
||||
public:
|
||||
NetFuncDef(const string&, NetProc*st, const svector<NetNet*>&po);
|
||||
NetFuncDef(const string&, const svector<NetNet*>&po);
|
||||
~NetFuncDef();
|
||||
|
||||
void set_proc(NetProc*st);
|
||||
|
||||
const string& name() const;
|
||||
const NetProc*proc() const;
|
||||
|
||||
unsigned port_count() const;
|
||||
const NetNet*port(unsigned idx) const;
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -951,6 +956,10 @@ class NetEUFunc : public NetExpr {
|
|||
const string& name() 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 void dump(ostream&) const;
|
||||
|
|
@ -1402,7 +1411,8 @@ class Design {
|
|||
|
||||
// Functions
|
||||
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
|
||||
void add_task(const string&n, NetTaskDef*);
|
||||
|
|
@ -1508,6 +1518,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
|
|
|
|||
65
t-vvm.cc
65
t-vvm.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <iostream>
|
||||
|
|
@ -206,11 +206,38 @@ void vvm_proc_rval::expr_subsignal(const NetESubSignal*sig)
|
|||
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)
|
||||
{
|
||||
string name = mangle(expr->name());
|
||||
os_ << " " << name << "(sim_);" << endl;
|
||||
result = mangle(expr->result()->name()) + "_bits";
|
||||
const NetFuncDef*def = expr->definition();
|
||||
const unsigned pcnt = expr->parm_count();
|
||||
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)
|
||||
|
|
@ -537,10 +564,13 @@ void target_vvm::func_def(ostream&os, const NetFuncDef*def)
|
|||
thread_step_ = 0;
|
||||
const string name = mangle(def->name());
|
||||
os << "// Function " << def->name() << endl;
|
||||
os << "static void " << name << "(vvm_simulation*sim_)" << endl;
|
||||
os << "{" << endl;
|
||||
def->proc()->emit_proc(os, this);
|
||||
os << "}" << endl;
|
||||
os << "static void " << name << "(vvm_simulation*);" << endl;
|
||||
|
||||
delayed << "// Function " << def->name() << 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();
|
||||
|
||||
#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() <<
|
||||
"];" << endl;
|
||||
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 << ";"
|
||||
<< endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
os << " vvm_calltask(sim_, \"" << net->name() << "\", " <<
|
||||
net->nparms() << ", " << ptmp << ");" << endl;
|
||||
|
|
@ -1385,6 +1401,11 @@ extern const struct target tgt_vvm = {
|
|||
};
|
||||
/*
|
||||
* $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
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue