From 53da6e9a335037ddd3a2021191ccd4eb5891ff5b Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 18 Mar 2005 02:56:03 +0000 Subject: [PATCH] Add support for LPM_UFUNC user defined functions. --- elab_net.cc | 17 ++-- ivl_target.h | 33 ++++++- net_func.cc | 87 ++++------------- netlist.h | 10 +- t-dll-api.cc | 22 ++++- t-dll.cc | 22 ++--- t-dll.h | 7 +- tgt-stub/stub.c | 36 ++++++- tgt-vvp/vvp_scope.c | 44 ++++----- vvp/README.txt | 22 ++++- vvp/compile.h | 14 ++- vvp/parse.y | 9 +- vvp/ufunc.cc | 229 +++++++++++++++++++++----------------------- vvp/ufunc.h | 102 ++++++++++++-------- vvp/vvp_net.cc | 17 +++- vvp/vvp_net.h | 6 +- 16 files changed, 375 insertions(+), 302 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index e7787e002..67e589e5d 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.155 2005/03/13 01:26:48 steve Exp $" +#ident "$Id: elab_net.cc,v 1.156 2005/03/18 02:56:03 steve Exp $" #endif # include "config.h" @@ -1227,7 +1227,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { const NetNet* port_reg = def->port(idx); NetNet*tmp = parms_[idx]->elaborate_net(des, scope, - port_reg->pin_count(), + port_reg->vector_width(), 0, 0, 0, Link::STRONG, Link::STRONG); @@ -1256,21 +1256,19 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, of the function net. */ NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, - def->return_sig()->pin_count()); + def->return_sig()->vector_width()); osig->local_flag(true); - for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) - connect(net->port_pin(0, idx), osig->pin(idx)); + connect(net->pin(0), osig->pin(0)); /* Connect the parameter pins to the parameter expressions. */ for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) { const NetNet* port = def->port(idx); NetNet*cur = eparms[idx]; - NetNet*tmp = pad_to_width(des, cur, port->pin_count()); + NetNet*tmp = pad_to_width(des, cur, port->vector_width()); - for (unsigned pin = 0 ; pin < port->pin_count() ; pin += 1) - connect(net->port_pin(idx+1, pin), tmp->pin(pin)); + connect(net->pin(idx+1), tmp->pin(0)); } return osig; @@ -2492,6 +2490,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope, /* * $Log: elab_net.cc,v $ + * Revision 1.156 2005/03/18 02:56:03 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.155 2005/03/13 01:26:48 steve * UPdate elabrate continuous assighn of string to net. * diff --git a/ivl_target.h b/ivl_target.h index 14062fabd..a11122216 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: ivl_target.h,v 1.146 2005/03/09 04:53:40 steve Exp $" +#ident "$Id: ivl_target.h,v 1.147 2005/03/18 02:56:03 steve Exp $" #endif #ifdef __cplusplus @@ -866,6 +866,25 @@ extern const char* ivl_udp_name(ivl_udp_t net); * ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1) * the shift distance. The vector input is the same width as the * output, but the distance has its own width. + * + * - User Function Call (IVL_LPM_UFUNC) + * This device is special as it represents a call to a user defined + * function (behavioral code) within a netlist. The inputs to the + * function are connected to the net, as is the output. + * + * The function definition is associated with a scope, and the + * ivl_lpm_define fuction returns the scope that is that definition. + * See the ivl_scope_* fuctions for how to get at the actual + * definition. + * + * As with many LPM nodes, the ivl_lpm_q function returns the nexus + * for the signal function return value. The width of this nexus must + * exactly match the width of the device from ivl_lpm_width. + * + * The ivl_lpm_data function retrives the nexa for all the input + * ports. The ivl_lpm_size function returns the number of inputs for + * the device, and the ivl_lpm_data() function index argument selects + * the port to retrieve. Each port is sized independently. */ extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */ @@ -891,14 +910,19 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); /* IVL_LPM_FF IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); /* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT - IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB */ + IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB + IVL_LPM_UFUNC */ extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */ extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); +#if 0 /* IVL_LPM_UFUNC */ extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx); +#endif +#if 0 /* IVL_LPM_UFUNC */ extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx); +#endif /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM IVL_LPM_SUB IVL_LPM_UFUNC */ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); @@ -906,7 +930,7 @@ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern unsigned ivl_lpm_selects(ivl_lpm_t net); /* IVL_LPM_MUX IVL_LPM_RAM */ extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx); - /* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT */ + /* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */ extern unsigned ivl_lpm_size(ivl_lpm_t net); /* IVL_LPM_RAM */ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net); @@ -1556,6 +1580,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.147 2005/03/18 02:56:03 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.146 2005/03/09 04:53:40 steve * Generate code for new form of memory ports. * diff --git a/net_func.cc b/net_func.cc index 384c77188..7fa4740a3 100644 --- a/net_func.cc +++ b/net_func.cc @@ -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.6 2004/05/31 23:34:37 steve Exp $" +#ident "$Id: net_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $" #endif # include "config.h" @@ -26,42 +26,25 @@ # include "PExpr.h" # include -static unsigned count_def_pins(const NetFuncDef*def) -{ - 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(); - - return sum; -} - +/* + * To make a NetUserFunc device, make as many pins as there are ports + * in the function. Get the port count from the function definition, + * which accounts for all the inputs, plus one for the phantom output + * that is the result. + */ NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d) -: NetNode(s, n, count_def_pins(d->func_def())), +: NetNode(s, n, d->func_def()->port_count()+1), def_(d) { - NetFuncDef*def = def_->func_def(); + pin(0).set_dir(Link::OUTPUT); + pin(0).set_name(def_->basename(), 0); - unsigned port_wid = port_width(0); - for (unsigned idx = 0 ; idx < port_wid ; idx += 1) { - pin(idx).set_dir(Link::OUTPUT); - pin(idx).set_name(def_->basename(), idx); - } + for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) { - unsigned pin_base = port_wid; - for (unsigned idx = 1 ; idx < port_count() ; idx += 1) { - - 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); - pin(pin_base+bit).set_name(port_sig->name(), bit); - pin(pin_base+bit).drive0(Link::HIGHZ); - pin(pin_base+bit).drive1(Link::HIGHZ); - } - - pin_base += bits; + pin(idx).set_dir(Link::INPUT); + pin(idx).set_name(perm_string::literal("D"), idx-1); + pin(idx).drive0(Link::HIGHZ); + pin(idx).drive1(Link::HIGHZ); } } @@ -69,11 +52,6 @@ NetUserFunc::~NetUserFunc() { } -unsigned NetUserFunc::port_count() const -{ - return def_->func_def()->port_count() + 1; -} - unsigned NetUserFunc::port_width(unsigned port) const { NetFuncDef*def = def_->func_def(); @@ -82,44 +60,16 @@ unsigned NetUserFunc::port_width(unsigned port) const if (port == 0) { const NetNet*sig = def->return_sig(); assert(sig); - return sig->pin_count(); + return sig->vector_width(); } port -= 1; assert(port < def->port_count()); const NetNet*port_sig = def->port(port); - return port_sig->pin_count(); + return port_sig->vector_width(); } -Link& NetUserFunc::port_pin(unsigned port, unsigned idx) -{ - NetFuncDef*def = def_->func_def(); - 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) { - port_sig = def->port(port_idx); - pin_base += port_sig->pin_count(); - } - - port_sig = def->port(port); - assert(idx < port_sig->pin_count()); - assert((pin_base+idx) < pin_count()); - - return pin(pin_base+idx); -} - - const NetScope* NetUserFunc::def() const { return def_; @@ -164,6 +114,9 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope) /* * $Log: net_func.cc,v $ + * Revision 1.7 2005/03/18 02:56:03 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.6 2004/05/31 23:34:37 steve * Rewire/generalize parsing an elaboration of * function return values to allow for better diff --git a/netlist.h b/netlist.h index 0c4173ebc..d45592a1b 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.337 2005/03/12 06:43:36 steve Exp $" +#ident "$Id: netlist.h,v 1.338 2005/03/18 02:56:03 steve Exp $" #endif /* @@ -960,7 +960,8 @@ class NetReplicate : public NetNode { /* * This node represents the call of a user defined function in a - * structural context. + * structural context. The pin count is the same as the port count, + * with pin0 the return value. */ class NetUserFunc : public NetNode { @@ -968,9 +969,7 @@ class NetUserFunc : public NetNode { NetUserFunc(NetScope*s, perm_string n, NetScope*def); ~NetUserFunc(); - unsigned port_count() const; unsigned port_width(unsigned port) const; - Link& port_pin(unsigned port, unsigned idx); const NetScope* def() const; @@ -3417,6 +3416,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.338 2005/03/18 02:56:03 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.337 2005/03/12 06:43:36 steve * Update support for LPM_MOD. * diff --git a/t-dll-api.cc b/t-dll-api.cc index f038baae1..029b63f41 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll-api.cc,v 1.120 2005/03/09 05:52:04 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.121 2005/03/18 02:56:04 steve Exp $" #endif # include "config.h" @@ -798,6 +798,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) assert(idx == 0); return net->u_.repeat.a; + case IVL_LPM_UFUNC: + // Skip the return port. + assert(idx < (net->u_.ufunc.ports-1)); + return net->u_.ufunc.pins[idx+1]; + default: assert(0); return 0; @@ -828,8 +833,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx) } } +#if 0 extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx) { + cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_data2." << endl; assert(net); switch (net->type) { @@ -848,7 +855,8 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx) return 0; } } - +#endif +#if 0 extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx) { assert(net); @@ -862,6 +870,7 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx) return 0; } } +#endif /* * This function returns the hierarchical name for the LPM device. The @@ -942,8 +951,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) return net->u_.shift.q; case IVL_LPM_UFUNC: - assert(idx < net->u_.ufunc.port_wid[0]); - return net->u_.ufunc.pins[idx]; + assert(idx == 0); + return net->u_.ufunc.pins[0]; case IVL_LPM_CONCAT: return net->u_.concat.pins[0]; @@ -1101,7 +1110,7 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net) case IVL_LPM_SHIFTR: return net->u_.shift.width; case IVL_LPM_UFUNC: - return net->u_.ufunc.port_wid[0]; + return net->u_.ufunc.width; case IVL_LPM_CONCAT: return net->u_.concat.width; case IVL_LPM_PART_VP: @@ -1991,6 +2000,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.121 2005/03/18 02:56:04 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.120 2005/03/09 05:52:04 steve * Handle case inequality in netlists. * diff --git a/t-dll.cc b/t-dll.cc index f52850b94..e028748b7 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: t-dll.cc,v 1.144 2005/03/12 06:43:36 steve Exp $" +#ident "$Id: t-dll.cc,v 1.145 2005/03/18 02:56:04 steve Exp $" #endif # include "config.h" @@ -1012,28 +1012,25 @@ bool dll_target::net_function(const NetUserFunc*net) /* Save information about the ports in the ivl_lpm_s structure. Note that port 0 is the return value. */ - obj->u_.ufunc.ports = net->port_count(); - obj->u_.ufunc.port_wid = new unsigned[net->port_count()]; - for (unsigned idx = 0 ; idx < obj->u_.ufunc.ports ; idx += 1) - obj->u_.ufunc.port_wid[idx] = net->port_width(idx); + obj->u_.ufunc.ports = net->pin_count(); + + assert(net->pin_count() >= 1); + obj->u_.ufunc.width = net->port_width(0); /* Now collect all the pins and connect them to the nexa of the net. The output pins have strong drive, and the remaining input pins are HiZ. */ - unsigned pin_count = net->pin_count(); - obj->u_.ufunc.pins = new ivl_nexus_t[pin_count]; + obj->u_.ufunc.pins = new ivl_nexus_t[net->pin_count()]; - for (unsigned idx = 0 ; idx < pin_count ; idx += 1) { + for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) { const Nexus*nex = net->pin(idx).nexus(); assert(nex->t_cookie()); ivl_nexus_t nn = (ivl_nexus_t)nex->t_cookie(); assert(nn); obj->u_.ufunc.pins[idx] = nn; - ivl_drive_t drive = idx < obj->u_.ufunc.port_wid[0] - ? IVL_DR_STRONG - : IVL_DR_HiZ; + ivl_drive_t drive = idx == 0 ? IVL_DR_STRONG : IVL_DR_HiZ; nexus_lpm_add(obj->u_.ufunc.pins[idx], obj, idx, drive, drive); } @@ -2136,6 +2133,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj }; /* * $Log: t-dll.cc,v $ + * Revision 1.145 2005/03/18 02:56:04 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.144 2005/03/12 06:43:36 steve * Update support for LPM_MOD. * diff --git a/t-dll.h b/t-dll.h index ddab84214..d3d1214a6 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.122 2005/02/19 02:43:39 steve Exp $" +#ident "$Id: t-dll.h,v 1.123 2005/03/18 02:56:04 steve Exp $" #endif # include "target.h" @@ -362,7 +362,7 @@ struct ivl_lpm_s { struct ivl_lpm_ufunc_s { ivl_scope_t def; unsigned ports; - unsigned *port_wid; + unsigned width; ivl_nexus_t*pins; } ufunc; } u_; @@ -685,6 +685,9 @@ struct ivl_variable_s { /* * $Log: t-dll.h,v $ + * Revision 1.123 2005/03/18 02:56:04 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.122 2005/02/19 02:43:39 steve * Support shifts and divide. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 33e2198c4..d0892804e 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: stub.c,v 1.116 2005/03/12 06:43:36 steve Exp $" +#ident "$Id: stub.c,v 1.117 2005/03/18 02:56:04 steve Exp $" #endif # include "config.h" @@ -604,6 +604,33 @@ static void show_lpm_sub(ivl_lpm_t net) show_lpm_arithmetic_pins(net); } +static void show_lpm_ufunc(ivl_lpm_t net) +{ + unsigned width = ivl_lpm_width(net); + unsigned ports = ivl_lpm_size(net); + ivl_scope_t def = ivl_lpm_define(net); + ivl_nexus_t nex; + unsigned idx; + + fprintf(out, " LPM_UFUNC %s: \n", + ivl_lpm_basename(net), ivl_scope_name(def), width, ports); + + nex = ivl_lpm_q(net, 0); + if (width != width_of_nexus(nex)) { + fprintf(out, " ERROR: Q output nexus width=%u " + " does not match part width\n", width_of_nexus(nex)); + stub_errors += 1; + } + + fprintf(out, " Q: %s\n", ivl_nexus_name(nex)); + + for (idx = 0 ; idx < ports ; idx += 1) { + nex = ivl_lpm_data(net, idx); + fprintf(out, " D%u: %s \n", idx, + ivl_nexus_name(nex), width_of_nexus(nex)); + } +} + static void show_lpm(ivl_lpm_t net) { unsigned idx; @@ -736,6 +763,10 @@ static void show_lpm(ivl_lpm_t net) show_lpm_repeat(net); break; + case IVL_LPM_UFUNC: + show_lpm_ufunc(net); + break; + default: fprintf(out, " LPM(%d) %s: \n", ivl_lpm_type(net), @@ -1185,6 +1216,9 @@ int target_design(ivl_design_t des) /* * $Log: stub.c,v $ + * Revision 1.117 2005/03/18 02:56:04 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.116 2005/03/12 06:43:36 steve * Update support for LPM_MOD. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index da8988974..a418546cd 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_scope.c,v 1.121 2005/03/09 05:52:04 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.122 2005/03/18 02:56:04 steve Exp $" #endif # include "vvp_priv.h" @@ -1714,8 +1714,7 @@ static void draw_lpm_shiftl(ivl_lpm_t net) static void draw_lpm_ufunc(ivl_lpm_t net) { - unsigned idx, bit; - char comma; + unsigned idx; ivl_scope_t def = ivl_lpm_define(net); fprintf(vvp_out, "L_%p .ufunc TD_%s, %u", net, @@ -1723,15 +1722,10 @@ static void draw_lpm_ufunc(ivl_lpm_t net) ivl_lpm_width(net)); /* Print all the net signals that connect to the input of the - function. Print them one per line, for convenience. */ + function. */ for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { - comma = ' '; - fprintf(vvp_out, ",\n"); - for (bit = 0 ; bit < ivl_lpm_data2_width(net, idx) ; bit += 1) { - fprintf(vvp_out, "%c ", comma); - draw_input_from_net(ivl_lpm_data2(net, idx, bit)); - comma = ','; - } + fprintf(vvp_out, ", "); + draw_input_from_net(ivl_lpm_data(net, idx)); } @@ -1741,32 +1735,23 @@ static void draw_lpm_ufunc(ivl_lpm_t net) receive the input values given in the previous list. */ for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { ivl_signal_t psig = ivl_scope_port(def, idx+1); - comma = ' '; if (idx == 0) - fprintf(vvp_out, "\n("); + fprintf(vvp_out, " ("); else - fprintf(vvp_out, ",\n"); + fprintf(vvp_out, ", "); - for (bit = 0 ; bit < ivl_signal_pins(psig) ; bit += 1) { - fprintf(vvp_out, "%c V_%s[%u]", comma, - vvp_signal_label(psig), bit); - comma = ','; - } + fprintf(vvp_out, "V_%s", vvp_signal_label(psig)); } - fprintf(vvp_out, ")\n"); + fprintf(vvp_out, ")"); + /* Finally, print the reference to the signal from which the + result is collected. */ { ivl_signal_t psig = ivl_scope_port(def, 0); - assert(ivl_lpm_width(net) == ivl_signal_pins(psig)); + assert(ivl_lpm_width(net) == ivl_signal_width(psig)); - comma = ' '; - for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) { - fprintf(vvp_out, "%c V_%s[%u]", comma, - vvp_signal_label(psig), - idx); - comma = ','; - } + fprintf(vvp_out, " V_%s", vvp_signal_label(psig)); } fprintf(vvp_out, ";\n"); @@ -2022,6 +2007,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.122 2005/03/18 02:56:04 steve + * Add support for LPM_UFUNC user defined functions. + * * Revision 1.121 2005/03/09 05:52:04 steve * Handle case inequality in netlists. * diff --git a/vvp/README.txt b/vvp/README.txt index bcf177614..bba2e57b8 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,7 +1,7 @@ /* * Copyright (c) 2001 Stephen Williams (steve@icarus.com) * - * $Id: README.txt,v 1.60 2005/03/09 05:52:04 steve Exp $ + * $Id: README.txt,v 1.61 2005/03/18 02:56:04 steve Exp $ */ VVP SIMULATION ENGINE @@ -609,8 +609,26 @@ STRUCTURAL FUNCTION CALLS: The .ufunc statement defines a call to a user defined function. -