From 3945b9df456d75ac174900b414f70dedb4b70a53 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 13 Oct 2013 17:54:39 -0700 Subject: [PATCH] Elaborate darray new element initializer to ivl_target API --- design_dump.cc | 9 ++++++++- elab_expr.cc | 23 +++++++++++++++++------ ivl_target.h | 14 ++++++++++++-- net_expr.cc | 6 +++--- netlist.h | 4 +++- t-dll-api.cc | 3 +++ t-dll-expr.cc | 9 +++++++++ t-dll.h | 1 + tgt-stub/expression.c | 12 ++++++++++++ 9 files changed, 68 insertions(+), 13 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 34d7aca89..cdc364826 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1562,7 +1562,14 @@ void NetENetenum::dump(ostream&o) const void NetENew::dump(ostream&o) const { - o << "new "; + o << "new ["; + if (size_) size_->dump(o); + o << "]"; + if (init_val_) { + o << "("; + init_val_->dump(o); + o << ")"; + } } void NetENull::dump(ostream&o) const diff --git a/elab_expr.cc b/elab_expr.cc index 6009f1a3e..d3ab6adaf 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4618,16 +4618,27 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope, width_mode_t mode = LOSSLESS; unsigned use_wid = size_->test_width(des, scope, mode); NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags); + NetExpr*init_val = 0; - NetENew*tmp = new NetENew(ntype, size); - tmp->set_line(*this); + if (dynamic_cast (init_)) { + // Special case: the initial value expression is an + // array_pattern. Elaborate the expresion like the + // r-value to an assignment to array. + init_val = init_->elaborate_expr(des, scope, ntype, flags); - if (init_) { - cerr << get_fileline() << ": sorry: Dynamic array initialization expressions " - << "not supported yet." << endl; - des->errors += 1; + } else if (init_) { + // Regular case: The initial value is an + // expression. Elaborate the expression as an element + // type. The run-time will assign this value to each element. + const netarray_t*array_type = dynamic_cast (ntype); + ivl_type_t elem_type = array_type->element_type(); + + init_val = init_->elaborate_expr(des, scope, elem_type, flags); } + NetENew*tmp = new NetENew(ntype, size, init_val); + tmp->set_line(*this); + return tmp; } diff --git a/ivl_target.h b/ivl_target.h index e8e8178fc..bfee04b75 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -828,6 +828,16 @@ extern unsigned ivl_event_lineno(ivl_event_t net); * table. That number can be passed to ivl_type_prop_*() functions to * get details about the property. * + * - IVL_EX_NEW + * This expression takes one or two operands. The first operand, + * returned by ivl_expr_oper1() is the number of elements to create + * for the dynamic array. The second operand, if present, is returned + * by the ivl_expr_oper2() function. If this returns a non-nil + * expression, it is the initial value to be written to the elements + * of the array. If the expression is an IVL_EX_ARRAY_PATTERN, then + * this is the very special case of a list of values to be written to + * array elements. + * * - IVL_EX_SELECT * This expression takes two operands, oper1 is the expression to * select from, and oper2 is the selection base. The ivl_expr_width @@ -896,9 +906,9 @@ extern const char* ivl_expr_name(ivl_expr_t net); extern ivl_nature_t ivl_expr_nature(ivl_expr_t net); /* IVL_EX_BINARY IVL_EX_UNARY */ extern char ivl_expr_opcode(ivl_expr_t net); - /* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_TERNARY */ + /* IVL_EX_BINARY IVL_EX_UNARY, IVL_EX_MEMORY IVL_EX_NEW IVL_EX_TERNARY */ extern ivl_expr_t ivl_expr_oper1(ivl_expr_t net); - /* IVL_EX_BINARY IVL_EX_TERNARY */ + /* IVL_EX_BINARY IVL_EX_NEW IVL_EX_TERNARY */ extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net); /* IVL_EX_TERNARY */ extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net); diff --git a/net_expr.cc b/net_expr.cc index 927c163ba..6ff935185 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -336,12 +336,12 @@ const netenum_t* NetENetenum::netenum() const } NetENew::NetENew(ivl_type_t t) -: obj_type_(t), size_(0) +: obj_type_(t), size_(0), init_val_(0) { } -NetENew::NetENew(ivl_type_t t, NetExpr*size) -: obj_type_(t), size_(size) +NetENew::NetENew(ivl_type_t t, NetExpr*size, NetExpr*init_val) +: obj_type_(t), size_(size), init_val_(init_val) { } diff --git a/netlist.h b/netlist.h index bc12cfcf9..b1d99b849 100644 --- a/netlist.h +++ b/netlist.h @@ -4030,11 +4030,12 @@ class NetENew : public NetExpr { // Make class object explicit NetENew(ivl_type_t); // dynamic array of objects. - explicit NetENew(ivl_type_t, NetExpr*); + explicit NetENew(ivl_type_t, NetExpr*size, NetExpr* init_val=0); ~NetENew(); inline ivl_type_t get_type() const { return obj_type_; } inline const NetExpr*size_expr() const { return size_; } + inline const NetExpr*init_expr() const { return init_val_; } virtual ivl_variable_type_t expr_type() const; @@ -4047,6 +4048,7 @@ class NetENew : public NetExpr { private: ivl_type_t obj_type_; NetExpr*size_; + NetExpr*init_val_; }; /* diff --git a/t-dll-api.cc b/t-dll-api.cc index 2b9549957..27f431576 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -520,6 +520,9 @@ extern "C" ivl_expr_t ivl_expr_oper2(ivl_expr_t net) case IVL_EX_BINARY: return net->u_.binary_.rig_; + case IVL_EX_NEW: + return net->u_.new_.init_val; + case IVL_EX_SELECT: return net->u_.select_.base_; diff --git a/t-dll-expr.cc b/t-dll-expr.cc index c1e96b177..30c73122e 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -346,12 +346,20 @@ void dll_target::expr_creal(const NetECReal*net) void dll_target::expr_new(const NetENew*net) { ivl_expr_t size = 0; + ivl_expr_t init_val = 0; + if (net->size_expr()) { net->size_expr()->expr_scan(this); size = expr_; expr_ = 0; } + if (net->init_expr()) { + net->init_expr()->expr_scan(this); + init_val = expr_; + expr_ = 0; + } + assert(expr_ == 0); expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); expr_->width_ = net->expr_width(); @@ -362,6 +370,7 @@ void dll_target::expr_new(const NetENew*net) expr_->value_ = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS expr_->net_type= net->get_type(); expr_->u_.new_.size = size; + expr_->u_.new_.init_val = init_val; } void dll_target::expr_null(const NetENull*net) diff --git a/t-dll.h b/t-dll.h index 405677a14..103c84272 100644 --- a/t-dll.h +++ b/t-dll.h @@ -337,6 +337,7 @@ struct ivl_expr_s { struct { ivl_expr_t size; + ivl_expr_t init_val; } new_; struct { diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index 6eb320f82..e80857e31 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -186,6 +186,12 @@ static void show_new_expression(ivl_expr_t net, unsigned ind) show_expression(ivl_expr_oper1(net), ind+3); stub_errors += 1; } + if (ivl_expr_oper2(net)){ + fprintf(out, "%*sERROR: class_new with array element initializer!\n", + ind+3, ""); + show_expression(ivl_expr_oper2(net), ind+3); + stub_errors += 1; + } break; case IVL_VT_DARRAY: fprintf(out, "%*snew [] \n", ind, ""); @@ -195,6 +201,12 @@ static void show_new_expression(ivl_expr_t net, unsigned ind) fprintf(out, "%*sERROR: darray_new missing size expression\n", ind+3, ""); stub_errors += 1; + } + /* The IVL_EX_NEW expression may include an element + initializer. This may be an array pattern or simple + expression. */ + if (ivl_expr_oper2(net)) { + show_expression(ivl_expr_oper2(net), ind+3); } break; default: