From 5bfdd52391f75ecc81efc3de56d3208878480e76 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 13 Jul 2005 04:52:31 +0000 Subject: [PATCH] Handle functions with real values. --- tgt-vvp/Makefile.in | 4 +- tgt-vvp/draw_ufunc.c | 158 +++++++++++++++++++++++++++++++++++++++++++ tgt-vvp/eval_expr.c | 76 ++------------------- tgt-vvp/eval_real.c | 11 ++- tgt-vvp/vvp_priv.h | 10 ++- 5 files changed, 181 insertions(+), 78 deletions(-) create mode 100644 tgt-vvp/draw_ufunc.c diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 2e4e53921..04269bcc9 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.22 2004/02/10 19:25:01 steve Exp $" +#ident "$Id: Makefile.in,v 1.23 2005/07/13 04:52:31 steve Exp $" # # SHELL = /bin/sh @@ -51,7 +51,7 @@ dep: $(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvp.o draw_mux.o draw_vpi.o eval_expr.o eval_real.o vector.o \ +O = vvp.o draw_mux.o draw_ufunc.o draw_vpi.o eval_expr.o eval_real.o vector.o \ vvp_process.o vvp_scope.o ifeq (@WIN32@,yes) diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c new file mode 100644 index 000000000..16f8ae0c0 --- /dev/null +++ b/tgt-vvp/draw_ufunc.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2005 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 + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $" +#endif + +# include "vvp_priv.h" +# include +#ifdef HAVE_MALLOC_H +# include +#endif +# include +# include + +static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp) +{ + struct vector_info res; + + res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0); + assert(res.wid <= ivl_signal_width(port)); + fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n", + vvp_signal_label(port), res.base, res.wid); + + clr_vector(res); +} + +static void function_argument_real(ivl_signal_t port, ivl_expr_t exp) +{ + int res = draw_eval_real(exp); + + fprintf(vvp_out, " %%set/wr V_%s, %d;\n", + vvp_signal_label(port), res); +} + +static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp) +{ + ivl_variable_type_t dtype = ivl_signal_data_type(port); + switch (dtype) { + case IVL_VT_LOGIC: + function_argument_logic(port, exp); + break; + case IVL_VT_REAL: + function_argument_real(port, exp); + break; + default: + fprintf(stderr, "XXXX function argument %s type=%d?!\n", + ivl_signal_basename(port), dtype); + assert(0); + } +} + +/* + * A call to a user defined function generates a result that is the + * result of this expression. + * + * The result of the function is placed by the function execution into + * a signal within the scope of the function that also has a basename + * the same as the function. The ivl_target API handled the result + * mapping already, and we get the name of the result signal as + * parameter 0 of the function definition. + */ + +struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid) +{ + unsigned idx; + unsigned swid = ivl_expr_width(exp); + ivl_scope_t def = ivl_expr_def(exp); + ivl_signal_t retval = ivl_scope_port(def, 0); + struct vector_info res; + + /* evaluate the expressions and send the results to the + function ports. */ + + assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1)); + for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) { + ivl_signal_t port = ivl_scope_port(def, idx+1); + draw_function_argument(port, ivl_expr_parm(exp,idx)); + } + + + /* Call the function */ + fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def))); + fprintf(vvp_out, ", S_%p;\n", def); + fprintf(vvp_out, " %%join;\n"); + + /* Fresh basic block starts after the join. */ + clear_expression_lookaside(); + + /* The return value is in a signal that has the name of the + expression. Load that into the thread and return the + vector result. */ + + res.base = allocate_vector(wid); + res.wid = wid; + + { unsigned load_wid = swid; + if (load_wid > ivl_signal_width(retval)) + load_wid = ivl_signal_width(retval); + + fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n", + res.base, vvp_signal_label(retval), load_wid); + + if (load_wid < swid) + fprintf(vvp_out, " %%mov %u, 0, %u;\n", + res.base+load_wid, swid-load_wid); + } + + /* Pad the signal value with zeros. */ + if (swid < wid) + fprintf(vvp_out, " %%mov %u, 0, %u;\n", + res.base+swid, wid-swid); + + return res; +} + +int draw_ufunc_real(ivl_expr_t exp) +{ + ivl_scope_t def = ivl_expr_def(exp); + ivl_signal_t retval = ivl_scope_port(def, 0); + int res = 0; + int idx; + + assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1)); + for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) { + ivl_signal_t port = ivl_scope_port(def, idx+1); + draw_function_argument(port, ivl_expr_parm(exp,idx)); + } + + + /* Call the function */ + fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def))); + fprintf(vvp_out, ", S_%p;\n", def); + fprintf(vvp_out, " %%join;\n"); + + /* Load the result into a word. */ + res = allocate_word(); + fprintf(vvp_out, " %%load/wr %d, V_%s;\n", + res, vvp_signal_label(retval)); + + return res; +} + diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 8e4fb7b88..ae67ada47 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval_expr.c,v 1.118 2005/07/11 16:56:51 steve Exp $" +#ident "$Id: eval_expr.c,v 1.119 2005/07/13 04:52:31 steve Exp $" #endif # include "vvp_priv.h" @@ -1752,77 +1752,6 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid) return res; } -/* - * A call to a user defined function generates a result that is the - * result of this expression. - * - * The result of the function is placed by the function execution into - * a signal within the scope of the function that also has a basename - * the same as the function. The ivl_target API handled the result - * mapping already, and we get the name of the result signal as - * parameter 0 of the function definition. - */ - -static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid) -{ - unsigned idx; - unsigned swid = ivl_expr_width(exp); - ivl_scope_t def = ivl_expr_def(exp); - ivl_signal_t retval = ivl_scope_port(def, 0); - struct vector_info res; - - /* evaluate the expressions and send the results to the - function ports. */ - - assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1)); - for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) { - ivl_signal_t port = ivl_scope_port(def, idx+1); - - res = draw_eval_expr_wid(ivl_expr_parm(exp, idx), - ivl_signal_width(port), 0); - assert(res.wid <= ivl_signal_width(port)); - fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n", - vvp_signal_label(port), res.base, res.wid); - - clr_vector(res); - } - - - /* Call the function */ - fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def))); - fprintf(vvp_out, ", S_%p;\n", def); - fprintf(vvp_out, " %%join;\n"); - - /* Fresh basic block starts after the join. */ - clear_expression_lookaside(); - - /* The return value is in a signal that has the name of the - expression. Load that into the thread and return the - vector result. */ - - res.base = allocate_vector(wid); - res.wid = wid; - - { unsigned load_wid = swid; - if (load_wid > ivl_signal_width(retval)) - load_wid = ivl_signal_width(retval); - - fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n", - res.base, vvp_signal_label(retval), load_wid); - - if (load_wid < swid) - fprintf(vvp_out, " %%mov %u, 0, %u;\n", - res.base+load_wid, swid-load_wid); - } - - /* Pad the signal value with zeros. */ - if (swid < wid) - fprintf(vvp_out, " %%mov %u, 0, %u;\n", - res.base+swid, wid-swid); - - return res; -} - static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) { struct vector_info res; @@ -2101,6 +2030,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag) /* * $Log: eval_expr.c,v $ + * Revision 1.119 2005/07/13 04:52:31 steve + * Handle functions with real values. + * * Revision 1.118 2005/07/11 16:56:51 steve * Remove NetVariable and ivl_variable_t structures. * diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 70bdab618..279c3e824 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2005 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: eval_real.c,v 1.13 2005/07/11 16:56:51 steve Exp $" +#ident "$Id: eval_real.c,v 1.14 2005/07/13 04:52:31 steve Exp $" #endif /* @@ -280,6 +280,10 @@ int draw_eval_real(ivl_expr_t exp) res = draw_signal_real(exp); break; + case IVL_EX_UFUNC: + res = draw_ufunc_real(exp); + break; + default: if (ivl_expr_value(exp) == IVL_VT_VECTOR) { struct vector_info sv = draw_eval_expr(exp, 0); @@ -308,6 +312,9 @@ int draw_eval_real(ivl_expr_t exp) /* * $Log: eval_real.c,v $ + * Revision 1.14 2005/07/13 04:52:31 steve + * Handle functions with real values. + * * Revision 1.13 2005/07/11 16:56:51 steve * Remove NetVariable and ivl_variable_t structures. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index fca55bbcd..58ac4fd69 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -1,7 +1,7 @@ #ifndef __vvp_priv_H #define __vvp_priv_H /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2005 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: vvp_priv.h,v 1.30 2005/07/11 16:56:51 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.31 2005/07/13 04:52:31 steve Exp $" #endif # include "vvp_config.h" @@ -63,6 +63,9 @@ extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent); extern void draw_lpm_mux(ivl_lpm_t net); +extern struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid); +extern int draw_ufunc_real(ivl_expr_t exp); + /* * This function draws the execution of a vpi_call statement, along * with the tricky handling of arguments. If this is called with a @@ -191,6 +194,9 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.31 2005/07/13 04:52:31 steve + * Handle functions with real values. + * * Revision 1.30 2005/07/11 16:56:51 steve * Remove NetVariable and ivl_variable_t structures. *