diff --git a/PExpr.h b/PExpr.h index a303bc849..0052ecaea 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.17 1999/08/01 21:18:55 steve Exp $" +#ident "$Id: PExpr.h,v 1.18 1999/08/31 22:38:29 steve Exp $" #endif # include @@ -254,6 +254,7 @@ class PECallFunction : public PExpr { ~PECallFunction() {} virtual void dump(ostream &) const; + virtual NetEUFunc*elaborate_expr(Design*des, const string&path) const; private: string name_; @@ -262,6 +263,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.18 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.17 1999/08/01 21:18:55 steve * elaborate rise/fall/decay for continuous assign. * diff --git a/design_dump.cc b/design_dump.cc index 2658fe9d1..a0bdedb5b 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -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.35 1999/08/25 22:22:41 steve Exp $" +#ident "$Id: design_dump.cc,v 1.36 1999/08/31 22:38:29 steve Exp $" #endif /* @@ -123,24 +123,25 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const void NetAssign::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "Procedural assign: " << *rval_ << endl; + o << setw(ind) << "" << "Procedural assign (NetAssign): " << + *rval_ << endl; dump_node_pins(o, ind+4); } void NetAssignNB::dump_node(ostream&o, unsigned ind) const { if (bmux_) - o << setw(ind) << "" << "Procedural NB assign: " << name() - << "[" << *bmux_ << "] <= " << *rval_ << endl; + o << setw(ind) << "" << "Procedural NB assign (NetAssignNB): " + << name() << "[" << *bmux_ << "] <= " << *rval_ << endl; else - o << setw(ind) << "" << "Procedural NB assign: " << name() - << " <= " << *rval_ << endl; + o << setw(ind) << "" << "Procedural NB assign (NetAssignNB): " + << name() << " <= " << *rval_ << endl; dump_node_pins(o, ind+4); } void NetBUFZ::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "BUFZ: " << name() << endl; + o << setw(ind) << "" << "NetBUFZ: " << name() << endl; dump_node_pins(o, ind+4); } @@ -616,7 +617,8 @@ void NetEMemory::dump(ostream&o) const void NetESignal::dump_node(ostream&o, unsigned ind) const { - o << setw(ind) << "" << "Expression Node: " << name() << endl; + o << setw(ind) << "" << "Expression Node (NetESignal): " << + name() << endl; dump_node_pins(o, ind+4); } @@ -627,6 +629,18 @@ void NetETernary::dump(ostream&o) const false_val_ << ")"; } +void NetEUFunc::dump(ostream&o) const +{ + o << name() << "("; + assert(parms_.count() > 0); + parms_[0]->dump(o); + for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) { + o << ", "; + parms_[idx]->dump(o); + } + o << ")"; +} + void NetEUnary::dump(ostream&o) const { o << op_ << "("; @@ -666,6 +680,15 @@ void Design::dump(ostream&o) const } } + o << "ELABORATED FUNCTION DEFINITIONS:" << endl; + { + map::const_iterator pp; + for (pp = funcs_.begin() + ; pp != funcs_.end() ; pp ++) { + (*pp).second->dump(o, 0); + } + } + o << "ELABORATED TASK DEFINITIONS:" << endl; { map::const_iterator pp; @@ -696,6 +719,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.36 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.35 1999/08/25 22:22:41 steve * elaborate some aspects of functions. * diff --git a/elaborate.cc b/elaborate.cc index 1dd8d271c..c9609794c 100644 --- a/elaborate.cc +++ b/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.73 1999/08/25 22:22:41 steve Exp $" +#ident "$Id: elaborate.cc,v 1.74 1999/08/31 22:38:29 steve Exp $" #endif /* @@ -733,6 +733,27 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path, return osig; } +NetEUFunc* PECallFunction::elaborate_expr(Design*des, const string&path) const +{ + string myname = path+"."+name_; + NetFuncDef*def = des->find_function(myname); + assert(def); + svector parms (parms_.count()); + + for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) { + NetExpr*tmp = parms_[idx]->elaborate_expr(des, myname); + parms[idx] = tmp; + } + + NetNet*res = des->find_signal(myname, name_); + assert(res); + NetESignal*eres = new NetESignal(res); + assert(eres); + des->add_node(eres); + NetEUFunc*func = new NetEUFunc(def, eres, parms); + return func; +} + /* * The concatenation operator, as a net, is a wide signal that is * connected to all the pins of the elaborated expression nets. @@ -1869,12 +1890,29 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const void PFunction::elaborate(Design*des, const string&path) const { NetProc*st = statement_->elaborate(des, path); - NetFuncDef*def = new NetFuncDef(path, st); - des->add_function(path, def); + if (st == 0) { + cerr << statement_->get_line() << ": Unable to elaborate " + "statement in function " << path << " at " << get_line() + << "." << endl; + return; + } - cerr << get_line() << ": Sorry, unable to elaborate " - "function definitions." << endl; - des->errors += 1; + /* 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 + calls to the task. (Remember, the task itself does not need + these ports.) */ + svectorports (ports_? ports_->count()+1 : 1); + ports[0] = des->find_signal(path, path); + for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) { + NetNet*tmp = des->find_signal(path, (*ports_)[idx]->name()); + + ports[idx+1] = tmp; + } + + + NetFuncDef*def = new NetFuncDef(path, st, ports); + des->add_function(path, def); } NetProc* PRepeat::elaborate(Design*des, const string&path) const @@ -2089,6 +2127,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.74 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.73 1999/08/25 22:22:41 steve * elaborate some aspects of functions. * diff --git a/emit.cc b/emit.cc index 044db78a2..cf54b2503 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: emit.cc,v 1.18 1999/07/17 19:50:59 steve Exp $" +#ident "$Id: emit.cc,v 1.19 1999/08/31 22:38:29 steve Exp $" #endif /* @@ -229,6 +229,14 @@ void Design::emit(ostream&o, struct target_t*tgt) const } + // emit function definitions + { + map::const_iterator ta; + for (ta = funcs_.begin() ; ta != funcs_.end() ; ta ++) { + tgt->func_def(o, (*ta).second); + } + } + // emit task definitions { map::const_iterator ta; @@ -269,6 +277,11 @@ void NetEMemory::expr_scan(struct expr_scan_t*tgt) const tgt->expr_memory(this); } +void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_ufunc(this); +} + void NetESignal::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_signal(this); @@ -308,6 +321,9 @@ void emit(ostream&o, const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.19 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.18 1999/07/17 19:50:59 steve * netlist support for ternary operator. * diff --git a/netlist.cc b/netlist.cc index df50fba4b..ec6beb639 100644 --- a/netlist.cc +++ b/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.53 1999/08/25 22:22:41 steve Exp $" +#ident "$Id: netlist.cc,v 1.54 1999/08/31 22:38:29 steve Exp $" #endif # include @@ -482,8 +482,8 @@ NetProc* NetCondit::else_clause() return else_; } -NetFuncDef::NetFuncDef(const string&n, NetProc*st) -: name_(n), statement_(st) +NetFuncDef::NetFuncDef(const string&n, NetProc*st, const svector&po) +: name_(n), statement_(st), ports_(po) { } @@ -491,6 +491,16 @@ NetFuncDef::~NetFuncDef() { } +const string& NetFuncDef::name() const +{ + return name_; +} + +const NetProc* NetFuncDef::proc() const +{ + return statement_; +} + NetNEvent::NetNEvent(const string&ev, unsigned wid, Type e, NetPEvent*pe) : NetNode(ev, wid), sref(pe), edge_(e) { @@ -547,6 +557,44 @@ const NetExpr* NetSTask::parm(unsigned idx) const return parms_[idx]; } +NetEUFunc::NetEUFunc(NetFuncDef*def, NetESignal*res, svector&p) +: func_(def), result_(res), parms_(p) +{ +} + +NetEUFunc::~NetEUFunc() +{ + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) + delete parms_[idx]; +} + +const string& NetEUFunc::name() const +{ + return func_->name(); +} + +const NetESignal*NetEUFunc::result() const +{ + return result_; +} + +/* + * 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 + * parameter of the function definition and take that into account. + */ +bool NetEUFunc::set_width(unsigned wid) +{ + expr_width(wid); + return true; +} + +NetEUFunc* NetEUFunc::dup_expr() const +{ + assert(0); + return 0; +} + NetUTask::NetUTask(NetTaskDef*def) : task_(def) { @@ -1453,6 +1501,15 @@ void Design::add_function(const string&key, NetFuncDef*def) funcs_[key] = def; } +NetFuncDef* Design::find_function(const string&key) +{ + map::const_iterator cur = funcs_.find(key); + if (cur == funcs_.end()) + return 0; + + return (*cur).second; +} + void Design::add_task(const string&key, NetTaskDef*def) { tasks_[key] = def; @@ -1585,6 +1642,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.54 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.53 1999/08/25 22:22:41 steve * elaborate some aspects of functions. * diff --git a/netlist.h b/netlist.h index 582c0d54f..10e44ba37 100644 --- a/netlist.h +++ b/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.57 1999/08/25 22:22:41 steve Exp $" +#ident "$Id: netlist.h,v 1.58 1999/08/31 22:38:29 steve Exp $" #endif /* @@ -40,6 +40,7 @@ class NetNode; class NetProc; class NetProcTop; class NetExpr; +class NetESignal; class ostream; @@ -758,17 +759,27 @@ class NetForever : public NetProc { NetProc*statement_; }; +/* + * A funciton definition is elaborated just like a task, though by now + * it is certain that the first parameter (a phantom parameter) is the + * output and all the remaining parameters are the inputs. This makes + * for easy code generation in targets that support behavioral descriptions. + */ class NetFuncDef { public: - explicit NetFuncDef(const string&, NetProc*st); + NetFuncDef(const string&, NetProc*st, const svector&po); ~NetFuncDef(); + const string& name() const; + const NetProc*proc() const; + virtual void dump(ostream&, unsigned ind) const; private: string name_; NetProc*statement_; + svectorports_; }; class NetPDelay : public NetProc { @@ -923,7 +934,44 @@ class NetTaskDef { }; /* - * A call to a user defined task is elaborated into this object. + * This node represents a function call in an expression. The object + * contains a pointer to the function definition, which is used to + * locate the value register and input expressions. + * + * The NetNet parameter to the constructor is the *register* NetNet + * that receives the result of the function, and the NetExpr list is + * the paraneters passed to the function. + */ +class NetEUFunc : public NetExpr { + + public: + NetEUFunc(NetFuncDef*, NetESignal*, svector&); + ~NetEUFunc(); + + const string& name() const; + + const NetESignal*result() const; + + virtual bool set_width(unsigned); + virtual void dump(ostream&) const; + + virtual void expr_scan(struct expr_scan_t*) const; + virtual NetEUFunc*dup_expr() const; + + private: + NetFuncDef*func_; + NetESignal*result_; + svector parms_; + + private: // not implemented + NetEUFunc(const NetEUFunc&); + NetEUFunc& operator= (const NetEUFunc&); +}; + +/* + * A call to a user defined task is elaborated into this object. This + * contains a pointer to the elaborated task definition, but is a + * NetProc object so that it can be linked into statements. */ class NetUTask : public NetProc { @@ -1354,6 +1402,7 @@ class Design { // Functions void add_function(const string&n, NetFuncDef*); + NetFuncDef* find_function(const string&key); // Tasks void add_task(const string&n, NetTaskDef*); @@ -1459,6 +1508,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.58 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.57 1999/08/25 22:22:41 steve * elaborate some aspects of functions. * diff --git a/pform.cc b/pform.cc index 77418093d..b2ca4937b 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.cc,v 1.40 1999/08/27 15:08:37 steve Exp $" +#ident "$Id: pform.cc,v 1.41 1999/08/31 22:38:29 steve Exp $" #endif # include "compiler.h" @@ -518,6 +518,11 @@ void pform_set_task(const string&name, PTask*task) pform_cur_module->add_task(name, task); } +/* + * This function is called to fill out the definition of the function + * with the trappings that are discovered after the basic function + * name is parsed. + */ void pform_set_function(const string&name, svector*ra, PFunction *func) { PWire*out = new PWire(name+"."+name, NetNet::REG, NetNet::POUTPUT); @@ -682,6 +687,9 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.41 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.40 1999/08/27 15:08:37 steve * continuous assignment lists. * diff --git a/t-vvm.cc b/t-vvm.cc index 7d4fe259a..362ad98a0 100644 --- a/t-vvm.cc +++ b/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.35 1999/08/15 01:23:56 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.36 1999/08/31 22:38:29 steve Exp $" #endif # include @@ -43,6 +43,7 @@ class target_vvm : public target_t { virtual void signal(ostream&os, const NetNet*); virtual void memory(ostream&os, const NetMemory*); virtual void task_def(ostream&os, const NetTaskDef*); + virtual void func_def(ostream&os, const NetFuncDef*); virtual void logic(ostream&os, const NetLogic*); virtual void bufz(ostream&os, const NetBUFZ*); virtual void udp(ostream&os, const NetUDP*); @@ -119,6 +120,7 @@ class vvm_proc_rval : public expr_scan_t { virtual void expr_subsignal(const NetESubSignal*sig); virtual void expr_unary(const NetEUnary*); virtual void expr_binary(const NetEBinary*); + virtual void expr_ufunc(const NetEUFunc*); }; void vvm_proc_rval::expr_concat(const NetEConcat*expr) @@ -204,6 +206,13 @@ void vvm_proc_rval::expr_subsignal(const NetESubSignal*sig) result = val; } +void vvm_proc_rval::expr_ufunc(const NetEUFunc*expr) +{ + string name = mangle(expr->name()); + os_ << " " << name << "(sim_);" << endl; + result = mangle(expr->result()->name()) + "_bits"; +} + void vvm_proc_rval::expr_unary(const NetEUnary*expr) { expr->expr()->expr_scan(this); @@ -515,6 +524,25 @@ void target_vvm::task_def(ostream&os, const NetTaskDef*def) os << "};" << endl; } +/* + * A function definition is emitted as a C++ function that takes no + * parameters and returns no result. The actual parameter passing + * happens in the function call, where the signals that are the inputs + * are assigned by the caller, the caller calls the function (which + * writes the result) then the caller copies the result out of the + * magic result register. + */ +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; +} + /* * This method handles writing output functions for gates that have a * single output (at pin 0). This writes the output_fun method into @@ -1357,6 +1385,9 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.36 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.35 1999/08/15 01:23:56 steve * Convert vvm to implement system tasks with vpi. * diff --git a/target.cc b/target.cc index 1fe4a0819..5bfa3aea5 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.cc,v 1.16 1999/08/18 04:00:02 steve Exp $" +#ident "$Id: target.cc,v 1.17 1999/08/31 22:38:29 steve Exp $" #endif # include "target.h" @@ -41,6 +41,12 @@ void target_t::memory(ostream&os, const NetMemory*) "Unhandled memory." << endl; } +void target_t::func_def(ostream&os, const NetFuncDef*) +{ + cerr << "target (" << typeid(*this).name() << "): " + "Unhandled function definition." << endl; +} + void target_t::task_def(ostream&os, const NetTaskDef*) { cerr << "target (" << typeid(*this).name() << "): " @@ -230,6 +236,12 @@ void expr_scan_t::expr_ternary(const NetETernary*) "unhandled expr_ternary." << endl; } +void expr_scan_t::expr_ufunc(const NetEUFunc*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled function call." << endl; +} + void expr_scan_t::expr_unary(const NetEUnary*) { cerr << "expr_scan_t (" << typeid(*this).name() << "): " @@ -244,6 +256,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.17 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.16 1999/08/18 04:00:02 steve * Fixup spelling and some error messages. * diff --git a/target.h b/target.h index e001f62e7..bc221ad1d 100644 --- a/target.h +++ b/target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: target.h,v 1.15 1999/07/17 19:51:00 steve Exp $" +#ident "$Id: target.h,v 1.16 1999/08/31 22:38:29 steve Exp $" #endif # include "netlist.h" @@ -63,6 +63,7 @@ struct target_t { /* Output a defined task. */ virtual void task_def(ostream&, const NetTaskDef*); + virtual void func_def(ostream&, const NetFuncDef*); /* Output a gate (called for each gate) */ virtual void logic(ostream&os, const NetLogic*); @@ -109,6 +110,7 @@ struct expr_scan_t { virtual void expr_signal(const NetESignal*); virtual void expr_subsignal(const NetESubSignal*); virtual void expr_ternary(const NetETernary*); + virtual void expr_ufunc(const NetEUFunc*); virtual void expr_unary(const NetEUnary*); virtual void expr_binary(const NetEBinary*); }; @@ -130,6 +132,9 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.16 1999/08/31 22:38:29 steve + * Elaborate and emit to vvm procedural functions. + * * Revision 1.15 1999/07/17 19:51:00 steve * netlist support for ternary operator. *