diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index f5903fff3..477ddfab8 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -191,9 +191,6 @@ void draw_ufunc_vec4(ivl_expr_t expr) /* Take in arguments to function and call function code. */ draw_ufunc_preamble(expr); - assert(ivl_signal_dimensions(retval) == 0); - fprintf(vvp_out, " %%load/vec4 v%p_0;\n", retval); - draw_ufunc_epilogue(expr); } diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 3587815eb..14e18e53a 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -99,6 +99,12 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result, /* This should never happen since we have IVL_EX_SELECT. */ return 0; + } else if (signal_is_return_value(ivl_expr_signal(expr))) { + /* If the signal is the return value of a function, + then this can't be handled as a true signal, so + fall back on general expression processing. */ + return 0; + } else if (ivl_expr_signed(expr) != ivl_signal_signed(ivl_expr_signal(expr))) { return 0; diff --git a/tgt-vvp/eval_vec4.c b/tgt-vvp/eval_vec4.c index 322b73573..2afd1fbbc 100644 --- a/tgt-vvp/eval_vec4.c +++ b/tgt-vvp/eval_vec4.c @@ -1005,6 +1005,15 @@ static void draw_signal_vec4(ivl_expr_t expr) { ivl_signal_t sig = ivl_expr_signal(expr); + /* Special Case: If the signal is the return value of the function, + then use a different opcode to get the value. */ + if (signal_is_return_value(sig)) { + assert(ivl_signal_dimensions(sig) == 0); + fprintf(vvp_out, " %%retload/vec4 0; Load %s (draw_signal_vec4)\n", + ivl_signal_basename(sig)); + return; + } + /* Handle the simple case, a signal expression that is a simple vector, no array dimensions. */ if (ivl_signal_dimensions(sig) == 0) { diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 8804c6ca2..a28f04ff5 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -209,6 +209,17 @@ static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice, ivl_signal_t sig = ivl_lval_sig(lval); int part_off_idx; + + /* Special Case: If the l-value signal is named after its scope, + and the scope is a function, then this is an assign to a return + value and should be handled differently. */ + if (signal_is_return_value(sig)) { + assert(ivl_signal_dimensions(sig) == 0); + fprintf(vvp_out, " %%ret/vec4 0; Assign to %s\n", + ivl_signal_basename(sig)); + return; + } + /* If the slice of the l-value is a BOOL variable, then cast the data to a BOOL vector so that the stores can be valid. */ if (ivl_signal_data_type(sig) == IVL_VT_BOOL) { @@ -345,6 +356,16 @@ static void store_vec4_to_lval(ivl_statement_t net) if (lidx+1 < ivl_stmt_lvals(net)) fprintf(vvp_out, " %%split/vec4 %u;\n", lwid); + /* Special Case: If the l-value signal is named after its scope, + and the scope is a function, then this is an assign to a return + value and should be handled differently. */ + if (signal_is_return_value(lsig)) { + assert(ivl_signal_dimensions(lsig) == 0); + fprintf(vvp_out, " %%ret/vec4 0; Assign to %s (store_vec4_to_lval)\n", + ivl_signal_basename(lsig)); + continue; + } + if (word_ex) { /* Handle index into an array */ int word_index = allocate_word(); diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 5255058cc..3a4c17bfc 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -208,6 +208,10 @@ extern void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix); */ extern int draw_eval_condition(ivl_expr_t expr); +/* + * Return true if the signal is the return value of a function. + */ +extern int signal_is_return_value(ivl_signal_t sig); extern int number_is_unknown(ivl_expr_t ex); extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid, int negative_is_ok); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 503682806..51a2e2615 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -290,6 +290,16 @@ static unsigned is_netlist_signal(ivl_net_logic_t net, ivl_nexus_t nex) return rtn; } +int signal_is_return_value(ivl_signal_t sig) +{ + ivl_scope_t sig_scope = ivl_signal_scope(sig); + if (ivl_scope_type(sig_scope) != IVL_SCT_FUNCTION) + return 0; + if (strcmp(ivl_signal_basename(sig), ivl_scope_basename(sig_scope)) == 0) + return 1; + return 0; +} + /* * This tests a bufz device against an output receiver, and determines * if the device can be skipped. If this function returns false, then a @@ -458,6 +468,13 @@ static void draw_reg_in_scope(ivl_signal_t sig) ivl_signal_basename(sig), ivl_signal_scope(sig)); return; } + if ((ivl_signal_data_type(sig)==IVL_VT_LOGIC) + && (ivl_scope_type(ivl_signal_scope(sig))==IVL_SCT_FUNCTION) + && (strcmp(ivl_signal_basename(sig),ivl_scope_basename(ivl_signal_scope(sig))) == 0)) { + fprintf(vvp_out, "; Variable %s is vec4 return value of scope S_%p\n", + ivl_signal_basename(sig), ivl_signal_scope(sig)); + return; + } const char *datatype_flag = ivl_signal_integer(sig) ? "/i" : ivl_signal_signed(sig)? "/s" : ""; diff --git a/vvp/README.txt b/vvp/README.txt index f74cf2fa6..16de088f0 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -702,11 +702,14 @@ STRUCTURAL FUNCTION CALLS: The .ufunc statements define a call to a user defined function. -