diff --git a/PExpr.h b/PExpr.h index 627e3183d2..b2d1d64304 100644 --- a/PExpr.h +++ b/PExpr.h @@ -221,10 +221,6 @@ 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_; }; diff --git a/design_dump.cc b/design_dump.cc index 67b41a7745..1f16f918ee 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1673,6 +1673,19 @@ void NetEArrayPattern::dump(ostream&fd) const fd << "}"; } +void NetEArrayPatternParam::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 c1c2246db4..b613f5bc55 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -43,6 +43,17 @@ NetEArrayPattern*NetEArrayPattern::dup_expr() const return res; } +NetEArrayPatternParam*NetEArrayPatternParam::dup_expr() const +{ + vectortmp (items_.size()); + for (size_t idx = 0 ; idx < tmp.size() ; idx += 1) + tmp[idx] = items_[idx]->dup_expr(); + + NetEArrayPatternParam*res = new NetEArrayPatternParam(scope_, name_, 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 c80cf223bd..66ea49d112 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -184,13 +184,21 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const * supported, can assign to packed arrays and structs, unpacked arrays * and dynamic arrays. */ -unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&) +unsigned PEAssignPattern::test_width(Design*des, NetScope*scope, width_mode_t&mode) { - expr_type_ = IVL_VT_DARRAY; - expr_width_ = 1; - min_width_ = 1; - signed_flag_= false; - return 1; + if (parms_.size() > 0) { + parms_[0]->test_width(des, scope, mode); + expr_type_ = parms_[0]->expr_type(); + expr_width_ = parms_.size(); + min_width_ = expr_width_; + signed_flag_= parms_[0]->has_sign(); + } else { + expr_type_ = IVL_VT_DARRAY; + expr_width_ = 1; + min_width_ = 1; + signed_flag_= false; + } + return expr_width_; } NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, @@ -207,9 +215,30 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope, return tmp; } - if (ntype->base_type()==IVL_VT_DARRAY || - ntype->base_type()==IVL_VT_QUEUE) - return elaborate_expr_darray_(des, scope, ntype, flags); + const netarray_t*array_type = dynamic_cast (ntype); + if (array_type) { + + if (array_type->slice_dimensions().size() > 1) { + des->errors += 1; + cerr << get_fileline() << ": sorry: I don't know how to elaborate " + << "multi-dimensions assignment patterns." << endl; + return 0; + } + + // 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; + } cerr << get_fileline() << ": sorry: I don't know how to elaborate " << "assignment_pattern expressions yet." << endl; @@ -219,27 +248,6 @@ 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" @@ -685,12 +693,12 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope, NetExpr*lp = left_->elaborate_expr(des, scope, l_width_, flags); if (lp && debug_elaborate) { cerr << get_fileline() << ": PEBComp::elaborate_expr: " - << "Elaborated left_: " << *lp << endl; + << "Elaborated left_: " << *lp << ", width_: " << l_width_ << endl; } NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags); if (rp && debug_elaborate) { cerr << get_fileline() << ": PEBComp::elaborate_expr: " - << "Elaborated right_: " << *rp << endl; + << "Elaborated right_: " << *rp << ", width_: " << r_width_ << endl; } if ((lp == 0) || (rp == 0)) { @@ -4061,6 +4069,32 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } + if (par != 0) { + const netuarray_t*array = dynamic_cast (par->net_type()); + if (array) { + switch (use_sel) { + case index_component_t::SEL_BIT: + case index_component_t::SEL_BIT_LAST: + expr_type_ = array->element_type()->base_type(); + if (expr_type_ == IVL_VT_STRING) { + des->errors += 1; + cerr << get_fileline() << ": sorry, I do not yet support string array parameters properly" << endl; + } + expr_width_ = array->element_type()->packed_width(); + min_width_ = expr_width_; + signed_flag_ = array->element_type()->get_signed(); + break; + default: + expr_type_ = array->base_type(); + expr_width_ = array->static_dimensions()[0].width(); + min_width_ = expr_width_; + signed_flag_ = false; + break; + } + return expr_width_; + } + } + // Look for a class property. if (gn_system_verilog() && cls_val) { expr_type_ = cls_val->base_type(); @@ -4255,6 +4289,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, symbol_search(this, des, use_scope, path_, net, par, eve, par_type, cls_val); + if (par != 0) { + return (NetExpr *)par; + } + if (net == 0 && gn_system_verilog() && path_.size() >= 2) { // NOTE: this is assuming the member_path is only one // component long, and that the use_path will wind up @@ -4615,9 +4653,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in, par_type, expr_wid, flags); - if (!tmp) return 0; + if (!tmp) return 0; - return pad_to_width(tmp, expr_wid, signed_flag_, *this); + return pad_to_width(tmp, expr_wid, signed_flag_, *this); } // If the identifier names a signal (a variable or a net) @@ -5044,12 +5082,25 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, ivl_type_t par_type, bool need_const) const { - const NetEConst*par_ex = dynamic_cast (par); - ivl_assert(*this, par_ex); - long par_msv, par_lsv; - if(! calculate_param_range(*this, par_type, par_msv, par_lsv, - par_ex->value().len())) return 0; + const NetEArrayPattern*par_aex; + const NetEConst*par_cex = dynamic_cast (par); + if(!par_cex) { + par_aex = dynamic_cast (par); + if (par_aex) { + const netuarray_t*array = dynamic_cast (par->net_type()); + if (!array) { + cerr << get_fileline() << "tried to get a word from non-array expression" << endl; + return 0; + } + } else { + cerr << get_fileline() << "cannot select element from provided expression" << endl; + } + } + int par_len = par_cex ? par_cex->value().len() : par_aex->item_size(); + + if(! calculate_param_range(*this, par_type, par_msv, par_lsv, par_len)) + return 0; const name_component_t&name_tail = path_.back(); ivl_assert(*this, !name_tail.index.empty()); @@ -5087,43 +5138,54 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope, return res; } // Calculate the canonical index value. - long sel_v = sel_c->value().as_long(); - if (par_msv >= par_lsv) sel_v -= par_lsv; - else sel_v = par_lsv - sel_v; - - // Select a bit from the parameter. - verinum par_v = par_ex->value(); - verinum::V rtn = verinum::Vx; - - // A constant in range select. - if ((sel_v >= 0) && ((unsigned long) sel_v < par_v.len())) { - rtn = par_v[sel_v]; - // An unsized after select. - } else if ((sel_v >= 0) && (! par_v.has_len())) { - if (par_v.has_sign()) rtn = par_v[par_v.len()-1]; - else rtn = verinum::V0; - } else if (warn_ob_select) { - cerr << get_fileline() << ": warning: " - "Constant bit select [" << sel_c->value().as_long() - << "] is "; - if (sel_v < 0) cerr << "before "; - else cerr << "after "; - cerr << name << "["; - if (par_v.has_len()) cerr << par_msv; - else cerr << ""; - cerr << ":" << par_lsv << "]." << endl; - cerr << get_fileline() << ": : " - "Replacing select with a constant 1'bx." << endl; + if (par_cex) { + long sel_v = sel_c->value().as_long(); + if (par_msv >= par_lsv) sel_v -= par_lsv; + else sel_v = par_lsv - sel_v; + + // Select a bit from the parameter. + verinum par_v = par_cex->value(); + verinum::V rtn = verinum::Vx; + + // A constant in range select. + if ((sel_v >= 0) && ((unsigned long) sel_v < par_v.len())) { + rtn = par_v[sel_v]; + // An unsized after select. + } else if ((sel_v >= 0) && (! par_v.has_len())) { + if (par_v.has_sign()) rtn = par_v[par_v.len()-1]; + else rtn = verinum::V0; + } else if (warn_ob_select) { + cerr << get_fileline() << ": warning: " + "Constant bit select [" << sel_c->value().as_long() + << "] is "; + if (sel_v < 0) cerr << "before "; + else cerr << "after "; + cerr << name << "["; + if (par_v.has_len()) cerr << par_msv; + else cerr << ""; + cerr << ":" << par_lsv << "]." << endl; + cerr << get_fileline() << ": : " + "Replacing select with a constant 1'bx." << endl; + } + NetEConst*res = new NetEConst(verinum(rtn, 1)); + res->set_line(*this); + return res; + } else { + long sel_v = sel_c->value().as_long(); + if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv; + else sel_v -= par_msv; + + // Select a bit from the parameter. + NetExpr*res = (NetExpr *)(par_aex->item(sel_v)->dup_expr()); + res->set_line(*this); + return res; } - NetEConst*res = new NetEConst(verinum(rtn, 1)); - res->set_line(*this); - return res; } sel = normalize_variable_base(sel, par_msv, par_lsv, 1, true); /* Create a parameter reference for the variable select. */ - NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_ex->value()); + NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_cex->value()); NetScope::param_ref_t pref = found_in->find_parameter(name); ptmp->set_line((*pref).second); @@ -5462,7 +5524,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, use_sel = name_tail.index.back().sel; if (par->expr_type() == IVL_VT_REAL && - use_sel != index_component_t::SEL_NONE) { + use_sel != index_component_t::SEL_NONE && + dynamic_cast(par) == 0) { perm_string name = peek_tail_name(path_); cerr << get_fileline() << ": error: " << "can not select part of real parameter: " << name << endl; @@ -5473,8 +5536,8 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST); if (use_sel == index_component_t::SEL_BIT) - return elaborate_expr_param_bit_(des, scope, par, found_in, - par_type, need_const); + return elaborate_expr_param_bit_(des, scope, par, found_in, + par_type, need_const); if (use_sel == index_component_t::SEL_PART) return elaborate_expr_param_part_(des, scope, par, found_in, @@ -5530,6 +5593,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des, << "Elaborate parameter <" << name << "> as constant " << *tmp << endl; } + + const NetEArrayPattern*atmp = dynamic_cast(par); + if (atmp) { + std::vector items(atmp->item_size()); + for (unsigned i = 0; i < atmp->item_size(); i++) { + items[i] = (NetExpr*)atmp->item(i)->dup_expr(); + } + tmp = new NetEArrayPatternParam(found_in, name, atmp->net_type(), items); + if (debug_elaborate) + cerr << get_fileline() << ": debug: " + << "Elaborate parameter <" << name + << "> as constant " << *tmp << endl; + } /* The numeric parameter value needs to have the file and line * information for the actual parameter not the expression. */ assert(tmp); diff --git a/emit.cc b/emit.cc index 26360c4f7e..755cc08470 100644 --- a/emit.cc +++ b/emit.cc @@ -593,6 +593,11 @@ void NetEArrayPattern::expr_scan(struct expr_scan_t*tgt) const tgt->expr_array_pattern(this); } +void NetEArrayPatternParam::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/net_design.cc b/net_design.cc index f6a7c15e9f..4c018d9a12 100644 --- a/net_design.cc +++ b/net_design.cc @@ -31,6 +31,7 @@ # include "netlist.h" # include "netscalar.h" # include "netvector.h" +# include "netparray.h" # include "util.h" # include "compiler.h" # include "netmisc.h" @@ -518,6 +519,29 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur) // this case, we'll try to take our type from the r-value. ivl_type_t param_type = cur->second.ivl_type; + // If this parameter is an array, then we need to process it directly + // with the new method + const netuarray_t* param_array = dynamic_cast(param_type); + if (param_array) { + ivl_assert(cur->second, val_expr); + + NetExpr*expr = elab_and_eval(des, val_scope, val_expr, param_type, true); + if (! expr) + return; + + cur->second.val = expr; + + if (debug_elaborate) { + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter type: " << *param_type << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter value: " << *val_expr << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Elaborated value: " << *expr << endl; + } + return; + } + // Most parameter declarations are packed vectors, of the form: // parameter [H:L] foo == bar; // so get the netvector_t. Note that this may also be the special @@ -707,7 +731,31 @@ void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur) NetScope*val_scope = (*cur).second.val_scope; ivl_type_t param_type = cur->second.ivl_type; + ivl_assert(cur->second, val_expr); ivl_assert(*val_expr, param_type); + + // If this parameter is an array, then we need to process it directly + // with the new method + const netuarray_t* param_array = dynamic_cast(param_type); + if (param_array) { + + NetExpr*expr = elab_and_eval(des, val_scope, val_expr, param_type, true); + if (! expr) + return; + + cur->second.val = expr; + + if (debug_elaborate) { + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter type: " << *param_type << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Parameter value: " << *val_expr << endl; + cerr << cur->second.get_fileline() << ": " << __func__ << ": " + << "Elaborated value: " << *expr << endl; + } + return; + } + NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true, cur->second.is_annotatable, param_type->base_type()); @@ -840,7 +888,7 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) if (cur->second.val_expr == 0) return; - // Guess the varaiable type of the parameter. If the parameter has no + // Guess the variable type of the parameter. If the parameter has no // given type, then guess the type from the expression and use that to // evaluate. ivl_variable_type_t use_type; @@ -849,6 +897,14 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) else use_type = cur->second.val_expr->expr_type(); + if (debug_elaborate) { + cerr << cur->second.get_fileline() << ": evaluating parameter " << cur->first + << ", param_type: " << param_type; + if (param_type) + cerr << "(base type: " << param_type->base_type() << ")"; + cerr << ", use_type: " << use_type + << "." << endl; + } if (cur->second.solving) { cerr << cur->second.get_fileline() << ": error: " << "Recursive parameter reference found involving " @@ -868,9 +924,9 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) evaluate_parameter_real_(des, cur); break; - case IVL_VT_STRING: - evaluate_parameter_string_(des, cur); - break; + case IVL_VT_STRING: + evaluate_parameter_string_(des, cur); + break; default: cerr << cur->second.get_fileline() << ": internal error: " diff --git a/net_expr.cc b/net_expr.cc index 525dd9bf70..b99a079fdb 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -73,6 +73,11 @@ const netenum_t*NetExpr::enumeration() const return 0; } +NetEArrayPattern::NetEArrayPattern(unsigned w, vector&items) +: NetExpr(w), items_(items) +{ +} + NetEArrayPattern::NetEArrayPattern(ivl_type_t lv_type, vector&items) : NetExpr(lv_type), items_(items) { @@ -83,6 +88,24 @@ NetEArrayPattern::~NetEArrayPattern() for (size_t idx = 0 ; idx < items_.size() ; idx += 1) delete items_[idx]; } +NetEArrayPatternParam::NetEArrayPatternParam(NetScope*s, perm_string n, ivl_type_t lv_type, vector&items) +: NetEArrayPattern(lv_type, items), scope_(s), name_(n) +{ +} + +NetEArrayPatternParam::~NetEArrayPatternParam() +{ +} + +perm_string NetEArrayPatternParam::name() const +{ + return name_; +} + +const NetScope* NetEArrayPatternParam::scope() const +{ + return scope_; +} /* * Create an add/sub node from the two operands. diff --git a/netlist.h b/netlist.h index 7827470c62..0637ae98af 100644 --- a/netlist.h +++ b/netlist.h @@ -2094,6 +2094,7 @@ class NetExpr : public LineInfo { class NetEArrayPattern : public NetExpr { public: + NetEArrayPattern(unsigned w, std::vector&items); NetEArrayPattern(ivl_type_t lv_type, std::vector&items); ~NetEArrayPattern(); @@ -2107,10 +2108,30 @@ class NetEArrayPattern : public NetExpr { NexusSet* nex_input(bool rem_out = true, bool always_sens = false, bool nested_func = false) const; - private: + protected: std::vector items_; }; +class NetEArrayPatternParam : public NetEArrayPattern { + + public: + explicit NetEArrayPatternParam(NetScope*scope, perm_string name, + ivl_type_t lv_type, std::vector&items); + ~NetEArrayPatternParam(); + + perm_string name() const; + const NetScope*scope() const; + + virtual void expr_scan(struct expr_scan_t*) const; + virtual void dump(ostream&) const; + + virtual NetEArrayPatternParam* dup_expr() const; + + private: + NetScope*scope_; + perm_string name_; +}; + /* * The expression constant is slightly special, and is sometimes * returned from other classes that can be evaluated at compile diff --git a/netmisc.cc b/netmisc.cc index 4f21eeca72..17494acfda 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1826,36 +1826,45 @@ void check_for_inconsistent_delays(NetScope*scope) bool calculate_param_range(const LineInfo&line, ivl_type_t par_type, long&par_msv, long&par_lsv, long length) { - const netvector_t*vector_type = dynamic_cast (par_type); - if (vector_type == 0) { - // If the parameter doesn't have an explicit range, then - // just return range values of [length-1:0]. - par_msv = length-1; - par_lsv = 0; - return true; - } - - ivl_assert(line, vector_type->packed()); - const std::vector& packed_dims = vector_type->packed_dims(); - - // This is a netvector_t with 0 dimensions, then the parameter was - // declared with a statement like this: - // - // parameter signed foo = ; - // - // The netvector_t is just here to carry the signed-ness, which we don't - // even need here. So act like the type is defined by the r-value - // length. - if (packed_dims.size() == 0) { - par_msv = length-1; - par_lsv = 0; - return true; - } - ivl_assert(line, packed_dims.size() == 1); - - netrange_t use_range = packed_dims[0]; - par_msv = use_range.get_msb(); - par_lsv = use_range.get_lsb(); - - return true; + const netvector_t*vector_type = dynamic_cast (par_type); + if (vector_type) { + ivl_assert(line, vector_type->packed()); + const std::vector& packed_dims = vector_type->packed_dims(); + // This is a netvector_t with 0 dimensions, then the parameter was + // declared with a statement like this: + // + // parameter signed foo = ; + // + // The netvector_t is just here to carry the signed-ness, which we don't + // even need here. So act like the type is defined by the r-value + // length. + if (packed_dims.size() == 0) { + par_msv = length-1; + par_lsv = 0; + return true; + } + ivl_assert(line, packed_dims.size() == 1); + + netrange_t use_range = packed_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + + return true; + } + const netsarray_t*array_type = dynamic_cast (par_type); + if (array_type) { + ivl_assert(line, array_type); + const std::vector& unpacked_dims = array_type->static_dimensions(); + ivl_assert(line, unpacked_dims.size() == 1); + + netrange_t use_range = unpacked_dims[0]; + par_msv = use_range.get_msb(); + par_lsv = use_range.get_lsb(); + return true; + } + // If the parameter doesn't have an explicit range, then + // just return range values of [length-1:0]. + par_msv = length-1; + par_lsv = 0; + return true; } diff --git a/parse.y b/parse.y index 21d0e090dc..d403924a96 100644 --- a/parse.y +++ b/parse.y @@ -746,6 +746,21 @@ assertion_item /* IEEE1800-2012: A.6.10 */ | deferred_immediate_assertion_item ; +array_pattern_item_list + : array_pattern_item_list ',' array_pattern_key ':' expression + | array_pattern_key ':' expression + ; + +array_pattern_key + : expression + | assignment_pattern_key + ; + +assignment_pattern_key + : simple_type_or_string + | K_default + ; + assignment_pattern /* IEEE1800-2005: A.6.7.1 */ : K_LP expression_list_proper '}' { PEAssignPattern*tmp = new PEAssignPattern(*$2); @@ -753,6 +768,10 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ delete $2; $$ = tmp; } + | K_LP array_pattern_item_list '}' + { yyerror(@1, "Unsupported array pattern list");} + | K_LP expr_primary '{' expression_list_proper '}' '}' + { yyerror(@1, "Unsupported concatenation");} | K_LP '}' { PEAssignPattern*tmp = new PEAssignPattern; FILE_NAME(tmp, @1); @@ -5668,17 +5687,27 @@ localparam_assign_list ; parameter_assign - : IDENTIFIER '=' expression parameter_value_ranges_opt - { PExpr*tmp = $3; - pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $4); + : IDENTIFIER dimensions_opt '=' expression parameter_value_ranges_opt + { PExpr*tmp = $4; + if ($2) { + uarray_type_t *array_type = new uarray_type_t(param_data_type, $2); + pform_set_parameter(@1, lex_strings.make($1), array_type, tmp, $5); + } else { + pform_set_parameter(@1, lex_strings.make($1), param_data_type, tmp, $5); + } delete[]$1; } ; localparam_assign - : IDENTIFIER '=' expression - { PExpr*tmp = $3; - pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp); + : IDENTIFIER dimensions_opt '=' expression + { PExpr*tmp = $4; + if ($2) { + uarray_type_t *array_type = new uarray_type_t(param_data_type, $2); + pform_set_localparam(@1, lex_strings.make($1), array_type, tmp); + } else { + pform_set_localparam(@1, lex_strings.make($1), param_data_type, tmp); + } delete[]$1; } ; diff --git a/t-dll.cc b/t-dll.cc index 1ad5d8f5c7..bc4f8fcac3 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -559,6 +559,14 @@ void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp) assert(expr_->type_ == IVL_EX_REALNUM); expr_->u_.real_.parameter = cur_par; + } else if (const NetEArrayPattern*ea = dynamic_cast(etmp)) { + + return; + //expr_uarray(er); + //assert(expr_); + //assert(expr_->type_ == IVL_EX_ARRAY_PATTERN); + //expr_->u_.array_pattern_.parameter = cur_par; + } if (expr_ == 0) { diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index bbe6b542d6..c64320a9f4 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -427,6 +427,8 @@ static void draw_vpi_taskfunc_args(const char*call_string, str_stack_need += 1; buffer[0] = 0; break; + case IVL_VT_DARRAY: + fprintf(stderr, "%s:%u: Unsupported array argument\n", ivl_expr_file(expr), ivl_expr_lineno(expr)); default: fprintf(stderr, "%s:%u: Sorry, cannot generate code for argument %u.\n", ivl_expr_file(expr), ivl_expr_lineno(expr), idx+1);