Handle initialized darray of strings
This includes adding support for returning strings from functions, adding initializing new darray with array_pattern strings, and assigning an array_pattern of strings to a preallocated darray. Also fix up support for initializing array with simple string expression.
This commit is contained in:
parent
d5a0f2fc07
commit
e60804cf41
3
PExpr.h
3
PExpr.h
|
|
@ -632,6 +632,9 @@ class PEString : public PExpr {
|
|||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
width_mode_t&mode);
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const;
|
||||
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
unsigned expr_wid, unsigned) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
|
|
|||
10
elab_expr.cc
10
elab_expr.cc
|
|
@ -4898,6 +4898,16 @@ unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
|
|||
return expr_width_;
|
||||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t type, unsigned)const
|
||||
{
|
||||
verinum val(value());
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*, NetScope*,
|
||||
unsigned expr_wid, unsigned) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -214,7 +214,23 @@ void draw_ufunc_real(ivl_expr_t expr)
|
|||
fprintf(vvp_out, " %%load/real v%p_0;\n", retval);
|
||||
|
||||
draw_ufunc_epilogue(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);
|
||||
|
||||
draw_ufunc_epilogue(expr);
|
||||
}
|
||||
|
||||
void draw_ufunc_object(ivl_expr_t expr)
|
||||
|
|
|
|||
|
|
@ -90,6 +90,14 @@ static int eval_darray_new(ivl_expr_t ex)
|
|||
fprintf(vvp_out, " %%pop/real 1;\n");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) {
|
||||
draw_eval_string(ivl_expr_parm(init_expr,idx));
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/str 3;\n");
|
||||
fprintf(vvp_out, " %%pop/str 1;\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
|
||||
errors += 1;
|
||||
|
|
@ -123,6 +131,14 @@ static int eval_darray_new(ivl_expr_t ex)
|
|||
}
|
||||
fprintf(vvp_out, " %%pop/real 1;\n");
|
||||
break;
|
||||
case IVL_VT_STRING:
|
||||
draw_eval_string(init_expr);
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%set/dar/obj/str 3;\n");
|
||||
}
|
||||
fprintf(vvp_out, " %%pop/str 1;\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, "; ERROR: Sorry, this type not supported here.\n");
|
||||
errors += 1;
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ void draw_eval_string(ivl_expr_t expr)
|
|||
fallback_eval(expr);
|
||||
break;
|
||||
|
||||
case IVL_EX_UFUNC:
|
||||
draw_ufunc_string(expr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fallback_eval(expr);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -853,6 +853,13 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%store/dar/r v%p_0;\n", var);
|
||||
break;
|
||||
|
||||
case IVL_VT_STRING:
|
||||
draw_eval_string(ivl_expr_parm(rval,idx));
|
||||
fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx);
|
||||
fprintf(vvp_out, " %%store/dar/str v%p_0;\n", var);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(vvp_out, "; ERROR: show_stmt_assign_darray_pattern: type_base=%d not implemented\n", ivl_type_base(element_type));
|
||||
errors += 1;
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ extern void draw_lpm_mux(ivl_lpm_t net);
|
|||
|
||||
extern struct vector_info draw_ufunc_expr(ivl_expr_t expr, unsigned wid);
|
||||
extern void draw_ufunc_real(ivl_expr_t expr);
|
||||
extern void draw_ufunc_string(ivl_expr_t expr);
|
||||
extern void draw_ufunc_object(ivl_expr_t expr);
|
||||
|
||||
extern void pad_expr_in_place(ivl_expr_t expr, struct vector_info res,
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ extern bool of_SET_AV(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_SET_DAR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_DAR_OBJ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X0_X(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/dar/obj", of_SET_DAR_OBJ, 3,{OA_NUMBER,OA_BIT1,OA_BIT2} },
|
||||
{ "%set/dar/obj/real",of_SET_DAR_OBJ_REAL,1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
||||
{ "%set/dar/obj/str", of_SET_DAR_OBJ_STR, 1,{OA_NUMBER,OA_NONE,OA_NONE} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -963,10 +963,15 @@ a dynamic array that is in the top of the object stack. Instead of
|
|||
using a fixed index register, use the register addressed by <index>.
|
||||
|
||||
* %set/dar/obj/real <index>
|
||||
* %set/dar/obj/str <index>
|
||||
|
||||
The "%set/dar/obj/real" opcode sets the top value from the real-value
|
||||
stack to the index. This does NOT pop the real value off the
|
||||
stack. The intent is that this value may be written to a bunch of values.
|
||||
stack. The intent is that this value may be written to a bunch of
|
||||
values.
|
||||
|
||||
The "%set/dar/obj/str" opcode does the same but for string values and
|
||||
uses the string stack.
|
||||
|
||||
* %set/v <var-label>, <bit>, <wid>
|
||||
|
||||
|
|
|
|||
|
|
@ -4957,6 +4957,23 @@ bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %set/dar/obj/str <index>
|
||||
*/
|
||||
bool of_SET_DAR_OBJ_STR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned adr = thr->words[cp->number].w_int;
|
||||
|
||||
string value = thr->peek_str(0);
|
||||
|
||||
vvp_object_t&top = thr->peek_object();
|
||||
vvp_darray*darray = top.peek<vvp_darray>();
|
||||
assert(darray);
|
||||
|
||||
darray->set_word(adr, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implements the "%set/v <label>, <bit>, <wid>" instruction.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue