@@ -109,6 +109,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
109109 int context_wid = -1 ;
110110 switch (lv_type) {
111111 case IVL_VT_DARRAY:
112+ case IVL_VT_UARRAY:
112113 case IVL_VT_QUEUE:
113114 case IVL_VT_CLASS:
114115 // For these types, use a different elab_and_eval that
@@ -186,11 +187,11 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
186187 */
187188unsigned PEAssignPattern::test_width (Design*, NetScope*, width_mode_t &)
188189{
189- expr_type_ = IVL_VT_DARRAY ;
190- expr_width_ = 1 ;
191- min_width_ = 1 ;
190+ expr_type_ = IVL_VT_UARRAY ;
191+ expr_width_ = parms_. size () ;
192+ min_width_ = expr_width_ ;
192193 signed_flag_= false ;
193- return 1 ;
194+ return expr_width_ ;
194195}
195196
196197NetExpr*PEAssignPattern::elaborate_expr (Design*des, NetScope*scope,
@@ -208,7 +209,8 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
208209 }
209210
210211 if (ntype->base_type ()==IVL_VT_DARRAY ||
211- ntype->base_type ()==IVL_VT_QUEUE)
212+ ntype->base_type ()==IVL_VT_QUEUE ||
213+ ntype->base_type ()==IVL_VT_UARRAY)
212214 return elaborate_expr_darray_ (des, scope, ntype, flags);
213215
214216 cerr << get_fileline () << " : sorry: I don't know how to elaborate "
@@ -222,7 +224,7 @@ NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
222224NetExpr*PEAssignPattern::elaborate_expr_darray_ (Design*des, NetScope*scope,
223225 ivl_type_t ntype, unsigned flags) const
224226{
225- const netdarray_t *array_type = dynamic_cast <const netdarray_t *> (ntype);
227+ const netarray_t *array_type = dynamic_cast <const netarray_t *> (ntype);
226228 ivl_assert (*this , array_type);
227229
228230 // This is an array pattern, so run through the elements of
@@ -3558,6 +3560,7 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
35583560 switch (ntype->base_type ()) {
35593561 case IVL_VT_QUEUE:
35603562// FIXME: Does a DARRAY support a zero size?
3563+ case IVL_VT_UARRAY:
35613564 case IVL_VT_DARRAY:
35623565 if (parms_.size () == 0 ) {
35633566 NetENull*tmp = new NetENull;
@@ -3728,6 +3731,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
37283731 switch (net->data_type ()) {
37293732 case IVL_VT_STRING:
37303733 case IVL_VT_DARRAY:
3734+ case IVL_VT_UARRAY:
37313735 case IVL_VT_QUEUE:
37323736 dimensions += 1 ;
37333737 default :
@@ -4061,6 +4065,27 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
40614065 return expr_width_;
40624066 }
40634067
4068+ if (par != 0 && par->expr_type () == IVL_VT_UARRAY) {
4069+ const netuarray_t *array = dynamic_cast <const netuarray_t *> (par->net_type ());
4070+ ivl_assert (*this , array);
4071+ switch (use_sel) {
4072+ case index_component_t ::SEL_BIT:
4073+ case index_component_t ::SEL_BIT_LAST:
4074+ expr_type_ = array->element_type ()->base_type ();
4075+ expr_width_ = array->element_type ()->packed_width ();
4076+ min_width_ = expr_width_;
4077+ signed_flag_ = array->element_type ()->get_signed ();
4078+ break ;
4079+ default :
4080+ expr_type_ = array->base_type ();
4081+ expr_width_ = array->static_dimensions ()[0 ].width ();
4082+ min_width_ = expr_width_;
4083+ signed_flag_ = false ;
4084+ break ;
4085+ }
4086+ return expr_width_;
4087+ }
4088+
40644089 // Look for a class property.
40654090 if (gn_system_verilog () && cls_val) {
40664091 expr_type_ = cls_val->base_type ();
@@ -4255,6 +4280,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
42554280
42564281 symbol_search (this , des, use_scope, path_, net, par, eve, par_type, cls_val);
42574282
4283+ if (par != 0 ) {
4284+ return (NetExpr *)par;
4285+ }
4286+
42584287 if (net == 0 && gn_system_verilog () && path_.size () >= 2 ) {
42594288 // NOTE: this is assuming the member_path is only one
42604289 // component long, and that the use_path will wind up
@@ -4615,9 +4644,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
46154644 NetExpr*tmp = elaborate_expr_param_ (des, scope, par, found_in,
46164645 par_type, expr_wid, flags);
46174646
4618- if (!tmp) return 0 ;
4647+ if (!tmp) return 0 ;
46194648
4620- return pad_to_width (tmp, expr_wid, signed_flag_, *this );
4649+ return pad_to_width (tmp, expr_wid, signed_flag_, *this );
46214650 }
46224651
46234652 // If the identifier names a signal (a variable or a net)
@@ -5132,6 +5161,78 @@ NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope,
51325161 return tmp;
51335162}
51345163
5164+ NetExpr* PEIdent::elaborate_expr_param_word_ (Design*des, NetScope*scope,
5165+ const NetExpr*par,
5166+ NetScope*found_in,
5167+ ivl_type_t par_type,
5168+ bool need_const) const
5169+ {
5170+ const NetEArrayPattern*par_ex = dynamic_cast <const NetEArrayPattern*> (par);
5171+ ivl_assert (*this , par_ex);
5172+ const netuarray_t *array = dynamic_cast <const netuarray_t *> (par->net_type ());
5173+ if (!array) {
5174+ cerr << get_fileline () << " tried to get a word from non-array expression" << endl;
5175+ return 0 ;
5176+ }
5177+
5178+ long par_msv, par_lsv;
5179+ if (! calculate_param_range (*this , par_type, par_msv, par_lsv,
5180+ par_ex->item_size ())) return 0 ;
5181+
5182+ const name_component_t &name_tail = path_.back ();
5183+ ivl_assert (*this , !name_tail.index .empty ());
5184+ const index_component_t &index_tail = name_tail.index .back ();
5185+ ivl_assert (*this , index_tail.msb );
5186+ ivl_assert (*this , !index_tail.lsb );
5187+
5188+ NetExpr*sel = elab_and_eval (des, scope, index_tail.msb , -1 , need_const);
5189+ if (sel == 0 ) return 0 ;
5190+
5191+ if (debug_elaborate)
5192+ cerr << get_fileline () << " : debug: Calculate bit select "
5193+ << " [" << *sel << " ] from range "
5194+ << " [" << par_msv << " :" << par_lsv << " ]." << endl;
5195+
5196+ perm_string name = peek_tail_name (path_);
5197+
5198+ // Handle the special case that the selection is constant. In this
5199+ // case, just precalculate the entire constant result.
5200+ NetEConst*sel_c = dynamic_cast <NetEConst*> (sel);
5201+ if (!sel_c) {
5202+ cerr << get_fileline () << " tried to get a word with non constant selector" << endl;
5203+ return 0 ;
5204+ }
5205+ // Special case: If the bit select is constant and not fully
5206+ // defined, then we know that the result must be 1'bx.
5207+ if (! sel_c->value ().is_defined ()) {
5208+ if (warn_ob_select) {
5209+ cerr << get_fileline () << " : warning: "
5210+ " Constant undefined bit select ["
5211+ << sel_c->value () << " ] for parameter '"
5212+ << name << " '." << endl;
5213+ cerr << get_fileline () << " : : "
5214+ " Replacing select with a constant 1'bx."
5215+ << endl;
5216+ }
5217+
5218+ // This is a convenience function for getting the width of an
5219+ // element. Strictly speaking it's not necessary.
5220+ NetEConst*res = make_const_x (array->element_type ()->packed_width ());
5221+ res->set_line (*this );
5222+ return res;
5223+ }
5224+ // Calculate the canonical index value.
5225+ long sel_v = sel_c->value ().as_long ();
5226+ if (par_msv >= par_lsv) sel_v = par_msv - sel_v - par_lsv;
5227+ else sel_v -= par_msv;
5228+
5229+ // Select a bit from the parameter.
5230+ NetExpr*res = (NetExpr *)(par_ex->item (sel_v)->dup_expr ());
5231+ // NetEConst*res = new NetEConst(rtn);
5232+ res->set_line (*this );
5233+ return res;
5234+ }
5235+
51355236NetExpr* PEIdent::elaborate_expr_param_part_ (Design*des, NetScope*scope,
51365237 const NetExpr*par,
51375238 NetScope*,
@@ -5458,6 +5559,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
54585559
54595560 const name_component_t &name_tail = path_.back ();
54605561 index_component_t ::ctype_t use_sel = index_component_t ::SEL_NONE;
5562+ // FIXME: this won't work with multidimensional array
54615563 if (!name_tail.index .empty ())
54625564 use_sel = name_tail.index .back ().sel ;
54635565
@@ -5473,8 +5575,13 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
54735575 ivl_assert (*this , use_sel != index_component_t ::SEL_BIT_LAST);
54745576
54755577 if (use_sel == index_component_t ::SEL_BIT)
5476- return elaborate_expr_param_bit_ (des, scope, par, found_in,
5477- par_type, need_const);
5578+ if (par->expr_type () == IVL_VT_UARRAY) {
5579+ return elaborate_expr_param_word_ (des, scope, par, found_in,
5580+ par_type, need_const);
5581+ } else {
5582+ return elaborate_expr_param_bit_ (des, scope, par, found_in,
5583+ par_type, need_const);
5584+ }
54785585
54795586 if (use_sel == index_component_t ::SEL_PART)
54805587 return elaborate_expr_param_part_ (des, scope, par, found_in,
@@ -5530,6 +5637,19 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
55305637 << " Elaborate parameter <" << name
55315638 << " > as constant " << *tmp << endl;
55325639 }
5640+
5641+ const NetEArrayPattern*atmp = dynamic_cast <const NetEArrayPattern*>(par);
5642+ if (atmp) {
5643+ std::vector<NetExpr*> items (atmp->item_size ());
5644+ for (unsigned i = 0 ; i < atmp->item_size (); i++) {
5645+ items[i] = (NetExpr*)atmp->item (i)->dup_expr ();
5646+ }
5647+ tmp = new NetEArrayPatternParam (found_in, name, atmp->net_type (), items);
5648+ if (debug_elaborate)
5649+ cerr << get_fileline () << " : debug: "
5650+ << " Elaborate parameter <" << name
5651+ << " > as constant " << *tmp << endl;
5652+ }
55335653 /* The numeric parameter value needs to have the file and line
55345654 * information for the actual parameter not the expression. */
55355655 assert (tmp);
0 commit comments