diff --git a/PFunction.cc b/PFunction.cc index eb2b631ec..ebf035b6e 100644 --- a/PFunction.cc +++ b/PFunction.cc @@ -17,16 +17,17 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PFunction.cc,v 1.6 2002/08/12 01:34:58 steve Exp $" +#ident "$Id: PFunction.cc,v 1.7 2004/05/31 23:34:36 steve Exp $" #endif # include "config.h" #include "PTask.h" -PFunction::PFunction() -: out_(0), ports_(0), statement_(0) +PFunction::PFunction(perm_string name) +: name_(name), ports_(0), statement_(0) { + return_type_.type = PTF_NONE; } PFunction::~PFunction() @@ -46,14 +47,18 @@ void PFunction::set_statement(Statement*s) statement_ = s; } -void PFunction::set_output(PWire*o) +void PFunction::set_return(PTaskFuncArg t) { - assert(out_ == 0); - out_ = o; + return_type_ = t; } /* * $Log: PFunction.cc,v $ + * Revision 1.7 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.6 2002/08/12 01:34:58 steve * conditional ident string using autoconfig. * diff --git a/PTask.h b/PTask.h index 985fc4100..3361849ec 100644 --- a/PTask.h +++ b/PTask.h @@ -19,16 +19,32 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: PTask.h,v 1.12 2002/08/12 01:34:58 steve Exp $" +#ident "$Id: PTask.h,v 1.13 2004/05/31 23:34:36 steve Exp $" #endif # include "LineInfo.h" # include "svector.h" +# include "StringHeap.h" # include class Design; class NetScope; class PWire; class Statement; +class PExpr; + +enum PTaskFuncEnum { + PTF_NONE, + PTF_REG, + PTF_INTEGER, + PTF_REAL, + PTF_REALTIME, + PTF_TIME +}; + +struct PTaskFuncArg { + PTaskFuncEnum type; + svector*range; +}; /* * The PTask holds the parsed definitions of a task. @@ -69,16 +85,18 @@ class PTask : public LineInfo { * The function is similar to a task (in this context) but there is a * single output port and a set of input ports. The output port is the * function return value. + * + * The output value is not elaborated until elaborate_sig. */ class PFunction : public LineInfo { public: - explicit PFunction(); + explicit PFunction(perm_string name); ~PFunction(); void set_ports(svector*p); void set_statement(Statement *s); - void set_output(PWire*); + void set_return(PTaskFuncArg t); void elaborate_scope(Design*des, NetScope*scope) const; @@ -91,13 +109,19 @@ class PFunction : public LineInfo { void dump(ostream&, unsigned) const; private: - PWire*out_; + perm_string name_; + PTaskFuncArg return_type_; svector *ports_; Statement *statement_; }; /* * $Log: PTask.h,v $ + * Revision 1.13 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.12 2002/08/12 01:34:58 steve * conditional ident string using autoconfig. * diff --git a/design_dump.cc b/design_dump.cc index 5a7bf1845..ed3022e69 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.147 2004/02/20 06:22:56 steve Exp $" +#ident "$Id: design_dump.cc,v 1.148 2004/05/31 23:34:36 steve Exp $" #endif # include "config.h" @@ -645,6 +645,13 @@ void NetForever::dump(ostream&o, unsigned ind) const void NetFuncDef::dump(ostream&o, unsigned ind) const { o << setw(ind) << "" << "function " << scope_->name() << endl; + if (result_sig_) + o << setw(ind+2) << "" << "Return signal: " + << result_sig_->name() << endl; + if (result_var_) + o << setw(ind+2) << "" << "Return variable: " + << result_var_->basename() << endl; + if (statement_) statement_->dump(o, ind+2); else @@ -781,7 +788,10 @@ void NetScope::dump(ostream&o) const switch (type_) { case FUNC: - func_def()->dump(o, 4); + if (func_def()) + func_def()->dump(o, 4); + else + o << " MISSING FUNCTION DEFINITION" << endl; break; case TASK: task_def()->dump(o, 4); @@ -1079,6 +1089,11 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.148 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.147 2004/02/20 06:22:56 steve * parameter keys are per_strings. * diff --git a/dup_expr.cc b/dup_expr.cc index 09ef949c4..70c97b813 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: dup_expr.cc,v 1.16 2003/10/31 02:47:11 steve Exp $" +#ident "$Id: dup_expr.cc,v 1.17 2004/05/31 23:34:36 steve Exp $" #endif # include "config.h" @@ -109,8 +109,13 @@ NetEUFunc* NetEUFunc::dup_expr() const tmp_parms[idx] = parms_[idx]->dup_expr(); } - tmp = new NetEUFunc(func_, result_->dup_expr(), tmp_parms); + tmp = 0; + if (result_sig_) + tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms); + if (result_var_) + tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms); + assert(tmp); return tmp; } @@ -136,6 +141,11 @@ NetEVariable* NetEVariable::dup_expr() const /* * $Log: dup_expr.cc,v $ + * Revision 1.17 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.16 2003/10/31 02:47:11 steve * NetEUReduce has its own dup_expr method. * diff --git a/elab_expr.cc b/elab_expr.cc index f6061c382..377b7cd8b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_expr.cc,v 1.85 2004/03/09 04:29:42 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.86 2004/05/31 23:34:36 steve Exp $" #endif # include "config.h" @@ -344,20 +344,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const dscope, in this case, is the scope of the function, so the return value is the name within that scope. */ - NetNet*res = dscope->find_signal(dscope->basename()); - if (res == 0) { - cerr << get_line() << ": internal error: Unable to locate " - "function return value for " << path_ << " in " << - def->name() << "." << endl; - des->errors += 1; - return 0; + if (NetNet*res = dscope->find_signal(dscope->basename())) { + NetESignal*eres = new NetESignal(res); + NetEUFunc*func = new NetEUFunc(dscope, eres, parms); + return func; } - assert(res); - NetESignal*eres = new NetESignal(res); - assert(eres); - NetEUFunc*func = new NetEUFunc(dscope, eres, parms); - return func; + if (NetVariable*res = dscope->find_variable(dscope->basename())) { + NetEVariable*eres = new NetEVariable(res); + eres->set_line(*res); + NetEUFunc*func = new NetEUFunc(dscope, eres, parms); + return func; + } + + cerr << get_line() << ": internal error: Unable to locate " + "function return value for " << path_ + << " in " << def->name() << "." << endl; + des->errors += 1; + return 0; } @@ -951,6 +955,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const /* * $Log: elab_expr.cc,v $ + * Revision 1.86 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.85 2004/03/09 04:29:42 steve * Separate out the lookup_sys_func table, for eventual * support for function type tables. diff --git a/elab_net.cc b/elab_net.cc index c281fd4dd..6037e28fd 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_net.cc,v 1.125 2004/02/20 18:53:34 steve Exp $" +#ident "$Id: elab_net.cc,v 1.126 2004/05/31 23:34:36 steve Exp $" #endif # include "config.h" @@ -1062,7 +1062,10 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, /* * This method elaborates a call to a function in the context of a - * continuous assignment. + * continuous assignment. The definition of the function contains a + * list of the ports, and an output port. The NetEUFunc that I create + * here has a port for all the input ports and the output port. The + * ports are connected by pins. */ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, unsigned width, @@ -1107,6 +1110,9 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, NetScope*dscope = def->scope(); assert(dscope); + /* This must be a ufuction that returns a signal. */ + assert(def->return_sig()); + /* check the validity of the parameters. */ if (! check_call_matches_definition_(des, dscope)) return 0; @@ -1115,9 +1121,9 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, and collect the resulting NetNet objects. All the parameters take on the size of the target port. */ - svector eparms (def->port_count()-1); + svector eparms (def->port_count()); for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { - const NetNet* port_reg = def->port(idx+1); + const NetNet* port_reg = def->port(idx); NetNet*tmp = parms_[idx]->elaborate_net(des, scope, port_reg->pin_count(), 0, 0, 0, @@ -1148,7 +1154,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, of the function net. */ NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, - def->port(0)->pin_count()); + def->return_sig()->pin_count()); osig->local_flag(true); for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) @@ -1156,7 +1162,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, /* Connect the parameter pins to the parameter expressions. */ for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { - const NetNet* port = def->port(idx+1); + const NetNet* port = def->port(idx); NetNet*cur = eparms[idx]; NetNet*tmp = pad_to_width(des, cur, port->pin_count()); @@ -2426,6 +2432,11 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.126 2004/05/31 23:34:36 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.125 2004/02/20 18:53:34 steve * Addtrbute keys are perm_strings. * diff --git a/elab_sig.cc b/elab_sig.cc index ddd00b541..0506304bf 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elab_sig.cc,v 1.33 2004/02/18 17:11:55 steve Exp $" +#ident "$Id: elab_sig.cc,v 1.34 2004/05/31 23:34:37 steve Exp $" #endif # include "config.h" @@ -231,7 +231,10 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope, } /* - * A function definition exists within an elaborated module. + * A function definition exists within an elaborated module. This + * matters when elaborating signals, as the ports of the function are + * created as signals/variables for each instance of the + * function. That is why PFunction has an elaborate_sig method. */ void PFunction::elaborate_sig(Design*des, NetScope*scope) const { @@ -249,21 +252,73 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const des->errors += 1; } - svectorports (ports_? ports_->count()+1 : 1); + NetNet*ret_sig = 0; + NetVariable*ret_real = 0; - /* Get the reg for the return value. I know the name of the - reg variable, and I know that it is in this scope, so look - it up directly. */ - ports[0] = scope->find_signal(scope->basename()); - if (ports[0] == 0) { - cerr << get_line() << ": internal error: function scope " - << scope->name() << " is missing return reg " - << fname << "." << endl; - scope->dump(cerr); - des->errors += 1; - return; + /* Create the signals/variables of the return value and write + them into the function scope. */ + switch (return_type_.type) { + + case PTF_REG: + if (return_type_.range) { + NetExpr*me = elab_and_eval(des, scope, + (*return_type_.range)[0]); + assert(me); + NetExpr*le = elab_and_eval(des, scope, + (*return_type_.range)[1]); + assert(le); + + long mnum = 0, lnum = 0; + if (NetEConst*tmp = dynamic_cast(me)) { + mnum = tmp->value().as_long(); + } else { + cerr << me->get_line() << ": error: " + "Unable to evaluate constant expression " + << *me << "." << endl; + des->errors += 1; + } + + if (NetEConst*tmp = dynamic_cast(le)) { + lnum = tmp->value().as_long(); + } else { + cerr << le->get_line() << ": error: " + "Unable to evaluate constant expression " + << *le << "." << endl; + des->errors += 1; + } + + ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum); + + } else { + ret_sig = new NetNet(scope, fname, NetNet::REG); + } + ret_sig->set_line(*this); + ret_sig->port_type(NetNet::POUTPUT); + break; + + case PTF_INTEGER: + ret_sig = new NetNet(scope, fname, NetNet::REG, INTEGER_WIDTH); + ret_sig->set_line(*this); + ret_sig->set_signed(true); + ret_sig->set_isint(true); + ret_sig->port_type(NetNet::POUTPUT); + break; + + case PTF_REAL: + case PTF_REALTIME: + ret_real = new NetVariable(fname); + ret_real->set_line(*this); + scope->add_variable(ret_real); + break; + + default: + cerr << get_line() << ": internal error: I don't know how " + << "to deal with return type of function " + << scope->basename() << "." << endl; } + svectorports (ports_? ports_->count() : 0); + if (ports_) for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) { @@ -289,14 +344,19 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const << scope->name() << " is missing port " << pname << "." << endl; scope->dump(cerr); + cerr << get_line() << ": Continuing..." << endl; des->errors += 1; } - ports[idx+1] = tmp; + ports[idx] = tmp; } - NetFuncDef*def = new NetFuncDef(scope, ports); + NetFuncDef*def = 0; + if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports); + if (ret_real) def = new NetFuncDef(scope, ret_real, ports); + + assert(def); scope->set_func_def(def); } @@ -367,6 +427,7 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const */ void PWire::elaborate_sig(Design*des, NetScope*scope) const { + /* The parser may produce hierarchical names for wires. I here follow the scopes down to the base where I actually want to elaborate the NetNet object. */ @@ -374,7 +435,13 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const free(tmp_path.remove_tail_name()); for (unsigned idx = 0 ; tmp_path.peek_name(idx) ; idx += 1) { scope = scope->child(tmp_path.peek_name(idx)); - assert(scope); + + if (scope == 0) { + cerr << get_line() << ": internal error: " + << "Bad scope component for name " + << hname_ << endl; + assert(scope); + } } } @@ -540,6 +607,11 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const /* * $Log: elab_sig.cc,v $ + * Revision 1.34 2004/05/31 23:34:37 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.33 2004/02/18 17:11:55 steve * Use perm_strings for named langiage items. * diff --git a/elaborate.cc b/elaborate.cc index 3626bd6a7..3b65a0f8d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.301 2004/05/25 03:42:58 steve Exp $" +#ident "$Id: elaborate.cc,v 1.302 2004/05/31 23:34:37 steve Exp $" #endif # include "config.h" @@ -1101,6 +1101,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const assert(rval()); NetExpr*rv = elab_and_eval(des, scope, rval()); + if (rv == 0) return 0; assert(rv); @@ -2313,6 +2314,13 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const void PFunction::elaborate(Design*des, NetScope*scope) const { NetFuncDef*def = scope->func_def(); + if (def == 0) { + cerr << get_line() << ": internal error: " + << "No function definition for function " + << scope->name() << endl; + return; + } + assert(def); NetProc*st = statement_->elaborate(des, scope); @@ -2700,6 +2708,11 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.302 2004/05/31 23:34:37 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.301 2004/05/25 03:42:58 steve * Handle wait with constant-false expression. * diff --git a/emit.cc b/emit.cc index e04ff89ab..71293b4a7 100644 --- a/emit.cc +++ b/emit.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: emit.cc,v 1.75 2003/09/13 01:30:07 steve Exp $" +#ident "$Id: emit.cc,v 1.76 2004/05/31 23:34:37 steve Exp $" #endif # include "config.h" @@ -335,17 +335,18 @@ void NetScope::emit_scope(struct target_t*tgt) const } } -void NetScope::emit_defs(struct target_t*tgt) const +bool NetScope::emit_defs(struct target_t*tgt) const { + bool flag = true; switch (type_) { case MODULE: for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) - cur->emit_defs(tgt); + flag &= cur->emit_defs(tgt); break; case FUNC: - tgt->func_def(this); + flag &= tgt->func_def(this); break; case TASK: tgt->task_def(this); @@ -354,6 +355,7 @@ void NetScope::emit_defs(struct target_t*tgt) const break; } + return flag; } void NetWhile::emit_proc_recurse(struct target_t*tgt) const @@ -388,7 +390,7 @@ bool Design::emit(struct target_t*tgt) const // emit task and function definitions for (list::const_iterator scope = root_scopes_.begin(); scope != root_scopes_.end(); scope++) - (*scope)->emit_defs(tgt); + rc &= (*scope)->emit_defs(tgt); // emit the processes @@ -509,6 +511,11 @@ bool emit(const Design*des, const char*type) /* * $Log: emit.cc,v $ + * Revision 1.76 2004/05/31 23:34:37 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.75 2003/09/13 01:30:07 steve * Missing case warnings. * diff --git a/net_func.cc b/net_func.cc index 86513d1fd..384c77188 100644 --- a/net_func.cc +++ b/net_func.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_func.cc,v 1.5 2004/02/18 17:11:56 steve Exp $" +#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $" #endif # include "config.h" @@ -28,7 +28,9 @@ static unsigned count_def_pins(const NetFuncDef*def) { - unsigned sum = 0; + assert(def->return_sig()); + + unsigned sum = def->return_sig()->pin_count(); for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1) sum += def->port(idx)->pin_count(); @@ -50,7 +52,7 @@ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d) unsigned pin_base = port_wid; for (unsigned idx = 1 ; idx < port_count() ; idx += 1) { - const NetNet*port_sig = def->port(idx); + const NetNet*port_sig = def->port(idx-1); unsigned bits = port_width(idx); for (unsigned bit = 0; bit < bits; bit += 1) { pin(pin_base+bit).set_dir(Link::INPUT); @@ -69,13 +71,21 @@ NetUserFunc::~NetUserFunc() unsigned NetUserFunc::port_count() const { - return def_->func_def()->port_count(); + return def_->func_def()->port_count() + 1; } unsigned NetUserFunc::port_width(unsigned port) const { NetFuncDef*def = def_->func_def(); + /* Port 0 is the return port. */ + if (port == 0) { + const NetNet*sig = def->return_sig(); + assert(sig); + return sig->pin_count(); + } + + port -= 1; assert(port < def->port_count()); const NetNet*port_sig = def->port(port); @@ -88,6 +98,13 @@ Link& NetUserFunc::port_pin(unsigned port, unsigned idx) unsigned pin_base = 0; const NetNet*port_sig; + if (port == 0) + return pin(idx); + + port_sig = def->return_sig(); + pin_base += port_sig->pin_count(); + port -= 1; + assert(port < def->port_count()); for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) { @@ -133,10 +150,10 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope) return false; } - if ((parms_count+1) != dscope->func_def()->port_count()) { + if (parms_count != dscope->func_def()->port_count()) { cerr << get_line() << ": error: Function " << dscope->name() << " expects " << (dscope->func_def()->port_count()-1) - << " parameters, you passed " << parms_count << "." + << " arguments, you passed " << parms_count << "." << endl; des->errors += 1; return false; @@ -147,6 +164,11 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope) /* * $Log: net_func.cc,v $ + * Revision 1.6 2004/05/31 23:34:37 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.5 2004/02/18 17:11:56 steve * Use perm_strings for named langiage items. * diff --git a/netlist.cc b/netlist.cc index 25ccbc63f..e74d0c2f2 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.222 2004/02/20 06:22:56 steve Exp $" +#ident "$Id: netlist.cc,v 1.223 2004/05/31 23:34:37 steve Exp $" #endif # include "config.h" @@ -237,6 +237,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) switch (t) { case REG: + case INTEGER: case IMPLICIT_REG: init_value = verinum::Vx; dir = Link::OUTPUT; @@ -1658,8 +1659,13 @@ verinum::V NetConst::value(unsigned idx) const return value_[idx]; } -NetFuncDef::NetFuncDef(NetScope*s, const svector&po) -: scope_(s), statement_(0), ports_(po) +NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector&po) +: scope_(s), statement_(0), result_sig_(result), result_var_(0), ports_(po) +{ +} + +NetFuncDef::NetFuncDef(NetScope*s, NetVariable*result, const svector&po) +: scope_(s), statement_(0), result_sig_(0), result_var_(result), ports_(po) { } @@ -1700,6 +1706,16 @@ const NetNet* NetFuncDef::port(unsigned idx) const return ports_[idx]; } +const NetNet* NetFuncDef::return_sig() const +{ + return result_sig_; +} + +const NetVariable* NetFuncDef::return_var() const +{ + return result_var_; +} + NetSTask::NetSTask(const char*na, const svector&pa) : name_(0), parms_(pa) { @@ -1731,9 +1747,14 @@ const NetExpr* NetSTask::parm(unsigned idx) const } NetEUFunc::NetEUFunc(NetScope*def, NetESignal*res, svector&p) -: func_(def), result_(res), parms_(p) +: func_(def), result_sig_(res), result_var_(0), parms_(p) +{ + expr_width(result_sig_->expr_width()); +} + +NetEUFunc::NetEUFunc(NetScope*def, NetEVariable*res, svector&p) +: func_(def), result_sig_(0), result_var_(res), parms_(p) { - expr_width(result_->expr_width()); } NetEUFunc::~NetEUFunc() @@ -1747,9 +1768,14 @@ const string NetEUFunc::name() const return func_->name(); } -const NetESignal*NetEUFunc::result() const +const NetESignal*NetEUFunc::result_sig() const { - return result_; + return result_sig_; +} + +const NetEVariable*NetEUFunc::result_var() const +{ + return result_var_; } unsigned NetEUFunc::parm_count() const @@ -1768,6 +1794,16 @@ const NetScope* NetEUFunc::func() const return func_; } +NetExpr::TYPE NetEUFunc::expr_type() const +{ + if (result_sig_) + return result_sig_->expr_type(); + if (result_var_) + return result_var_->expr_type(); + + return ET_VOID; +} + NetUTask::NetUTask(NetScope*def) : task_(def) { @@ -2218,6 +2254,11 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.223 2004/05/31 23:34:37 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.222 2004/02/20 06:22:56 steve * parameter keys are per_strings. * diff --git a/netlist.h b/netlist.h index d0016a4fc..dd0b4ef01 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.311 2004/02/20 06:22:57 steve Exp $" +#ident "$Id: netlist.h,v 1.312 2004/05/31 23:34:38 steve Exp $" #endif /* @@ -57,6 +57,7 @@ class NetVariable; class NetEvProbe; class NetExpr; class NetESignal; +class NetEVariable; class NetFuncDef; @@ -1996,7 +1997,8 @@ class NetForever : public NetProc { class NetFuncDef { public: - NetFuncDef(NetScope*, const svector&po); + NetFuncDef(NetScope*, NetNet*result, const svector&po); + NetFuncDef(NetScope*, NetVariable*result, const svector&po); ~NetFuncDef(); void set_proc(NetProc*st); @@ -2008,11 +2010,16 @@ class NetFuncDef { unsigned port_count() const; const NetNet*port(unsigned idx) const; + const NetNet*return_sig() const; + const NetVariable*return_var() const; + void dump(ostream&, unsigned ind) const; private: NetScope*scope_; NetProc*statement_; + NetNet*result_sig_; + NetVariable*result_var_; svectorports_; }; @@ -2205,18 +2212,22 @@ class NetVariable : public LineInfo { class NetEUFunc : public NetExpr { public: - NetEUFunc(NetScope*, NetESignal*, svector&); + NetEUFunc(NetScope*, NetESignal*, svector&); + NetEUFunc(NetScope*, NetEVariable*, svector&); ~NetEUFunc(); const string name() const; - const NetESignal*result() const; + const NetESignal*result_sig() const; + const NetEVariable*result_var() const; + unsigned parm_count() const; const NetExpr* parm(unsigned idx) const; const NetScope* func() const; virtual bool set_width(unsigned); + virtual TYPE expr_type() const; virtual void dump(ostream&) const; virtual void expr_scan(struct expr_scan_t*) const; @@ -2225,7 +2236,8 @@ class NetEUFunc : public NetExpr { private: NetScope*func_; - NetESignal*result_; + NetESignal*result_sig_; + NetEVariable*result_var_; svector parms_; private: // not implemented @@ -3103,7 +3115,7 @@ class NetScope : public Attrib { void dump(ostream&) const; void emit_scope(struct target_t*tgt) const; - void emit_defs(struct target_t*tgt) const; + bool emit_defs(struct target_t*tgt) const; /* This method runs the functor on me. Recurse through the children of this node as well. */ @@ -3315,6 +3327,11 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.312 2004/05/31 23:34:38 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.311 2004/02/20 06:22:57 steve * parameter keys are per_strings. * diff --git a/parse.y b/parse.y index c2ea1e8b3..54852a546 100644 --- a/parse.y +++ b/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.195 2004/05/25 19:21:06 steve Exp $" +#ident "$Id: parse.y,v 1.196 2004/05/31 23:34:38 steve Exp $" #endif # include "config.h" @@ -114,7 +114,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG }; Statement*statement; svector*statement_list; - struct { svector*range; NetNet::Type ntype; } range_type; + PTaskFuncArg function_type; struct { svector*range; svector*delay; } range_delay; net_decl_assign_t*net_decl_assign; @@ -204,7 +204,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG }; %type port_type %type parameter_value_opt -%type range_or_type_opt +%type function_range_or_type_opt %type event_expression_list %type event_expression %type event_control @@ -1667,16 +1667,18 @@ module_item definitions in the func_body to take on the scope of the function instead of the module. */ - | K_function range_or_type_opt IDENTIFIER ';' + | K_function function_range_or_type_opt IDENTIFIER ';' { pform_push_scope($3); } function_item_list statement K_endfunction - { PFunction *tmp = new PFunction; + { perm_string name = lex_strings.make($3); + PFunction *tmp = new PFunction(name); tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); tmp->set_ports($6); tmp->set_statement($7); - pform_set_function($3, $2.ntype, $2.range, tmp); + tmp->set_return($2); + pform_set_function(name, tmp); pform_pop_scope(); delete $3; } @@ -2155,13 +2157,13 @@ range_opt ; /* This is used to express the return type of a function. */ -range_or_type_opt - : range { $$.range = $1; $$.ntype = NetNet::REG; } - | K_integer { $$.range = 0; $$.ntype = NetNet::INTEGER; } - | K_real { $$.range = 0; $$.ntype = NetNet::IMPLICIT; } - | K_realtime { $$.range = 0; $$.ntype = NetNet::IMPLICIT; } - | K_time { $$.range = 0; $$.ntype = NetNet::IMPLICIT; } - | { $$.range = 0; $$.ntype = NetNet::IMPLICIT; } +function_range_or_type_opt + : range { $$.range = $1; $$.type = PTF_REG; } + | K_integer { $$.range = 0; $$.type = PTF_INTEGER; } + | K_real { $$.range = 0; $$.type = PTF_REAL; } + | K_realtime { $$.range = 0; $$.type = PTF_REALTIME; } + | K_time { $$.range = 0; $$.type = PTF_TIME; } + | { $$.range = 0; $$.type = PTF_REG; } ; /* The register_variable rule is matched only when I am parsing diff --git a/pform.cc b/pform.cc index ae9e737c8..cb0d9016c 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.125 2004/05/25 19:21:07 steve Exp $" +#ident "$Id: pform.cc,v 1.126 2004/05/31 23:34:39 steve Exp $" #endif # include "config.h" @@ -1302,42 +1302,10 @@ void pform_set_task(perm_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 char*name, NetNet::Type ntype, - svector*ra, PFunction *func) + +void pform_set_function(perm_string name, PFunction*func) { - if (ntype == NetNet::IMPLICIT) - ntype = NetNet::REG; - - /* Form into path_return a hierarchical name for the synthetic - return value for the function. The return value is the same - name as the function, so if the function name is "foo", the - wire is "foo.foo". */ - hname_t path_return (name); - path_return.append(name); - - PWire*out = new PWire(path_return, ntype, NetNet::POUTPUT); - if (ra) { - assert(ra->count() == 2); - out->set_range((*ra)[0], (*ra)[1]); - delete ra; - } - - /* If the return type of the function is INTEGER, then - generate a range for it. */ - if (ntype == NetNet::INTEGER) { - out->set_signed(true); - out->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)), - new PENumber(new verinum(0UL, INTEGER_WIDTH))); - } - - pform_cur_module->add_wire(out); - func->set_output(out); - pform_cur_module->add_function(lex_strings.make(name), func); + pform_cur_module->add_function(name, func); } void pform_set_attrib(perm_string name, perm_string key, char*value) @@ -1598,6 +1566,11 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.126 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.125 2004/05/25 19:21:07 steve * More identifier lists use perm_strings. * diff --git a/pform.h b/pform.h index 761ff09c1..76d2ff19d 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.78 2004/05/25 19:21:07 steve Exp $" +#ident "$Id: pform.h,v 1.79 2004/05/31 23:34:39 steve Exp $" #endif # include "netlist.h" @@ -203,8 +203,7 @@ extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r); extern void pform_set_reg_integer(list*names); extern void pform_set_reg_time(list*names); extern void pform_set_task(perm_string name, PTask*); -extern void pform_set_function(const char*, NetNet::Type, - svector*, PFunction*); +extern void pform_set_function(perm_string name, PFunction*); /* pform_set_attrib and pform_set_type_attrib exist to support the $attribute syntax, which can only set string values to @@ -291,6 +290,11 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.79 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.78 2004/05/25 19:21:07 steve * More identifier lists use perm_strings. * diff --git a/pform_dump.cc b/pform_dump.cc index 92e000001..a95807e0d 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.86 2004/05/25 19:21:07 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.87 2004/05/31 23:34:39 steve Exp $" #endif # include "config.h" @@ -600,7 +600,35 @@ void PForStatement::dump(ostream&out, unsigned ind) const void PFunction::dump(ostream&out, unsigned ind) const { - out << setw(ind) << "" << "output " << out_->path() << ";" << endl; + out << setw(ind) << "" << "function "; + switch (return_type_.type) { + case PTF_NONE: + out << "?none? "; + break; + case PTF_REG: + out << "reg "; + break; + case PTF_INTEGER: + out << "integer "; + break; + case PTF_REAL: + out << "real "; + break; + case PTF_REALTIME: + out << "realtime "; + break; + case PTF_TIME: + out << "time "; + break; + } + + if (return_type_.range) { + out << "["; + out << "] "; + } + + out << name_ << ";" << endl; + if (ports_) for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) { out << setw(ind) << ""; @@ -881,6 +909,11 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.87 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.86 2004/05/25 19:21:07 steve * More identifier lists use perm_strings. * diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 63f659b9e..c833f7638 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-proc.cc,v 1.63 2004/05/19 03:18:40 steve Exp $" +#ident "$Id: t-dll-proc.cc,v 1.64 2004/05/31 23:34:39 steve Exp $" #endif # include "config.h" @@ -99,7 +99,7 @@ void dll_target::task_def(const NetScope*net) } -void dll_target::func_def(const NetScope*net) +bool dll_target::func_def(const NetScope*net) { ivl_scope_t scope = lookup_scope_(net); const NetFuncDef*def = net->func_def(); @@ -113,12 +113,35 @@ void dll_target::func_def(const NetScope*net) scope->def = stmt_cur_; stmt_cur_ = 0; - scope->ports = def->port_count(); + scope->ports = def->port_count() + 1; if (scope->ports > 0) { scope->port = new ivl_signal_t[scope->ports]; - for (unsigned idx = 0 ; idx < scope->ports ; idx += 1) - scope->port[idx] = find_signal(des_, def->port(idx)); + for (unsigned idx = 1 ; idx < scope->ports ; idx += 1) + scope->port[idx] = find_signal(des_, def->port(idx-1)); } + + /* FIXME: the ivl_target API expects port-0 to be the output + port. This assumes that the return value is a signal, which + 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()) { + scope->port[0] = find_signal(des_, ret_sig); + return true; + } + + if (const NetVariable*ret_var = def->return_var()) { + cerr << ret_var->get_line() << ": internal error: " + << "Function " << net->name() << " has an unsupported " + << "return type." << endl; + return false; + } + + cerr << "?:0" << ": internal error: " + << "Function " << net->name() << " has a return type" + << " that I do not understand." << endl; + + return false; } /* @@ -849,6 +872,11 @@ void dll_target::proc_while(const NetWhile*net) /* * $Log: t-dll-proc.cc,v $ + * Revision 1.64 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.63 2004/05/19 03:18:40 steve * Add ivl_target support for non-blocking assign of real. * diff --git a/t-dll.h b/t-dll.h index 8542c0988..d4c37121f 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.h,v 1.112 2004/02/20 06:22:58 steve Exp $" +#ident "$Id: t-dll.h,v 1.113 2004/05/31 23:34:39 steve Exp $" #endif # include "target.h" @@ -123,7 +123,7 @@ struct dll_target : public target_t, public expr_scan_t { bool proc_wait(const NetEvWait*); void proc_while(const NetWhile*); - void func_def(const NetScope*); + bool func_def(const NetScope*); void task_def(const NetScope*); struct ivl_expr_s*expr_; @@ -683,6 +683,11 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.113 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.112 2004/02/20 06:22:58 steve * parameter keys are per_strings. * diff --git a/target.cc b/target.cc index 247788f2e..117662933 100644 --- a/target.cc +++ b/target.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.cc,v 1.68 2003/05/30 02:55:32 steve Exp $" +#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $" #endif # include "config.h" @@ -53,10 +53,11 @@ void target_t::variable(const NetVariable*that) << "): Unhandled variable <" << that->basename() << ">." << endl; } -void target_t::func_def(const NetScope*) +bool target_t::func_def(const NetScope*) { cerr << "target (" << typeid(*this).name() << "): " "Unhandled function definition." << endl; + return false; } void target_t::task_def(const NetScope*) @@ -419,6 +420,11 @@ void expr_scan_t::expr_binary(const NetEBinary*ex) /* * $Log: target.cc,v $ + * Revision 1.69 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.68 2003/05/30 02:55:32 steve * Support parameters in real expressions and * as real expressions, and fix multiply and diff --git a/target.h b/target.h index 422c82c03..21b366667 100644 --- a/target.h +++ b/target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: target.h,v 1.64 2003/05/30 02:55:32 steve Exp $" +#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $" #endif # include "netlist.h" @@ -73,7 +73,7 @@ struct target_t { /* Output a defined task. */ virtual void task_def(const NetScope*); - virtual void func_def(const NetScope*); + virtual bool func_def(const NetScope*); /* LPM style components are handled here. */ virtual void lpm_add_sub(const NetAddSub*); @@ -170,6 +170,11 @@ extern const struct target *target_table[]; /* * $Log: target.h,v $ + * Revision 1.65 2004/05/31 23:34:39 steve + * Rewire/generalize parsing an elaboration of + * function return values to allow for better + * speed and more type support. + * * Revision 1.64 2003/05/30 02:55:32 steve * Support parameters in real expressions and * as real expressions, and fix multiply and