diff --git a/design_dump.cc b/design_dump.cc index 9dfaac2e1..3e14e52b8 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1527,7 +1527,14 @@ void NetESelect::dump(ostream&o) const else o << "(0)"; - o << "+:" << expr_width() << "]>"; + o << "+:" << expr_width() << "]"; + if (ivl_type_t nt = net_type()) { + o << " net_type=(" << *nt << ")"; + } else { + o << " expr_type=" << expr_type(); + } + + o << ">"; } void NetESFunc::dump(ostream&o) const diff --git a/elaborate.cc b/elaborate.cc index 320aa0af8..0d8e10cf1 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2509,10 +2509,17 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const if (lv->expr_type() == IVL_VT_BOOL && rv->expr_type() != IVL_VT_BOOL) { if (debug_elaborate) - cerr << get_fileline() << ": debug: Cast expression to int2" << endl; + cerr << get_fileline() << ": debug: " + << "Cast expression to int2" << endl; rv = cast_to_int2(rv); } + if (lv->expr_type() == IVL_VT_REAL && rv->expr_type() != IVL_VT_REAL) { + if (debug_elaborate) + cerr << get_fileline() << ": debug: " + << "Cast expression to real." << endl; + rv = cast_to_real(rv); + } if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) { cerr << get_fileline() << ": error: " << "Enumeration type mismatch in assignment." << endl; diff --git a/eval_tree.cc b/eval_tree.cc index 12e5f0b35..d677e774d 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -53,6 +53,9 @@ static bool get_real_arg_(const NetExpr*expr, verireal&val) break; } + case IVL_VT_DARRAY: + return false; + default: assert(0); } diff --git a/net_expr.cc b/net_expr.cc index 76fa2caff..12713bbe7 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -348,6 +348,25 @@ ivl_select_type_t NetESelect::select_type() const return sel_type_; } +ivl_variable_type_t NetESelect::expr_type() const +{ + ivl_variable_type_t type = expr_->expr_type(); + if (type != IVL_VT_DARRAY) + return type; + + ivl_assert(*this, type == IVL_VT_DARRAY); + + // Special case: If the expression is a DARRAY, then the + // sub-expression must be a NetESignal and the type of the + // NetESelect expression is the element type of the arrayed signal. + NetESignal*sig = dynamic_cast(expr_); + ivl_assert(*this, sig); + const netarray_t*array_type = dynamic_cast (sig->sig()->net_type()); + ivl_assert(*this, array_type); + + return array_type->element_type()->base_type(); +} + bool NetESelect::has_width() const { return true; diff --git a/netlist.h b/netlist.h index b0d58b54b..f75a6121c 100644 --- a/netlist.h +++ b/netlist.h @@ -3807,6 +3807,10 @@ class NetESelect : public NetExpr { const NetExpr*select() const; ivl_select_type_t select_type() const; + // The type of a NetESelect is the base type of the + // sub-expression. + virtual ivl_variable_type_t expr_type() const; + virtual NexusSet* nex_input(bool rem_out = true); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; diff --git a/netmisc.cc b/netmisc.cc index ee85a9104..b71439fc2 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -152,6 +152,16 @@ NetExpr* cast_to_int2(NetExpr*expr) return cast; } +NetExpr* cast_to_real(NetExpr*expr) +{ + if (expr->expr_type() == IVL_VT_REAL) + return expr; + + NetECast*cast = new NetECast('r', expr, 1, true); + cast->set_line(*expr); + return cast; +} + /* * Add a signed constant to an existing expression. Generate a new * NetEBAdd node that has the input expression and an expression made diff --git a/netmisc.h b/netmisc.h index 4eb35c04b..792f62ac8 100644 --- a/netmisc.h +++ b/netmisc.h @@ -79,6 +79,7 @@ extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid) extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src); extern NetExpr*cast_to_int2(NetExpr*expr); +extern NetExpr*cast_to_real(NetExpr*expr); /* * Take the input expression and return a variation that assures that diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 1ec966637..87164c6a2 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -383,7 +383,7 @@ void dll_target::expr_select(const NetESelect*net) expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->type_ = IVL_EX_SELECT; - expr_->value_= IVL_VT_VECTOR; + expr_->value_= net->expr_type(); expr_->net_type=0; expr_->width_= net->expr_width(); expr_->signed_ = net->has_sign()? 1 : 0; diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 83be3a195..5f9cda357 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -31,7 +31,9 @@ static unsigned show_assign_lval_darray(ivl_lval_t lval, unsigned ind) assert(sig); if (ivl_lval_idx(lval)) { - fprintf(out, "%*sAddress-0 select of dynamic array:\n", ind+4, ""); + fprintf(out, "%*sAddress-0 select of ", ind+4, ""); + show_type_of_signal(sig); + fprintf(out, ":\n"); show_expression(ivl_lval_idx(lval), ind+6); } diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index f0e05b956..72d9053e2 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -36,14 +36,28 @@ static int eval_darray_new(ivl_expr_t ex) ivl_type_t element_type = ivl_type_element(net_type); assert(element_type); - assert(ivl_type_packed_dimensions(element_type) == 1); - int msb = ivl_type_packed_msb(element_type, 0); - int lsb = ivl_type_packed_lsb(element_type, 0); - int wid = msb>=lsb? msb - lsb : lsb - msb; - wid += 1; + switch (ivl_type_base(element_type)) { + case IVL_VT_REAL: + // REAL objects are not packable. + assert(ivl_type_packed_dimensions(element_type) == 0); + fprintf(vvp_out, " %%new/darray %u, \"r\";\n", size_reg); + break; + case IVL_VT_BOOL: + // bool objects are vectorable, but for now only support + // a single dimensions. + assert(ivl_type_packed_dimensions(element_type) == 1); + int msb = ivl_type_packed_msb(element_type, 0); + int lsb = ivl_type_packed_lsb(element_type, 0); + int wid = msb>=lsb? msb - lsb : lsb - msb; + wid += 1; - // XXXX: Assume elements are signed integers. - fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); + fprintf(vvp_out, " %%new/darray %u, \"sb%d\";\n", size_reg, wid); + break; + + default: + assert(0); + break; + } return 0; } diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 6c1c4176e..17269c0dc 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -306,6 +306,26 @@ static int draw_real_logic_expr(ivl_expr_t expr, int stuff_ok_flag) return res; } +static int draw_select_real(ivl_expr_t expr) +{ + int res; + /* The sube references the expression to be selected from. */ + ivl_expr_t sube = ivl_expr_oper1(expr); + /* This is the select expression */ + ivl_expr_t shift= ivl_expr_oper2(expr); + + /* Assume the sub-expression is a signal */ + ivl_signal_t sig = ivl_expr_signal(sube); + assert(ivl_signal_data_type(sig) == IVL_VT_DARRAY); + + res = allocate_word(); + + draw_eval_expr_into_integer(shift, 3); + fprintf(vvp_out, " %%load/dar/r %u, v%p_0;\n", res, sig); + + return res; +} + static int draw_sfunc_real(ivl_expr_t expr) { int res; @@ -619,6 +639,10 @@ int draw_eval_real(ivl_expr_t expr) res = draw_realnum_real(expr); break; + case IVL_EX_SELECT: + res = draw_select_real(expr); + break; + case IVL_EX_SFUNC: res = draw_sfunc_real(expr); break; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 3badf40d7..aca4c198d 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -773,6 +773,10 @@ 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_type_t var_type= ivl_signal_net_type(var); + assert(ivl_type_base(var_type) == IVL_VT_DARRAY); + ivl_type_t element_type = ivl_type_element(var_type); + ivl_expr_t mux = ivl_lval_idx(lval); assert(ivl_stmt_lvals(net) == 1); @@ -780,7 +784,17 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) assert(ivl_lval_mux(lval) == 0); assert(part == 0); - if (mux) { + if (mux && (ivl_type_base(element_type)==IVL_VT_REAL)) { + int dst = draw_eval_real(rval); + + /* 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/r v%p_0, %u;\n", var, dst); + clr_word(dst); + + } else 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 diff --git a/vvp/codes.h b/vvp/codes.h index f34b48c31..0e330e4a8 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -126,6 +126,7 @@ 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_DAR_R(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); @@ -165,6 +166,7 @@ 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_DAR_R(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 6dd05a13f..bbe80bf35 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -170,14 +170,15 @@ static const struct opcode_table_s opcode_table[] = { { "%join/detach",of_JOIN_DETACH,1,{OA_NUMBER,OA_NONE, OA_NONE} }, { "%load/ar",of_LOAD_AR,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, - { "%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/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/dar/r",of_LOAD_DAR_R,2,{OA_BIT1, OA_FUNC_PTR, OA_NONE} }, { "%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} }, - { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, + { "%load/vp0/s",of_LOAD_VP0_S,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/wr",of_LOAD_WR,2, {OA_BIT1, OA_VPI_PTR, OA_BIT2} }, { "%load/x1p",of_LOAD_X1P,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%loadi/wr",of_LOADI_WR,3,{OA_BIT1, OA_NUMBER, OA_BIT2} }, @@ -213,6 +214,7 @@ static const struct opcode_table_s opcode_table[] = { { "%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/dar/r",of_SET_DAR_R,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} }, { "%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 1884f7b38..9b27187bb 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -598,12 +598,15 @@ 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 , , +* %load/dar/r , This instruction loads an array word from a dynamic array. The