From 9a7f31c728ade1e732d8da5fe5d854455a043383 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 1 Mar 2016 15:38:28 -0800 Subject: [PATCH] Functions that return strings pass the return value on the stack. --- parse.y | 9 +++++++ tgt-vvp/draw_ufunc.c | 15 ++---------- tgt-vvp/eval_string.c | 9 +++++++ tgt-vvp/stmt_assign.c | 13 ++++++++++ tgt-vvp/vvp_scope.c | 6 +++++ vvp/codes.h | 2 ++ vvp/compile.cc | 2 ++ vvp/opcodes.txt | 1 + vvp/vthread.cc | 55 +++++++++++++++++++++++++++++++++++++++++-- 9 files changed, 97 insertions(+), 15 deletions(-) diff --git a/parse.y b/parse.y index 806b58713..7f2249475 100644 --- a/parse.y +++ b/parse.y @@ -2067,6 +2067,15 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */ $$ = tmp; } + + /* Ports can be string. */ + + | port_direction K_string list_of_identifiers ';' + { vector*tmp = pform_make_task_ports(@1, $1, IVL_VT_STRING, true, + 0, $3); + $$ = tmp; + } + ; diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index 7fe88abf2..7f6fd1aaf 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -185,9 +185,6 @@ static void draw_ufunc_epilogue(ivl_expr_t expr) void draw_ufunc_vec4(ivl_expr_t expr) { - ivl_scope_t def = ivl_expr_def(expr); - ivl_signal_t retval = ivl_scope_port(def, 0); - (void) retval; /* Take in arguments to function and call function code. */ draw_ufunc_preamble(expr); @@ -197,9 +194,6 @@ void draw_ufunc_vec4(ivl_expr_t expr) void draw_ufunc_real(ivl_expr_t expr) { - ivl_scope_t def = ivl_expr_def(expr); - ivl_signal_t retval = ivl_scope_port(def, 0); - (void) retval; /* Take in arguments to function and call the function code. */ draw_ufunc_preamble(expr); @@ -212,17 +206,12 @@ void draw_ufunc_real(ivl_expr_t expr) void draw_ufunc_string(ivl_expr_t expr) { - ivl_scope_t def = ivl_expr_def(expr); - ivl_signal_t retval = ivl_scope_port(def, 0); /* Take in arguments to function and call the function code. */ draw_ufunc_preamble(expr); - /* Return value signal cannot be an array. */ - assert(ivl_signal_dimensions(retval) == 0); - - /* Load the result into a word. */ - fprintf(vvp_out, " %%load/str v%p_0;\n", retval); + /* The %callf/str function emitted by the preamble leaves + the result in the stack for us. */ draw_ufunc_epilogue(expr); } diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c index 8cdb26338..d3bc1362d 100644 --- a/tgt-vvp/eval_string.c +++ b/tgt-vvp/eval_string.c @@ -76,6 +76,15 @@ static void string_ex_signal(ivl_expr_t expr) return; } + /* 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/str 0; Load %s (string_ex_signal)\n", + ivl_signal_basename(sig)); + return; + } + /* Simple case: This is a simple variable. Generate a load statement to load the string into the stack. */ if (ivl_signal_dimensions(sig) == 0) { diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 339a4ee60..f10291e20 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -894,6 +894,19 @@ static int show_stmt_assign_sig_string(ivl_statement_t net) assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_opcode(net) == 0); + /* Special case: If the l-value signal (string) 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(var)) { + assert(ivl_signal_dimensions(var) == 0); + assert(part == 0 && aidx == 0); + draw_eval_string(rval); + fprintf(vvp_out, " %%ret/str 0; Assign to %s\n", + ivl_signal_basename(var)); + return 0; + } + /* Simplest case: no mux. Evaluate the r-value as a string and store the result into the variable. Note that the %store/str opcode pops the string result. */ diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 615a322d4..9bd197df6 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -467,6 +467,12 @@ 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_STRING) + && signal_is_return_value(sig)) { + fprintf(vvp_out, "; Variable %s is string return value of scope S_%p\n", + ivl_signal_basename(sig), ivl_signal_scope(sig)); + return; + } if ((ivl_signal_data_type(sig)==IVL_VT_LOGIC) && signal_is_return_value(sig)) { fprintf(vvp_out, "; Variable %s is vec4 return value of scope S_%p\n", diff --git a/vvp/codes.h b/vvp/codes.h index 8466386b4..b8db26ae6 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -199,8 +199,10 @@ extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code); extern bool of_REPLICATE(vthread_t thr, vvp_code_t code); extern bool of_RET_REAL(vthread_t thr, vvp_code_t code); +extern bool of_RET_STR(vthread_t thr, vvp_code_t code); extern bool of_RET_VEC4(vthread_t thr, vvp_code_t code); extern bool of_RETLOAD_REAL(vthread_t thr, vvp_code_t code); +extern bool of_RETLOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t code); extern bool of_SCOPY(vthread_t thr, vvp_code_t code); extern bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 3bb461e0d..1bd7d0d8c 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -250,8 +250,10 @@ static const struct opcode_table_s opcode_table[] = { { "%release/wr", of_RELEASE_WR, 2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} }, { "%replicate", of_REPLICATE, 1,{OA_NUMBER, OA_NONE,OA_NONE} }, { "%ret/real", of_RET_REAL, 1,{OA_NUMBER, OA_NONE,OA_NONE} }, + { "%ret/str", of_RET_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} }, { "%ret/vec4", of_RET_VEC4, 3,{OA_NUMBER, OA_BIT1,OA_BIT2} }, { "%retload/real",of_RETLOAD_REAL,1,{OA_NUMBER, OA_NONE,OA_NONE} }, + { "%retload/str", of_RETLOAD_STR, 1,{OA_NUMBER, OA_NONE,OA_NONE} }, { "%retload/vec4",of_RETLOAD_VEC4,1,{OA_NUMBER, OA_NONE,OA_NONE} }, { "%scopy", of_SCOPY, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index a9529373e..6df430586 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1026,6 +1026,7 @@ if not 1, the assign is suppressed. * %retload/vec4 * %retload/real +* %retload/str Read a value from the indexed function argument. The value is read from the argument and pushed to the appropriate stack. diff --git a/vvp/vthread.cc b/vvp/vthread.cc index e99206198..df8bb0399 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -115,6 +115,7 @@ struct vthread_s { // corresponding stack. This is how the %ret/* instructions // get at parent thread arguments. vector args_real; + vector args_str; vector args_vec4; private: @@ -218,6 +219,12 @@ struct vthread_s { unsigned use_index = stack_str_.size()-1-depth; return stack_str_[use_index]; } + inline void poke_str(unsigned depth, const string&val) + { + assert(depth < stack_str_.size()); + unsigned use_index = stack_str_.size()-1-depth; + stack_str_[use_index] = val; + } inline void pop_str(unsigned cnt) { while (cnt > 0) { @@ -1357,9 +1364,11 @@ bool of_CALLF_REAL(vthread_t thr, vvp_code_t cp) bool of_CALLF_STR(vthread_t thr, vvp_code_t cp) { vthread_t child = vthread_new(cp->cptr2, cp->scope); - return do_callf_void(thr, child); - // XXXX NOT IMPLEMENTED + thr->push_str(""); + child->args_str.push_back(0); + + return do_callf_void(thr, child); } bool of_CALLF_VEC4(vthread_t thr, vvp_code_t cp) @@ -4993,6 +5002,27 @@ bool of_RET_REAL(vthread_t thr, vvp_code_t cp) return true; } +/* + * %ret/str + */ +bool of_RET_STR(vthread_t thr, vvp_code_t cp) +{ + size_t index = cp->number; + string val = thr->pop_str(); + + vthread_t fun_thr = thr; + while (fun_thr->parent_scope->get_type_code() != vpiFunction) { + assert(fun_thr->parent); + fun_thr = fun_thr->parent; + } + assert(index < fun_thr->args_str.size()); + unsigned depth = fun_thr->args_str[index]; + // Use the depth to put the value into the stack of + // the parent thread. + fun_thr->parent->poke_str(depth, val); + return true; +} + /* * %ret/vec4 , , */ @@ -5085,6 +5115,27 @@ bool of_RETLOAD_REAL(vthread_t thr, vvp_code_t cp) return true; } +/* + * %retload/str + */ +bool of_RETLOAD_STR(vthread_t thr, vvp_code_t cp) +{ + size_t index = cp->number; + + + vthread_t fun_thr = thr; + while (fun_thr->parent_scope->get_type_code() != vpiFunction) { + assert(fun_thr->parent); + fun_thr = fun_thr->parent; + } + assert(index < fun_thr->args_str.size()); + unsigned depth = fun_thr->args_str[index]; + // Use the depth to extract the values from the stack + // of the parent thread. + thr->push_str(fun_thr->parent->peek_str(depth)); + return true; +} + /* * %retload/vec4 */