From 2030e06988dfc418fd9cab1b201c52190af14e0b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 9 Oct 2013 20:15:10 -0700 Subject: [PATCH] Parse/elaborate some array-patterns down to the ivl_target API. --- PExpr.cc | 6 +++--- PExpr.h | 10 +++++++--- Statement.h | 5 +++-- design_dump.cc | 13 +++++++++++++ dup_expr.cc | 11 +++++++++++ elab_expr.cc | 39 +++++++++++++++++++++++++++++++++++---- elaborate.cc | 15 ++++++++------- emit.cc | 5 +++++ ivl_target.h | 5 +++-- net_expr.cc | 16 +++++++++++++++- net_nex_input.cc | 15 +++++++++++++++ netlist.h | 19 +++++++++++++++++++ parse.y | 15 +++++++-------- pform_dump.cc | 4 +++- t-dll-api.cc | 7 +++++++ t-dll-expr.cc | 25 +++++++++++++++++++++++++ t-dll.h | 6 ++++++ target.cc | 6 ++++++ target.h | 1 + tgt-stub/expression.c | 14 ++++++++++++++ 20 files changed, 206 insertions(+), 31 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index 75792cded..8365720ef 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -436,12 +436,12 @@ bool PEIdent::has_aa_term(Design*des, NetScope*scope) const return false; } -PENew::PENew(PExpr*size_expr) -: size_(size_expr) +PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr) +: size_(size_expr), init_(init_expr) { } -PENew::~PENew() +PENewArray::~PENewArray() { delete size_; } diff --git a/PExpr.h b/PExpr.h index fff5e4208..aedf82cd7 100644 --- a/PExpr.h +++ b/PExpr.h @@ -209,6 +209,9 @@ class PEAssignPattern : public PExpr { virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, unsigned expr_wid, unsigned flags) const; + private: + NetExpr* elaborate_expr_darray_(Design*des, NetScope*scope, + ivl_type_t type, unsigned flags) const; private: std::vectorparms_; @@ -499,11 +502,11 @@ class PEIdent : public PExpr { long&midx, long&lidx) const; }; -class PENew : public PExpr { +class PENewArray : public PExpr { public: - explicit PENew (PExpr*s); - ~PENew(); + explicit PENewArray (PExpr*s, PExpr*i); + ~PENewArray(); virtual void dump(ostream&) const; virtual unsigned test_width(Design*des, NetScope*scope, @@ -516,6 +519,7 @@ class PENew : public PExpr { private: PExpr*size_; + PExpr*init_; }; class PENewClass : public PExpr { diff --git a/Statement.h b/Statement.h index c3043aed6..938eb55d6 100644 --- a/Statement.h +++ b/Statement.h @@ -105,8 +105,9 @@ class PAssign_ : public Statement { protected: NetAssign_* elaborate_lval(Design*, NetScope*scope) const; - NetExpr* elaborate_rval_(Design*, NetScope*, unsigned lv_width, - ivl_variable_type_t type) const; + NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type, + ivl_variable_type_t lv_type, + unsigned lv_width) const; NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const; NetExpr* elaborate_rval_obj_(Design*, NetScope*, diff --git a/design_dump.cc b/design_dump.cc index 5fff01054..34d7aca89 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1410,6 +1410,19 @@ void NetEAccess::dump(ostream&o) const o << ")"; } +void NetEArrayPattern::dump(ostream&fd) const +{ + fd << "'{"; + if (items_.size() >= 1) { + if (items_[0]) fd << *items_[0]; + } + for (size_t idx = 1 ; idx < items_.size() ; idx += 1) { + fd << ", "; + if (items_[idx]) fd << *items_[idx]; + } + fd << "}"; +} + void NetEBinary::dump(ostream&o) const { if (op_ == 'm' || op_ == 'M') { diff --git a/dup_expr.cc b/dup_expr.cc index 30b0c22fb..93c509270 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -32,6 +32,17 @@ NetEAccess* NetEAccess::dup_expr() const return tmp; } +NetEArrayPattern*NetEArrayPattern::dup_expr() const +{ + vectortmp (items_.size()); + for (size_t idx = 0 ; idx < tmp.size() ; idx += 1) + tmp[idx] = items_[idx]->dup_expr(); + + NetEArrayPattern*res = new NetEArrayPattern(net_type(), tmp); + res->set_line(*this); + return res; +} + NetEBinary* NetEBinary::dup_expr() const { ivl_assert(*this, 0); diff --git a/elab_expr.cc b/elab_expr.cc index 2cd5966f0..6009f1a3e 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -210,6 +210,9 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return tmp; } + if (ntype->base_type()==IVL_VT_DARRAY) + return elaborate_expr_darray_(des, scope, ntype, flags); + cerr << get_fileline() << ": sorry: I don't know how to elaborate " << "assignment_pattern expressions yet." << endl; cerr << get_fileline() << ": : Expression is: " << *this @@ -218,6 +221,27 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return 0; } +NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope, + ivl_type_t ntype, unsigned flags) const +{ + const netdarray_t*array_type = dynamic_cast (ntype); + ivl_assert(*this, array_type); + + // This is an array pattern, so run through the elements of + // the expression and elaborate each as if they are + // element_type expressions. + ivl_type_t elem_type = array_type->element_type(); + vector elem_exprs (parms_.size()); + for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) { + NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags); + elem_exprs[idx] = tmp; + } + + NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs); + res->set_line(*this); + return res; +} + NetExpr* PEAssignPattern::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const { cerr << get_fileline() << ": sorry: I do not know how to" @@ -4578,7 +4602,7 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope, return node; } -unsigned PENew::test_width(Design*, NetScope*, width_mode_t&) +unsigned PENewArray::test_width(Design*, NetScope*, width_mode_t&) { expr_type_ = IVL_VT_DARRAY; expr_width_ = 1; @@ -4587,8 +4611,8 @@ unsigned PENew::test_width(Design*, NetScope*, width_mode_t&) return 1; } -NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, - ivl_type_t ntype, unsigned flags) const +NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope, + ivl_type_t ntype, unsigned flags) const { // Elaborate the size expression. width_mode_t mode = LOSSLESS; @@ -4597,13 +4621,20 @@ NetExpr* PENew::elaborate_expr(Design*des, NetScope*scope, NetENew*tmp = new NetENew(ntype, size); tmp->set_line(*this); + + if (init_) { + cerr << get_fileline() << ": sorry: Dynamic array initialization expressions " + << "not supported yet." << endl; + des->errors += 1; + } + return tmp; } /* * This method should never actually be called. */ -NetExpr* PENew::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const +NetExpr* PENewArray::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const { ivl_assert(*this, 0); return 0; diff --git a/elaborate.cc b/elaborate.cc index 4657d1e60..ac1924090 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2245,8 +2245,9 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, } NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, - unsigned lv_width, - ivl_variable_type_t lv_type) const + ivl_type_t lv_net_type, + ivl_variable_type_t lv_type, + unsigned lv_width) const { ivl_assert(*this, rval_); @@ -2254,8 +2255,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, // elaborate_rval_expr, so punt and pass nil. In the future we // should look into fixing calls to this method to pass a // net_type instead of the separate lv_width/lv_type values. - NetExpr*rv = elaborate_rval_expr(des, scope, 0, lv_type, lv_width, rval(), - is_constant_); + NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width, + rval(), is_constant_); if (!is_constant_ || !rv) return rv; @@ -2373,7 +2374,7 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const NetAssign_*lv = elaborate_lval(des, scope); if (lv == 0) return 0; - NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); + NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv)); if (rv == 0) return 0; NetAssign*cur = new NetAssign(lv, op_, rv); @@ -2461,7 +2462,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const } else { /* Elaborate the r-value expression, then try to evaluate it. */ - rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); + rv = elaborate_rval_(des, scope, lv_net_type, lv->expr_type(), count_lval_width(lv)); } if (rv == 0) return 0; @@ -2653,7 +2654,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const // because it would necessarily trigger other errors. } - NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv), lv->expr_type()); + NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv)); if (rv == 0) return 0; NetExpr*delay = 0; diff --git a/emit.cc b/emit.cc index e58b7e098..02f2e729c 100644 --- a/emit.cc +++ b/emit.cc @@ -546,6 +546,11 @@ void NetEAccess::expr_scan(struct expr_scan_t*tgt) const tgt->expr_access_func(this); } +void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const +{ + tgt->expr_array_pattern(this); +} + void NetEBinary::expr_scan(struct expr_scan_t*tgt) const { tgt->expr_binary(this); diff --git a/ivl_target.h b/ivl_target.h index 130bcbdc3..e8e8178fc 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -228,6 +228,7 @@ typedef enum ivl_expr_type_e { IVL_EX_NEW = 23, IVL_EX_NULL = 22, IVL_EX_NUMBER = 5, + IVL_EX_ARRAY_PATTERN = 26, IVL_EX_PROPERTY = 24, IVL_EX_REALNUM = 16, IVL_EX_SCOPE = 6, @@ -903,9 +904,9 @@ extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net); extern ivl_expr_t ivl_expr_oper3(ivl_expr_t net); /* and expression */ extern ivl_parameter_t ivl_expr_parameter(ivl_expr_t net); - /* IVL_EX_CONCAT IVL_EX_UFUNC */ + /* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_UFUNC */ extern ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx); - /* IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */ + /* IVL_EX_ARRAY_PATTERN IVL_EX_CONCAT IVL_EX_SFUNC IVL_EX_UFUNC */ extern unsigned ivl_expr_parms(ivl_expr_t net); /* IVL_EX_CONCAT */ extern unsigned ivl_expr_repeat(ivl_expr_t net); diff --git a/net_expr.cc b/net_expr.cc index 0057e5dec..927c163ba 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -61,7 +61,10 @@ bool NetExpr::has_width() const */ ivl_variable_type_t NetExpr::expr_type() const { - return IVL_VT_LOGIC; + if (net_type_) + return net_type_->base_type(); + else + return IVL_VT_LOGIC; } const netenum_t*NetExpr::enumeration() const @@ -69,6 +72,17 @@ const netenum_t*NetExpr::enumeration() const return 0; } +NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector&items) +: NetExpr(lv_type), items_(items) +{ +} + +NetEArrayPattern::~NetEArrayPattern() +{ + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) + delete items_[idx]; +} + /* * Create an add/sub node from the two operands. */ diff --git a/net_nex_input.cc b/net_nex_input.cc index 7b83577c4..e46899458 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -43,6 +43,21 @@ NexusSet* NetProc::nex_input(bool) return 0; } +NexusSet* NetEArrayPattern::nex_input(bool rem_out) +{ + NexusSet*result = new NexusSet; + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { + if (items_[idx]==0) continue; + + NexusSet*tmp = items_[idx]->nex_input(rem_out); + if (tmp == 0) continue; + + result->add(*tmp); + delete tmp; + } + return result; +} + NexusSet* NetEBinary::nex_input(bool rem_out) { NexusSet*result = left_->nex_input(rem_out); diff --git a/netlist.h b/netlist.h index 4e9586fc3..bc12cfcf9 100644 --- a/netlist.h +++ b/netlist.h @@ -1914,6 +1914,25 @@ class NetExpr : public LineInfo { NetExpr& operator=(const NetExpr&); }; +class NetEArrayPattern : public NetExpr { + + public: + NetEArrayPattern(ivl_type_t lv_type, std::vector&items); + ~NetEArrayPattern(); + + inline size_t item_size() const { return items_.size(); } + const NetExpr* item(size_t idx) const { return items_[idx]; } + + void expr_scan(struct expr_scan_t*) const; + void dump(ostream&) const; + + NetEArrayPattern* dup_expr() const; + NexusSet* nex_input(bool rem_out =true); + + private: + std::vector items_; +}; + /* * The expression constant is slightly special, and is sometimes * returned from other classes that can be evaluated at compile diff --git a/parse.y b/parse.y index 1e2313725..e26656d24 100644 --- a/parse.y +++ b/parse.y @@ -1069,13 +1069,11 @@ endnew_opt : ':' K_new | ; dynamic_array_new /* IEEE1800-2005: A.2.4 */ : K_new '[' expression ']' - { $$ = new PENew($3); + { $$ = new PENewArray($3, 0); FILE_NAME($$, @1); } | K_new '[' expression ']' '(' expression ')' - { yyerror(@1, "sorry: Dynamic array new expression with initializer not supported."); - delete $6; - $$ = new PENew($3); + { $$ = new PENewArray($3, $6); FILE_NAME($$, @1); } ; @@ -5075,11 +5073,12 @@ register_variable pform_set_reg_idx(name, $2); $$ = $1; } - | IDENTIFIER '=' expression - { perm_string ident_name = lex_strings.make($1); - pform_makewire(@1, ident_name, NetNet::REG, + | IDENTIFIER dimensions_opt '=' expression + { perm_string name = lex_strings.make($1); + pform_makewire(@1, name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_NO_TYPE, 0); - pform_make_reginit(@1, ident_name, $3); + pform_set_reg_idx(name, $2); + pform_make_reginit(@1, name, $4); $$ = $1; } ; diff --git a/pform_dump.cc b/pform_dump.cc index 55f5db8bd..46f920e99 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -312,9 +312,11 @@ void PEFNumber::dump(ostream &out) const out << value(); } -void PENew::dump(ostream&out) const +void PENewArray::dump(ostream&out) const { out << "new [" << *size_ << "]"; + if (init_) + out << "(" << *init_ << ")"; } void PENewClass::dump(ostream&out) const diff --git a/t-dll-api.cc b/t-dll-api.cc index b63db6f0b..2b9549957 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -570,6 +570,10 @@ extern "C" ivl_expr_t ivl_expr_parm(ivl_expr_t net, unsigned idx) assert(net); switch (net->type_) { + case IVL_EX_ARRAY_PATTERN: + assert(idx < net->u_.array_pattern_.parms); + return net->u_.array_pattern_.parm[idx]; + case IVL_EX_CONCAT: assert(idx < net->u_.concat_.parms); return net->u_.concat_.parm[idx]; @@ -593,6 +597,9 @@ extern "C" unsigned ivl_expr_parms(ivl_expr_t net) assert(net); switch (net->type_) { + case IVL_EX_ARRAY_PATTERN: + return net->u_.array_pattern_.parms; + case IVL_EX_CONCAT: return net->u_.concat_.parms; diff --git a/t-dll-expr.cc b/t-dll-expr.cc index 019ca9773..c1e96b177 100644 --- a/t-dll-expr.cc +++ b/t-dll-expr.cc @@ -175,6 +175,31 @@ void dll_target::expr_access_func(const NetEAccess*net) expr_->u_.branch_.nature = net->get_nature(); } +void dll_target::expr_array_pattern(const NetEArrayPattern*net) +{ + assert(expr_ == 0); + ivl_expr_t expr_tmp = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s)); + expr_tmp->type_ = IVL_EX_ARRAY_PATTERN; + expr_tmp->value_= net->expr_type(); + expr_tmp->net_type = net->net_type(); + expr_tmp->width_ = 1; + expr_tmp->signed_ = 0; + expr_tmp->sized_ = 0; + FILE_NAME(expr_tmp, net); + + expr_tmp->u_.array_pattern_.parms = net->item_size(); + expr_tmp->u_.array_pattern_.parm = new ivl_expr_t [net->item_size()]; + + for (size_t idx = 0 ; idx < net->item_size() ; idx += 1) { + const NetExpr*tmp = net->item(idx); + tmp->expr_scan(this); + expr_tmp->u_.array_pattern_.parm[idx] = expr_; + expr_ = 0; + } + + expr_ = expr_tmp; +} + void dll_target::expr_binary(const NetEBinary*net) { assert(expr_ == 0); diff --git a/t-dll.h b/t-dll.h index 499fdad84..405677a14 100644 --- a/t-dll.h +++ b/t-dll.h @@ -135,6 +135,7 @@ struct dll_target : public target_t, public expr_scan_t { struct ivl_expr_s*expr_; void expr_access_func(const NetEAccess*); + void expr_array_pattern(const NetEArrayPattern*); void expr_binary(const NetEBinary*); void expr_concat(const NetEConcat*); void expr_const(const NetEConst*); @@ -239,6 +240,11 @@ struct ivl_expr_s { ivl_expr_t rig_; } binary_; + struct { + size_t parms; + ivl_expr_t*parm; + } array_pattern_; + struct { ivl_select_type_t sel_type_; ivl_expr_t expr_; diff --git a/target.cc b/target.cc index d20ba32f5..bb5bfb8c1 100644 --- a/target.cc +++ b/target.cc @@ -452,6 +452,12 @@ void expr_scan_t::expr_access_func(const NetEAccess*) "unhandled expr_access_func." << endl; } +void expr_scan_t::expr_array_pattern(const NetEArrayPattern*) +{ + cerr << "expr_scan_t (" << typeid(*this).name() << "): " + "unhandled expr_array_pattern." << endl; +} + void expr_scan_t::expr_const(const NetEConst*) { cerr << "expr_scan_t (" << typeid(*this).name() << "): " diff --git a/target.h b/target.h index a70047d73..69642ac64 100644 --- a/target.h +++ b/target.h @@ -152,6 +152,7 @@ struct target_t { struct expr_scan_t { virtual ~expr_scan_t(); virtual void expr_access_func(const NetEAccess*); + virtual void expr_array_pattern(const NetEArrayPattern*); virtual void expr_const(const NetEConst*); virtual void expr_new(const NetENew*); virtual void expr_null(const NetENull*); diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index b711d9f93..6eb320f82 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -40,6 +40,16 @@ static void show_array_expression(ivl_expr_t net, unsigned ind) ivl_signal_dimensions(sig), width, vt); } +static void show_array_pattern_expression(ivl_expr_t net, unsigned ind) +{ + size_t idx; + fprintf(out, "%*sArrayPattern (%s): %u expressions\n", + ind, "", vt_type_string(net), ivl_expr_parms(net)); + for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1) { + show_expression(ivl_expr_parm(net,idx), ind+4); + } +} + static void show_branch_access_expression(ivl_expr_t net, unsigned ind) { ivl_branch_t bra = ivl_expr_branch(net); @@ -408,6 +418,10 @@ void show_expression(ivl_expr_t net, unsigned ind) show_array_expression(net, ind); break; + case IVL_EX_ARRAY_PATTERN: + show_array_pattern_expression(net, ind); + break; + case IVL_EX_BACCESS: show_branch_access_expression(net, ind); break;