diff --git a/PExpr.h b/PExpr.h index b2c32854f..ea4b20ecc 100644 --- a/PExpr.h +++ b/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; diff --git a/elab_expr.cc b/elab_expr.cc index 0c9270bf7..e2c58dd0f 100644 --- a/elab_expr.cc +++ b/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 { diff --git a/tgt-vvp/draw_ufunc.c b/tgt-vvp/draw_ufunc.c index 3d1d6f519..c7fc80081 100644 --- a/tgt-vvp/draw_ufunc.c +++ b/tgt-vvp/draw_ufunc.c @@ -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) diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index d76cc5c3f..332f519ae 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -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; diff --git a/tgt-vvp/eval_string.c b/tgt-vvp/eval_string.c index d7964ceb1..e477229f2 100644 --- a/tgt-vvp/eval_string.c +++ b/tgt-vvp/eval_string.c @@ -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; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 978ce4b55..e1a256c24 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -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; diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index e382ba960..40d8d87dc 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -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, diff --git a/vvp/codes.h b/vvp/codes.h index e906e770d..709db5495 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -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); diff --git a/vvp/compile.cc b/vvp/compile.cc index a7f345a7e..c5c6857d0 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -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} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index e1e5eb50b..e6c5bc08f 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -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 . * %set/dar/obj/real +* %set/dar/obj/str 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 , , diff --git a/vvp/vthread.cc b/vvp/vthread.cc index bbc87b25e..4895b5a44 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -4957,6 +4957,23 @@ bool of_SET_DAR_OBJ_REAL(vthread_t thr, vvp_code_t cp) return true; } +/* + * %set/dar/obj/str + */ +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(); + assert(darray); + + darray->set_word(adr, value); + return true; +} + /* * This implements the "%set/v