diff --git a/elab_expr.cc b/elab_expr.cc index 91085f3da..853981878 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3676,6 +3676,20 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const); + if (netdarray_t*darray = net->sig()->darray_type()) { + // Special case: This is a select of a dynamic + // array. Generate a NetESelect and attach it to + // the NetESignal. This should be interpreted as + // an array word select downstream. + if (debug_elaborate) { + cerr << get_fileline() << ": debug: " + << "Bit select of a dynamic array becomes NetESelect." << endl; + } + NetESelect*res = new NetESelect(net, mux, darray->vector_width()); + res->set_line(*net); + return res; + } + // If the bit select is constant, then treat it similar // to the part select, so that I save the effort of // making a mux part in the netlist. @@ -3754,20 +3768,6 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, return res; } - if (netdarray_t*darray = net->sig()->darray_type()) { - // Special case: This is a select of a dynamic - // array. Generate a NetESelect ant attach it to - // the NetESignal. This should be interpreted as - // an array word select downstream. - if (debug_elaborate) { - cerr << get_fileline() << ": debug: " - << "Bit select of a dynamic array becomes NetESelect." << endl; - } - NetESelect*res = new NetESelect(net, mux, darray->vector_width()); - res->set_line(*net); - return res; - } - long idx = net->sig()->sb_to_idx(prefix_indices,msv); if (idx >= (long)net->vector_width() || idx < 0) { diff --git a/netlist.cc b/netlist.cc index 42ca44bb3..554517d61 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2447,7 +2447,10 @@ long NetESignal::msi() const ivl_variable_type_t NetESignal::expr_type() const { - return net_->data_type(); + if (net_->darray_type()) + return IVL_VT_DARRAY; + else + return net_->data_type(); } /* diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 279d65caa..5972827a5 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -209,6 +209,7 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind) ivl_expr_t word = ivl_expr_oper1(net); ivl_signal_t sig = ivl_expr_signal(net); + const char*vt_sig = data_type_string(ivl_signal_data_type(sig)); unsigned dimensions = ivl_signal_dimensions(sig); unsigned word_count = ivl_signal_array_count(sig); @@ -218,8 +219,8 @@ static void show_signal_expression(ivl_expr_t net, unsigned ind) stub_errors += 1; } - fprintf(out, "%*s\n", ind, "", - ivl_expr_name(net), word_count, width, sign, vt); + fprintf(out, "%*s\n", ind, "", + ivl_expr_name(net), word_count, width, sign, vt, vt_sig); /* If the expression refers to a signal array, then there must also be a word select expression, and if the signal is not an diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 619c058af..d7bb7317d 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -187,6 +187,12 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result, if (ivl_expr_value(vexpr) == IVL_VT_STRING) return 0; + /* If the sub-expression is a DARRAY, then this select + is a dynamic-array word select. Handle that + elsewhere. */ + if (ivl_expr_value(vexpr) == IVL_VT_DARRAY) + return 0; + /* The signal is part of an array. */ /* Add &APV<> code here when it is finished. */ bexpr = ivl_expr_oper2(expr); diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 4aa95ca2d..47b997c08 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -2812,6 +2812,19 @@ static struct vector_info draw_select_expr(ivl_expr_t expr, unsigned wid, return res; } + /* Special case: The sub-expression is a DARRAY variable, so + do a dynamic array word load. */ + if (ivl_expr_value(sube) == IVL_VT_DARRAY) { + ivl_signal_t sig = ivl_expr_signal(sube); + assert(sig); + res.base = allocate_vector(wid); + res.wid = wid; + draw_eval_expr_into_integer(shift, 3); + fprintf(vvp_out, " %%load/dar %u, v%p_0, %u;\n", + res.base, sig, res.wid); + return res; + } + if (ivl_expr_type(sube) == IVL_EX_SIGNAL) { res = draw_select_signal(expr, sube, shift, ivl_expr_width(expr), wid); diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index f54ea5889..ae72f8686 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -28,7 +28,8 @@ static int eval_darray_new(ivl_expr_t ex) draw_eval_expr_into_integer(size_expr, size_reg); clr_word(size_reg); - fprintf(vvp_out, " %%new/darray %u;\n", size_reg); + // XXXX: Assume elements are 32bit integers. + fprintf(vvp_out, " %%new/darray %u, \"sb32\";\n", size_reg); return 0; } diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 4b9199ffa..22e117687 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -773,14 +773,30 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) ivl_expr_t rval = ivl_stmt_rval(net); ivl_expr_t part = ivl_lval_part_off(lval); ivl_signal_t var= ivl_lval_sig(lval); + ivl_expr_t mux = ivl_lval_idx(lval); assert(ivl_stmt_lvals(net) == 1); assert(ivl_stmt_opcode(net) == 0); assert(ivl_lval_mux(lval) == 0); assert(part == 0); - errors += draw_eval_object(rval); - fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + if (mux) { + struct vector_info rvec = draw_eval_expr_wid(rval, ivl_lval_width(lval), + STUFF_OK_XZ); + /* The %set/dar expects the array index to be in index + register 3. Calculate the index in place. */ + draw_eval_expr_into_integer(mux, 3); + + fprintf(vvp_out, " %%set/dar v%p_0, %u, %u;\n", + var, rvec.base, rvec.wid); + + if (rvec.base >= 4) clr_vector(rvec); + + } else { + errors += draw_eval_object(rval); + fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + } + return errors; } diff --git a/vvp/codes.h b/vvp/codes.h index e0bc181fb..8bd139c6e 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -125,6 +125,7 @@ extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0_S(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code); +extern bool of_LOAD_DAR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_STR(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); @@ -163,6 +164,7 @@ 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_SET_AR(vthread_t thr, vvp_code_t code); 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_VEC(vthread_t thr, vvp_code_t code); extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code); extern bool of_SET_X0(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 1e6f5eef3..a5d03dd14 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -173,6 +173,7 @@ static const struct opcode_table_s opcode_table[] = { { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0/s",of_LOAD_AVP0_S,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, + { "%load/dar",of_LOAD_DAR,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/str",of_LOAD_STR,1,{OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, @@ -192,7 +193,7 @@ static const struct opcode_table_s opcode_table[] = { { "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%new/darray",of_NEW_DARRAY,1,{OA_NUMBER,OA_NONE, OA_NONE} }, + { "%new/darray",of_NEW_DARRAY,2,{OA_BIT1, OA_STRING, OA_NONE} }, { "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }, { "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -211,6 +212,7 @@ static const struct opcode_table_s opcode_table[] = { { "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} }, { "%set/ar", of_SET_AR, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, + { "%set/dar",of_SET_DAR,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/wr", of_SET_WORDR,2,{OA_FUNC_PTR, OA_BIT1, OA_NONE} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 5f94a2249..57ad13ee4 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -597,6 +597,15 @@ bit, and the is the selector for the bit to use. If is out of range, then x is loaded. The index value is incremented by one if it is defined (bit 4 is not 1). +* %load/dar , , + +This instruction loads an array word from a dynamic array. The +