diff --git a/elab_expr.cc b/elab_expr.cc index bba38a273..7513c1701 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4007,9 +4007,8 @@ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, unsigned use_wid = size_->test_width(des, scope, mode); NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); - NetESFunc*tmp = new NetESFunc("$ivl_darray_method$new", ntype, 1); + NetENew*tmp = new NetENew(ntype, size); tmp->set_line(*this); - tmp->parm(0, size); return tmp; } @@ -4019,14 +4018,8 @@ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, unsigned, unsigned flags) const { - width_mode_t mode = LOSSLESS; - unsigned use_wid = size_->test_width(des, scope, mode); - NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); - NetESFunc*tmp = new NetESFunc("$ivl_darray_method$new", - IVL_VT_DARRAY, 1, 1); - tmp->set_line(*this); - tmp->parm(0, size); - return tmp; + ivl_assert(*this, 0); + return 0; } unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&) diff --git a/net_expr.cc b/net_expr.cc index a60136487..7e04540c7 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -322,7 +322,12 @@ netenum_t* NetENetenum::netenum() const } NetENew::NetENew(ivl_type_t t) -: obj_type_(t) +: obj_type_(t), size_(0) +{ +} + +NetENew::NetENew(ivl_type_t t, NetExpr*size) +: obj_type_(t), size_(size) { } @@ -330,6 +335,11 @@ NetENew::~NetENew() { } +ivl_variable_type_t NetENew::expr_type() const +{ + return size_ ? IVL_VT_DARRAY : IVL_VT_CLASS; +} + NetENull::NetENull() { } diff --git a/netlist.h b/netlist.h index 2a214d03a..51be20e33 100644 --- a/netlist.h +++ b/netlist.h @@ -3879,10 +3879,16 @@ class NetENetenum : public NetExpr { class NetENew : public NetExpr { public: + // Make class object explicit NetENew(ivl_type_t); + // dynamic array of objects. + explicit NetENew(ivl_type_t, NetExpr*); ~NetENew(); inline ivl_type_t get_type() const { return obj_type_; } + inline const NetExpr*size_expr() const { return size_; } + + virtual ivl_variable_type_t expr_type() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetENew* dup_expr() const; @@ -3892,6 +3898,7 @@ class NetENew : public NetExpr { private: ivl_type_t obj_type_; + NetExpr*size_; }; /* diff --git a/t-dll-api.cc b/t-dll-api.cc index 592aa59a0..3960831d9 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -472,6 +472,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net) case IVL_EX_MEMORY: return net->u_.memory_.idx_; + case IVL_EX_NEW: + return net->u_.new_.size; + case IVL_EX_SIGNAL: return net->u_.signal_.word; diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 1b2ae8576..740369e31 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -318,6 +318,13 @@ void dll_target::expr_creal(const NetECReal*net) void dll_target::expr_new(const NetENew*net) { + ivl_expr_t size = 0; + if (net->size_expr()) { + net->size_expr()->expr_scan(this); + size = expr_; + expr_ = 0; + } + assert(expr_ == 0); expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->width_ = net->expr_width(); @@ -325,8 +332,9 @@ void dll_target::expr_new(const NetENew*net) expr_->sized_ = 1; expr_->type_ = IVL_EX_NEW; FILE_NAME(expr_, net); - expr_->value_ = IVL_VT_CLASS; + expr_->value_ = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS expr_->net_type= net->get_type(); + expr_->u_.new_.size = size; } void dll_target::expr_null(const NetENull*net) diff --git a/t-dll.h b/t-dll.h index 8f966379a..8ea42b35e 100644 --- a/t-dll.h +++ b/t-dll.h @@ -320,6 +320,10 @@ struct ivl_expr_s { uint64_t value; } delay_; + struct { + ivl_expr_t size; + } new_; + } u_; }; diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 894a48c7e..431793f7c 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -167,11 +167,31 @@ static void show_memory_expression(ivl_expr_t net, unsigned ind) static void show_new_expression(ivl_expr_t net, unsigned ind) { - fprintf(out, "%*snew \n", ind, ""); - if (ivl_expr_value(net) != IVL_VT_CLASS) { - fprintf(out, "%sERROR: new expression must be IVL_VT_CLASS, got %s.\n", + switch (ivl_expr_value(net)) { + case IVL_VT_CLASS: + fprintf(out, "%*snew \n", ind, ""); + if (ivl_expr_oper1(net)) { + fprintf(out, "%*sERROR: class_new expression has a size!\n", + ind+3, ""); + show_expression(ivl_expr_oper1(net), ind+3); + stub_errors += 1; + } + break; + case IVL_VT_DARRAY: + fprintf(out, "%*snew [] \n", ind, ""); + if (ivl_expr_oper1(net)) { + show_expression(ivl_expr_oper1(net), ind+3); + } else { + fprintf(out, "%*sERROR: darray_new missing size expression\n", + ind+3, ""); + stub_errors += 1; + } + break; + default: + fprintf(out, "%*snew ERROR: expression type: %s\n", ind+3, "", vt_type_string(net)); stub_errors += 1; + break; } } @@ -179,7 +199,7 @@ static void show_null_expression(ivl_expr_t net, unsigned ind) { fprintf(out, "%*s\n", ind, ""); if (ivl_expr_value(net) != IVL_VT_CLASS) { - fprintf(out, "%sERROR: null expression must be IVL_VT_CLASS, got %s.\n", + fprintf(out, "%*sERROR: null expression must be IVL_VT_CLASS, got %s.\n", ind+3, "", vt_type_string(net)); stub_errors += 1; } diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index a48ca77d6..2e60db26f 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -24,7 +24,7 @@ static int eval_darray_new(ivl_expr_t ex) { unsigned size_reg = allocate_word(); - ivl_expr_t size_expr = ivl_expr_parm(ex, 0); + ivl_expr_t size_expr = ivl_expr_oper1(ex); draw_eval_expr_into_integer(size_expr, size_reg); clr_word(size_reg); @@ -67,23 +67,27 @@ static int eval_darray_new(ivl_expr_t ex) return 0; } -static int draw_eval_object_sfunc(ivl_expr_t ex) +static int eval_class_new(ivl_expr_t ex) { - const char*name = ivl_expr_name(ex); - - if (strcmp(name, "$ivl_darray_method$new") == 0) - return eval_darray_new(ex); - - fprintf(vvp_out, "; ERROR: Invalid system function %s for darray\n", name); - return 1; + fprintf(vvp_out, " %%new/cobj ; XXXX Need to specify the type?\n"); + return 0; } int draw_eval_object(ivl_expr_t ex) { switch (ivl_expr_type(ex)) { - case IVL_EX_SFUNC: - return draw_eval_object_sfunc(ex); + case IVL_EX_NEW: + switch (ivl_expr_value(ex)) { + case IVL_VT_CLASS: + return eval_class_new(ex); + case IVL_VT_DARRAY: + return eval_darray_new(ex); + default: + fprintf(vvp_out, "; ERROR: Invalid type (%d) for \n", + ivl_expr_value(ex)); + return 0; + } default: fprintf(vvp_out, "; ERROR: Invalid expression type %u\n", ivl_expr_type(ex)); return 1; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index c0b8c8472..08ec69360 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -811,6 +811,9 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) if (rvec.base >= 4) clr_vector(rvec); } else { + /* There is no l-value mux, so this must be an + assignment to the array as a whole. Evaluate the + "object", and store the evaluated result. */ errors += draw_eval_object(rval); fprintf(vvp_out, " %%store/obj v%p_0;\n", var); } @@ -818,6 +821,18 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net) return errors; } +static int show_stmt_assign_sig_cobject(ivl_statement_t net) +{ + int errors = 0; + ivl_lval_t lval = ivl_stmt_lval(net, 0); + ivl_expr_t rval = ivl_stmt_rval(net); + ivl_signal_t var= ivl_lval_sig(lval); + + errors += draw_eval_object(rval); + fprintf(vvp_out, " %%store/obj v%p_0;\n", var); + return errors; +} + int show_stmt_assign(ivl_statement_t net) { ivl_lval_t lval; @@ -840,5 +855,9 @@ int show_stmt_assign(ivl_statement_t net) return show_stmt_assign_sig_darray(net); } + if (sig && (ivl_signal_data_type(sig) == IVL_VT_CLASS)) { + return show_stmt_assign_sig_cobject(net); + } + return show_stmt_assign_vector(net); }