Functions that return strings pass the return value on the stack.
This commit is contained in:
parent
7d21891147
commit
9a7f31c728
9
parse.y
9
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<pform_tf_port_t>*tmp = pform_make_task_ports(@1, $1, IVL_VT_STRING, true,
|
||||
0, $3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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} },
|
||||
|
|
|
|||
|
|
@ -1026,6 +1026,7 @@ if not 1, the assign is suppressed.
|
|||
|
||||
* %retload/vec4 <index>
|
||||
* %retload/real <index>
|
||||
* %retload/str <index>
|
||||
|
||||
Read a value from the indexed function argument. The value is read
|
||||
from the argument and pushed to the appropriate stack.
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ struct vthread_s {
|
|||
// corresponding stack. This is how the %ret/* instructions
|
||||
// get at parent thread arguments.
|
||||
vector<unsigned> args_real;
|
||||
vector<unsigned> args_str;
|
||||
vector<unsigned> 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 <index>
|
||||
*/
|
||||
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 <index>, <offset>, <wid>
|
||||
*/
|
||||
|
|
@ -5085,6 +5115,27 @@ bool of_RETLOAD_REAL(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %retload/str <index>
|
||||
*/
|
||||
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 <index>
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue