1 /*
2  * Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
3  * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
4  *
5  *    This source code is free software; you can redistribute it
6  *    and/or modify it in source code form under the terms of the GNU
7  *    General Public License as published by the Free Software
8  *    Foundation; either version 2 of the License, or (at your option)
9  *    any later version.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  *
16  *    You should have received a copy of the GNU General Public License
17  *    along with this program; if not, write to the Free Software
18  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 # include "config.h"
22 # include  <typeinfo>
23 # include  <cstdlib>
24 # include  <cstring>
25 # include  <climits>
26 # include "compiler.h"
27 
28 # include  "PPackage.h"
29 # include  "pform.h"
30 # include  "netlist.h"
31 # include  "netclass.h"
32 # include  "netenum.h"
33 # include  "netparray.h"
34 # include  "netvector.h"
35 # include  "discipline.h"
36 # include  "netmisc.h"
37 # include  "netdarray.h"
38 # include  "netqueue.h"
39 # include  "netstruct.h"
40 # include  "netscalar.h"
41 # include  "util.h"
42 # include  "ivl_assert.h"
43 
type_is_vectorable(ivl_variable_type_t type)44 bool type_is_vectorable(ivl_variable_type_t type)
45 {
46       switch (type) {
47 	  case IVL_VT_BOOL:
48 	  case IVL_VT_LOGIC:
49 	    return true;
50 	  default:
51 	    return false;
52       }
53 }
54 
find_access_function(const pform_name_t & path)55 static ivl_nature_t find_access_function(const pform_name_t&path)
56 {
57       if (path.size() != 1)
58 	    return 0;
59       else
60 	    return access_function_nature[peek_tail_name(path)];
61 }
62 
63 /*
64  * Look at the signal to see if there is already a branch that
65  * connects the sig to the gnd. If there is, then return it. If not,
66  * return 0.
67  */
find_existing_implicit_branch(NetNet * sig,NetNet * gnd)68 static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
69 {
70       Nexus*nex = sig->pin(0).nexus();
71       for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
72 	    if (cur->is_equal(sig->pin(0)))
73 		  continue;
74 
75 	    if (cur->get_pin() != 0)
76 		  continue;
77 
78 	    NetBranch*tmp = dynamic_cast<NetBranch*> (cur->get_obj());
79 	    if (tmp == 0)
80 		  continue;
81 
82 	    if (tmp->name())
83 		  continue;
84 
85 	    if (tmp->pin(1).is_linked(gnd->pin(0)))
86 		  return tmp;
87       }
88 
89       return 0;
90 }
91 
elaborate_rval_expr(Design * des,NetScope * scope,ivl_type_t lv_net_type,ivl_variable_type_t lv_type,unsigned lv_width,PExpr * expr,bool need_const,bool force_unsigned)92 NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
93 			     ivl_variable_type_t lv_type, unsigned lv_width,
94 			     PExpr*expr, bool need_const, bool force_unsigned)
95 {
96       if (debug_elaborate) {
97 	    cerr << expr->get_fileline() << ": elaborate_rval_expr: "
98 		 << "expr=" << *expr;
99 	    if (lv_net_type)
100 		  cerr << ", lv_net_type=" << *lv_net_type;
101 	    else
102 		  cerr << ", lv_net_type=<nil>";
103 
104 	    cerr << ", lv_type=" << lv_type
105 		 << ", lv_width=" << lv_width
106 		 << endl;
107       }
108 
109       int context_wid = -1;
110       switch (lv_type) {
111 	  case IVL_VT_DARRAY:
112 	  case IVL_VT_QUEUE:
113 	      // For these types, use a different elab_and_eval that
114 	      // uses the lv_net_type. We should eventually transition
115 	      // all the types to this new form.
116 	    if (lv_net_type)
117 		  return elab_and_eval(des, scope, expr, lv_net_type, need_const);
118 	    break;
119 	  case IVL_VT_REAL:
120 	  case IVL_VT_STRING:
121 	    break;
122 	  case IVL_VT_BOOL:
123 	  case IVL_VT_LOGIC:
124             context_wid = lv_width;
125 	    break;
126 	  case IVL_VT_VOID:
127 	  case IVL_VT_NO_TYPE:
128 	    ivl_assert(*expr, 0);
129 	    break;
130 	  case IVL_VT_CLASS:
131 	    cerr << expr->get_fileline() << ": sorry: "
132 		 << "I do not know how to elaborate r-value as IVL_VT_CLASS." << endl;
133 	    des->errors += 1;
134 	    return 0;
135 	    break;
136       }
137 
138       return elab_and_eval(des, scope, expr, context_wid, need_const,
139 			   false, lv_type, force_unsigned);
140 }
141 
142 /*
143  * If the mode is UPSIZE, make sure the final expression width is at
144  * least integer_width, but return the calculated lossless width to
145  * the caller.
146  */
fix_width_(width_mode_t mode)147 unsigned PExpr::fix_width_(width_mode_t mode)
148 {
149       unsigned width = expr_width_;
150       if ((mode == UPSIZE) && type_is_vectorable(expr_type_)
151           && (width < integer_width))
152             expr_width_ = integer_width;
153 
154       return width;
155 }
156 
test_width(Design * des,NetScope *,width_mode_t &)157 unsigned PExpr::test_width(Design*des, NetScope*, width_mode_t&)
158 {
159       cerr << get_fileline() << ": internal error: I do not know how to"
160 	   << " test the width of this expression. " << endl;
161       cerr << get_fileline() << ":               : Expression is: " << *this
162 	   << endl;
163       des->errors += 1;
164       return 1;
165 }
166 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t,unsigned flags) const167 NetExpr* PExpr::elaborate_expr(Design*des, NetScope*scope, ivl_type_t, unsigned flags) const
168 {
169 	// Fall back to the old method. Currently the new method won't be used
170 	// if the target is a vector type, so we can use an arbitrary width.
171       return elaborate_expr(des, scope, 1, flags);
172 }
173 
174 
elaborate_expr(Design * des,NetScope *,unsigned,unsigned) const175 NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
176 {
177       cerr << get_fileline() << ": internal error: I do not know how to"
178 	   << " elaborate this expression. " << endl;
179       cerr << get_fileline() << ":               : Expression is: " << *this
180 	   << endl;
181       cerr << get_fileline() << ":               : Expression type: " << typeid(*this).name() << endl;
182       des->errors += 1;
183       return 0;
184 }
185 
186 /*
187  * For now, assume that assignment patterns are for dynamic
188  * objects. This is not really true as this expression type, fully
189  * supported, can assign to packed arrays and structs, unpacked arrays
190  * and dynamic arrays.
191  */
test_width(Design *,NetScope *,width_mode_t &)192 unsigned PEAssignPattern::test_width(Design*, NetScope*, width_mode_t&)
193 {
194       expr_type_  = IVL_VT_DARRAY;
195       expr_width_ = 1;
196       min_width_  = 1;
197       signed_flag_= false;
198       return 1;
199 }
200 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const201 NetExpr*PEAssignPattern::elaborate_expr(Design*des, NetScope*scope,
202 					ivl_type_t ntype, unsigned flags) const
203 {
204 	// Special case: If this is an empty pattern (i.e. '{}) and
205 	// the expected type is a DARRAY or QUEUE, then convert this
206 	// to a null handle. Internally, Icarus Verilog uses this to
207 	// represent nil dynamic arrays.
208       if (parms_.size() == 0 && (ntype->base_type()==IVL_VT_DARRAY ||
209                                  ntype->base_type()==IVL_VT_QUEUE)) {
210 	    NetENull*tmp = new NetENull;
211 	    tmp->set_line(*this);
212 	    return tmp;
213       }
214 
215       if (ntype->base_type()==IVL_VT_DARRAY ||
216           ntype->base_type()==IVL_VT_QUEUE)
217 	    return elaborate_expr_darray_(des, scope, ntype, flags);
218 
219       cerr << get_fileline() << ": sorry: I don't know how to elaborate "
220 	   << "assignment_pattern expressions yet." << endl;
221       cerr << get_fileline() << ":      : Expression is: " << *this
222 	   << endl;
223       des->errors += 1;
224       return 0;
225 }
226 
elaborate_expr_darray_(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const227 NetExpr*PEAssignPattern::elaborate_expr_darray_(Design*des, NetScope*scope,
228 						ivl_type_t ntype, unsigned flags) const
229 {
230       const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype);
231       ivl_assert(*this, array_type);
232 
233 	// This is an array pattern, so run through the elements of
234 	// the expression and elaborate each as if they are
235 	// element_type expressions.
236       ivl_type_t elem_type = array_type->element_type();
237       vector<NetExpr*> elem_exprs (parms_.size());
238       for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
239 	    NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags);
240 	    elem_exprs[idx] = tmp;
241       }
242 
243       NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs);
244       res->set_line(*this);
245       return res;
246 }
247 
elaborate_expr(Design * des,NetScope *,unsigned,unsigned) const248 NetExpr* PEAssignPattern::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
249 {
250       cerr << get_fileline() << ": sorry: I do not know how to"
251 	   << " elaborate assignment patterns using old method." << endl;
252       cerr << get_fileline() << ":      : Expression is: " << *this
253 	   << endl;
254       des->errors += 1;
255       ivl_assert(*this, 0);
256       return 0;
257 }
258 
test_width(Design * des,NetScope * scope,width_mode_t & mode)259 unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
260 {
261       ivl_assert(*this, left_);
262       ivl_assert(*this, right_);
263 
264       unsigned r_width = right_->test_width(des, scope, mode);
265 
266       width_mode_t saved_mode = mode;
267 
268       unsigned l_width = left_->test_width(des, scope, mode);
269 
270       if (debug_elaborate) {
271 	    cerr << get_fileline() << ": PEBinary::test_width: "
272 		 << "op_=" << op_ << ", l_width=" << l_width
273 		 << ", r_width=" << r_width
274 		 << ", saved_mode=" << saved_mode << endl;
275       }
276 
277         // If the width mode changed, retest the right operand, as it
278         // may choose a different width if it is in a lossless context.
279       if ((mode >= LOSSLESS) && (saved_mode < LOSSLESS))
280 	    r_width = right_->test_width(des, scope, mode);
281 
282       ivl_variable_type_t l_type =  left_->expr_type();
283       ivl_variable_type_t r_type = right_->expr_type();
284 
285       if (l_type == IVL_VT_REAL || r_type == IVL_VT_REAL)
286 	    expr_type_ = IVL_VT_REAL;
287       else if (l_type == IVL_VT_LOGIC || r_type == IVL_VT_LOGIC)
288 	    expr_type_ = IVL_VT_LOGIC;
289       else
290 	    expr_type_ = IVL_VT_BOOL;
291 
292       if (expr_type_ == IVL_VT_REAL) {
293             expr_width_  = 1;
294             min_width_   = 1;
295             signed_flag_ = true;
296       } else {
297             expr_width_  = max(l_width, r_width);
298             min_width_   = max(left_->min_width(), right_->min_width());
299             signed_flag_ = left_->has_sign() && right_->has_sign();
300 
301               // If the operands are different types, the expression is
302               // forced to unsigned. In this case the lossless width
303               // calculation is unreliable and we need to make sure the
304               // final expression width is at least integer_width.
305             if ((mode == LOSSLESS) && (left_->has_sign() != right_->has_sign()))
306                   mode = UPSIZE;
307 
308             switch (op_) {
309                 case '+':
310                 case '-':
311                   if (mode >= EXPAND)
312                         expr_width_ += 1;
313                   break;
314 
315                 case '*':
316                   if (mode >= EXPAND)
317                         expr_width_ = l_width + r_width;
318                   break;
319 
320                 case '%':
321                 case '/':
322                   min_width_ = UINT_MAX; // disable width pruning
323                   break;
324 
325                 case 'l': // <<  Should be handled by PEBLeftWidth
326                 case 'r': // >>  Should be handled by PEBLeftWidth
327                 case 'R': // >>> Should be handled by PEBLeftWidth
328                 case '<': // <   Should be handled by PEBComp
329                 case '>': // >   Should be handled by PEBComp
330                 case 'e': // ==  Should be handled by PEBComp
331                 case 'E': // === Should be handled by PEBComp
332                 case 'w': // ==? Should be handled by PEBComp
333                 case 'L': // <=  Should be handled by PEBComp
334                 case 'G': // >=  Should be handled by PEBComp
335                 case 'n': // !=  Should be handled by PEBComp
336                 case 'N': // !== Should be handled by PEBComp
337                 case 'W': // !=? Should be handled by PEBComp
338                 case 'p': // **  should be handled by PEBLeftWidth
339                   ivl_assert(*this, 0);
340                 default:
341                   break;
342             }
343       }
344 
345       return fix_width_(mode);
346 }
347 
348 /*
349  * Elaborate binary expressions. This involves elaborating the left
350  * and right sides, and creating one of a variety of different NetExpr
351  * types.
352  */
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const353 NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
354 				  unsigned expr_wid, unsigned flags) const
355 {
356       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
357 
358       ivl_assert(*this, left_);
359       ivl_assert(*this, right_);
360 
361 	// Handle the special case that one of the operands is a real
362 	// value and the other is a vector type. In that case,
363 	// elaborate the vectorable argument as self-determined.
364         // Propagate the expression type (signed/unsigned) down to
365         // any context-determined operands.
366       unsigned l_width = expr_wid;
367       unsigned r_width = expr_wid;
368       if (left_->expr_type()==IVL_VT_REAL
369 	  && type_is_vectorable(right_->expr_type())) {
370 	    r_width = right_->expr_width();
371       } else {
372             right_->cast_signed(signed_flag_);
373       }
374       if (right_->expr_type()==IVL_VT_REAL
375 	  && type_is_vectorable(left_->expr_type())) {
376 	    l_width = left_->expr_width();
377       } else {
378             left_->cast_signed(signed_flag_);
379       }
380 
381       NetExpr*lp =  left_->elaborate_expr(des, scope, l_width, flags);
382       NetExpr*rp = right_->elaborate_expr(des, scope, r_width, flags);
383       if ((lp == 0) || (rp == 0)) {
384 	    delete lp;
385 	    delete rp;
386 	    return 0;
387       }
388 
389       return elaborate_expr_base_(des, lp, rp, expr_wid);
390 }
391 
392 /*
393  * This is the common elaboration of the operator. It presumes that the
394  * operands are elaborated as necessary, and all I need to do is make
395  * the correct NetEBinary object and connect the parameters.
396  */
elaborate_expr_base_(Design * des,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const397 NetExpr* PEBinary::elaborate_expr_base_(Design*des,
398 					NetExpr*lp, NetExpr*rp,
399 					unsigned expr_wid) const
400 {
401       if (debug_elaborate) {
402 	    cerr << get_fileline() << ": debug: elaborate expression "
403 		 << *this << " expr_width=" << expr_wid << endl;
404       }
405 
406       NetExpr*tmp;
407 
408       switch (op_) {
409 	  default:
410 	    tmp = new NetEBinary(op_, lp, rp, expr_wid, signed_flag_);
411 	    tmp->set_line(*this);
412 	    break;
413 
414 	  case 'a':
415 	  case 'o':
416 	  case 'q':
417 	  case 'Q':
418 	    cerr << get_fileline() << ": internal error: "
419 		 << "Elaboration of " << human_readable_op(op_)
420 		 << " Should have been handled in NetEBLogic::elaborate."
421 		 << endl;
422 	    des->errors += 1;
423 	    return 0;
424 
425 	  case 'p':
426 	    cerr << get_fileline() << ": internal error: "
427 		 << "Elaboration of " << human_readable_op(op_)
428 		 << " Should have been handled in NetEBPower::elaborate."
429 		 << endl;
430 	    des->errors += 1;
431 	    return 0;
432 
433 	  case '*':
434 	    tmp = elaborate_expr_base_mult_(des, lp, rp, expr_wid);
435 	    break;
436 
437 	  case '%':
438 	  case '/':
439 	    tmp = elaborate_expr_base_div_(des, lp, rp, expr_wid);
440 	    break;
441 
442 	  case 'l':
443 	  case 'r':
444 	  case 'R':
445 	    cerr << get_fileline() << ": internal error: "
446 		 << "Elaboration of " << human_readable_op(op_)
447 		 << " Should have been handled in NetEBShift::elaborate."
448 		 << endl;
449 	    des->errors += 1;
450 	    return 0;
451 
452 	  case '^':
453 	  case '&':
454 	  case '|':
455 	  case 'O': // NOR (~|)
456 	  case 'A': // NAND (~&)
457 	  case 'X':
458 	    tmp = elaborate_expr_base_bits_(des, lp, rp, expr_wid);
459 	    break;
460 
461 	  case '+':
462 	  case '-':
463 	    tmp = new NetEBAdd(op_, lp, rp, expr_wid, signed_flag_);
464 	    tmp->set_line(*this);
465 	    break;
466 
467 	  case 'E': /* === */
468 	  case 'N': /* !== */
469 	  case 'e': /* == */
470 	  case 'n': /* != */
471 	  case 'L': /* <= */
472 	  case 'G': /* >= */
473 	  case '<':
474 	  case '>':
475 	    cerr << get_fileline() << ": internal error: "
476 		 << "Elaboration of " << human_readable_op(op_)
477 		 << " Should have been handled in NetEBComp::elaborate."
478 		 << endl;
479 	    des->errors += 1;
480 	    return 0;
481 
482 	  case 'm': // min(l,r)
483 	  case 'M': // max(l,r)
484 	    tmp = new NetEBMinMax(op_, lp, rp, expr_wid, signed_flag_);
485 	    tmp->set_line(*this);
486 	    break;
487       }
488 
489       return tmp;
490 }
491 
elaborate_expr_base_bits_(Design * des,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const492 NetExpr* PEBinary::elaborate_expr_base_bits_(Design*des,
493 					     NetExpr*lp, NetExpr*rp,
494 					     unsigned expr_wid) const
495 {
496       if (lp->expr_type() == IVL_VT_REAL || rp->expr_type() == IVL_VT_REAL) {
497 	    cerr << get_fileline() << ": error: "
498 	         << human_readable_op(op_)
499 	         << " operator may not have REAL operands." << endl;
500 	    des->errors += 1;
501 	    return 0;
502       }
503 
504       NetEBBits*tmp = new NetEBBits(op_, lp, rp, expr_wid, signed_flag_);
505       tmp->set_line(*this);
506 
507       return tmp;
508 }
509 
elaborate_expr_base_div_(Design * des,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const510 NetExpr* PEBinary::elaborate_expr_base_div_(Design*des,
511 					    NetExpr*lp, NetExpr*rp,
512 					    unsigned expr_wid) const
513 {
514 	/* The % operator does not support real arguments in
515 	   baseline Verilog. But we allow it in our extended
516 	   form of Verilog. */
517       if (op_ == '%' && ! gn_icarus_misc_flag) {
518 	    if (lp->expr_type() == IVL_VT_REAL ||
519 		rp->expr_type() == IVL_VT_REAL) {
520 		  cerr << get_fileline() << ": error: Modulus operator "
521 			"may not have REAL operands." << endl;
522 		  des->errors += 1;
523 	    }
524       }
525 
526       NetEBDiv*tmp = new NetEBDiv(op_, lp, rp, expr_wid, signed_flag_);
527       tmp->set_line(*this);
528 
529       return tmp;
530 }
531 
elaborate_expr_base_mult_(Design *,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const532 NetExpr* PEBinary::elaborate_expr_base_mult_(Design*,
533 					     NetExpr*lp, NetExpr*rp,
534 					     unsigned expr_wid) const
535 {
536 	// Keep constants on the right side.
537       if (dynamic_cast<NetEConst*>(lp)) {
538 	    NetExpr*tmp = lp;
539 	    lp = rp;
540 	    rp = tmp;
541       }
542 
543 	// Handle a few special case multiplies against constants.
544       if (NetEConst*rp_const = dynamic_cast<NetEConst*> (rp)) {
545 	    verinum rp_val = rp_const->value();
546 
547 	    if (!rp_val.is_defined() && (lp->expr_type() == IVL_VT_LOGIC)) {
548 		  NetEConst*tmp = make_const_x(expr_wid);
549                   tmp->cast_signed(signed_flag_);
550                   tmp->set_line(*this);
551 
552 		  return tmp;
553 	    }
554 
555 	    if (rp_val.is_zero() && (lp->expr_type() == IVL_VT_BOOL)) {
556 		  NetEConst*tmp = make_const_0(expr_wid);
557                   tmp->cast_signed(signed_flag_);
558                   tmp->set_line(*this);
559 
560 		  return tmp;
561 	    }
562       }
563 
564       NetEBMult*tmp = new NetEBMult(op_, lp, rp, expr_wid, signed_flag_);
565       tmp->set_line(*this);
566 
567       return tmp;
568 }
569 
test_width(Design * des,NetScope * scope,width_mode_t &)570 unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&)
571 {
572       ivl_assert(*this, left_);
573       ivl_assert(*this, right_);
574 
575 	// The width and type of a comparison are fixed and well known.
576       expr_type_   = IVL_VT_LOGIC;
577       expr_width_  = 1;
578       min_width_   = 1;
579       signed_flag_ = false;
580 
581 	// The widths of the operands are semi-self-determined. They
582         // affect each other, but not the result.
583       width_mode_t mode = SIZED;
584 
585       unsigned r_width = right_->test_width(des, scope, mode);
586 
587       width_mode_t saved_mode = mode;
588 
589       unsigned l_width = left_->test_width(des, scope, mode);
590 
591         // If the width mode changed, retest the right operand, as it
592         // may choose a different width if it is in a lossless context.
593       if ((mode >= LOSSLESS) && (saved_mode < LOSSLESS))
594 	    r_width = right_->test_width(des, scope, mode);
595 
596       ivl_variable_type_t l_type =  left_->expr_type();
597       ivl_variable_type_t r_type = right_->expr_type();
598 
599       l_width_ = l_width;
600       if (type_is_vectorable(l_type) && (r_width > l_width))
601 	    l_width_ = r_width;
602 
603       r_width_ = r_width;
604       if (type_is_vectorable(r_type) && (l_width > r_width))
605 	    r_width_ = l_width;
606 
607 	// If the expression is lossless and smaller than the integer
608 	// minimum, then tweak the size up.
609 	// NOTE: I really would rather try to figure out what it would
610 	// take to get expand the sub-expressions so that they are
611 	// exactly the right width to behave just like infinite
612 	// width. I suspect that adding 1 more is sufficient in all
613 	// cases, but I'm not certain. Ideas?
614       if (mode >= EXPAND) {
615             if (type_is_vectorable(l_type) && (l_width_ < integer_width))
616 	          l_width_ += 1;
617             if (type_is_vectorable(r_type) && (r_width_ < integer_width))
618 	          r_width_ += 1;
619       }
620 
621       if (debug_elaborate) {
622 	    cerr << get_fileline() << ": debug: "
623 		 << "Comparison expression operands are "
624 		 << l_type << " " << l_width << " bits and "
625 		 << r_type << " " << r_width << " bits. Resorting to "
626 		 << l_width_ << " bits and "
627 		 << r_width_ << " bits." << endl;
628       }
629 
630       return expr_width_;
631 }
632 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const633 NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
634 				 unsigned expr_wid, unsigned flags) const
635 {
636       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
637 
638       ivl_assert(*this, left_);
639       ivl_assert(*this, right_);
640 
641         // Propagate the comparison type (signed/unsigned) down to
642         // the operands.
643       if (type_is_vectorable(left_->expr_type()) && !left_->has_sign())
644 	    right_->cast_signed(false);
645       if (type_is_vectorable(right_->expr_type()) && !right_->has_sign())
646 	    left_->cast_signed(false);
647 
648       NetExpr*lp =  left_->elaborate_expr(des, scope, l_width_, flags);
649       NetExpr*rp = right_->elaborate_expr(des, scope, r_width_, flags);
650       if ((lp == 0) || (rp == 0)) {
651 	    delete lp;
652 	    delete rp;
653 	    return 0;
654       }
655 
656       eval_expr(lp, l_width_);
657       eval_expr(rp, r_width_);
658 
659 	// Handle some operand-specific special cases...
660       switch (op_) {
661 	  case 'E': /* === */
662 	  case 'N': /* !== */
663 	    if (lp->expr_type() == IVL_VT_REAL ||
664 		lp->expr_type() == IVL_VT_STRING ||
665 		rp->expr_type() == IVL_VT_REAL ||
666 		rp->expr_type() == IVL_VT_STRING) {
667 		  cerr << get_fileline() << ": error: "
668 		       << human_readable_op(op_)
669 		       << " operator may not have REAL or STRING operands."
670 		       << endl;
671 		  des->errors += 1;
672 		  return 0;
673 	    }
674 	    break;
675 	  case 'w': /* ==? */
676 	  case 'W': /* !=? */
677 	    if ((lp->expr_type() != IVL_VT_BOOL && lp->expr_type() != IVL_VT_LOGIC) ||
678 		(rp->expr_type() != IVL_VT_BOOL && rp->expr_type() != IVL_VT_LOGIC)) {
679 		  cerr << get_fileline() << ": error: "
680 		       << human_readable_op(op_)
681 		       << " operator may only have INTEGRAL operands."
682 		       << endl;
683 		  des->errors += 1;
684 		  return 0;
685 	    }
686 	    break;
687 	  default:
688 	    break;
689       }
690 
691       NetExpr*tmp = new NetEBComp(op_, lp, rp);
692       tmp->set_line(*this);
693 
694       return pad_to_width(tmp, expr_wid, signed_flag_, *this);
695 }
696 
test_width(Design *,NetScope *,width_mode_t &)697 unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
698 {
699 	// The width and type of a logical operation are fixed.
700       expr_type_   = IVL_VT_LOGIC;
701       expr_width_  = 1;
702       min_width_   = 1;
703       signed_flag_ = false;
704 
705         // The widths of the operands are self determined. We don't need
706         // them now, so they can be tested when they are elaborated.
707 
708       return expr_width_;
709 }
710 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const711 NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
712 				 unsigned expr_wid, unsigned flags) const
713 {
714       ivl_assert(*this, left_);
715       ivl_assert(*this, right_);
716 
717       bool need_const = NEED_CONST & flags;
718       NetExpr*lp = elab_and_eval(des, scope,  left_, -1, need_const);
719       NetExpr*rp = elab_and_eval(des, scope, right_, -1, need_const);
720       if ((lp == 0) || (rp == 0)) {
721 	    delete lp;
722 	    delete rp;
723 	    return 0;
724       }
725 
726       lp = condition_reduce(lp);
727       rp = condition_reduce(rp);
728 
729       NetExpr*tmp = new NetEBLogic(op_, lp, rp);
730       tmp->set_line(*this);
731 
732       return pad_to_width(tmp, expr_wid, signed_flag_, *this);
733 }
734 
test_width(Design * des,NetScope * scope,width_mode_t & mode)735 unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
736 {
737       ivl_assert(*this, left_);
738       ivl_assert(*this, right_);
739 
740       if (debug_elaborate) {
741 	    cerr << get_fileline() << ": PEBLeftWidth::test_width: "
742 		 << "op_=" << op_
743 		 << ", left_=" << *left_
744 		 << ", right_=" << *right_
745 		 << ", mode=" << width_mode_name(mode) << endl;
746       }
747 
748         // The right operand is self determined. Test its type and
749         // width for use later. We only need to know its width now
750         // if the left operand is unsized and we need to calculate
751         // the lossless width.
752       width_mode_t r_mode = SIZED;
753       unsigned r_width = right_->test_width(des, scope, r_mode);
754 
755 	// The left operand is what will determine the size of the
756 	// expression. The l_mode will be converted to UNSIZED if the
757 	// expression does not have a well-determined size.
758       width_mode_t l_mode = SIZED;
759       expr_width_  = left_->test_width(des, scope, l_mode);
760       expr_type_   = left_->expr_type();
761       signed_flag_ = left_->has_sign();
762 
763       if (mode==SIZED)
764 	    mode = l_mode;
765 
766 	// The left operand width defines the size of the
767 	// expression. If the expression has a well-defined size, the
768 	// left_->test_width() above would have set mode==SIZED and we
769 	// can skip a lot of stuff. But if the mode is an undetermined
770 	// size, we need to figure out what we really want to keep a
771 	// lossless value. That's what the following if(...) {...} is
772 	// all about.
773       if ((mode >= EXPAND) && type_is_vectorable(expr_type_)) {
774 
775               // We need to make our best guess at the right operand
776               // value, to minimize the calculated width. This is
777               // particularly important for the power operator...
778 
779               // Start off by assuming the maximum value for the
780               // type and width of the right operand.
781             long r_val = LONG_MAX;
782             if (r_width < sizeof(long)*8) {
783                   r_val = (1L << r_width) - 1L;
784                   if ((op_ == 'p') && right_->has_sign())
785                         r_val >>= 1;
786             }
787 
788               // If the right operand is constant, we can use the
789               // actual value.
790             NetExpr*rp = right_->elaborate_expr(des, scope, r_width, NO_FLAGS);
791             if (rp) {
792                   eval_expr(rp, r_width);
793             } else {
794                   // error recovery
795                   PEVoid*tmp = new PEVoid();
796                   tmp->set_line(*this);
797                   delete right_;
798                   right_ = tmp;
799             }
800             NetEConst*rc = dynamic_cast<NetEConst*> (rp);
801 	      // Adjust the expression width that can be converter depending
802 	      // on if the R-value is signed or not.
803 	    unsigned c_width = sizeof(long)*8;
804 	    if (! right_->has_sign()) c_width -= 1;
805 	    if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
806 
807 	    if (debug_elaborate && rc) {
808 		  cerr << get_fileline() << ": PEBLeftWidth::test_width: "
809 		       << "Evaluated rc=" << *rc
810 		       << ", r_val=" << r_val
811 		       << ", width_cap=" << width_cap << endl;
812 	    }
813 
814               // Clip to a sensible range to avoid underflow/overflow
815               // in the following calculations.
816             if (r_val < 0)
817                   r_val = 0;
818             if ((unsigned long)r_val > width_cap)
819                   r_val = width_cap;
820 
821               // If the left operand is a simple unsized number, we
822               // can calculate the actual width required for the power
823               // operator.
824             PENumber*lc = dynamic_cast<PENumber*> (left_);
825 
826               // Now calculate the lossless width.
827             unsigned use_width = expr_width_;
828             switch (op_) {
829                 case 'l': // <<
830 		  if (l_mode != SIZED)
831 			use_width += (unsigned)r_val;
832                   break;
833 
834                 case 'r': // >>
835                 case 'R': // >>>
836                     // A logical shift will effectively coerce a signed
837                     // operand to unsigned. We have to assume an arithmetic
838                     // shift may do the same, as we don't yet know the final
839                     // expression type.
840                   if ((mode == LOSSLESS) && signed_flag_)
841                         mode = UPSIZE;
842                   break;
843 
844                 case 'p': // **
845                   if (lc && rc) {
846                         verinum result = pow(lc->value(), rc->value());
847                         use_width = max(use_width, result.len());
848                   } else {
849                         if (signed_flag_) use_width -= 1;
850                         use_width *= (unsigned)r_val;
851                         if (signed_flag_) use_width += 2;
852                   }
853                   break;
854 
855                 default:
856                   cerr << get_fileline() << ": internal error: "
857                        << "Unexpected opcode " << human_readable_op(op_)
858                        << " in PEBLeftWidth::test_width." << endl;
859                   des->errors += 1;
860             }
861 
862               // If the right operand is not constant, we could end up
863               // grossly overestimating the required width. So in this
864               // case, don't expand beyond the width of an integer
865               // (which meets the requirements of the standard).
866             if ((rc == 0) && (use_width > expr_width_) && (use_width > integer_width))
867                   use_width = integer_width;
868 
869 	    if (use_width >= width_cap) {
870 		  cerr << get_fileline() << ": warning: "
871 		       << "Unsized expression (" << *this << ")"
872 		       << " expanded beyond and was clipped to " << use_width
873 		       << " bits. Try using sized operands." << endl;
874 	    }
875             expr_width_ = use_width;
876       }
877 
878       if (op_ == 'l')
879             min_width_ = left_->min_width();
880       else
881             min_width_ = UINT_MAX; // disable width pruning
882 
883       if (debug_elaborate) {
884 	    cerr << get_fileline() << ": PEBLeftWidth::test_width: "
885 		 << "Done calculating expr_width_=" << expr_width_
886 		 << ", min_width_=" << min_width_
887 		 << ", mode=" << width_mode_name(mode) << endl;
888       }
889 
890       return fix_width_(mode);
891 }
892 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const893 NetExpr*PEBLeftWidth::elaborate_expr(Design*des, NetScope*scope,
894 				     unsigned expr_wid, unsigned flags) const
895 {
896       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
897 
898       ivl_assert(*this, left_);
899 
900         // The left operand is always context determined, so propagate
901         // down the expression type (signed/unsigned).
902       left_->cast_signed(signed_flag_);
903 
904       unsigned r_width = right_->expr_width();
905 
906       NetExpr*lp =  left_->elaborate_expr(des, scope, expr_wid, flags);
907       NetExpr*rp = right_->elaborate_expr(des, scope, r_width,  flags);
908       if (lp == 0 || rp == 0) {
909 	    delete lp;
910 	    delete rp;
911 	    return 0;
912       }
913 
914         // For shift operations, the right operand is always treated as
915         // unsigned, so coerce it if necessary.
916       if ((op_ != 'p') && rp->has_sign()) {
917             rp = new NetESelect(rp, 0, rp->expr_width());
918             rp->cast_signed(false);
919             rp->set_line(*this);
920       }
921 
922       eval_expr(lp, expr_wid);
923       eval_expr(rp, r_width);
924 
925       return elaborate_expr_leaf(des, lp, rp, expr_wid);
926 }
927 
elaborate_expr_leaf(Design *,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const928 NetExpr*PEBPower::elaborate_expr_leaf(Design*, NetExpr*lp, NetExpr*rp,
929 				      unsigned expr_wid) const
930 {
931       if (debug_elaborate) {
932 	    cerr << get_fileline() << ": debug: elaborate expression "
933 		 << *this << " expr_wid=" << expr_wid << endl;
934       }
935 
936       NetExpr*tmp = new NetEBPow(op_, lp, rp, expr_wid, signed_flag_);
937       tmp->set_line(*this);
938 
939       return tmp;
940 }
941 
elaborate_expr_leaf(Design * des,NetExpr * lp,NetExpr * rp,unsigned expr_wid) const942 NetExpr*PEBShift::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
943 				      unsigned expr_wid) const
944 {
945       switch (op_) {
946 	  case 'l': // <<
947 	  case 'r': // >>
948 	  case 'R': // >>>
949 	    break;
950 
951 	  default:
952 	    cerr << get_fileline() << ": internal error: "
953 		 << "Unexpected opcode " << human_readable_op(op_)
954 		 << " in PEBShift::elaborate_expr_leaf." << endl;
955 	    des->errors += 1;
956             return 0;
957       }
958 
959       if (lp->expr_type() == IVL_VT_REAL || rp->expr_type() == IVL_VT_REAL) {
960 	    cerr << get_fileline() << ": error: "
961 	         << human_readable_op(op_)
962 	         << " operator may not have REAL operands." << endl;
963 	    des->errors += 1;
964             delete lp;
965             delete rp;
966 	    return 0;
967       }
968 
969       NetExpr*tmp;
970 
971 	// If the left expression is constant, then there are some
972 	// special cases we can work with. If the left expression is
973 	// not constant, but the right expression is constant, then
974 	// there are some other interesting cases. But if neither are
975 	// constant, then there is the general case.
976 
977       if (NetEConst*lpc = dynamic_cast<NetEConst*> (lp)) {
978 
979 	      // Special case: The left expression is zero. If the
980 	      // shift value contains no 'x' or 'z' bits, the result
981 	      // is going to be zero.
982 	    if (lpc->value().is_defined() && lpc->value().is_zero()
983 		&& (rp->expr_type() == IVL_VT_BOOL)) {
984 
985 		  if (debug_elaborate)
986 			cerr << get_fileline() << ": debug: "
987 			     << "Shift of zero always returns zero."
988 			     << " Elaborate as constant zero." << endl;
989 
990 		  tmp = make_const_0(expr_wid);
991                   tmp->cast_signed(signed_flag_);
992                   tmp->set_line(*this);
993 
994                   return tmp;
995             }
996 
997       } else if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
998 
999               // Special case: The shift value contains 'x' or 'z' bits.
1000               // Elaborate as a constant-x.
1001             if (!rpc->value().is_defined()) {
1002 
1003 		  if (debug_elaborate)
1004 			cerr << get_fileline() << ": debug: "
1005 			     << "Shift by undefined value. "
1006 			     << "Elaborate as constant 'x'." << endl;
1007 
1008 		  tmp = make_const_x(expr_wid);
1009                   tmp->cast_signed(signed_flag_);
1010                   tmp->set_line(*this);
1011 
1012                   delete lp;
1013                   delete rp;
1014                   return tmp;
1015 	    }
1016 
1017 	    unsigned long shift = rpc->value().as_ulong();
1018 
1019               // Special case: The shift is zero. The result is simply
1020               // the left operand.
1021 	    if (shift == 0) {
1022 
1023 		  if (debug_elaborate)
1024 			cerr << get_fileline() << ": debug: "
1025 			     << "Shift by zero. Elaborate as the "
1026 			     << "left hand operand." << endl;
1027 
1028                   delete rp;
1029                   return lp;
1030 	    }
1031 
1032 	      // Special case: the shift is at least the size of the entire
1033 	      // left operand, and the shift is a signed right shift.
1034               // Elaborate as a replication of the top bit of the left
1035               // expression.
1036 	    if ((op_=='R' && signed_flag_) && (shift >= expr_wid)) {
1037 
1038 		  if (debug_elaborate)
1039 			cerr << get_fileline() << ": debug: "
1040 			     << "Value signed-right-shifted " << shift
1041 			     << " beyond width of " << expr_wid
1042 			     << ". Elaborate as replicated top bit." << endl;
1043 
1044 		  tmp = new NetEConst(verinum(expr_wid-1));
1045 		  tmp->set_line(*this);
1046 		  tmp = new NetESelect(lp, tmp, 1);
1047 		  tmp->set_line(*this);
1048 		  tmp = pad_to_width(tmp, expr_wid, true, *this);
1049 
1050                   delete rp;
1051 		  return tmp;
1052 	    }
1053 
1054 	      // Special case: The shift is at least the size of the entire
1055 	      // left operand, and the shift is not a signed right shift
1056               // (which is caught by the previous special case). Elaborate
1057               // as a constant-0.
1058 	    if (shift >= expr_wid) {
1059 
1060 		  if (debug_elaborate)
1061 			cerr << get_fileline() << ": debug: "
1062 			     << "Value shifted " << shift
1063 			     << " beyond width of " << expr_wid
1064 			     << ". Elaborate as constant zero." << endl;
1065 
1066 		  tmp = make_const_0(expr_wid);
1067                   tmp->cast_signed(signed_flag_);
1068 		  tmp->set_line(*this);
1069 
1070                   delete lp;
1071                   delete rp;
1072 		  return tmp;
1073 	    }
1074       }
1075 
1076 	// Fallback, handle the general case.
1077       tmp = new NetEBShift(op_, lp, rp, expr_wid, signed_flag_);
1078       tmp->set_line(*this);
1079 
1080       return tmp;
1081 }
1082 
test_width_sfunc_(Design * des,NetScope * scope,width_mode_t & mode)1083 unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
1084                                            width_mode_t&mode)
1085 {
1086       perm_string name = peek_tail_name(path_);
1087 
1088       if (name=="$ivlh_to_unsigned") {
1089 	    ivl_assert(*this, parms_.size() == 2);
1090 	      // The Icarus Verilog specific $ivlh_to_unsigned() system
1091 	      // task takes a second argument which is the output
1092 	      // size. This can be an arbitrary constant function.
1093 	    PExpr*pexpr = parms_[1];
1094 	    if (pexpr == 0) {
1095 		  cerr << get_fileline() << ": error: "
1096 		       << "Missing $ivlh_to_unsigned width." << endl;
1097 		  return 0;
1098 	    }
1099 
1100 	    NetExpr*nexpr = elab_and_eval(des, scope, pexpr, -1, true);
1101 	    if (nexpr == 0) {
1102 		  cerr << get_fileline() << ": error: "
1103 		       << "Unable to evaluate " << name
1104 		       << " width argument: " << *pexpr << endl;
1105 		  return 0;
1106 	    }
1107 
1108 	    long value = 0;
1109 	    bool rc = eval_as_long(value, nexpr);
1110 	    ivl_assert(*this, rc && value>=0);
1111 
1112 	      // The argument width is self-determined and doesn't
1113 	      // affect the result width.
1114 	    width_mode_t arg_mode = SIZED;
1115 	    parms_[0]->test_width(des, scope, arg_mode);
1116 
1117 	    expr_type_  = pexpr->expr_type();
1118 	    expr_width_ = value;
1119 	    min_width_  = value;
1120 	    signed_flag_= false;
1121 	    return expr_width_;
1122       }
1123 
1124       if (name=="$signed" || name=="$unsigned") {
1125 	    PExpr*expr = parms_[0];
1126 	    if (expr == 0)
1127 		  return 0;
1128 
1129               // The argument type/width is self-determined, but affects
1130               // the result width.
1131             width_mode_t arg_mode = SIZED;
1132 	    expr_width_  = expr->test_width(des, scope, arg_mode);
1133 	    expr_type_   = expr->expr_type();
1134             min_width_   = expr->min_width();
1135             signed_flag_ = (name[1] == 's');
1136 
1137             if ((arg_mode >= EXPAND) && type_is_vectorable(expr_type_)) {
1138                   if (mode < LOSSLESS)
1139                         mode = LOSSLESS;
1140                   if (expr_width_ < integer_width)
1141                         expr_width_ = integer_width;
1142             }
1143 
1144 	    if (debug_elaborate)
1145 		  cerr << get_fileline() << ": debug: " << name
1146 		       << " argument width = " << expr_width_ << "." << endl;
1147 
1148             return expr_width_;
1149       }
1150 
1151       if (name=="$sizeof" || name=="$bits") {
1152 	    PExpr*expr = parms_[0];
1153 	    if (expr == 0)
1154 		  return 0;
1155 
1156 	    if (! dynamic_cast<PETypename*>(expr)) {
1157 		    // The argument type/width is self-determined and doesn't
1158 		    // affect the result type/width. Note that if the
1159 		    // argument is a type name (a special case) then
1160 		    // don't bother with this step.
1161 		  width_mode_t arg_mode = SIZED;
1162 		  expr->test_width(des, scope, arg_mode);
1163 	    }
1164 
1165 	    expr_type_   = IVL_VT_BOOL;
1166 	    expr_width_  = integer_width;
1167 	    min_width_   = integer_width;
1168             signed_flag_ = false;
1169 
1170 	    if (debug_elaborate)
1171 		  cerr << get_fileline() << ": debug: test_width"
1172 		       << " of " << name << " returns test_width"
1173 		       << " of compiler integer." << endl;
1174 
1175 	    return expr_width_;
1176       }
1177 
1178       if (name=="$is_signed") {
1179 	    PExpr*expr = parms_[0];
1180 	    if (expr == 0)
1181 		  return 0;
1182 
1183               // The argument type/width is self-determined and doesn't
1184               // affect the result type/width.
1185             width_mode_t arg_mode = SIZED;
1186 	    expr->test_width(des, scope, arg_mode);
1187 
1188 	    expr_type_   = IVL_VT_BOOL;
1189 	    expr_width_  = 1;
1190 	    min_width_   = 1;
1191             signed_flag_ = false;
1192 
1193 	    if (debug_elaborate)
1194 		  cerr << get_fileline() << ": debug: test_width"
1195 		       << " of $is_signed returns test_width"
1196 		       << " of 1." << endl;
1197 
1198 	    return expr_width_;
1199       }
1200 
1201 	/* Get the return type of the system function by looking it up
1202 	   in the sfunc_table. */
1203       const struct sfunc_return_type*sfunc_info = lookup_sys_func(name);
1204 
1205       expr_type_   = sfunc_info->type;
1206       expr_width_  = sfunc_info->wid;
1207       min_width_   = expr_width_;
1208       signed_flag_ = sfunc_info->signed_flag;
1209 
1210       is_overridden_ = sfunc_info->override_flag;
1211 
1212       if (debug_elaborate)
1213 	    cerr << get_fileline() << ": debug: test_width "
1214 		 << "of system function " << name
1215 		 << " returns wid=" << expr_width_
1216 		 << ", type=" << expr_type_ << "." << endl;
1217 
1218       return expr_width_;
1219 }
1220 
test_width(Design * des,NetScope * scope,width_mode_t & mode)1221 unsigned PECallFunction::test_width(Design*des, NetScope*scope,
1222                                     width_mode_t&mode)
1223 {
1224       if (peek_tail_name(path_)[0] == '$')
1225 	    return test_width_sfunc_(des, scope, mode);
1226 
1227 	// The width of user defined functions depends only on the
1228 	// width of the return value. The arguments are entirely
1229 	// self-determined.
1230       NetFuncDef*def = des->find_function(scope, path_);
1231       if (def == 0) {
1232 	      // If this is an access function, then the width and
1233 	      // type are known by definition.
1234 	    if (find_access_function(path_)) {
1235 		  expr_type_   = IVL_VT_REAL;
1236 		  expr_width_  = 1;
1237 		  min_width_   = 1;
1238                   signed_flag_ = true;
1239 
1240 		  return expr_width_;
1241 	    }
1242 
1243 	    if (test_width_method_(des, scope, mode)) {
1244 		  if (debug_elaborate)
1245 			cerr << get_fileline() << ": debug: test_width "
1246 			     << "of method returns width " << expr_width_
1247 			     << ", type=" << expr_type_
1248 			     << "." << endl;
1249 		  return expr_width_;
1250 	    }
1251 
1252 	    if (debug_elaborate)
1253 		  cerr << get_fileline() << ": debug: test_width "
1254 		       << "cannot find definition of " << path_
1255 		       << " in " << scope_path(scope) << "." << endl;
1256 	    return 0;
1257       }
1258 
1259       NetScope*dscope = def->scope();
1260       assert(dscope);
1261 
1262       if (NetNet*res = dscope->find_signal(dscope->basename())) {
1263 	    expr_type_   = res->data_type();
1264 	    expr_width_  = res->vector_width();
1265             min_width_   = expr_width_;
1266             signed_flag_ = res->get_signed();
1267 
1268 	    if (debug_elaborate)
1269 		  cerr << get_fileline() << ": debug: test_width "
1270 		       << "of function returns width " << expr_width_
1271 		       << ", type=" << expr_type_
1272 		       << "." << endl;
1273 
1274 	    return expr_width_;
1275       }
1276 
1277       ivl_assert(*this, 0);
1278       return 0;
1279 }
1280 
test_width_method_(Design * des,NetScope * scope,width_mode_t &)1281 unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
1282 					    width_mode_t&)
1283 {
1284       if (!gn_system_verilog())
1285 	    return 0;
1286 
1287 	// This is only useful if the path is at least 2 elements. For
1288 	// example, foo.bar() is a method, bar() is not.
1289       if (path_.size() < 2)
1290 	    return 0;
1291 
1292       perm_string member_name;
1293       pform_name_t use_path = path_;
1294       perm_string method_name = peek_tail_name(use_path);
1295       use_path.pop_back();
1296 
1297       NetNet *net = 0;
1298       const NetExpr *par;
1299       NetEvent *eve;
1300       const NetExpr *ex1, *ex2;
1301 
1302       symbol_search(this, des, scope, use_path,
1303 		    net, par, eve, ex1, ex2);
1304 
1305       const netdarray_t*use_darray = 0;
1306 
1307       if (net != 0)
1308 	    use_darray = net->darray_type();
1309 
1310 	// Net is not found, but maybe it is a member of a
1311 	// struct or class. Try to locate net without the member
1312 	// name and test if it is a type that has members.
1313       if (net == 0 && use_path.size() >= 2) {
1314 	    pform_name_t tmp_path = use_path;
1315 	    member_name = peek_tail_name(tmp_path);
1316 	    tmp_path.pop_back();
1317 
1318 	    net = 0;
1319 	    symbol_search(this, des, scope, tmp_path,
1320 			  net, par, eve, ex1, ex2);
1321 	    if (net && net->class_type()) {
1322 		  if (debug_elaborate) {
1323 			cerr << get_fileline() << ": PECallFunction::test_width_method_: "
1324 			     << "Found net=" << tmp_path
1325 			     << ", member_name=" << member_name
1326 			     << ", method_name=" << method_name
1327 			     << endl;
1328 		  }
1329 
1330 		  const netclass_t* class_type = net->class_type();
1331 		  int midx = class_type->property_idx_from_name(member_name);
1332 		  ivl_type_t  member_type = 0;
1333 		  if (midx >= 0) member_type = class_type->get_prop_type(midx);
1334 
1335 		  use_darray = dynamic_cast<const netdarray_t*> (member_type);
1336 
1337 	    } else {
1338 		  member_name = perm_string();
1339 		  net = 0;
1340 	    }
1341       }
1342 
1343 	// After all, no sign of a net match. Give up.
1344       if (net == 0)
1345 	    return 0;
1346 
1347 	// Look for built in string attributes.
1348       if (net->data_type()==IVL_VT_STRING) {
1349 
1350 	    if (method_name == "len") {
1351 		  expr_type_  = IVL_VT_BOOL;
1352 		  expr_width_ = 32;
1353 		  min_width_  = 32;
1354 		  signed_flag_= true;
1355 		  return expr_width_;
1356 	    }
1357       }
1358 
1359 	// function int size()
1360       if (use_darray && method_name == "size") {
1361 	    if (debug_elaborate) {
1362 		  cerr << get_fileline() << ": PECallFunction::test_width_method_: "
1363 		       << "Match darray size() method." << endl;
1364 	    }
1365 
1366 	    expr_type_  = IVL_VT_BOOL;
1367 	    expr_width_ = 32;
1368 	    min_width_  = expr_width_;
1369 	    signed_flag_= true;
1370 	    return expr_width_;
1371       }
1372 
1373       if (use_darray && (method_name == "pop_back" || method_name=="pop_front")) {
1374 	    if (debug_elaborate) {
1375 		  cerr << get_fileline() << ": PECallFunction::test_width_method_: "
1376 		       << "Detected " << method_name << " method"
1377 		       << " of dynamic arrays." << endl;
1378 	    }
1379 
1380 	    expr_type_  = use_darray->element_base_type();
1381 	    expr_width_ = use_darray->element_width();
1382 	    min_width_  = expr_width_;
1383 	    signed_flag_= false;
1384 
1385 	    return expr_width_;
1386       }
1387 
1388       if (const netclass_t*class_type = net->class_type()) {
1389 	    if (debug_elaborate) {
1390 		  cerr << get_fileline() << ": PECallFunction::test_width_method_: "
1391 		       << "Try to find method " << method_name
1392 		       << " of class " << class_type->get_name() << endl;
1393 	    }
1394 
1395 	    NetScope*func = class_type->method_from_name(method_name);
1396 	    if (func == 0) {
1397 		  return 0;
1398 	    }
1399 
1400 	      // Get the function result size be getting the details
1401 	      // from the variable in the function scope that has the
1402 	      // name of the function.
1403 	    if (NetNet*res = func->find_signal(method_name)) {
1404 		  expr_type_ = res->data_type();
1405 		  expr_width_= res->vector_width();
1406 		  min_width_ = expr_width_;
1407 		  signed_flag_ = res->get_signed();
1408 		  return expr_width_;
1409 	    } else {
1410 		  ivl_assert(*this, 0);
1411 	    }
1412       }
1413 
1414       return 0;
1415 }
1416 
cast_to_width_(NetExpr * expr,unsigned wid) const1417 NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
1418 {
1419       if (debug_elaborate) {
1420             cerr << get_fileline() << ": PECallFunction::cast_to_width_: "
1421 		 << "cast to " << wid
1422                  << " bits " << (signed_flag_ ? "signed" : "unsigned")
1423 		 << " from expr_width()=" << expr->expr_width() << endl;
1424       }
1425 
1426       return cast_to_width(expr, wid, signed_flag_, *this);
1427 }
1428 
1429 /*
1430  * Given a call to a system function, generate the proper expression
1431  * nodes to represent the call in the netlist. Since we don't support
1432  * size_tf functions, make assumptions about widths based on some
1433  * known function names.
1434  */
elaborate_sfunc_(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const1435 NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
1436                                           unsigned expr_wid,
1437                                           unsigned flags) const
1438 {
1439       perm_string name = peek_tail_name(path_);
1440 
1441 	/* Catch the special case that the system function is the
1442 	   $ivl_unsigned function. In this case the second argument is
1443 	   the size of the expression, but should already be accounted
1444 	   for so treat this very much like the $unsigned() function. */
1445       if (name=="$ivlh_to_unsigned") {
1446 	    ivl_assert(*this, parms_.size()==2);
1447 
1448 	    PExpr*expr = parms_[0];
1449 	    ivl_assert(*this, expr);
1450 	    NetExpr*sub = expr->elaborate_expr(des, scope, expr->expr_width(), flags);
1451 	    return cast_to_width_(sub, expr_wid);
1452       }
1453 
1454 	/* Catch the special case that the system function is the $signed
1455 	   function. Its argument will be evaluated as a self-determined
1456            expression. */
1457       if (name=="$signed" || name=="$unsigned") {
1458 	    if ((parms_.size() != 1) || (parms_[0] == 0)) {
1459 		  cerr << get_fileline() << ": error: The " << name
1460 		       << " function takes exactly one(1) argument." << endl;
1461 		  des->errors += 1;
1462 		  return 0;
1463 	    }
1464 
1465             if (!type_is_vectorable(expr_type_)) {
1466 	          cerr << get_fileline() << ": error: The argument to "
1467 		       << name << " must be a vector type." << endl;
1468 	          des->errors += 1;
1469 	          return 0;
1470             }
1471 
1472 	    if (debug_elaborate) {
1473 		  cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
1474 		       << name << " expression is the argument cast to expr_wid=" << expr_wid << endl;
1475 	    }
1476 	    PExpr*expr = parms_[0];
1477 	    NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
1478 
1479 	    return cast_to_width_(sub, expr_wid);
1480       }
1481 
1482 	/* Interpret the internal $sizeof system function to return
1483 	   the bit width of the sub-expression. The value of the
1484 	   sub-expression is not used, so the expression itself can be
1485 	   deleted. */
1486       if (name=="$sizeof" || name=="$bits") {
1487 	    if ((parms_.size() != 1) || (parms_[0] == 0)) {
1488 		  cerr << get_fileline() << ": error: The " << name
1489 		       << " function takes exactly one(1) argument." << endl;
1490 		  des->errors += 1;
1491 		  return 0;
1492 	    }
1493 
1494 	    if (name=="$sizeof")
1495 		  cerr << get_fileline() << ": warning: $sizeof is deprecated."
1496 		       << " Use $bits() instead." << endl;
1497 
1498 	    PExpr*expr = parms_[0];
1499 
1500 	    uint64_t use_width = 0;
1501 	    if (PETypename*type_expr = dynamic_cast<PETypename*>(expr)) {
1502 		  ivl_type_t tmp_type = type_expr->get_type()->elaborate_type(des, scope);
1503 		  ivl_assert(*this, tmp_type);
1504 		  use_width = tmp_type->packed_width();
1505 		  if (debug_elaborate) {
1506 			cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
1507 			     << " Packed width of type argument is " << use_width << endl;
1508 		  }
1509 
1510 	    } else {
1511 		  use_width = expr->expr_width();
1512 		  if (debug_elaborate) {
1513 			cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
1514 			     << " Width of expression argument is " << use_width << endl;
1515 		  }
1516 	    }
1517 
1518 	    verinum val (use_width, integer_width);
1519 	    NetEConst*sub = new NetEConst(val);
1520 	    sub->set_line(*this);
1521 
1522 	    return cast_to_width_(sub, expr_wid);
1523       }
1524 
1525 	/* Interpret the internal $is_signed system function to return
1526 	   a single bit flag -- 1 if the expression is signed, 0
1527 	   otherwise. */
1528       if (name=="$is_signed") {
1529 	    if ((parms_.size() != 1) || (parms_[0] == 0)) {
1530 		  cerr << get_fileline() << ": error: The " << name
1531 		       << " function takes exactly one(1) argument." << endl;
1532 		  des->errors += 1;
1533 		  return 0;
1534 	    }
1535 
1536 	    PExpr*expr = parms_[0];
1537 
1538 	    verinum val (expr->has_sign() ? verinum::V1 : verinum::V0, 1);
1539 	    NetEConst*sub = new NetEConst(val);
1540 	    sub->set_line(*this);
1541 
1542 	    return cast_to_width_(sub, expr_wid);
1543       }
1544 
1545 	/* How many parameters are there? The Verilog language allows
1546 	   empty parameters in certain contexts, so the parser will
1547 	   allow things like func(1,,3). It will also cause func() to
1548 	   be interpreted as a single empty parameter.
1549 
1550 	   Functions cannot really take empty parameters, but the
1551 	   case ``func()'' is the same as no parameters at all. So
1552 	   catch that special case here. */
1553       unsigned nparms = parms_.size();
1554       if ((nparms == 1) && (parms_[0] == 0))
1555 	    nparms = 0;
1556 
1557       NetESFunc*fun = new NetESFunc(name, expr_type_, expr_width_, nparms, is_overridden_);
1558       fun->set_line(*this);
1559 
1560       bool need_const = NEED_CONST & flags;
1561 
1562 	/* We don't support evaluating overridden functions. */
1563       if (is_overridden_ && (need_const || scope->need_const_func())) {
1564 	    cerr << get_fileline() << ": sorry: Cannot evaluate "
1565 		    "overridden system function." << endl;
1566 	    des->errors += 1;
1567       }
1568 
1569       if (is_overridden_ || !fun->is_built_in()) {
1570 	    if (scope->need_const_func()) {
1571 		  cerr << get_fileline() << ": error: " << name
1572 		       << " is not a built-in function, so cannot"
1573 		       << " be used in a constant function." << endl;
1574 		  des->errors += 1;
1575 	    }
1576 	    scope->is_const_func(false);
1577       }
1578 
1579 	/* Now run through the expected parameters. If we find that
1580 	   there are missing parameters, print an error message.
1581 
1582 	   While we're at it, try to evaluate the function parameter
1583 	   expression as much as possible, and use the reduced
1584 	   expression if one is created. */
1585 
1586 	/* These functions can work in a constant context with a signal expression. */
1587       if ((nparms == 1) && (dynamic_cast<PEIdent*>(parms_[0]))) {
1588 	    if (strcmp(name, "$dimensions") == 0) need_const = false;
1589 	    else if (strcmp(name, "$high") == 0) need_const = false;
1590 	    else if (strcmp(name, "$increment") == 0) need_const = false;
1591 	    else if (strcmp(name, "$left") == 0) need_const = false;
1592 	    else if (strcmp(name, "$low") == 0) need_const = false;
1593 	    else if (strcmp(name, "$right") == 0) need_const = false;
1594 	    else if (strcmp(name, "$size") == 0) need_const = false;
1595 	    else if (strcmp(name, "$unpacked_dimensions") == 0) need_const = false;
1596       }
1597 
1598       unsigned parm_errors = 0;
1599       unsigned missing_parms = 0;
1600       for (unsigned idx = 0 ;  idx < nparms ;  idx += 1) {
1601 	    PExpr*expr = parms_[idx];
1602 	    if (expr) {
1603 		  NetExpr*tmp = elab_sys_task_arg(des, scope, name, idx,
1604                                                   expr, need_const);
1605                   if (tmp) {
1606                         fun->parm(idx, tmp);
1607                   } else {
1608                         parm_errors += 1;
1609                         fun->parm(idx, 0);
1610                   }
1611 	    } else {
1612 		  missing_parms += 1;
1613 		  fun->parm(idx, 0);
1614 	    }
1615       }
1616 
1617       if (missing_parms > 0) {
1618 	    cerr << get_fileline() << ": error: The function " << name
1619 		 << " has been called with missing/empty parameters." << endl;
1620 	    cerr << get_fileline() << ":      : Verilog doesn't allow "
1621 		 << "passing empty parameters to functions." << endl;
1622 	    des->errors += 1;
1623       }
1624 
1625       if (missing_parms || parm_errors)
1626             return 0;
1627 
1628       return pad_to_width(fun, expr_wid, signed_flag_, *this);
1629 }
1630 
elaborate_access_func_(Design * des,NetScope * scope,ivl_nature_t nature,unsigned expr_wid) const1631 NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
1632 						ivl_nature_t nature,
1633                                                 unsigned expr_wid) const
1634 {
1635 	// An access function must have 1 or 2 arguments.
1636       ivl_assert(*this, parms_.size()==2 || parms_.size()==1);
1637 
1638       NetBranch*branch = 0;
1639 
1640       if (parms_.size() == 1) {
1641 	    PExpr*arg1 = parms_[0];
1642 	    PEIdent*arg_ident = dynamic_cast<PEIdent*> (arg1);
1643 	    ivl_assert(*this, arg_ident);
1644 
1645 	    const pform_name_t&path = arg_ident->path();
1646 	    ivl_assert(*this, path.size()==1);
1647 	    perm_string name = peek_tail_name(path);
1648 
1649 	    NetNet*sig = scope->find_signal(name);
1650 	    ivl_assert(*this, sig);
1651 
1652 	    ivl_discipline_t dis = sig->get_discipline();
1653 	    ivl_assert(*this, dis);
1654 	    ivl_assert(*this, nature == dis->potential() || nature == dis->flow());
1655 
1656 	    NetNet*gnd = des->find_discipline_reference(dis, scope);
1657 
1658 	    if ( (branch = find_existing_implicit_branch(sig, gnd)) ) {
1659 		  if (debug_elaborate)
1660 			cerr << get_fileline() << ": debug: "
1661 			     << "Re-use implicit branch from "
1662 			     << branch->get_fileline() << endl;
1663 	    } else {
1664 		  branch = new NetBranch(dis);
1665 		  branch->set_line(*this);
1666 		  connect(branch->pin(0), sig->pin(0));
1667 		  connect(branch->pin(1), gnd->pin(0));
1668 
1669 		  des->add_branch(branch);
1670 		  join_island(branch);
1671 
1672 		  if (debug_elaborate)
1673 			cerr << get_fileline() << ": debug: "
1674 			     << "Create implicit branch." << endl;
1675 
1676 	    }
1677 
1678       } else {
1679 	    ivl_assert(*this, 0);
1680       }
1681 
1682       NetExpr*tmp = new NetEAccess(branch, nature);
1683       tmp->set_line(*this);
1684 
1685       return pad_to_width(tmp, expr_wid, signed_flag_, *this);
1686 }
1687 
1688 /*
1689  * Routine to look for and build enumeration method calls.
1690  */
check_for_enum_methods(const LineInfo * li,Design * des,NetScope * scope,const netenum_t * netenum,const pform_name_t & use_path,perm_string method_name,NetExpr * expr,unsigned rtn_wid,PExpr * parg,unsigned args)1691 static NetExpr* check_for_enum_methods(const LineInfo*li,
1692                                        Design*des, NetScope*scope,
1693                                        const netenum_t*netenum,
1694                                        const pform_name_t&use_path,
1695                                        perm_string method_name,
1696                                        NetExpr*expr,
1697                                        unsigned rtn_wid,
1698                                        PExpr*parg, unsigned args)
1699 {
1700 	// The "num()" method returns the number of elements.
1701       if (method_name == "num") {
1702 	    if (args != 0) {
1703 		  cerr << li->get_fileline() << ": error: enumeration "
1704 		          "method " << use_path << ".num() does not "
1705 		          "take an argument." << endl;
1706 		  des->errors += 1;
1707 	    }
1708 	    NetEConst*tmp = make_const_val(netenum->size());
1709 	    tmp->set_line(*li);
1710 	    delete expr; // The elaborated enum variable is not needed.
1711 	    return tmp;
1712       }
1713 
1714 	// The "first()" method returns the first enumeration value.
1715       if (method_name == "first") {
1716 	    if (args != 0) {
1717 		  cerr << li->get_fileline() << ": error: enumeration "
1718 		          "method " << use_path << ".first() does not "
1719 		          "take an argument." << endl;
1720 		  des->errors += 1;
1721 	    }
1722 	    netenum_t::iterator item = netenum->first_name();
1723 	    NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
1724 	                                          netenum, item->second);
1725 	    tmp->set_line(*li);
1726 	    delete expr; // The elaborated enum variable is not needed.
1727 	    return tmp;
1728       }
1729 
1730 	// The "last()" method returns the first enumeration value.
1731       if (method_name == "last") {
1732 	    if (args != 0) {
1733 		  cerr << li->get_fileline() << ": error: enumeration "
1734 		          "method " << use_path << ".last() does not "
1735 		          "take an argument." << endl;
1736 		  des->errors += 1;
1737 	    }
1738 	    netenum_t::iterator item = netenum->last_name();
1739 	    NetEConstEnum*tmp = new NetEConstEnum(scope, item->first,
1740 	                                          netenum, item->second);
1741 	    tmp->set_line(*li);
1742 	    delete expr; // The elaborated enum variable is not needed.
1743 	    return tmp;
1744       }
1745 
1746       NetESFunc*sys_expr;
1747 
1748 	// Process the method argument if it is available.
1749       NetExpr* count = 0;
1750       if (args != 0 && parg) {
1751 	    count = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
1752 					IVL_VT_BOOL, 32, parg);
1753 	    if (count == 0) {
1754 		  cerr << li->get_fileline() << ": error: unable to elaborate "
1755 		          "enumeration method argument " << use_path << "."
1756 		       << method_name << "(" << parg << ")." << endl;
1757 		  args = 0;
1758 		  des->errors += 1;
1759 	    } else if (NetEEvent*evt = dynamic_cast<NetEEvent*> (count)) {
1760 		  cerr << evt->get_fileline() << ": error: An event '"
1761 		       << evt->event()->name() << "' cannot be an enumeration "
1762 		          "method argument." << endl;
1763 		  args = 0;
1764 		  des->errors += 1;
1765 	    }
1766       }
1767 
1768 	// The "name()" method returns the name of the current
1769 	// enumeration value.
1770       if (method_name == "name") {
1771 	    if (args != 0) {
1772 		  cerr << li->get_fileline() << ": error: enumeration "
1773 		          "method " << use_path << ".name() does not "
1774 		          "take an argument." << endl;
1775 		  des->errors += 1;
1776 	    }
1777 	    sys_expr = new NetESFunc("$ivl_enum_method$name", IVL_VT_STRING,
1778 	                             rtn_wid, 2);
1779 	    sys_expr->parm(0, new NetENetenum(netenum));
1780 	    sys_expr->parm(1, expr);
1781 
1782 	      /* The compiler/code generators need to be fixed to support a
1783 	       * string return value. In some contexts we could use the
1784 	       * expression width, but that doesn't always work. */
1785 	    if (rtn_wid == 0) {
1786 		  cerr << li->get_fileline() << ": sorry: Enumeration method "
1787 		          "name() is not currently supported in this context "
1788 		          "(self-determined)." << endl;
1789 		  des->errors += 1;
1790 	    }
1791 
1792 	// The "next()" method returns the next enumeration value.
1793       } else if (method_name == "next") {
1794 	    if (args > 1) {
1795 		  cerr << li->get_fileline() << ": error: enumeration "
1796 		          "method " << use_path << ".next() take at "
1797 		          "most one argument." << endl;
1798 		  des->errors += 1;
1799 	    }
1800 	    sys_expr = new NetESFunc("$ivl_enum_method$next", netenum,
1801 	                             2 + (args != 0));
1802 	    sys_expr->parm(0, new NetENetenum(netenum));
1803 	    sys_expr->parm(1, expr);
1804 	    if (args != 0) sys_expr->parm(2, count);
1805 
1806 	// The "prev()" method returns the previous enumeration value.
1807       } else if (method_name == "prev") {
1808 	    if (args > 1) {
1809 		  cerr << li->get_fileline() << ": error: enumeration "
1810 		          "method " << use_path << ".prev() take at "
1811 		          "most one argument." << endl;
1812 		  des->errors += 1;
1813 	    }
1814 	    sys_expr = new NetESFunc("$ivl_enum_method$prev", netenum,
1815 	                             2 + (args != 0));
1816 	    sys_expr->parm(0, new NetENetenum(netenum));
1817 	    sys_expr->parm(1, expr);
1818 	    if (args != 0) sys_expr->parm(2, count);
1819 
1820 	// This is an unknown enumeration method.
1821       } else {
1822 	    cerr << li->get_fileline() << ": error: Unknown enumeration "
1823 	            "method " << use_path << "." << method_name << "()."
1824 	         << endl;
1825 	    des->errors += 1;
1826 	    return expr;
1827       }
1828 
1829       sys_expr->set_line(*li);
1830 
1831       if (debug_elaborate) {
1832 	    cerr << li->get_fileline() << ": debug: Generate "
1833 	         << sys_expr->name() << "(" << use_path << ")" << endl;
1834       }
1835 
1836       return sys_expr;
1837 }
1838 
1839 /*
1840  * If the method matches a structure member then return the member otherwise
1841  * return 0. Also return the offset of the member.
1842  */
get_struct_member(const LineInfo * li,Design * des,NetScope *,NetNet * net,perm_string method_name,unsigned long & off)1843 static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
1844                                                      Design*des, NetScope*,
1845                                                      NetNet*net,
1846                                                      perm_string method_name,
1847                                                      unsigned long&off)
1848 {
1849       const netstruct_t*type = net->struct_type();
1850       ivl_assert(*li, type);
1851 
1852       if (! type->packed()) {
1853 	    cerr << li->get_fileline()
1854 	         << ": sorry: unpacked structures not supported here. "
1855 		 << "Method=" << method_name << endl;
1856 	    des->errors += 1;
1857 	    return 0;
1858       }
1859 
1860       return type->packed_member(method_name, off);
1861 }
1862 
calculate_part(const LineInfo * li,Design * des,NetScope * scope,const index_component_t & index,long & off,unsigned long & wid)1863 bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
1864 		    const index_component_t&index, long&off, unsigned long&wid)
1865 {
1866       if (index.sel == index_component_t::SEL_BIT_LAST) {
1867 	    cerr << li->get_fileline() << ": sorry: "
1868 		 << "Last element select expression "
1869 		 << "not supported." << endl;
1870 	    des->errors += 1;
1871 	    return false;
1872       }
1873 
1874 	// Evaluate the last index expression into a constant long.
1875       NetExpr*texpr = elab_and_eval(des, scope, index.msb, -1, true);
1876       long msb;
1877       if (texpr == 0 || !eval_as_long(msb, texpr)) {
1878 	    cerr << li->get_fileline() << ": error: "
1879 		  "Array/part index expressions must be constant here." << endl;
1880 	    des->errors += 1;
1881 	    return false;
1882       }
1883 
1884       delete texpr;
1885 
1886       long lsb = msb;
1887       if (index.lsb) {
1888 	    texpr = elab_and_eval(des, scope, index.lsb, -1, true);
1889 	    if (texpr==0 || !eval_as_long(lsb, texpr)) {
1890 		  cerr << li->get_fileline() << ": error: "
1891 			"Array/part index expressions must be constant here." << endl;
1892 		  des->errors += 1;
1893 		  return false;
1894 	    }
1895 
1896 	    delete texpr;
1897       }
1898 
1899       switch (index.sel) {
1900 	  case index_component_t::SEL_BIT:
1901 	    off = msb;
1902 	    wid = 1;
1903 	    return true;
1904 
1905 	  case index_component_t::SEL_PART:
1906 	    if (msb >= lsb) {
1907 		  off = lsb;
1908 		  wid = msb - lsb + 1;
1909 	    } else {
1910 		  off = msb;
1911 		  wid = lsb - msb + 1;
1912 	    }
1913 	    return true;
1914 
1915 	  case index_component_t::SEL_IDX_UP:
1916 	    wid = lsb;
1917 	    off = msb;
1918 	    break;
1919 
1920 	  default:
1921 	    ivl_assert(*li, 0);
1922 	    break;
1923       }
1924       return true;
1925 }
1926 
1927 /*
1928  * Test if the tail name (method_name argument) is a member name and
1929  * the net is a struct. If that turns out to be the case, and the
1930  * struct is packed, then return a NetExpr that selects the member out
1931  * of the variable.
1932  */
check_for_struct_members(const LineInfo * li,Design * des,NetScope * scope,NetNet * net,const list<index_component_t> & base_index,pform_name_t member_path)1933 static NetExpr* check_for_struct_members(const LineInfo*li,
1934 					 Design*des, NetScope*scope,
1935 					 NetNet*net,
1936 					 const list<index_component_t>&base_index,
1937 					 pform_name_t member_path)
1938 {
1939       const netstruct_t*struct_type = net->struct_type();
1940       ivl_assert(*li, struct_type);
1941 
1942       if (! struct_type->packed()) {
1943 	    cerr << li->get_fileline() << ": sorry: "
1944 		 << "Unpacked structures not supported here."
1945 		 << endl;
1946 	    des->errors += 1;
1947 	    return 0;
1948       }
1949 
1950 	// These make up the "part" select that is the equivilent of
1951 	// following the member path through the nested structs. To
1952 	// start with, the off[set] is zero, and use_width is the
1953 	// width of the entire variable. The first member_comp is at
1954 	// some offset within the variable, and will have a reduced
1955 	// width. As we step through the member_path the off
1956 	// increases, and use_width shrinks.
1957       unsigned long off = 0;
1958       unsigned long use_width = struct_type->packed_width();
1959 
1960       pform_name_t completed_path;
1961       do {
1962 	    const name_component_t member_comp = member_path.front();
1963 	    const perm_string&member_name = member_comp.name;
1964 
1965 	    if (debug_elaborate) {
1966 		  cerr << li->get_fileline() << ": check_for_struct_members: "
1967 		       << "Processing member_comp=" << member_comp
1968 		       << " (completed_path=" << completed_path << ")"
1969 		       << endl;
1970 	    }
1971 
1972 	      // Calculate the offset within the packed structure of the
1973 	      // member, and any indices. We will add in the offset of the
1974 	      // struct into the packed array later. Note that this works
1975 	      // for packed unions as well (although the offset will be 0
1976 	      // for union members).
1977 	    unsigned long tmp_off;
1978 	    const netstruct_t::member_t* member = struct_type->packed_member(member_name, tmp_off);
1979 
1980 	    if (member == 0) {
1981 		  cerr << li->get_fileline() << ": error: Member " << member_name
1982 		       << " is not a member of struct type of "
1983 		       << net->name()
1984 		       << "." << completed_path << endl;
1985 		  des->errors += 1;
1986 		  return 0;
1987 	    }
1988 	    if (debug_elaborate) {
1989 		  cerr << li->get_fileline() << ": check_for_struct_members: "
1990 		       << "Member type: " << *(member->net_type)
1991 		       << " (" << typeid(*(member->net_type)).name() << ")"
1992 		       << endl;
1993 	    }
1994 
1995 	    off += tmp_off;
1996 	    ivl_assert(*li, use_width >= (unsigned long)member->net_type->packed_width());
1997 	    use_width = member->net_type->packed_width();
1998 
1999 	      // At this point, off and use_width are the part select
2000 	      // expressed by the member_comp, which is a member of the
2001 	      // struct. We can further refine the part select with any
2002 	      // indices that might be present.
2003 
2004 	    if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*>(member->net_type)) {
2005 		    // If the member is itself a struct, then get
2006 		    // ready to go on to the next iteration.
2007 		  struct_type = tmp_struct;
2008 
2009 	    } else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member->net_type)) {
2010 
2011 		    // If the element is an enum, then we don't have
2012 		    // anything special to do.
2013 		  if (debug_elaborate) {
2014 			cerr << li->get_fileline() << ": check_for_struct_members: "
2015 			     << "Tail element is an enum" << *tmp_enum
2016 			     << endl;
2017 		  }
2018 		  struct_type = 0;
2019 
2020 	    } else if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type)) {
2021 
2022 		  if (debug_elaborate) {
2023 			cerr << li->get_fileline() << ": check_for_struct_members: "
2024 			     << "member_comp=" << member_comp
2025 			     << " has " << member_comp.index.size() << " indices."
2026 			     << endl;
2027 		  }
2028 
2029 		    // If the member type is a netvector_t, then it is a
2030 		    // vector of atom or scaler objects. For example, if the
2031 		    // l-value expression is "foo.member[1][2]",
2032 		    // then the member should be something like:
2033 		    //    ... logic [h:l][m:n] member;
2034 		    // There should be index expressions index the vector
2035 		    // down, but there doesn't need to be all of them. We
2036 		    // can, for example, be selecting a part of the vector.
2037 
2038 		    // We only need to process this if there are any
2039 		    // index expressions. If not, then the packed
2040 		    // vector can be handled atomically.
2041 
2042 		    // In any case, this should be the tail of the
2043 		    // member_path, because the array element of this
2044 		    // kind of array cannot be a struct.
2045 		  if (member_comp.index.size() > 0) {
2046 			  // These are the dimensions defined by the type
2047 			const vector<netrange_t>&mem_packed_dims = mem_vec->packed_dims();
2048 
2049 			if (member_comp.index.size() > mem_packed_dims.size()) {
2050 			      cerr << li->get_fileline() << ": error: "
2051 				   << "Too many index expressions for member." << endl;
2052 			      des->errors += 1;
2053 			      return 0;
2054 			}
2055 
2056 			  // Evaluate all but the last index expression, into prefix_indices.
2057 			list<long>prefix_indices;
2058 			bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
2059 			ivl_assert(*li, rc);
2060 
2061 			if (debug_elaborate) {
2062 			      cerr << li->get_fileline() << ": check_for_struct_members: "
2063 				   << "prefix_indices.size()==" << prefix_indices.size()
2064 				   << ", mem_packed_dims.size()==" << mem_packed_dims.size()
2065 				   << endl;
2066 			}
2067 
2068 			long tail_off = 0;
2069 			unsigned long tail_wid = 0;
2070 			rc = calculate_part(li, des, scope, member_comp.index.back(), tail_off, tail_wid);
2071 			if (! rc) return 0;
2072 
2073 			if (debug_elaborate) {
2074 			      cerr << li->get_fileline() << ": check_for_struct_member: "
2075 				   << "calculate_part for tail returns tail_off=" << tail_off
2076 				   << ", tail_wid=" << tail_wid
2077 				   << endl;
2078 			}
2079 
2080 
2081 			  // Now use the prefix_to_slice function to calculate the
2082 			  // offset and width of the addressed slice
2083 			  // of the member. The lwid comming out of
2084 			  // the prefix_to_slice is the number of
2085 			  // elements, and should be 1. The tmp_wid it
2086 			  // the bit with of the result.
2087 			long loff;
2088 			unsigned long lwid;
2089 			prefix_to_slice(mem_packed_dims, prefix_indices, tail_off, loff, lwid);
2090 
2091 			if (debug_elaborate) {
2092 			      cerr << li->get_fileline() << ": check_for_struct_members: "
2093 				   << "Calculate loff=" << loff << " lwid=" << lwid
2094 				   << " tail_off=" << tail_off << " tail_wid=" << tail_wid
2095 				   << " off=" << off << " use_width=" << use_width
2096 				   << endl;
2097 			}
2098 
2099 			off += loff;
2100 			use_width = lwid * tail_wid;
2101 		  }
2102 
2103 		    // The netvector_t only has atom elements, so
2104 		    // there is no next struct type.
2105 		  struct_type = 0;
2106 
2107 	    } else if (const netparray_t*array = dynamic_cast<const netparray_t*>(member->net_type)) {
2108 
2109 		    // If the member is a parray, then the elements
2110 		    // are themselves packed object, including
2111 		    // possibly a struct. Handle this by taking the
2112 		    // part select of the current part of the
2113 		    // variable, then stepping to the element type to
2114 		    // possibly iterate through more of the member_path.
2115 		  ivl_assert(*li, array->packed());
2116 		  ivl_assert(*li, member_comp.index.size() > 0);
2117 
2118 		    // These are the dimensions defined by the type
2119 		  const vector<netrange_t>&mem_packed_dims = array->static_dimensions();
2120 
2121 		  if (member_comp.index.size() != mem_packed_dims.size()) {
2122 			cerr << li->get_fileline() << ": error: "
2123 			     << "Incorrect number of index expressions for member "
2124 			     << member_name << "." << endl;
2125 			des->errors += 1;
2126 			return 0;
2127 		  }
2128 
2129 		    // Evaluate all but the last index expression, into prefix_indices.
2130 		  list<long>prefix_indices;
2131 		  bool rc = evaluate_index_prefix(des, scope, prefix_indices, member_comp.index);
2132 		  ivl_assert(*li, rc);
2133 
2134 		    // Evaluate the last index expression into a constant long.
2135 		  NetExpr*texpr = elab_and_eval(des, scope, member_comp.index.back().msb, -1, true);
2136 		  long tmp;
2137 		  if (texpr == 0 || !eval_as_long(tmp, texpr)) {
2138 			cerr << li->get_fileline() << ": error: "
2139 			     << "Array index expressions for member " << member_name
2140 			     << " must be constant here." << endl;
2141 			des->errors += 1;
2142 			return 0;
2143 		  }
2144 
2145 		  delete texpr;
2146 
2147 		    // Now use the prefix_to_slice function to calculate the
2148 		    // offset and width of the addressed slice of the member.
2149 		  long loff;
2150 		  unsigned long lwid;
2151 		  prefix_to_slice(mem_packed_dims, prefix_indices, tmp, loff, lwid);
2152 
2153 		  ivl_type_t element_type = array->element_type();
2154 		  long element_width = element_type->packed_width();
2155 		  if (debug_elaborate) {
2156 			cerr << li->get_fileline() << ": PEIdent::elaborate_lval_net_packed_member_: "
2157 			     << "parray subselection loff=" << loff
2158 			     << ", lwid=" << lwid
2159 			     << ", element_width=" << element_width
2160 			     << endl;
2161 		  }
2162 
2163 		    // The width and offset calculated from the
2164 		    // indices is actually in elements, and not
2165 		    // bits. In fact, in this context, the lwid should
2166 		    // come down to 1 (one element).
2167 		  off += loff * element_width;
2168 		  ivl_assert(*li, lwid==1);
2169 		  use_width = element_width;
2170 
2171 		    // To move on to the next component in the member
2172 		    // path, get the element type. For example, for
2173 		    // the path a.b[1].c, we are processing b[1] here,
2174 		    // and the element type should be a netstruct_t
2175 		    // that will wind up containing the member c.
2176 		  struct_type = dynamic_cast<const netstruct_t*> (element_type);
2177 
2178 	    } else {
2179 		    // Unknown type?
2180 		  cerr << li->get_fileline() << ": internal error: "
2181 		       << "Unexpected member type? " << *(member->net_type)
2182 		       << endl;
2183 		  des->errors += 1;
2184 		  struct_type = 0;
2185 	    }
2186 
2187 	      // Complete this component of the path, mark it
2188 	      // completed, and set up for the next component.
2189 	    completed_path .push_back(member_comp);
2190 	    member_path.pop_front();
2191 
2192       } while (member_path.size() > 0 && struct_type != 0);
2193 
2194 	// The dimensions in the expression must match the packed
2195 	// dimensions that are declared for the variable. For example,
2196 	// if foo is a packed array of struct, then this expression
2197 	// must be "b[n][m]" with the right number of dimensions to
2198 	// match the declaration of "b".
2199 	// Note that one of the packed dimensions is the packed struct
2200 	// itself.
2201       ivl_assert(*li, base_index.size()+1 == net->packed_dimensions());
2202 
2203       NetExpr*packed_base = 0;
2204       if (net->packed_dimensions() > 1) {
2205 	    list<index_component_t>tmp_index = base_index;
2206 	    index_component_t member_select;
2207 	    member_select.sel = index_component_t::SEL_BIT;
2208 	    member_select.msb = new PENumber(new verinum(off));
2209 	    tmp_index.push_back(member_select);
2210 	    packed_base = collapse_array_exprs(des, scope, li, net, tmp_index);
2211 	    ivl_assert(*li, packed_base);
2212 	    if (debug_elaborate) {
2213 		  cerr << li->get_fileline() << ": debug: check_for_struct_members: "
2214 		       << "Got collapsed array expr: " << *packed_base << endl;
2215 	    }
2216       }
2217 
2218       long tmp;
2219       if (packed_base && eval_as_long(tmp, packed_base)) {
2220 	    off += tmp;
2221 	    delete packed_base;
2222 	    packed_base = 0;
2223       }
2224 
2225       NetESignal*sig = new NetESignal(net);
2226       NetExpr   *base = packed_base? packed_base : make_const_val(off);
2227       NetESelect*sel = new NetESelect(sig, base, use_width);
2228 
2229       if (debug_elaborate) {
2230 	    cerr << li->get_fileline() << ": check_for_struct_member: "
2231 		 << "Finally, completed_path=" << completed_path
2232 		 << ", off=" << off << ", use_width=" << use_width
2233 		 << ", base=" << *base
2234 		 << endl;
2235       }
2236 
2237       return sel;
2238 }
2239 
class_static_property_expression(const LineInfo * li,const netclass_t * class_type,perm_string name)2240 static NetExpr* class_static_property_expression(const LineInfo*li,
2241 						 const netclass_t*class_type,
2242 						 perm_string name)
2243 {
2244       NetNet*sig = class_type->find_static_property(name);
2245       ivl_assert(*li, sig);
2246       NetESignal*expr = new NetESignal(sig);
2247       expr->set_line(*li);
2248       return expr;
2249 }
2250 
check_for_class_property(const LineInfo * li,Design * des,NetScope * scope,NetNet * net,const name_component_t & comp)2251 static NetExpr* check_for_class_property(const LineInfo*li,
2252 					 Design*des, NetScope*scope,
2253 					 NetNet*net,
2254 					 const name_component_t&comp)
2255 {
2256       const netclass_t*class_type = net->class_type();
2257       int pidx = class_type->property_idx_from_name(comp.name);
2258       if (pidx < 0) {
2259 	    cerr << li->get_fileline() << ": error: "
2260 		 << "Class " << class_type->get_name()
2261 		 << " has no property " << comp.name << "." << endl;
2262 	    des->errors += 1;
2263 	    return 0;
2264       }
2265 
2266       if (debug_elaborate) {
2267 	    cerr << li->get_fileline() << ": check_for_class_property: "
2268 		 << "Property " << comp.name
2269 		 << " of net " << net->name()
2270 		 << ", context scope=" << scope_path(scope)
2271 		 << endl;
2272       }
2273 
2274       property_qualifier_t qual = class_type->get_prop_qual(pidx);
2275       if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
2276 	    cerr << li->get_fileline() << ": error: "
2277 		 << "Local property " << class_type->get_prop_name(pidx)
2278 		 << " is not accessible in this context."
2279 		 << " (scope=" << scope_path(scope) << ")" << endl;
2280 	    des->errors += 1;
2281       }
2282 
2283       if (qual.test_static()) {
2284 	    perm_string prop_name = lex_strings.make(class_type->get_prop_name(pidx));
2285 	    return class_static_property_expression(li, class_type,
2286 						    prop_name);
2287       }
2288 
2289       NetEProperty*tmp = new NetEProperty(net, comp.name);
2290       tmp->set_line(*li);
2291       return tmp;
2292 }
2293 
elaborate_expr_pkg_(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const2294 NetExpr* PECallFunction::elaborate_expr_pkg_(Design*des, NetScope*scope,
2295 					     unsigned expr_wid,
2296 					     unsigned flags) const
2297 {
2298       if (debug_elaborate) {
2299 	    cerr << get_fileline() << ": PECallFunction::elaborate_expr_pkg_: "
2300 		 << "Elaborate " << path_
2301 		 << " as function in package " << package_->pscope_name()
2302 		 << "." << endl;
2303       }
2304 
2305 	// Find the package that contains this definition, and use the
2306 	// package scope as the search starting point for the function
2307 	// definition.
2308       NetScope*pscope = des->find_package(package_->pscope_name());
2309       ivl_assert(*this, pscope);
2310 
2311       NetFuncDef*def = des->find_function(pscope, path_);
2312       ivl_assert(*this, def);
2313 
2314       NetScope*dscope = def->scope();
2315       ivl_assert(*this, dscope);
2316 
2317       if (! check_call_matches_definition_(des, dscope))
2318 	    return 0;
2319 
2320       return elaborate_base_(des, scope, dscope, expr_wid, flags);
2321 }
2322 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const2323 NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
2324 					unsigned expr_wid, unsigned flags) const
2325 {
2326       if (package_)
2327 	    return elaborate_expr_pkg_(des, scope, expr_wid, flags);
2328 
2329       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
2330 
2331       if (peek_tail_name(path_)[0] == '$')
2332 	    return elaborate_sfunc_(des, scope, expr_wid, flags);
2333 
2334       NetFuncDef*def = des->find_function(scope, path_);
2335       if (def == 0) {
2336 	      // Not a user defined function. Maybe it is an access
2337 	      // function for a nature? If so then elaborate it that
2338 	      // way.
2339 	    ivl_nature_t access_nature = find_access_function(path_);
2340 	    if (access_nature)
2341 		  return elaborate_access_func_(des, scope, access_nature,
2342                                                 expr_wid);
2343 
2344 	      // Maybe this is a method attached to a signal? If this
2345 	      // is SystemVerilog then try that possibility.
2346 	    if (gn_system_verilog()) {
2347 		  NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid);
2348 		  if (tmp) return tmp;
2349 	    }
2350 
2351 	      // Nothing was found so report this as an error.
2352 	    cerr << get_fileline() << ": error: No function named `" << path_
2353 	         << "' found in this context (" << scope_path(scope) << ")."
2354                  << endl;
2355 	    des->errors += 1;
2356 	    return 0;
2357       }
2358 
2359       ivl_assert(*this, def);
2360       NetScope*dscope = def->scope();
2361       ivl_assert(*this, dscope);
2362 
2363        /* In SystemVerilog a method calling another method in the
2364         * current class needs to be elaborated as a method with an
2365         * implicit this added.  */
2366       if (gn_system_verilog() && (path_.size() == 1)) {
2367            const NetScope *c_scope = scope->get_class_scope();
2368            if (c_scope && (c_scope == dscope->get_class_scope())) {
2369                  NetExpr*tmp = elaborate_expr_method_(des, scope, expr_wid,
2370 		                                      true);
2371                  assert(tmp);
2372                  return tmp;
2373            }
2374       }
2375 
2376       bool need_const = NEED_CONST & flags;
2377 
2378         // It is possible to get here before the called function has been
2379         // fully elaborated. If this is the case, elaborate it now. This
2380         // ensures we know whether or not it is a constant function.
2381       if (dscope->elab_stage() < 3) {
2382             dscope->need_const_func(need_const || scope->need_const_func());
2383             const PFunction*pfunc = dscope->func_pform();
2384             ivl_assert(*this, pfunc);
2385             pfunc->elaborate(des, dscope);
2386       }
2387 
2388       if (dscope->parent() != scope->parent() || !dscope->is_const_func()) {
2389             if (scope->need_const_func()) {
2390 	          cerr << get_fileline() << ": error: A function invoked by "
2391                           "a constant function must be a constant function "
2392                           "local to the current module." << endl;
2393                   des->errors += 1;
2394             }
2395             scope->is_const_func(false);
2396       }
2397 
2398       return elaborate_base_(des, scope, dscope, expr_wid, flags);
2399 }
2400 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t type,unsigned flags) const2401 NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
2402 					ivl_type_t type, unsigned flags) const
2403 {
2404       const netdarray_t*darray = dynamic_cast<const netdarray_t*>(type);
2405       assert(darray);
2406       return elaborate_expr(des, scope, darray->element_type()->packed_width(), flags);
2407 }
2408 
elaborate_base_(Design * des,NetScope * scope,NetScope * dscope,unsigned expr_wid,unsigned flags) const2409 NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
2410 					 unsigned expr_wid, unsigned flags) const
2411 {
2412 
2413       if (! check_call_matches_definition_(des, dscope))
2414 	    return 0;
2415 
2416       NetFuncDef*def = dscope->func_def();
2417 
2418       bool need_const = NEED_CONST & flags;
2419 
2420 	// If this is a constant expression, it is possible that we
2421 	// are being elaborated before the function definition. If
2422 	// that's the case, try to elaborate the function as a const
2423 	// function.
2424       if (need_const && ! def->proc()) {
2425 	    if (debug_elaborate) {
2426 		  cerr << get_fileline() << ": PECallFunction::elaborate_base_: "
2427 		       << "Try to elaborate " << scope_path(dscope)
2428 		       << " as constant function." << endl;
2429 	    }
2430 	    dscope->set_elab_stage(2);
2431 	    dscope->need_const_func(true);
2432 	    const PFunction*pfunc = dscope->func_pform();
2433 	    ivl_assert(*this, pfunc);
2434 	    pfunc->elaborate(des, dscope);
2435       }
2436 
2437       unsigned parms_count = def->port_count();
2438       vector<NetExpr*> parms (parms_count);
2439 
2440       if (debug_elaborate) {
2441 	    cerr << get_fileline() << ": PECallFunction::elaborate_base_: "
2442 		 << "Expecting " << parms_count
2443 		 << " argument for function " << scope_path(dscope) << "." << endl;
2444       }
2445 
2446 	/* Elaborate the input expressions for the function. This is
2447 	   done in the scope of the function call, and not the scope
2448 	   of the function being called. The scope of the called
2449 	   function is elaborated when the definition is elaborated. */
2450       unsigned parm_errors = elaborate_arguments_(des, scope,
2451 						  def, need_const,
2452 						  parms, 0);
2453 
2454       if (need_const && !dscope->is_const_func()) {
2455 
2456               // If this is the first time the function has been called in
2457               // a constant context, force the function to be re-elaborated.
2458               // This will generate the necessary error messages to allow
2459               // the user to diagnose the fault.
2460             if (!dscope->need_const_func()) {
2461                   dscope->set_elab_stage(2);
2462                   dscope->need_const_func(true);
2463                   const PFunction*pfunc = dscope->func_pform();
2464                   ivl_assert(*this, pfunc);
2465                   pfunc->elaborate(des, dscope);
2466             }
2467 
2468             cerr << get_fileline() << ": error: `" << dscope->basename()
2469                  << "' is not a constant function." << endl;
2470             des->errors += 1;
2471             return 0;
2472       }
2473 
2474       if (parm_errors)
2475             return 0;
2476 
2477 	/* Look for the return value signal for the called
2478 	   function. This return value is a magic signal in the scope
2479 	   of the function, that has the name of the function. The
2480 	   function code assigns to this signal to return a value.
2481 
2482 	   dscope, in this case, is the scope of the function, so the
2483 	   return value is the name within that scope. */
2484 
2485       if (NetNet*res = dscope->find_signal(dscope->basename())) {
2486 	    NetESignal*eres = new NetESignal(res);
2487 	    NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
2488 	    func->set_line(*this);
2489 
2490 	    if(res->darray_type())
2491 	        return func;
2492 
2493             return pad_to_width(func, expr_wid, signed_flag_, *this);
2494       }
2495 
2496       cerr << get_fileline() << ": internal error: Unable to locate "
2497               "function return value for " << path_
2498            << " in " << dscope->basename() << "." << endl;
2499       des->errors += 1;
2500       return 0;
2501 }
2502 
2503 /*
2504  * Elaborate the arguments of a function or method. The parms vector
2505  * is where to place the elaborated expressions, so it an output. The
2506  * parm_off is where in the parms vector to start writing
2507  * arguments. This value is normally 0, but is 1 if this is a method
2508  * so that parms[0] can hold the "this" argument. In this latter case,
2509  * def->port(0) will be the "this" argument and should be skipped.
2510  */
elaborate_arguments_(Design * des,NetScope * scope,NetFuncDef * def,bool need_const,vector<NetExpr * > & parms,unsigned parm_off) const2511 unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
2512 					      NetFuncDef*def, bool need_const,
2513 					      vector<NetExpr*>&parms,
2514 					      unsigned parm_off) const
2515 {
2516       unsigned parm_errors = 0;
2517       unsigned missing_parms = 0;
2518 
2519       const unsigned parm_count = parms.size() - parm_off;
2520       const unsigned actual_count = parms_.size();
2521 
2522 	/* The parser can't distinguish between a function call with
2523 	   no arguments and a function call with one empty argument,
2524 	   and always supplies one empty argument. Handle the no
2525 	   argument case here. */
2526       if ((parm_count == 0) && (actual_count == 1) && (parms_[0] == 0))
2527 	    return 0;
2528 
2529       if (actual_count > parm_count) {
2530 	    cerr << get_fileline() << ": error: "
2531 		 << "Too many arguments (" << actual_count
2532 		 << ", expecting " << parm_count << ")"
2533 		 << " in call to function." << endl;
2534 	    des->errors += 1;
2535       }
2536 
2537       for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
2538 	    unsigned pidx = idx + parm_off;
2539 	    PExpr*tmp = (idx < actual_count) ? parms_[idx] : 0;
2540 	    if (tmp) {
2541 		  parms[pidx] = elaborate_rval_expr(des, scope,
2542 						    def->port(pidx)->net_type(),
2543 						    def->port(pidx)->data_type(),
2544 						    (unsigned)def->port(pidx)->vector_width(),
2545 						    tmp, need_const);
2546 		  if (parms[pidx] == 0) {
2547 			parm_errors += 1;
2548 			continue;
2549 		  }
2550 
2551 		  if (NetEEvent*evt = dynamic_cast<NetEEvent*> (parms[pidx])) {
2552 			cerr << evt->get_fileline() << ": error: An event '"
2553 			     << evt->event()->name() << "' can not be a user "
2554 			        "function argument." << endl;
2555 			des->errors += 1;
2556 		  }
2557 		  if (debug_elaborate)
2558 			cerr << get_fileline() << ": debug:"
2559 			     << " function " << path_
2560 			     << " arg " << (idx+1)
2561 			     << " argwid=" << parms[pidx]->expr_width()
2562 			     << ": " << *parms[idx] << endl;
2563 
2564 	    } else if (def->port_defe(pidx)) {
2565 		  if (! gn_system_verilog()) {
2566 			cerr << get_fileline() << ": internal error: "
2567 			     << "Found (and using) default function argument "
2568 			     << "requires SystemVerilog." << endl;
2569 			des->errors += 1;
2570 		  }
2571 		  parms[pidx] = def->port_defe(pidx);
2572 
2573 	    } else {
2574 		  missing_parms += 1;
2575 		  parms[pidx] = 0;
2576 	    }
2577       }
2578 
2579       if (missing_parms > 0) {
2580 	    cerr << get_fileline() << ": error: The function " << path_
2581 		 << " has been called with missing/empty parameters." << endl;
2582 	    cerr << get_fileline() << ":      : Verilog doesn't allow "
2583 		 << "passing empty parameters to functions." << endl;
2584 	    parm_errors += 1;
2585 	    des->errors += 1;
2586       }
2587 
2588       return parm_errors;
2589 }
2590 
elaborate_expr_method_(Design * des,NetScope * scope,unsigned expr_wid,bool add_this_flag) const2591 NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
2592 						unsigned expr_wid,
2593 						bool add_this_flag) const
2594 {
2595       pform_name_t use_path = path_;
2596       perm_string method_name = peek_tail_name(use_path);
2597       use_path.pop_back();
2598 
2599 	/* Add the implicit this reference when requested. */
2600       if (add_this_flag) {
2601 	    assert(use_path.empty());
2602 	    use_path.push_front(name_component_t(perm_string::literal("@")));
2603       }
2604 
2605 	// If there is no object to the left of the method name, then
2606 	// give up on the idea of looking for an object method.
2607       if (use_path.empty()) return 0;
2608 
2609       NetNet *net = 0;
2610       const NetExpr *par;
2611       NetEvent *eve;
2612       const NetExpr *ex1, *ex2;
2613 
2614       symbol_search(this, des, scope, use_path,
2615 		    net, par, eve, ex1, ex2);
2616 
2617       if (net == 0)
2618 	    return 0;
2619 
2620       if (net->data_type() == IVL_VT_STRING) {
2621 
2622 	    if (method_name == "len") {
2623 		  NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$len",
2624 						     IVL_VT_BOOL, 32, 1);
2625 		  sys_expr->parm(0, new NetESignal(net));
2626 		  return sys_expr;
2627 	    }
2628 
2629 	    if (method_name == "substr") {
2630 		  NetESFunc*sys_expr = new NetESFunc("$ivl_string_method$substr",
2631 						     IVL_VT_STRING, 1, 3);
2632 		  sys_expr->set_line(*this);
2633 
2634 		    // First argument is the source string.
2635 		  sys_expr->parm(0, new NetESignal(net));
2636 
2637 		  ivl_assert(*this, parms_.size() == 2);
2638 		  NetExpr*tmp;
2639 
2640 		  tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
2641 					    IVL_VT_BOOL, 32, parms_[0], false);
2642 		  sys_expr->parm(1, tmp);
2643 
2644 		  tmp = elaborate_rval_expr(des, scope, &netvector_t::atom2u32,
2645 					    IVL_VT_BOOL, 32, parms_[1], false);
2646 		  sys_expr->parm(2, tmp);
2647 
2648 		  return sys_expr;
2649 	    }
2650       }
2651 
2652       if (const netenum_t*netenum = net->enumeration()) {
2653 	      // We may need the net expression for the
2654 	      // enumeration variable so get it.
2655 	    NetESignal*expr = new NetESignal(net);
2656 	    expr->set_line(*this);
2657 	      // This expression cannot be a select!
2658 	    assert(use_path.back().index.empty());
2659 
2660 	    PExpr*tmp = parms_.size() ? parms_[0] : 0;
2661 	    return check_for_enum_methods(this, des, scope,
2662 					  netenum, use_path,
2663 					  method_name, expr,
2664 					  expr_wid, tmp,
2665 					  parms_.size());
2666       }
2667 
2668       if (net->darray_type()) {
2669 
2670 	    if (method_name == "size") {
2671 		  if (parms_.size() != 0) {
2672 			cerr << get_fileline() << ": error: size() method "
2673 			     << "takes no arguments" << endl;
2674 			des->errors += 1;
2675 		  }
2676 		  NetESFunc*sys_expr = new NetESFunc("$size",
2677 						     IVL_VT_BOOL, 32, 1);
2678 		  sys_expr->set_line(*this);
2679 
2680 		  NetESignal*arg = new NetESignal(net);
2681 		  arg->set_line(*net);
2682 
2683 		  sys_expr->parm(0, arg);
2684 		  return sys_expr;
2685 	    }
2686       }
2687 
2688       if (net->queue_type()) {
2689 	    if (method_name == "pop_back") {
2690 		  if (parms_.size() != 0) {
2691 			cerr << get_fileline() << ": error: pop_back() method "
2692 			     << "takes no arguments" << endl;
2693 			des->errors += 1;
2694 		  }
2695 		  NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_back",
2696 						     expr_type_,
2697 						     expr_width_, 1);
2698 		  sys_expr->set_line(*this);
2699 
2700 		  NetESignal*arg = new NetESignal(net);
2701 		  arg->set_line(*net);
2702 
2703 		  sys_expr->parm(0, arg);
2704 		  return sys_expr;
2705 	    }
2706 
2707 	    if (method_name == "pop_front") {
2708 		  if (parms_.size() != 0) {
2709 			cerr << get_fileline() << ": error: pop_front() method "
2710 			     << "takes no arguments" << endl;
2711 			des->errors += 1;
2712 		  }
2713 		  NetESFunc*sys_expr = new NetESFunc("$ivl_queue_method$pop_front",
2714 						     expr_type_,
2715 						     expr_width_, 1);
2716 		  sys_expr->set_line(*this);
2717 
2718 		  NetESignal*arg = new NetESignal(net);
2719 		  arg->set_line(*net);
2720 
2721 		  sys_expr->parm(0, arg);
2722 		  return sys_expr;
2723 	    }
2724 
2725       }
2726 
2727       if (const netclass_t*class_type = net->class_type()) {
2728 	    NetScope*func = class_type->method_from_name(method_name);
2729 	    if (func == 0) {
2730 		  return 0;
2731 	    }
2732 
2733 	    NetFuncDef*def = func->func_def();
2734 	    ivl_assert(*this, def);
2735 
2736 	    NetNet*res = func->find_signal(func->basename());
2737 	    ivl_assert(*this, res);
2738 
2739 	    vector<NetExpr*>parms;
2740 
2741 	    NetESignal*ethis = new NetESignal(net);
2742 	    ethis->set_line(*this);
2743 	    parms.push_back(ethis);
2744 
2745 	    parms.resize(1 + parms_.size());
2746 	    elaborate_arguments_(des, scope, def, false, parms, 1);
2747 
2748 	    NetESignal*eres = new NetESignal(res);
2749 	    NetEUFunc*call = new NetEUFunc(scope, func, eres, parms, false);
2750 	    call->set_line(*this);
2751 	    return call;
2752       }
2753 
2754       return 0;
2755 }
2756 
test_width(Design * des,NetScope * scope,width_mode_t &)2757 unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
2758 {
2759       ivl_assert(*this, size_);
2760       ivl_assert(*this, base_);
2761 
2762       NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
2763       NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
2764       expr_width_ = size_ce ? size_ce->value().as_ulong() : 0;
2765       delete size_ex;
2766       if (expr_width_ == 0) {
2767 	    cerr << get_fileline() << ": error: Cast size expression "
2768 		    "must be constant and greater than zero." << endl;
2769 	    des->errors += 1;
2770 	    return 0;
2771       }
2772 
2773       width_mode_t tmp_mode = PExpr::SIZED;
2774       base_->test_width(des, scope, tmp_mode);
2775 
2776       if (!type_is_vectorable(base_->expr_type())) {
2777 	    cerr << get_fileline() << ": error: Cast base expression "
2778 		    "must be a vector type." << endl;
2779 	    des->errors += 1;
2780 	    return 0;
2781       }
2782 
2783       expr_type_   = base_->expr_type();
2784       min_width_   = expr_width_;
2785       signed_flag_ = base_->has_sign();
2786 
2787       return expr_width_;
2788 }
2789 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const2790 NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
2791 				    unsigned expr_wid, unsigned flags) const
2792 {
2793       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
2794 
2795       ivl_assert(*this, size_);
2796       ivl_assert(*this, base_);
2797 
2798 	// A cast behaves exactly like an assignment to a temporary variable,
2799 	// so the temporary result size may affect the sub-expression width.
2800       unsigned cast_width = base_->expr_width();
2801       if (cast_width < expr_width_)
2802             cast_width = expr_width_;
2803 
2804       NetExpr*sub = base_->elaborate_expr(des, scope, cast_width, flags);
2805       if (sub == 0)
2806 	    return 0;
2807 
2808 	// Perform the cast. The extension method (zero/sign), if needed,
2809 	// depends on the type of the base expression.
2810       NetExpr*tmp = cast_to_width(sub, expr_width_, base_->has_sign(), *this);
2811 
2812 	// Pad up to the expression width. The extension method (zero/sign)
2813 	// depends on the type of enclosing expression.
2814       return pad_to_width(tmp, expr_wid, signed_flag_, *this);
2815 }
2816 
test_width(Design * des,NetScope * scope,width_mode_t &)2817 unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&)
2818 {
2819       ivl_type_t t = target_->elaborate_type(des, scope);
2820 
2821       width_mode_t tmp_mode = PExpr::SIZED;
2822       base_->test_width(des, scope, tmp_mode);
2823 
2824       if (const netdarray_t*use_darray = dynamic_cast<const netdarray_t*>(t)) {
2825 	    expr_type_  = use_darray->element_base_type();
2826 	    expr_width_ = use_darray->element_width();
2827 
2828       } else if (const netstring_t*use_string = dynamic_cast<const netstring_t*>(t)) {
2829 	    expr_type_  = use_string->base_type();
2830 	    expr_width_ = 8;
2831 
2832       } else {
2833 	    expr_type_  = t->base_type();
2834 	    expr_width_ = t->packed_width();
2835       }
2836       min_width_   = expr_width_;
2837       signed_flag_ = t->get_signed();
2838 
2839       return expr_width_;
2840 }
2841 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t type,unsigned flags) const2842 NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
2843                                     ivl_type_t type, unsigned flags) const
2844 {
2845     const netdarray_t*darray = NULL;
2846     const netvector_t*vector = NULL;
2847 
2848     // Casting array of vectors to dynamic array type
2849     if((darray = dynamic_cast<const netdarray_t*>(type)) &&
2850             (vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
2851         PExpr::width_mode_t mode = PExpr::SIZED;
2852         unsigned use_wid = base_->test_width(des, scope, mode);
2853         NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
2854 
2855         assert(vector->packed_width() > 0);
2856         assert(base->expr_width() > 0);
2857 
2858         // Find rounded up length that can fit the whole casted array of vectors
2859         int len = base->expr_width() + vector->packed_width() - 1;
2860         if(base->expr_width() > (unsigned)vector->packed_width()) {
2861             len /= vector->packed_width();
2862         } else {
2863             len /= base->expr_width();
2864         }
2865 
2866         // Number of words in the created dynamic array
2867         NetEConst*len_expr = new NetEConst(verinum(len));
2868         return new NetENew(type, len_expr, base);
2869     }
2870 
2871     // Fallback
2872     return elaborate_expr(des, scope, (unsigned) 0, flags);
2873 }
2874 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const2875 NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
2876 				    unsigned expr_wid, unsigned flags) const
2877 {
2878       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
2879 
2880 	// A cast behaves exactly like an assignment to a temporary variable,
2881 	// so the temporary result size may affect the sub-expression width.
2882       unsigned cast_width = base_->expr_width();
2883       if (type_is_vectorable(base_->expr_type()) && (cast_width < expr_width_))
2884 	    cast_width = expr_width_;
2885 
2886       NetExpr*sub = base_->elaborate_expr(des, scope, cast_width, flags);
2887       if (sub == 0)
2888 	    return 0;
2889 
2890       if (dynamic_cast<const real_type_t*>(target_)) {
2891 	    return cast_to_real(sub);
2892       }
2893 
2894       NetExpr*tmp = 0;
2895       if (dynamic_cast<const atom2_type_t*>(target_)) {
2896 	    tmp = cast_to_int2(sub, expr_width_);
2897       }
2898       if (const vector_type_t*vec = dynamic_cast<const vector_type_t*>(target_)) {
2899 	    switch (vec->base_type) {
2900 		case IVL_VT_BOOL:
2901 		  tmp = cast_to_int2(sub, expr_width_);
2902 		  break;
2903 
2904 		case IVL_VT_LOGIC:
2905 		  tmp = cast_to_int4(sub, expr_width_);
2906 		  break;
2907 
2908 		default:
2909 		  break;
2910 	    }
2911       }
2912       if (tmp) {
2913 	    if (tmp == sub) {
2914 		    // We already had the correct base type, so we just need to
2915 		    // fix the size. Note that even if the size is already correct,
2916                     // we still need to isolate the sub-expression from changes in
2917                     // the signedness pushed down from the main expression.
2918 		  tmp = cast_to_width(sub, expr_width_, sub->has_sign(), *this);
2919 	    }
2920 	    return pad_to_width(tmp, expr_wid, signed_flag_, *this);
2921       }
2922 
2923       if (dynamic_cast<const string_type_t*>(target_)) {
2924 	    if (base_->expr_type() == IVL_VT_STRING)
2925 		  return sub; // no conversion
2926 
2927 	    if (base_->expr_type() == IVL_VT_LOGIC
2928 	     || base_->expr_type() == IVL_VT_BOOL)
2929 		  return sub; // handled by the target as special cases
2930       }
2931 
2932       cerr << get_fileline() << ": sorry: This cast operation is not yet supported." << endl;
2933       des->errors += 1;
2934       return 0;
2935 }
2936 
test_width(Design * des,NetScope * scope,width_mode_t &)2937 unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
2938 {
2939       expr_width_ = 0;
2940       enum {NO, MAYBE, YES} expr_is_string = MAYBE;
2941       for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
2942 	      // Add in the width of this sub-expression.
2943 	    expr_width_ += parms_[idx]->test_width(des, scope, width_modes_[idx]);
2944 
2945 	      // If we already know this is not a string, then move on.
2946 	    if (expr_is_string == NO)
2947 		  continue;
2948 
2949 	      // If this expression is a string, then the
2950 	      // concatenation is a string until we find a reason to
2951 	      // deny it.
2952 	    if (parms_[idx]->expr_type()==IVL_VT_STRING) {
2953 		  expr_is_string = YES;
2954 		  continue;
2955 	    }
2956 
2957 	      // If this is a string literal, then this may yet be a string.
2958 	    if (dynamic_cast<PEString*> (parms_[idx]))
2959 		  continue;
2960 
2961 	      // Failed to allow a string result.
2962 	    expr_is_string = NO;
2963       }
2964 
2965       expr_type_   = (expr_is_string==YES) ? IVL_VT_STRING : IVL_VT_LOGIC;
2966       signed_flag_ = false;
2967 
2968 	// If there is a repeat expression, then evaluate the constant
2969 	// value and set the repeat count.
2970       if (repeat_ && (scope != tested_scope_)) {
2971 	    NetExpr*tmp = elab_and_eval(des, scope, repeat_, -1, true);
2972 	    if (tmp == 0) return 0;
2973 
2974 	    if (tmp->expr_type() == IVL_VT_REAL) {
2975 		  cerr << tmp->get_fileline() << ": error: Concatenation "
2976 		       << "repeat expression can not be REAL." << endl;
2977 		  des->errors += 1;
2978 		  return 0;
2979 	    }
2980 
2981 	    NetEConst*rep = dynamic_cast<NetEConst*>(tmp);
2982 
2983 	    if (rep == 0) {
2984 		  cerr << get_fileline() << ": error: "
2985 			"Concatenation repeat expression is not constant."
2986 		       << endl;
2987 		  cerr << get_fileline() << ":      : The expression is: "
2988 		       << *tmp << endl;
2989 		  des->errors += 1;
2990 		  return 0;
2991 	    }
2992 
2993 	    if (!rep->value().is_defined()) {
2994 		  cerr << get_fileline() << ": error: Concatenation repeat "
2995 		       << "may not be undefined (" << rep->value()
2996 		       << ")." << endl;
2997 		  des->errors += 1;
2998 		  return 0;
2999 	    }
3000 
3001 	    if (rep->value().is_negative()) {
3002 		  cerr << get_fileline() << ": error: Concatenation repeat "
3003 		       << "may not be negative (" << rep->value().as_long()
3004 		       << ")." << endl;
3005 		  des->errors += 1;
3006 		  return 0;
3007 	    }
3008 
3009             repeat_count_ = rep->value().as_ulong();
3010 
3011             tested_scope_ = scope;
3012       }
3013       expr_width_ *= repeat_count_;
3014       min_width_   = expr_width_;
3015 
3016       return expr_width_;
3017 }
3018 
3019 // Keep track of the concatenation/repeat depth.
3020 static int concat_depth = 0;
3021 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const3022 NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
3023 				  ivl_type_t ntype, unsigned flags) const
3024 {
3025       switch (ntype->base_type()) {
3026 	  case IVL_VT_QUEUE:
3027 // FIXME: Does a DARRAY support a zero size?
3028 	  case IVL_VT_DARRAY:
3029 	    if (parms_.size() == 0) {
3030 		  NetENull*tmp = new NetENull;
3031 		  tmp->set_line(*this);
3032 		  return tmp;
3033 	    } else {
3034 		  const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype);
3035 		  ivl_assert(*this, array_type);
3036 
3037 		    // This is going to be an array pattern, so run through the
3038 		    // elements of the expression and elaborate each as if they
3039 		    // are element_type expressions.
3040 		  ivl_type_t elem_type = array_type->element_type();
3041 		  vector<NetExpr*> elem_exprs (parms_.size());
3042 		  for (size_t idx = 0 ; idx < parms_.size() ; idx += 1) {
3043 			NetExpr*tmp = parms_[idx]->elaborate_expr(des, scope, elem_type, flags);
3044 			elem_exprs[idx] = tmp;
3045 		  }
3046 
3047 		  NetEArrayPattern*res = new NetEArrayPattern(array_type, elem_exprs);
3048 		  res->set_line(*this);
3049 		  return res;
3050 	    }
3051 	  default:
3052 	    cerr << get_fileline() << ": internal error: "
3053 		 << "I don't know how to elaborate(ivl_type_t)"
3054 		 << " this expression: " << *this << endl;
3055 	    return 0;
3056       }
3057 }
3058 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const3059 NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
3060 				  unsigned expr_wid, unsigned flags) const
3061 {
3062       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
3063 
3064       concat_depth += 1;
3065 
3066       if (debug_elaborate) {
3067 	    cerr << get_fileline() << ": debug: Elaborate expr=" << *this
3068 		 << ", expr_wid=" << expr_wid << endl;
3069       }
3070 
3071       if (repeat_count_ == 0 && concat_depth < 2) {
3072             cerr << get_fileline() << ": error: Concatenation repeat "
3073                  << "may not be zero in this context." << endl;
3074             des->errors += 1;
3075             concat_depth -= 1;
3076             return 0;
3077       }
3078 
3079       unsigned wid_sum = 0;
3080       unsigned parm_cnt = 0;
3081       unsigned parm_errors = 0;
3082       svector<NetExpr*> parms(parms_.size());
3083 
3084 	/* Elaborate all the parameters and attach them to the concat node. */
3085       for (unsigned idx = 0 ;  idx < parms_.size() ;  idx += 1) {
3086 	    if (parms_[idx] == 0) {
3087 		  cerr << get_fileline() << ": error: Missing expression "
3088 		       << (idx+1) << " of concatenation list." << endl;
3089 		  des->errors += 1;
3090 		  continue;
3091 	    }
3092 
3093 	    assert(parms_[idx]);
3094             unsigned wid = parms_[idx]->expr_width();
3095 	    NetExpr*ex = parms_[idx]->elaborate_expr(des, scope, wid, flags);
3096 	    if (ex == 0) continue;
3097 
3098 	    ex->set_line(*parms_[idx]);
3099 
3100             eval_expr(ex, -1);
3101 
3102 	    if (ex->expr_type() == IVL_VT_REAL) {
3103 		  cerr << ex->get_fileline() << ": error: "
3104 		       << "Concatenation operand can not be real: "
3105 		       << *parms_[idx] << endl;
3106 		  des->errors += 1;
3107                   parm_errors += 1;
3108 		  continue;
3109 	    }
3110 
3111 	    if (width_modes_[idx] != SIZED) {
3112 		  cerr << ex->get_fileline() << ": error: "
3113 		       << "Concatenation operand \"" << *parms_[idx]
3114 		       << "\" has indefinite width." << endl;
3115 		  des->errors += 1;
3116                   parm_errors += 1;
3117 		  continue;
3118 	    }
3119 
3120 	      /* We are going to ignore zero width constants. */
3121 	    if ((ex->expr_width() == 0) && dynamic_cast<NetEConst*>(ex)) {
3122 		  parms[idx] = 0;
3123 	    } else {
3124 		  parms[idx] = ex;
3125 		  parm_cnt += 1;
3126 	    }
3127 	    wid_sum += ex->expr_width();
3128       }
3129       if (parm_errors) {
3130 	    concat_depth -= 1;
3131 	    return 0;
3132       }
3133 
3134 	/* Make the empty concat expression. */
3135       NetEConcat*concat = new NetEConcat(parm_cnt, repeat_count_, expr_type_);
3136       concat->set_line(*this);
3137 
3138 	/* Remove any zero width constants. */
3139       unsigned off = 0;
3140       for (unsigned idx = 0 ;  idx < parm_cnt ;  idx += 1) {
3141 	    while (parms[off+idx] == 0) off += 1;
3142 	    concat->set(idx, parms[off+idx]);
3143       }
3144 
3145       if (wid_sum == 0 && expr_type_ != IVL_VT_STRING) {
3146 	    cerr << get_fileline() << ": error: Concatenation/replication "
3147 	         << "may not have zero width in this context." << endl;
3148 	    des->errors += 1;
3149 	    concat_depth -= 1;
3150 	    delete concat;
3151 	    return 0;
3152       }
3153 
3154       NetExpr*tmp = pad_to_width(concat, expr_wid, signed_flag_, *this);
3155 
3156       concat_depth -= 1;
3157       return tmp;
3158 }
3159 
3160 /*
3161  * Floating point literals are not vectorable. It's not particularly
3162  * clear what to do about an actual width to return, but whatever the
3163  * width, it is unsigned.
3164  *
3165  * Absent any better idea, we call all real valued results a width of 1.
3166  */
test_width(Design *,NetScope *,width_mode_t &)3167 unsigned PEFNumber::test_width(Design*, NetScope*, width_mode_t&)
3168 {
3169       expr_type_   = IVL_VT_REAL;
3170       expr_width_  = 1;
3171       min_width_   = 1;
3172       signed_flag_ = true;
3173 
3174       return expr_width_;
3175 }
3176 
elaborate_expr(Design *,NetScope *,ivl_type_t,unsigned) const3177 NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned) const
3178 {
3179       NetECReal*tmp = new NetECReal(*value_);
3180       tmp->set_line(*this);
3181       return tmp;
3182 }
3183 
elaborate_expr(Design *,NetScope *,unsigned,unsigned) const3184 NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
3185 {
3186       NetECReal*tmp = new NetECReal(*value_);
3187       tmp->set_line(*this);
3188       return tmp;
3189 }
3190 
calculate_packed_indices_(Design * des,NetScope * scope,NetNet * net,list<long> & prefix_indices) const3191 bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
3192 					list<long>&prefix_indices) const
3193 {
3194       unsigned dimensions = net->unpacked_dimensions() + net->packed_dimensions();
3195       switch (net->data_type()) {
3196 	  case IVL_VT_STRING:
3197 	  case IVL_VT_DARRAY:
3198 	  case IVL_VT_QUEUE:
3199 	    dimensions += 1;
3200 	  default:
3201 	    break;
3202       }
3203       if (path_.back().index.size() > dimensions) {
3204 	    cerr << get_fileline() << ": error: the number of indices ("
3205 		 << path_.back().index.size()
3206 		 << ") is greater than the number of dimensions ("
3207 		 << dimensions
3208 		 << ")." << endl;
3209 	    des->errors += 1;
3210 	    return false;
3211       }
3212 
3213       list<index_component_t> index;
3214       index = path_.back().index;
3215       ivl_assert(*this, index.size() >= net->unpacked_dimensions());
3216       for (size_t idx = 0 ; idx < net->unpacked_dimensions() ; idx += 1)
3217 	    index.pop_front();
3218 
3219       return evaluate_index_prefix(des, scope, prefix_indices, index);
3220 }
3221 
3222 
calculate_bits_(Design * des,NetScope * scope,long & msb,bool & defined) const3223 bool PEIdent::calculate_bits_(Design*des, NetScope*scope,
3224 			      long&msb, bool&defined) const
3225 {
3226       defined = true;
3227       const name_component_t&name_tail = path_.back();
3228       ivl_assert(*this, !name_tail.index.empty());
3229 
3230       const index_component_t&index_tail = name_tail.index.back();
3231       ivl_assert(*this, index_tail.sel == index_component_t::SEL_BIT);
3232       ivl_assert(*this, index_tail.msb && !index_tail.lsb);
3233 
3234 	/* This handles bit selects. In this case, there in one
3235 	   bit select expressions which must be constant. */
3236 
3237       NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
3238       NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
3239       if (msb_c == 0) {
3240 	    cerr << index_tail.msb->get_fileline() << ": error: "
3241 		  "Bit select expressions must be constant."
3242 		 << endl;
3243 	    cerr << index_tail.msb->get_fileline() << ":      : "
3244                   "This msb expression violates the rule: "
3245                  << *index_tail.msb << endl;
3246 	    des->errors += 1;
3247               /* Attempt to recover from error. */
3248             msb = 0;
3249       } else {
3250 	    if (! msb_c->value().is_defined())
3251 		  defined = false;
3252             msb = msb_c->value().as_long();
3253       }
3254 
3255       delete msb_ex;
3256       return true;
3257 }
3258 
3259 /*
3260  * Given that the msb_ and lsb_ are part select expressions, this
3261  * function calculates their values. Note that this method does *not*
3262  * convert the values to canonical form.
3263  */
calculate_parts_(Design * des,NetScope * scope,long & msb,long & lsb,bool & defined) const3264 bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
3265 			       long&msb, long&lsb, bool&defined) const
3266 {
3267       defined = true;
3268       const name_component_t&name_tail = path_.back();
3269       ivl_assert(*this, !name_tail.index.empty());
3270 
3271       const index_component_t&index_tail = name_tail.index.back();
3272       ivl_assert(*this, index_tail.sel == index_component_t::SEL_PART);
3273       ivl_assert(*this, index_tail.msb && index_tail.lsb);
3274 
3275 	/* This handles part selects. In this case, there are
3276 	   two bit select expressions, and both must be
3277 	   constant. Evaluate them and pass the results back to
3278 	   the caller. */
3279       NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
3280       NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
3281       if (lsb_c == 0) {
3282 	    cerr << index_tail.lsb->get_fileline() << ": error: "
3283 		  "Part select expressions must be constant."
3284 		 << endl;
3285 	    cerr << index_tail.lsb->get_fileline() << ":      : "
3286 		  "This lsb expression violates the rule: "
3287 		 << *index_tail.lsb << endl;
3288 	    des->errors += 1;
3289               /* Attempt to recover from error. */
3290             lsb = 0;
3291       } else {
3292 	    if (! lsb_c->value().is_defined())
3293 		  defined = false;
3294             lsb = lsb_c->value().as_long();
3295       }
3296 
3297       NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
3298       NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
3299       if (msb_c == 0) {
3300 	    cerr << index_tail.msb->get_fileline() << ": error: "
3301 		  "Part select expressions must be constant."
3302 		 << endl;
3303 	    cerr << index_tail.msb->get_fileline() << ":      : "
3304                   "This msb expression violates the rule: "
3305                  << *index_tail.msb << endl;
3306 	    des->errors += 1;
3307               /* Attempt to recover from error. */
3308             msb = lsb;
3309       } else {
3310 	    if (! msb_c->value().is_defined())
3311 		  defined = false;
3312             msb = msb_c->value().as_long();
3313       }
3314 
3315       delete msb_ex;
3316       delete lsb_ex;
3317       return true;
3318 }
3319 
calculate_up_do_width_(Design * des,NetScope * scope,unsigned long & wid) const3320 bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
3321 				     unsigned long&wid) const
3322 {
3323       const name_component_t&name_tail = path_.back();
3324       ivl_assert(*this, !name_tail.index.empty());
3325 
3326       const index_component_t&index_tail = name_tail.index.back();
3327       ivl_assert(*this, index_tail.lsb && index_tail.msb);
3328 
3329       bool flag = true;
3330 
3331 	/* Calculate the width expression (in the lsb_ position)
3332 	   first. If the expression is not constant, error but guess 1
3333 	   so we can keep going and find more errors. */
3334       NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1, true);
3335       NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
3336 
3337       wid = wid_c ? wid_c->value().as_ulong() : 0;
3338       if (wid == 0) {
3339 	    cerr << index_tail.lsb->get_fileline() << ": error: "
3340 		  "Indexed part widths must be constant and greater than zero."
3341 		 << endl;
3342 	    cerr << index_tail.lsb->get_fileline() << ":      : "
3343 		  "This part width expression violates the rule: "
3344 		 << *index_tail.lsb << endl;
3345 	    des->errors += 1;
3346 	    flag = false;
3347 	    wid = 1;
3348       }
3349       delete wid_ex;
3350 
3351       return flag;
3352 }
3353 
3354 /*
3355  * When we know that this is an indexed part select (up or down) this
3356  * method calculates the up/down base, as far at it can be calculated.
3357  */
calculate_up_do_base_(Design * des,NetScope * scope,bool need_const) const3358 NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope,
3359                                         bool need_const) const
3360 {
3361       const name_component_t&name_tail = path_.back();
3362       ivl_assert(*this, !name_tail.index.empty());
3363 
3364       const index_component_t&index_tail = name_tail.index.back();
3365       ivl_assert(*this, index_tail.lsb != 0);
3366       ivl_assert(*this, index_tail.msb != 0);
3367 
3368       NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
3369       return tmp;
3370 }
3371 
calculate_param_range_(Design *,NetScope *,const NetExpr * par_msb,long & par_msv,const NetExpr * par_lsb,long & par_lsv,long length) const3372 bool PEIdent::calculate_param_range_(Design*, NetScope*,
3373 				     const NetExpr*par_msb, long&par_msv,
3374 				     const NetExpr*par_lsb, long&par_lsv,
3375 				     long length) const
3376 {
3377       if (par_msb == 0) {
3378 	      // If the parameter doesn't have an explicit range, then
3379 	      // just return range values of [length-1:0].
3380 	    ivl_assert(*this, par_lsb == 0);
3381 	    par_msv = length-1;
3382 	    par_lsv = 0;
3383 	    return true;
3384       }
3385 
3386       const NetEConst*tmp = dynamic_cast<const NetEConst*> (par_msb);
3387       ivl_assert(*this, tmp);
3388 
3389       par_msv = tmp->value().as_long();
3390 
3391       tmp = dynamic_cast<const NetEConst*> (par_lsb);
3392       ivl_assert(*this, tmp);
3393 
3394       par_lsv = tmp->value().as_long();
3395 
3396       return true;
3397 }
3398 
test_width_method_(Design * des,NetScope * scope,width_mode_t &)3399 unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
3400 {
3401       if (!gn_system_verilog())
3402 	    return 0;
3403       if (path_.size() < 2)
3404 	    return 0;
3405 
3406       pform_name_t use_path = path_;
3407       perm_string member_name = peek_tail_name(path_);
3408       use_path.pop_back();
3409 
3410       if (debug_elaborate) {
3411 	    cerr << get_fileline() << ": PEIdent::test_width_method_: "
3412 		 << "Try to find method=" << member_name
3413 		 << " of signal " << use_path << endl;
3414       }
3415 
3416       NetNet*net = 0;
3417       const NetExpr*par = 0;
3418       NetEvent*eve = 0;
3419       const NetExpr*ex1 = 0, *ex2 = 0;
3420       symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
3421       if (net == 0) {
3422 	    if (debug_elaborate)
3423 		  cerr << get_fileline() << ": PEIdent::test_width_method_: "
3424 		       << "Only nets can have methods, so give up here." << endl;
3425 	    return 0;
3426       }
3427 
3428       if (/*const netdarray_t*dtype =*/ net->darray_type()) {
3429 	    if (member_name == "size") {
3430 		  expr_type_  = IVL_VT_BOOL;
3431 		  expr_width_ = 32;
3432 		  min_width_  = 32;
3433 		  signed_flag_= true;
3434 		  return 32;
3435 	    }
3436       }
3437 
3438 	// Look for the enumeration attributes.
3439       if (const netenum_t*netenum = net->enumeration()) {
3440 	    if (member_name == "num") {
3441 		  expr_type_  = IVL_VT_BOOL;
3442 		  expr_width_ = 32;
3443 		  min_width_  = 32;
3444 		  signed_flag_= true;
3445 		  return 32;
3446 	    }
3447 	    if ((member_name == "first") || (member_name == "last") ||
3448 	        (member_name == "next") || (member_name == "prev")) {
3449 		  expr_type_  = netenum->base_type();
3450 		  expr_width_ = netenum->packed_width();;
3451 		  min_width_ = expr_width_;
3452 		  signed_flag_ = netenum->get_signed();
3453 		  return expr_width_;
3454 	    }
3455       }
3456 
3457       return 0;
3458 }
3459 
test_width(Design * des,NetScope * scope,width_mode_t & mode)3460 unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
3461 {
3462       NetNet*       net = 0;
3463       const NetExpr*par = 0;
3464       NetEvent*     eve = 0;
3465 
3466       const NetExpr*ex1, *ex2;
3467 
3468       NetScope*use_scope = scope;
3469       if (package_) {
3470 	    use_scope = des->find_package(package_->pscope_name());
3471 	    ivl_assert(*this, use_scope);
3472       }
3473 
3474       if (unsigned tmp = test_width_method_(des, scope, mode)) {
3475 	    return tmp;
3476       }
3477 
3478       NetScope*found_in = symbol_search(this, des, use_scope, path_,
3479 					net, par, eve,
3480                                         ex1, ex2);
3481 
3482 	// If there is a part/bit select expression, then process it
3483 	// here. This constrains the results no matter what kind the
3484 	// name is.
3485 
3486       const name_component_t&name_tail = path_.back();
3487       index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
3488       if (!name_tail.index.empty()) {
3489 	    const index_component_t&index_tail = name_tail.index.back();
3490 	      // Skip full array word net selects.
3491 	    if (!net || (name_tail.index.size() > net->unpacked_dimensions())) {
3492 		  use_sel = index_tail.sel;
3493 	    }
3494       }
3495 
3496       unsigned use_width = UINT_MAX;
3497       switch (use_sel) {
3498 	  case index_component_t::SEL_NONE:
3499 	    break;
3500 	  case index_component_t::SEL_PART:
3501 	      { long msb, lsb;
3502 		bool parts_defined;
3503 		calculate_parts_(des, scope, msb, lsb, parts_defined);
3504 		if (parts_defined)
3505 		      use_width = 1 + ((msb>lsb) ? (msb-lsb) : (lsb-msb));
3506 		else
3507 		      use_width = UINT_MAX;
3508 		break;
3509 	      }
3510 	  case index_component_t::SEL_IDX_UP:
3511 	  case index_component_t::SEL_IDX_DO:
3512 	      { unsigned long tmp = 0;
3513 		calculate_up_do_width_(des, scope, tmp);
3514 		use_width = tmp;
3515 		break;
3516 	      }
3517 	  case index_component_t::SEL_BIT:
3518 	      { ivl_assert(*this, !name_tail.index.empty());
3519 		const index_component_t&index_tail = name_tail.index.back();
3520 		ivl_assert(*this, index_tail.msb);
3521 	      }
3522 		// If we have a net in hand, then we can predict what the
3523 		// slice width will be. If not, then assume it will be a
3524 		// simple bit select. If the net only has a single dimension
3525 		// then this is still a simple bit select.
3526 	      if ((net == 0) || (net->packed_dimensions() <= 1))
3527 		    use_width = 1;
3528 	      break;
3529 	  case index_component_t::SEL_BIT_LAST:
3530 	    if (debug_elaborate) {
3531 		  cerr << get_fileline() << ": PEIdent::test_width: "
3532 		       << "Queue/Darray last index ($)" << endl;
3533 	    }
3534 	    break;
3535 	  default:
3536 	    ivl_assert(*this, 0);
3537       }
3538 
3539       if (const netdarray_t*darray = net ? net->darray_type() : 0) {
3540 	    switch (use_sel) {
3541 		case index_component_t::SEL_BIT:
3542 		case index_component_t::SEL_BIT_LAST:
3543 		  expr_type_   = darray->element_base_type();
3544 		  expr_width_  = darray->element_width();
3545 		  min_width_   = expr_width_;
3546 		  signed_flag_ = net->get_signed();
3547 		  break;
3548 		default:
3549 		  expr_type_   = net->data_type();
3550 		  expr_width_  = net->vector_width();
3551 		  min_width_   = expr_width_;
3552 		  signed_flag_ = net->get_signed();
3553 		  break;
3554 	    }
3555 	    return expr_width_;
3556       }
3557 
3558       if (use_width != UINT_MAX) {
3559 	    expr_type_   = IVL_VT_LOGIC; // Assume bit/parts selects are logic
3560 	    expr_width_  = use_width;
3561 	    min_width_   = use_width;
3562             signed_flag_ = false;
3563 
3564 	    return expr_width_;
3565       }
3566 
3567 	// The width of a signal expression is the width of the signal.
3568       if (net != 0) {
3569 	    size_t use_depth = name_tail.index.size();
3570 	      // Account for unpacked dimensions by assuming that the
3571 	      // unpacked dimensions are consumed first, so subtract
3572 	      // the unpacked dimensions from the dimension depth
3573 	      // useable for making the slice.
3574 	    if (use_depth >= net->unpacked_dimensions()) {
3575 		  use_depth -= net->unpacked_dimensions();
3576 
3577 	    } else {
3578 		    // In this case, we have a slice of an unpacked
3579 		    // array. This likely handled as an array instead
3580 		    // of a slice. Hmm...
3581 		  use_depth = 0;
3582 	    }
3583 
3584 	    expr_type_   = net->data_type();
3585 	    expr_width_  = net->slice_width(use_depth);
3586 	    min_width_   = expr_width_;
3587 	    signed_flag_ = net->get_signed();
3588 	    if (debug_elaborate) {
3589 		  cerr << get_fileline() << ": PEIdent::test_width: "
3590 		       << net->name() << " is a net, "
3591 		       << "type=" << expr_type_
3592 		       << ", width=" << expr_width_
3593 		       << ", signed_=" << (signed_flag_ ? "true" : "false")
3594 		       << ", use_depth=" << use_depth
3595 		       << ", packed_dimensions=" << net->packed_dimensions()
3596 		       << ", unpacked_dimensions=" << net->unpacked_dimensions()
3597 		       << endl;
3598 	    }
3599 	    return expr_width_;
3600       }
3601 
3602 	// The width of an enumeration literal is the width of the
3603 	// enumeration base.
3604       if (const NetEConstEnum*par_enum = dynamic_cast<const NetEConstEnum*> (par)) {
3605 	    const netenum_t*use_enum = par_enum->enumeration();
3606 	    ivl_assert(*this, use_enum != 0);
3607 
3608 	    expr_type_   = use_enum->base_type();
3609 	    expr_width_  = use_enum->packed_width();
3610 	    min_width_   = expr_width_;
3611 	    signed_flag_ = par_enum->has_sign();
3612 
3613 	    return expr_width_;
3614       }
3615 
3616 	// The width of a parameter is the width of the parameter value
3617         // (as evaluated earlier).
3618       if (par != 0) {
3619 	    expr_type_   = par->expr_type();
3620 	    expr_width_  = par->expr_width();
3621             min_width_   = expr_width_;
3622             signed_flag_ = par->has_sign();
3623 
3624             if (!par->has_width() && (mode < LOSSLESS))
3625                   mode = LOSSLESS;
3626 
3627 	    return expr_width_;
3628       }
3629 
3630       if (path_.size() == 1
3631 	  && scope->genvar_tmp.str()
3632 	  && strcmp(peek_tail_name(path_), scope->genvar_tmp) == 0) {
3633 	    verinum val (scope->genvar_tmp_val);
3634             expr_type_   = IVL_VT_BOOL;
3635             expr_width_  = val.len();
3636             min_width_   = expr_width_;
3637             signed_flag_ = true;
3638 
3639             if (gn_strict_expr_width_flag) {
3640                   expr_width_ = integer_width;
3641                   mode = UNSIZED;
3642             } else if (mode < LOSSLESS) {
3643                   mode = LOSSLESS;
3644             }
3645 
3646             return expr_width_;
3647       }
3648 
3649 	// If this is SystemVerilog then maybe this is a structure element.
3650       if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
3651 	    pform_name_t use_path = path_;
3652 	    perm_string method_name = peek_tail_name(use_path);
3653 	    use_path.pop_back();
3654 
3655 	    ivl_assert(*this, net == 0);
3656 	    symbol_search(this, des, scope, use_path, net, par, eve, ex1, ex2);
3657 
3658 	      // Check to see if we have a net and if so is it a structure?
3659 	    if (net != 0) {
3660 		    // If this net is a struct, the method name may be
3661 		    // a struct member. If it is, then we know the
3662 		    // width of this identifier my knowing the width
3663 		    // of the member. We don't even need to know
3664 		    // anything about positions in containing arrays.
3665 		  if (net->struct_type() != 0) {
3666 
3667 			if (debug_elaborate) {
3668 			      cerr << get_fileline() << ": debug: PEIdent::test_width: "
3669 				   << "Net " << use_path << " is a struct, "
3670 				   << "checking width of member " << method_name << endl;
3671 			}
3672 
3673 			const netstruct_t::member_t*mem;
3674 			unsigned long unused;
3675 			mem = get_struct_member(this, des, scope, net,
3676 			                        method_name, unused);
3677 			if (mem) {
3678 			      expr_type_   = mem->data_type();
3679 			      expr_width_  = mem->net_type->packed_width();
3680 			      min_width_   = expr_width_;
3681 			      signed_flag_ = mem->get_signed();
3682 			      return expr_width_;
3683 			}
3684 		  }
3685 
3686 		  if (const netclass_t*class_type = net->class_type()) {
3687 			int pidx = class_type->property_idx_from_name(method_name);
3688 			if (pidx >= 0) {
3689 			      ivl_type_t ptype = class_type->get_prop_type(pidx);
3690 			      expr_type_   = ptype->base_type();
3691 			      expr_width_  = ptype->packed_width();
3692 			      min_width_   = expr_width_;
3693 			      signed_flag_ = ptype->get_signed();
3694 			      return expr_width_;
3695 			}
3696 		  }
3697 	    }
3698       }
3699 
3700 	// Not a net, and not a parameter? Give up on the type, but
3701 	// set the width to 0.
3702       expr_type_   = IVL_VT_NO_TYPE;
3703       expr_width_  = 0;
3704       min_width_   = 0;
3705       signed_flag_ = false;
3706 
3707       return expr_width_;
3708 }
3709 
3710 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const3711 NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
3712 				 ivl_type_t ntype, unsigned flags) const
3713 {
3714       bool need_const = NEED_CONST & flags;
3715 
3716       NetNet*       net = 0;
3717       const NetExpr*par = 0;
3718       NetEvent*     eve = 0;
3719       const NetExpr*ex1, *ex2;
3720 
3721       NetScope*use_scope = scope;
3722       if (package_) {
3723 	    use_scope = des->find_package(package_->pscope_name());
3724 	    ivl_assert(*this, use_scope);
3725       }
3726 
3727       if (NetExpr* tmp = elaborate_expr_class_member_(des, scope, 0, flags)) {
3728 	    return tmp;
3729       }
3730 
3731       /* NetScope*found_in = */ symbol_search(this, des, use_scope, path_,
3732 					      net, par, eve,
3733 					      ex1, ex2);
3734 
3735       if (net == 0 && gn_system_verilog() && path_.size() >= 2) {
3736 	      // NOTE: this is assuming the member_path is only one
3737 	      // component long, and that the use_path will wind up
3738 	      // being the path to the variable. This is not
3739 	      // necessarily true. Should fix this.
3740 	    pform_name_t use_path = path_;
3741 	    name_component_t member_comp = use_path.back();
3742 	    use_path.pop_back();
3743 
3744 	    ivl_assert(*this, net == 0);
3745 	    symbol_search(this, des, use_scope, use_path, net, par, eve, ex1, ex2);
3746 
3747 	    if (net == 0) {
3748 		    // Nope, no struct/class with member.
3749 
3750 	    } else if (net->struct_type() != 0) {
3751 		  pform_name_t member_path;
3752 		  member_path.push_back( member_comp );
3753 		  return check_for_struct_members(this, des, use_scope,
3754 						  net, use_path.back().index,
3755 						  member_path);
3756 
3757 	    } else if (net->class_type()!=0) {
3758 		  if (debug_elaborate) {
3759 			cerr << get_fileline() << ": PEIdent::elaborate_expr: "
3760 			     << "Ident " << use_path
3761 			     << " look for property " << member_comp << endl;
3762 		  }
3763 
3764 		  return check_for_class_property(this, des, scope,
3765 						  net, member_comp);
3766 	    }
3767       }
3768 
3769       if (net == 0) {
3770             cerr << get_fileline() << ": error: Unable to bind variable `"
3771 	         << path_ << "' in `" << scope_path(use_scope) << "'" << endl;
3772 	    des->errors += 1;
3773 	    return 0;
3774       }
3775 
3776       if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype)) {
3777             if (array_type->type_compatible(net->net_type())) {
3778                   NetESignal*tmp = new NetESignal(net);
3779                   tmp->set_line(*this);
3780                   return tmp;
3781             }
3782 
3783               // Icarus allows a dynamic array to be initialised with a
3784               // single elementary value, so try that next.
3785 	    ntype = array_type->element_type();
3786       }
3787 
3788       if (! ntype->type_compatible(net->net_type())) {
3789 	    cerr << get_fileline() << ": error: the type of the variable '"
3790 		 << path_ << "' doesn't match the context type." << endl;
3791 
3792 	    cerr << get_fileline() << ":      : " << "variable type=";
3793 	    if (net->net_type())
3794 		  net->net_type()->debug_dump(cerr);
3795 	    else
3796 		  cerr << "<nil>";
3797 	    cerr << endl;
3798 
3799 	    cerr << get_fileline() << ":      : " << "context type=";
3800 	    ivl_assert(*this, ntype);
3801 	    ntype->debug_dump(cerr);
3802 	    cerr << endl;
3803 	    des->errors += 1;
3804 	    return 0;
3805       }
3806       ivl_assert(*this, ntype->type_compatible(net->net_type()));
3807 
3808       const name_component_t&use_comp = path_.back();
3809 
3810       if (debug_elaborate) {
3811 	    cerr << get_fileline() << ": PEIdent::elaborate_expr: "
3812 		 << "Typed ident " << net->name()
3813 		 << " with " << use_comp.index.size() << " indices"
3814 		 << " and " << net->unpacked_dimensions() << " expected."
3815 		 << endl;
3816       }
3817 
3818 // FIXME: The real array to queue is failing here.
3819       if (net->unpacked_dimensions() != use_comp.index.size()) {
3820 	    cerr << get_fileline() << ": sorry: "
3821 		 << "Net " << net->name()
3822 		 << " expects " << net->unpacked_dimensions()
3823 		 << ", but got " << use_comp.index.size() << "."
3824 		 << endl;
3825 	    des->errors += 1;
3826 
3827 	    NetESignal*tmp = new NetESignal(net);
3828 	    tmp->set_line(*this);
3829 	    return tmp;
3830       }
3831 
3832       if (net->unpacked_dimensions() == 0) {
3833 	    NetESignal*tmp = new NetESignal(net);
3834 	    tmp->set_line(*this);
3835 	    return tmp;
3836       }
3837 
3838 	// Convert a set of index expressions to a single expression
3839 	// that addresses the canonical element.
3840       list<NetExpr*>unpacked_indices;
3841       list<long> unpacked_indices_const;
3842       indices_flags idx_flags;
3843       indices_to_expressions(des, scope, this,
3844 			     use_comp.index, net->unpacked_dimensions(),
3845 			     need_const,
3846 			     idx_flags,
3847 			     unpacked_indices,
3848 			     unpacked_indices_const);
3849 
3850       NetExpr*canon_index = 0;
3851 
3852       if (idx_flags.invalid) {
3853 	      // Nothing to do
3854 
3855       } else if (idx_flags.undefined) {
3856 	    cerr << get_fileline() << ": warning: "
3857 		 << "returning 'bx for undefined array access "
3858 		 << net->name() << as_indices(unpacked_indices)
3859 		 << "." << endl;
3860 
3861       } else if (idx_flags.variable) {
3862 	    ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
3863 	    canon_index = normalize_variable_unpacked(net, unpacked_indices);
3864 
3865       } else {
3866 	    ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
3867 	    canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
3868       }
3869 
3870       ivl_assert(*this, canon_index);
3871       NetESignal*tmp = new NetESignal(net, canon_index);
3872       tmp->set_line(*this);
3873 
3874       return tmp;
3875 }
3876 
3877 /*
3878  * Guess that the path_ is the name of a member of a containing class,
3879  * and see how that works. If it turns out that the current scope is
3880  * not a method, or the name is not in the parent class, then
3881  * fail. Otherwise, return a NetEProperty.
3882  */
elaborate_expr_class_member_(Design * des,NetScope * scope,unsigned,unsigned) const3883 NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
3884 					       unsigned, unsigned) const
3885 {
3886       if (!gn_system_verilog())
3887 	    return 0;
3888       if (scope->parent() == 0)
3889 	    return 0;
3890       if (path_.size() != 1)
3891 	    return 0;
3892 
3893       const netclass_t*class_type = find_class_containing_scope(*this, scope);
3894       if (class_type == 0)
3895 	    return 0;
3896 
3897       const name_component_t&name_comp = path_.back();
3898 
3899       perm_string member_name = name_comp.name;
3900       int pidx = class_type->property_idx_from_name(member_name);
3901       if (pidx < 0)
3902 	    return 0;
3903 
3904       NetScope*scope_method = find_method_containing_scope(*this, scope);
3905       ivl_assert(*this, scope_method);
3906 
3907       NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
3908       if (this_net == 0) {
3909 	    cerr << get_fileline() << ": internal error: "
3910 		 << "Unable to find 'this' port of " << scope_path(scope_method)
3911 		 << "." << endl;
3912 	    return 0;
3913       }
3914 
3915       if (debug_elaborate) {
3916 	    cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member: "
3917 		 << "Found member " << member_name
3918 		 << " is a member of class " << class_type->get_name()
3919 		 << ", context scope=" << scope_path(scope)
3920 		 << ", type=" << *class_type->get_prop_type(pidx)
3921 		 << ", so making a NetEProperty." << endl;
3922       }
3923 
3924       property_qualifier_t qual = class_type->get_prop_qual(pidx);
3925       if (qual.test_local() && ! class_type->test_scope_is_method(scope)) {
3926 	    cerr << get_fileline() << ": error: "
3927 		 << "Local property " << class_type->get_prop_name(pidx)
3928 		 << " is not accessible in this context."
3929 		 << " (scope=" << scope_path(scope) << ")" << endl;
3930 	    des->errors += 1;
3931       }
3932 
3933       if (qual.test_static()) {
3934 	    return class_static_property_expression(this, class_type, member_name);
3935       }
3936 
3937       NetExpr*canon_index = 0;
3938       ivl_type_t tmp_type = class_type->get_prop_type(pidx);
3939       if (const netuarray_t*tmp_ua = dynamic_cast<const netuarray_t*>(tmp_type)) {
3940 
3941 	    const std::vector<netrange_t>&dims = tmp_ua->static_dimensions();
3942 
3943 	    if (debug_elaborate) {
3944 		  cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
3945 		       << "Property " << class_type->get_prop_name(pidx)
3946 		       << " has " << dims.size() << " dimensions, "
3947 		       << " got " << name_comp.index.size() << " indices." << endl;
3948 	    }
3949 
3950 	    if (dims.size() != name_comp.index.size()) {
3951 		  cerr << get_fileline() << ": error: "
3952 		       << "Got " << name_comp.index.size() << " indices, "
3953 		       << "expecting " << dims.size()
3954 		       << " to index the property " << class_type->get_prop_name(pidx) << "." << endl;
3955 		  des->errors += 1;
3956 
3957 	    } else {
3958 
3959 		  canon_index = make_canonical_index(des, scope, this,
3960 						     name_comp.index, tmp_ua, false);
3961 	    }
3962       }
3963 
3964       if (debug_elaborate && canon_index) {
3965 	    cerr << get_fileline() << ": PEIdent::elaborate_expr_class_member_: "
3966 		 << "Property " << class_type->get_prop_name(pidx)
3967 		 << " canonical index: " << *canon_index << endl;
3968       }
3969 
3970       NetEProperty*tmp = new NetEProperty(this_net, member_name, canon_index);
3971       tmp->set_line(*this);
3972       return tmp;
3973 }
3974 
3975 
3976 /*
3977  * Elaborate an identifier in an expression. The identifier can be a
3978  * parameter name, a signal name or a memory name. It can also be a
3979  * scope name (Return a NetEScope) but only certain callers can use
3980  * scope names. However, we still support it here.
3981  *
3982  * Function names are not handled here, they are detected by the
3983  * parser and are elaborated by PECallFunction.
3984  *
3985  * The signal name may be escaped, but that affects nothing here.
3986  */
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const3987 NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
3988 				 unsigned expr_wid, unsigned flags) const
3989 {
3990       assert(scope);
3991 
3992       NetNet*       net = 0;
3993       const NetExpr*par = 0;
3994       NetEvent*     eve = 0;
3995 
3996       const NetExpr*ex1, *ex2;
3997 
3998       if (debug_elaborate) {
3999 	    cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4000 		 << "path_=" << path_
4001 		 << endl;
4002       }
4003 
4004 	// Special case: Detect the special situation that this name
4005 	// is the name of a variable in the class, and this is a class
4006 	// method. We sense that this might be the case by noting that
4007 	// the parent scope of where we are working is a
4008 	// NetScope::CLASS, the path_ is a single component, and the
4009 	// name is a property of the class. If that turns out to be
4010 	// the case, then handle this specially.
4011       if (NetExpr*tmp = elaborate_expr_class_member_(des, scope, expr_wid, flags)) {
4012 	    return tmp;
4013       }
4014 
4015       if (path_.size() > 1) {
4016             if (NEED_CONST & flags) {
4017                   cerr << get_fileline() << ": error: A hierarchical reference"
4018                           " (`" << path_ << "') is not allowed in a constant"
4019                           " expression." << endl;
4020                   des->errors += 1;
4021                   return 0;
4022             }
4023             if (scope->need_const_func()) {
4024                   cerr << get_fileline() << ": error: A hierarchical reference"
4025                           " (`" << path_ << "') is not allowed in a constant"
4026                           " function." << endl;
4027                   des->errors += 1;
4028                   return 0;
4029             }
4030             scope->is_const_func(false);
4031       }
4032 
4033 	// If this identifier is pulled from a package, then switch
4034 	// the scope we are using.
4035       NetScope*use_scope = scope;
4036       if (package_) {
4037 	    use_scope = des->find_package(package_->pscope_name());
4038 	    ivl_assert(*this, use_scope);
4039       }
4040 
4041 
4042 	// Find the net/parameter/event object that this name refers
4043 	// to. The path_ may be a scoped path, and may include method
4044 	// or member name parts. For example, main.a.b.c may refer to
4045 	// a net called "b" in the scope "main.a" and with a member
4046 	// named "c". This loop tries to figure that out and the
4047 	// result is the complete path_ split into a base_path (that
4048 	// locates the object) and the member_path that selects parts
4049 	// in the object.
4050       pform_name_t base_path = path_;
4051       pform_name_t member_path;
4052       NetScope*found_in = 0;
4053       while (net==0 && par==0 && eve==0 && base_path.size()>0) {
4054 	    found_in = symbol_search(this, des, use_scope, base_path,
4055 				     net, par, eve, ex1, ex2);
4056 	    if (net) break;
4057 	    if (par) break;
4058 	    if (eve) break;
4059 	      // Not found. Try to pop another name off the base_path
4060 	      // and push it to the front of the member path.
4061 	    member_path.push_front( base_path.back() );
4062 	    base_path.pop_back();
4063       }
4064 
4065       if (debug_elaborate) {
4066 	    cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4067 		 << "Symbol search found base_path=" << base_path
4068 		 << ", member_path=" << member_path
4069 		 << ", par=" << par
4070 		 << ", net=" << net
4071 		 << ", eve=" << eve
4072 		 << endl;
4073       }
4074 
4075 	// If the identifier name is a parameter name, then return
4076 	// the parameter value.
4077       if (par != 0) {
4078 
4079 	    if (member_path.size() > 0) {
4080 		  cerr << get_fileline() << ": error: Paramater name " << base_path
4081 		       << " can't have member names (member_path=" << member_path << ")."
4082 		       << endl;
4083 		  des->errors += 1;
4084 	    }
4085 
4086 	    NetExpr*tmp = elaborate_expr_param_(des, scope, par, found_in,
4087                                                 ex1, ex2, expr_wid, flags);
4088 
4089             if (!tmp) return 0;
4090 
4091             return pad_to_width(tmp, expr_wid, signed_flag_, *this);
4092       }
4093 
4094 	// If the identifier names a signal (a variable or a net)
4095 	// then create a NetESignal node to handle it.
4096       if (net != 0) {
4097             if (NEED_CONST & flags) {
4098                   cerr << get_fileline() << ": error: A reference to a wire "
4099                           "or reg (`" << path_ << "') is not allowed in "
4100                           "a constant expression." << endl;
4101 	          des->errors += 1;
4102                   return 0;
4103             }
4104             if (net->scope()->type() == NetScope::MODULE) {
4105                   if (scope->need_const_func()) {
4106                         cerr << get_fileline() << ": error: A reference to a "
4107                                 "non-local wire or reg (`" << path_ << "') is "
4108                                 "not allowed in a constant function." << endl;
4109                         des->errors += 1;
4110                         return 0;
4111                   }
4112                   scope->is_const_func(false);
4113             }
4114 
4115 	      // If this is a struct, and there are members in the
4116 	      // member_path, then generate an expression that
4117 	      // reflects the member selection.
4118 	    if (net->struct_type() && member_path.size() > 0) {
4119 		  if (debug_elaborate) {
4120 			cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4121 			     << "Ident " << base_path
4122 			     << " look for struct member " << member_path
4123 			     << endl;
4124 		  }
4125 
4126 		  NetExpr*tmp = check_for_struct_members(this, des, use_scope,
4127 							 net, base_path.back().index,
4128 							 member_path);
4129 		  if (!tmp) return 0;
4130 		  else return pad_to_width(tmp, expr_wid, signed_flag_, *this);
4131 	    }
4132 
4133 	      // If this is an array object, and there are members in
4134 	      // the member_path, check for array properties.
4135 	    if (net->darray_type() && member_path.size() > 0) {
4136                   if (debug_elaborate) {
4137                         cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4138                              << "Ident " << base_path
4139                              << " looking for array property " << member_path
4140                              << endl;
4141                   }
4142 
4143 		  ivl_assert(*this, member_path.size() == 1);
4144 		  const name_component_t member_comp = member_path.front();
4145 		  if (member_comp.name == "size") {
4146 			NetESFunc*fun = new NetESFunc("$size", IVL_VT_BOOL, 32, 1);
4147 			fun->set_line(*this);
4148 
4149 			NetESignal*arg = new NetESignal(net);
4150 			arg->set_line(*net);
4151 
4152 			fun->parm(0, arg);
4153 			return fun;
4154 		  }
4155 	    }
4156 
4157 	      // If this is a queue object, and there are members in
4158 	      // the member_path, check for array properties.
4159 	    if (net->queue_type() && member_path.size() > 0) {
4160                   if (debug_elaborate) {
4161                         cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4162                              << "Ident " << base_path
4163                              << " looking for queue property " << member_path
4164                              << endl;
4165                   }
4166 
4167 		  ivl_assert(*this, member_path.size() == 1);
4168 		  const name_component_t member_comp = member_path.front();
4169 		  const netqueue_t*queue = net->queue_type();
4170 		  ivl_variable_type_t qelem_type = queue->element_base_type();
4171 		  unsigned qelem_width = queue->element_width();
4172 		  if (member_comp.name == "pop_back") {
4173 			NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_back",
4174 			                              qelem_type, qelem_width, 1);
4175 			fun->set_line(*this);
4176 
4177 			NetESignal*arg = new NetESignal(net);
4178 			arg->set_line(*net);
4179 
4180 			fun->parm(0, arg);
4181 			return fun;
4182 		  }
4183 
4184 		  if (member_comp.name == "pop_front") {
4185 			NetESFunc*fun = new NetESFunc("$ivl_queue_method$pop_front",
4186 			                              qelem_type, qelem_width, 1);
4187 			fun->set_line(*this);
4188 
4189 			NetESignal*arg = new NetESignal(net);
4190 			arg->set_line(*net);
4191 
4192 			fun->parm(0, arg);
4193 			return fun;
4194 		  }
4195 	    }
4196 
4197 	    if (net->class_type() && member_path.size() > 0) {
4198 		  if (debug_elaborate) {
4199 			cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4200 			     << "Ident " << base_path
4201 			     << " look for class property " << member_path
4202 			     << endl;
4203 		  }
4204 
4205 		  ivl_assert(*this, member_path.size() == 1);
4206 		  const name_component_t member_comp = member_path.front();
4207 		  return check_for_class_property(this, des, use_scope,
4208 							net, member_comp);
4209 	    }
4210 
4211 	    if (net->enumeration() && member_path.size() > 0) {
4212 		  const netenum_t*netenum = net->enumeration();
4213 		  if (debug_elaborate) {
4214 			cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4215 			     << "Ident " << base_path
4216 			     << " look for enumeration method " << member_path
4217 			     << endl;
4218 		  }
4219 
4220 		  NetESignal*expr = new NetESignal(net);
4221 		  expr->set_line(*this);
4222 		  ivl_assert(*this, member_path.size() == 1);
4223 		  const name_component_t member_comp = member_path.front();
4224 		  ivl_assert(*this, member_comp.index.empty());
4225 		  return check_for_enum_methods(this, des, use_scope,
4226 						netenum, base_path, member_comp.name,
4227 						expr, expr_wid, NULL, 0);
4228 	    }
4229 
4230 	    ivl_assert(*this, member_path.size() == 0);
4231 	    NetExpr*tmp = elaborate_expr_net(des, scope, net, found_in,
4232                                              expr_wid, flags);
4233 
4234             if (!tmp) return 0;
4235 
4236 	    if (debug_elaborate) {
4237 		  cerr << get_fileline() << ": PEIdent::elaborate_expr: "
4238 		       << "Expression as net. expr_wid=" << expr_wid
4239 		       << ", tmp->expr_width()=" << tmp->expr_width()
4240 		       << ", tmp=" << *tmp << endl;
4241 	    }
4242 
4243             return pad_to_width(tmp, expr_wid, signed_flag_, *this);
4244       }
4245 
4246 	// If the identifier is a named event
4247         // then create a NetEEvent node to handle it.
4248       if (eve != 0) {
4249             if (NEED_CONST & flags) {
4250                   cerr << get_fileline() << ": error: A reference to a named "
4251                           "event (`" << path_ << "') is not allowed in a "
4252                           "constant expression." << endl;
4253 	          des->errors += 1;
4254                   return 0;
4255             }
4256             if (eve->scope() != scope) {
4257                   if (scope->need_const_func()) {
4258                         cerr << get_fileline() << ": error: A reference to a "
4259                                 "non-local named event (`" << path_ << "') is "
4260                                 "not allowed in a constant function." << endl;
4261                         des->errors += 1;
4262                         return 0;
4263                   }
4264                   scope->is_const_func(false);
4265             }
4266 
4267 	    if (member_path.size() > 0) {
4268 		  cerr << get_fileline() << ": error: Event name " << base_path
4269 		       << " can't have member names (member_path=" << member_path << ")"
4270 		       << endl;
4271 		  des->errors += 1;
4272 	    }
4273 
4274 	    NetEEvent*tmp = new NetEEvent(eve);
4275 	    tmp->set_line(*this);
4276 	    return tmp;
4277       }
4278 
4279 	// Hmm... maybe this is a genvar? This is only possible while
4280 	// processing generate blocks, but then the genvar_tmp will be
4281 	// set in the scope.
4282       if (path_.size() == 1
4283 	  && scope->genvar_tmp.str()
4284 	  && strcmp(peek_tail_name(path_), scope->genvar_tmp) == 0) {
4285 	    if (debug_elaborate)
4286 		  cerr << get_fileline() << ": debug: " << path_
4287 		       << " is genvar with value " << scope->genvar_tmp_val
4288 		       << "." << endl;
4289 	    verinum val (scope->genvar_tmp_val, expr_wid);
4290 	    val.has_sign(true);
4291 	    NetEConst*tmp = new NetEConst(val);
4292 	    tmp->set_line(*this);
4293 	    return tmp;
4294       }
4295 
4296 
4297 	// At this point we've exhausted all the possibilities that
4298 	// are not scopes. If this is not a system task argument, then
4299 	// it cannot be a scope name, so give up.
4300 
4301       if ( !(SYS_TASK_ARG & flags) ) {
4302 	      // I cannot interpret this identifier. Error message.
4303             cerr << get_fileline() << ": error: Unable to bind "
4304                  << ((NEED_CONST & flags) ? "parameter" : "wire/reg/memory")
4305                  << " `" << path_ << "' in `" << scope_path(scope) << "'"
4306                  << endl;
4307             if (scope->need_const_func()) {
4308                   cerr << get_fileline() << ":      : `" << scope->basename()
4309                        << "' is being used as a constant function, so may "
4310                           "only reference local variables." << endl;
4311             }
4312 	    des->errors += 1;
4313 	    return 0;
4314       }
4315 
4316 	// Finally, if this is a scope name, then return that. Look
4317 	// first to see if this is a name of a local scope. Failing
4318 	// that, search globally for a hierarchical name.
4319       if ((path_.size() == 1)) {
4320 	    hname_t use_name ( peek_tail_name(path_) );
4321 	    if (NetScope*nsc = scope->child(use_name)) {
4322 		  NetEScope*tmp = new NetEScope(nsc);
4323 		  tmp->set_line(*this);
4324 
4325 		  if (debug_elaborate)
4326 			cerr << get_fileline() << ": debug: Found scope "
4327 			     << use_name << " in scope " << scope->basename()
4328 			     << endl;
4329 
4330 		  return tmp;
4331 	    }
4332       }
4333 
4334       list<hname_t> spath = eval_scope_path(des, scope, path_);
4335 
4336       ivl_assert(*this, spath.size() == path_.size());
4337 
4338 	// Try full hierarchical scope name.
4339       if (NetScope*nsc = des->find_scope(spath)) {
4340 	    NetEScope*tmp = new NetEScope(nsc);
4341 	    tmp->set_line(*this);
4342 
4343 	    if (debug_elaborate)
4344 		  cerr << get_fileline() << ": debug: Found scope "
4345 		       << nsc->basename()
4346 		       << " path=" << path_ << endl;
4347 
4348 	    if ( !(SYS_TASK_ARG & flags) ) {
4349 		  cerr << get_fileline() << ": error: Scope name "
4350 		       << nsc->basename() << " not allowed here." << endl;
4351 		  des->errors += 1;
4352 	    }
4353 
4354 	    return tmp;
4355       }
4356 
4357 	// Try relative scope name.
4358       if (NetScope*nsc = des->find_scope(scope, spath)) {
4359 	    NetEScope*tmp = new NetEScope(nsc);
4360 	    tmp->set_line(*this);
4361 
4362 	    if (debug_elaborate)
4363 		  cerr << get_fileline() << ": debug: Found scope "
4364 		       << nsc->basename() << " in " << scope_path(scope) << endl;
4365 
4366 	    return tmp;
4367       }
4368 
4369 	// I cannot interpret this identifier. Error message.
4370       cerr << get_fileline() << ": error: Unable to bind wire/reg/memory "
4371 	    "`" << path_ << "' in `" << scope_path(scope) << "'" << endl;
4372       des->errors += 1;
4373       return 0;
4374 }
4375 
param_part_select_bits(const verinum & par_val,long wid,long lsv)4376 static verinum param_part_select_bits(const verinum&par_val, long wid,
4377 				     long lsv)
4378 {
4379       verinum result (verinum::Vx, wid, true);
4380 
4381       for (long idx = 0 ; idx < wid ; idx += 1) {
4382 	    long off = idx + lsv;
4383 	    if (off < 0)
4384 		  continue;
4385 	    else if (off < (long)par_val.len())
4386 		  result.set(idx, par_val.get(off));
4387 	    else if (par_val.is_string()) // Pad strings with nulls.
4388 		  result.set(idx, verinum::V0);
4389 	    else if (par_val.has_len()) // Pad sized parameters with X
4390 		  continue;
4391 	    else // Unsized parameters are "infinite" width.
4392 		  result.set(idx, sign_bit(par_val));
4393       }
4394 
4395 	// If the input is a string, and the part select is working on
4396 	// byte boundaries, then make the result into a string.
4397       if (par_val.is_string() && (labs(lsv)%8 == 0) && (wid%8 == 0))
4398 	    return verinum(result.as_string());
4399 
4400       return result;
4401 }
4402 
elaborate_expr_param_bit_(Design * des,NetScope * scope,const NetExpr * par,NetScope * found_in,const NetExpr * par_msb,const NetExpr * par_lsb,bool need_const) const4403 NetExpr* PEIdent::elaborate_expr_param_bit_(Design*des, NetScope*scope,
4404 					    const NetExpr*par,
4405 					    NetScope*found_in,
4406 					    const NetExpr*par_msb,
4407 					    const NetExpr*par_lsb,
4408                                             bool need_const) const
4409 {
4410       const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
4411       ivl_assert(*this, par_ex);
4412 
4413       long par_msv, par_lsv;
4414       if(! calculate_param_range_(des, scope, par_msb, par_msv,
4415                                   par_lsb, par_lsv,
4416                                   par_ex->value().len())) return 0;
4417 
4418       const name_component_t&name_tail = path_.back();
4419       ivl_assert(*this, !name_tail.index.empty());
4420       const index_component_t&index_tail = name_tail.index.back();
4421       ivl_assert(*this, index_tail.msb);
4422       ivl_assert(*this, !index_tail.lsb);
4423 
4424       NetExpr*sel = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
4425       if (sel == 0) return 0;
4426 
4427       if (debug_elaborate)
4428 	    cerr << get_fileline() << ": debug: Calculate bit select "
4429 		 << "[" << *sel << "] from range "
4430 		 << "[" << par_msv << ":" << par_lsv << "]." << endl;
4431 
4432       perm_string name = peek_tail_name(path_);
4433 
4434 	// Handle the special case that the selection is constant. In this
4435 	// case, just precalculate the entire constant result.
4436       if (NetEConst*sel_c = dynamic_cast<NetEConst*> (sel)) {
4437 	      // Special case: If the bit select is constant and not fully
4438 	      // defined, then we know that the result must be 1'bx.
4439 	    if (! sel_c->value().is_defined()) {
4440 		  if (warn_ob_select) {
4441 			cerr << get_fileline() << ": warning: "
4442 			        "Constant undefined bit select ["
4443 			     << sel_c->value() << "] for parameter '"
4444 			     << name << "'." << endl;
4445 			cerr << get_fileline() << ":        : "
4446 			        "Replacing select with a constant 1'bx."
4447 			     << endl;
4448 		  }
4449 		  NetEConst*res = make_const_x(1);
4450 		  res->set_line(*this);
4451 		  return res;
4452 	    }
4453 	      // Calculate the canonical index value.
4454 	    long sel_v = sel_c->value().as_long();
4455 	    if (par_msv >= par_lsv) sel_v -= par_lsv;
4456 	    else sel_v = par_lsv - sel_v;
4457 
4458 	      // Select a bit from the parameter.
4459 	    verinum par_v = par_ex->value();
4460 	    verinum::V rtn = verinum::Vx;
4461 
4462 	      // A constant in range select.
4463 	    if ((sel_v >= 0) && ((unsigned long) sel_v < par_v.len())) {
4464 		  rtn = par_v[sel_v];
4465 	      // An unsized after select.
4466 	    } else if ((sel_v >= 0) && (! par_v.has_len())) {
4467 		  if (par_v.has_sign()) rtn = par_v[par_v.len()-1];
4468 		  else rtn = verinum::V0;
4469 	    } else if (warn_ob_select) {
4470 		  cerr << get_fileline() << ": warning: "
4471 		          "Constant bit select [" << sel_c->value().as_long()
4472 		       << "] is ";
4473 		  if (sel_v < 0) cerr << "before ";
4474 		  else cerr << "after ";
4475 		  cerr << name << "[";
4476 		  if (par_v.has_len()) cerr << par_msv;
4477 		  else cerr << "<inf>";
4478 		  cerr << ":" << par_lsv << "]." << endl;
4479 		  cerr << get_fileline() << ":        : "
4480 		          "Replacing select with a constant 1'bx." << endl;
4481 	    }
4482 	    NetEConst*res = new NetEConst(verinum(rtn, 1));
4483 	    res->set_line(*this);
4484 	    return res;
4485       }
4486 
4487       sel = normalize_variable_base(sel, par_msv, par_lsv, 1, true);
4488 
4489 	/* Create a parameter reference for the variable select. */
4490       NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_ex->value());
4491       NetScope::param_ref_t pref = found_in->find_parameter(name);
4492       ptmp->set_line((*pref).second);
4493 
4494       NetExpr*tmp = new NetESelect(ptmp, sel, 1);
4495       tmp->set_line(*this);
4496       return tmp;
4497 }
4498 
elaborate_expr_param_part_(Design * des,NetScope * scope,const NetExpr * par,NetScope *,const NetExpr * par_msb,const NetExpr * par_lsb,unsigned expr_wid) const4499 NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
4500 					     const NetExpr*par,
4501 					     NetScope*,
4502 					     const NetExpr*par_msb,
4503 					     const NetExpr*par_lsb,
4504                                              unsigned expr_wid) const
4505 {
4506       long msv, lsv;
4507       bool parts_defined_flag;
4508       bool flag = calculate_parts_(des, scope, msv, lsv, parts_defined_flag);
4509       if (!flag)
4510 	    return 0;
4511 
4512       const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
4513       ivl_assert(*this, par_ex);
4514 
4515 
4516       long par_msv, par_lsv;
4517       if (! calculate_param_range_(des, scope, par_msb, par_msv,
4518                                    par_lsb, par_lsv,
4519                                    par_ex->value().len())) return 0;
4520 
4521       if (! parts_defined_flag) {
4522 	    if (warn_ob_select) {
4523 		  const index_component_t&psel = path_.back().index.back();
4524 		  perm_string name = peek_tail_name(path_);
4525 		  cerr << get_fileline() << ": warning: "
4526 		          "Undefined part select [" << *(psel.msb) << ":"
4527 		       << *(psel.lsb) << "] for parameter '" << name
4528 		       << "'." << endl;
4529 		  cerr << get_fileline() << ":        : "
4530 		          "Replacing select with a constant 'bx." << endl;
4531 	    }
4532 
4533 	    verinum val(verinum::Vx, expr_wid, true);
4534 	    NetEConst*tmp = new NetEConst(val);
4535 	    tmp->set_line(*this);
4536 	    return tmp;
4537       }
4538 
4539 	// Notice that the par_msv is not used in this function other
4540 	// than for this test. It is used to tell the direction that
4541 	// the bits are numbers, so that we can make sure the
4542 	// direction matches the part select direction. After that,
4543 	// we only need the par_lsv.
4544       if ((msv>lsv && par_msv<par_lsv) || (msv<lsv && par_msv>=par_lsv)) {
4545 	    perm_string name = peek_tail_name(path_);
4546 	    cerr << get_fileline() << ": error: Part select " << name
4547 		 << "[" << msv << ":" << lsv << "] is out of order." << endl;
4548 	    des->errors += 1;
4549 	    return 0;
4550       }
4551 
4552       long wid = 1 + labs(msv-lsv);
4553 
4554 	// Watch out for reversed bit numbering. We're making
4555 	// the part select from LSB to MSB.
4556       long base;
4557       if (par_msv < par_lsv) {
4558 	    base = par_lsv - lsv;
4559       } else {
4560 	    base = lsv - par_lsv;
4561       }
4562 
4563       if (warn_ob_select) {
4564 	    if (base < 0) {
4565 		  perm_string name = peek_tail_name(path_);
4566 		  cerr << get_fileline() << ": warning: Part select "
4567 		       << "[" << msv << ":" << lsv << "] is selecting "
4568 		          "before the parameter " << name << "[";
4569 		  if (par_ex->value().has_len()) cerr << par_msv;
4570 		  else cerr << "<inf>";
4571 		  cerr << ":" << par_lsv << "]." << endl;
4572 		  cerr << get_fileline() << ":        : Replacing "
4573 		          "the out of bound bits with 'bx." << endl;
4574 	    }
4575 	    if (par_ex->value().has_len() &&
4576                 (base+wid > (long)par->expr_width())) {
4577 		  perm_string name = peek_tail_name(path_);
4578 		  cerr << get_fileline() << ": warning: Part select "
4579 		       << name << "[" << msv << ":" << lsv << "] is selecting "
4580 		          "after the parameter " << name << "[" << par_msv
4581 		       << ":" << par_lsv << "]." << endl;
4582 		  cerr << get_fileline() << ":        : Replacing "
4583 		          "the out of bound bits with 'bx." << endl;
4584 	    }
4585       }
4586 
4587       verinum result = param_part_select_bits(par_ex->value(), wid, base);
4588       NetEConst*result_ex = new NetEConst(result);
4589       result_ex->set_line(*this);
4590 
4591       return result_ex;
4592 }
4593 
warn_param_ob(long par_msv,long par_lsv,bool defined,long par_base,unsigned long wid,long pwid,const LineInfo * info,perm_string name,bool up)4594 static void warn_param_ob(long par_msv, long par_lsv, bool defined,
4595                           long par_base, unsigned long wid, long pwid,
4596                           const LineInfo *info, perm_string name, bool up)
4597 {
4598       long par_max;
4599 
4600       if (defined) {
4601 	    if (par_msv < par_lsv) par_max = par_lsv-par_msv;
4602 	     else par_max = par_msv-par_lsv;
4603       } else {
4604 	    if (pwid < 0) par_max = integer_width;
4605 	    else par_max = pwid;
4606       }
4607 
4608 	/* Is this a select before the start of the parameter? */
4609       if (par_base < 0) {
4610 	    cerr << info->get_fileline() << ": warning: " << name << "["
4611 	         << par_base;
4612 	    if (up) cerr << "+:";
4613 	    else cerr << "-:";
4614 	    cerr << wid << "] is selecting before vector." << endl;
4615       }
4616 
4617 	/* Is this a select after the end of the parameter? */
4618       if (par_base + (long)wid - 1 > par_max) {
4619 	    cerr << info->get_fileline() << ": warning: " << name << "["
4620 	         << par_base << "+:" << wid << "] is selecting after vector."
4621 	         << endl;
4622       }
4623 }
4624 
elaborate_expr_param_idx_up_(Design * des,NetScope * scope,const NetExpr * par,NetScope * found_in,const NetExpr * par_msb,const NetExpr * par_lsb,bool need_const) const4625 NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
4626 					       const NetExpr*par,
4627 					       NetScope*found_in,
4628 					       const NetExpr*par_msb,
4629 					       const NetExpr*par_lsb,
4630                                                bool need_const) const
4631 {
4632       const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
4633       ivl_assert(*this, par_ex);
4634 
4635       long par_msv, par_lsv;
4636       if(! calculate_param_range_(des, scope, par_msb, par_msv,
4637                                   par_lsb, par_lsv,
4638                                   par_ex->value().len())) return 0;
4639 
4640       NetExpr*base = calculate_up_do_base_(des, scope, need_const);
4641       if (base == 0) return 0;
4642 
4643 	// Use the part select width already calculated by test_width().
4644       unsigned long wid = min_width_;
4645 
4646       if (debug_elaborate)
4647 	    cerr << get_fileline() << ": debug: Calculate part select "
4648 		 << "[" << *base << "+:" << wid << "] from range "
4649 		 << "[" << par_msv << ":" << par_lsv << "]." << endl;
4650 
4651       perm_string name = peek_tail_name(path_);
4652 
4653 	// Handle the special case that the base is constant. In this
4654 	// case, just precalculate the entire constant result.
4655       if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
4656 	    if (! base_c->value().is_defined()) {
4657 		  NetEConst *ex;
4658 		  ex = new NetEConst(verinum(verinum::Vx, wid, true));
4659 		  ex->set_line(*this);
4660 		  if (warn_ob_select) {
4661 			cerr << get_fileline() << ": warning: " << name
4662 			     << "['bx+:" << wid
4663 			     << "] is always outside vector." << endl;
4664 		  }
4665 		  return ex;
4666 	    }
4667 	    long lsv = base_c->value().as_long();
4668 	    long par_base = par_lsv;
4669 
4670 	      // Watch out for reversed bit numbering. We're making
4671 	      // the part select from LSB to MSB.
4672 	    if (par_msv < par_lsv) {
4673 		  par_base = lsv;
4674 		  lsv = par_lsv - wid + 1;
4675 	    }
4676 
4677 	    if (warn_ob_select) {
4678                   bool defined = true;
4679 		    // Check to see if the parameter has a defined range.
4680                   if (par_msb == 0) {
4681 			assert(par_lsb == 0);
4682 			defined = false;
4683                   }
4684 		    // Get the parameter values width.
4685                   long pwid = -1;
4686                   if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
4687                   warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
4688                                 pwid, this, name, true);
4689 	    }
4690 	    verinum result = param_part_select_bits(par_ex->value(), wid,
4691 						    lsv-par_base);
4692 	    NetEConst*result_ex = new NetEConst(result);
4693 	    result_ex->set_line(*this);
4694 	    return result_ex;
4695       }
4696 
4697       base = normalize_variable_base(base, par_msv, par_lsv, wid, true);
4698 
4699 	/* Create a parameter reference for the variable select. */
4700       NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_ex->value());
4701       NetScope::param_ref_t pref = found_in->find_parameter(name);
4702       ptmp->set_line((*pref).second);
4703 
4704       NetExpr*tmp = new NetESelect(ptmp, base, wid, IVL_SEL_IDX_UP);
4705       tmp->set_line(*this);
4706       return tmp;
4707 }
4708 
elaborate_expr_param_idx_do_(Design * des,NetScope * scope,const NetExpr * par,NetScope * found_in,const NetExpr * par_msb,const NetExpr * par_lsb,bool need_const) const4709 NetExpr* PEIdent::elaborate_expr_param_idx_do_(Design*des, NetScope*scope,
4710 					       const NetExpr*par,
4711 					       NetScope*found_in,
4712 					       const NetExpr*par_msb,
4713 					       const NetExpr*par_lsb,
4714                                                bool need_const) const
4715 {
4716       const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
4717       ivl_assert(*this, par_ex);
4718 
4719       long par_msv, par_lsv;
4720       if(! calculate_param_range_(des, scope, par_msb, par_msv,
4721                                   par_lsb, par_lsv,
4722                                   par_ex->value().len())) return 0;
4723 
4724       NetExpr*base = calculate_up_do_base_(des, scope, need_const);
4725       if (base == 0) return 0;
4726 
4727 	// Use the part select width already calculated by test_width().
4728       unsigned long wid = min_width_;
4729 
4730       if (debug_elaborate)
4731 	    cerr << get_fileline() << ": debug: Calculate part select "
4732 		 << "[" << *base << "-:" << wid << "] from range "
4733 		 << "[" << par_msv << ":" << par_lsv << "]." << endl;
4734 
4735       perm_string name = peek_tail_name(path_);
4736 
4737 	// Handle the special case that the base is constant. In this
4738 	// case, just precalculate the entire constant result.
4739       if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
4740 	    if (! base_c->value().is_defined()) {
4741 		  NetEConst *ex;
4742 		  ex = new NetEConst(verinum(verinum::Vx, wid, true));
4743 		  ex->set_line(*this);
4744 		  if (warn_ob_select) {
4745 			cerr << get_fileline() << ": warning: " << name
4746 			     << "['bx-:" << wid
4747 			     << "] is always outside vector." << endl;
4748 		  }
4749 		  return ex;
4750 	    }
4751 	    long lsv = base_c->value().as_long();
4752 	    long par_base = par_lsv + wid - 1;
4753 
4754 	      // Watch out for reversed bit numbering. We're making
4755 	      // the part select from LSB to MSB.
4756 	    if (par_msv < par_lsv) {
4757 		  par_base = lsv;
4758 		  lsv = par_lsv;
4759 	    }
4760 
4761 	    if (warn_ob_select) {
4762                   bool defined = true;
4763 		    // Check to see if the parameter has a defined range.
4764                   if (par_msb == 0) {
4765 			assert(par_lsb == 0);
4766 			defined = false;
4767                   }
4768 		    // Get the parameter values width.
4769                   long pwid = -1;
4770                   if (par_ex->has_width()) pwid = par_ex->expr_width()-1;
4771                   warn_param_ob(par_msv, par_lsv, defined, lsv-par_base, wid,
4772                                 pwid, this, name, false);
4773 	    }
4774 
4775 	    verinum result = param_part_select_bits(par_ex->value(), wid,
4776 						    lsv-par_base);
4777 	    NetEConst*result_ex = new NetEConst(result);
4778 	    result_ex->set_line(*this);
4779 	    return result_ex;
4780       }
4781 
4782       base = normalize_variable_base(base, par_msv, par_lsv, wid, false);
4783 
4784 	/* Create a parameter reference for the variable select. */
4785       NetEConstParam*ptmp = new NetEConstParam(found_in, name, par_ex->value());
4786       NetScope::param_ref_t pref = found_in->find_parameter(name);
4787       ptmp->set_line((*pref).second);
4788 
4789       NetExpr*tmp = new NetESelect(ptmp, base, wid, IVL_SEL_IDX_DOWN);
4790       tmp->set_line(*this);
4791       return tmp;
4792 }
4793 
4794 /*
4795  * Handle the case that the identifier is a parameter reference. The
4796  * parameter expression has already been located for us (as the par
4797  * argument) so we just need to process the sub-expression.
4798  */
elaborate_expr_param_(Design * des,NetScope * scope,const NetExpr * par,NetScope * found_in,const NetExpr * par_msb,const NetExpr * par_lsb,unsigned expr_wid,unsigned flags) const4799 NetExpr* PEIdent::elaborate_expr_param_(Design*des,
4800 					NetScope*scope,
4801 					const NetExpr*par,
4802 					NetScope*found_in,
4803 					const NetExpr*par_msb,
4804 					const NetExpr*par_lsb,
4805 					unsigned expr_wid, unsigned flags) const
4806 {
4807       bool need_const = NEED_CONST & flags;
4808 
4809       if (need_const && !(ANNOTATABLE & flags)) {
4810             perm_string name = peek_tail_name(path_);
4811             if (found_in->make_parameter_unannotatable(name)) {
4812                   cerr << get_fileline() << ": warning: specparam '" << name
4813                        << "' is being used in a constant expression." << endl;
4814                   cerr << get_fileline() << ":        : This will prevent it "
4815                           "being annotated at run time." << endl;
4816             }
4817       }
4818 
4819       const name_component_t&name_tail = path_.back();
4820       index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
4821       if (!name_tail.index.empty())
4822 	    use_sel = name_tail.index.back().sel;
4823 
4824       if (par->expr_type() == IVL_VT_REAL &&
4825           use_sel != index_component_t::SEL_NONE) {
4826 	    perm_string name = peek_tail_name(path_);
4827 	    cerr << get_fileline() << ": error: "
4828 	         << "can not select part of real parameter: " << name << endl;
4829 	    des->errors += 1;
4830 	    return 0;
4831       }
4832 
4833       ivl_assert(*this, use_sel != index_component_t::SEL_BIT_LAST);
4834 
4835       if (use_sel == index_component_t::SEL_BIT)
4836 	    return elaborate_expr_param_bit_(des, scope, par, found_in,
4837 					     par_msb, par_lsb, need_const);
4838 
4839       if (use_sel == index_component_t::SEL_PART)
4840 	    return elaborate_expr_param_part_(des, scope, par, found_in,
4841 					      par_msb, par_lsb, expr_wid);
4842 
4843       if (use_sel == index_component_t::SEL_IDX_UP)
4844 	    return elaborate_expr_param_idx_up_(des, scope, par, found_in,
4845 						par_msb, par_lsb, need_const);
4846 
4847       if (use_sel == index_component_t::SEL_IDX_DO)
4848 	    return elaborate_expr_param_idx_do_(des, scope, par, found_in,
4849 						par_msb, par_lsb, need_const);
4850 
4851       NetExpr*tmp = 0;
4852 
4853       const NetEConstEnum*etmp = dynamic_cast<const NetEConstEnum*>(par);
4854       if (etmp) {
4855 	    if (debug_elaborate)
4856 		  cerr << get_fileline() << ": debug: "
4857 		       << "Elaborate parameter <" << path_
4858 		       << "> as enumeration constant." << *etmp << endl;
4859 	    tmp = etmp->dup_expr();
4860             tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
4861 
4862       } else {
4863 	    perm_string name = peek_tail_name(path_);
4864 
4865 	      /* No bit or part select. Make the constant into a
4866 		 NetEConstParam or NetECRealParam as appropriate. */
4867 	    const NetEConst*ctmp = dynamic_cast<const NetEConst*>(par);
4868 	    if (ctmp) {
4869                   verinum cvalue = ctmp->value();
4870                   if (cvalue.has_len())
4871 			cvalue.has_sign(signed_flag_);
4872                   cvalue = cast_to_width(cvalue, expr_wid);
4873 		  tmp = new NetEConstParam(found_in, name, cvalue);
4874 		  tmp->cast_signed(signed_flag_);
4875 		  tmp->set_line(*par);
4876 
4877 		  if (debug_elaborate)
4878 			cerr << get_fileline() << ": debug: "
4879 			     << "Elaborate parameter <" << name
4880 			     << "> as constant " << *tmp << endl;
4881 	    }
4882 
4883 	    const NetECReal*rtmp = dynamic_cast<const NetECReal*>(par);
4884 	    if (rtmp) {
4885 		  tmp = new NetECRealParam(found_in, name, rtmp->value());
4886 		  tmp->set_line(*par);
4887 
4888 		  if (debug_elaborate)
4889 			cerr << get_fileline() << ": debug: "
4890 			     << "Elaborate parameter <" << name
4891 			     << "> as constant " << *tmp << endl;
4892 	    }
4893 	      /* The numeric parameter value needs to have the file and line
4894 	       * information for the actual parameter not the expression. */
4895 	    assert(tmp);
4896 	    NetScope::param_ref_t pref = found_in->find_parameter(name);
4897 	    tmp->set_line((*pref).second);
4898       }
4899 
4900       return tmp;
4901 }
4902 
4903 /*
4904  * Handle word selects of vector arrays.
4905  */
elaborate_expr_net_word_(Design * des,NetScope * scope,NetNet * net,NetScope * found_in,unsigned expr_wid,unsigned flags) const4906 NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
4907 					   NetNet*net, NetScope*found_in,
4908                                            unsigned expr_wid,
4909 					   unsigned flags) const
4910 {
4911       bool need_const = NEED_CONST & flags;
4912 
4913       const name_component_t&name_tail = path_.back();
4914 
4915       if (debug_elaborate) {
4916 	    cerr << get_fileline() << ": PEIdent::elaborate_net_word_: "
4917 		 << "expr_wid=" << expr_wid
4918 		 << ", net->get_scalar()==" << (net->get_scalar()?"true":"false")
4919 		 << endl;
4920       }
4921 
4922 	// Special case: This is the entire array, and we are a direct
4923 	// argument of a system task.
4924       if (name_tail.index.empty() && (SYS_TASK_ARG & flags)) {
4925 	    NetESignal*res = new NetESignal(net, 0);
4926 	    res->set_line(*this);
4927 	    return res;
4928       }
4929 
4930       if (name_tail.index.empty()) {
4931 	    cerr << get_fileline() << ": error: Array " << path()
4932 		 << " needs an array index here." << endl;
4933 	    des->errors += 1;
4934 	    return 0;
4935       }
4936 
4937 	// Make sure there are enough indices to address an array element.
4938       if (name_tail.index.size() < net->unpacked_dimensions()) {
4939 	    cerr << get_fileline() << ": error: Array " << path()
4940 		 << " needs " << net->unpacked_dimensions() << " indices,"
4941 		 << " but got only " << name_tail.index.size() << "." << endl;
4942 	    des->errors += 1;
4943 	    return 0;
4944       }
4945 
4946 	// Evaluate all the index expressions into an
4947 	// "unpacked_indices" array.
4948       list<NetExpr*>unpacked_indices;
4949       list<long> unpacked_indices_const;
4950       indices_flags idx_flags;
4951       indices_to_expressions(des, scope, this,
4952 			     name_tail.index, net->unpacked_dimensions(),
4953 			     need_const,
4954 			     idx_flags,
4955 			     unpacked_indices,
4956 			     unpacked_indices_const);
4957 
4958       NetExpr*canon_index = 0;
4959       if (idx_flags.invalid) {
4960 	    // Nothing to do.
4961 
4962       } else if (idx_flags.undefined) {
4963 	    cerr << get_fileline() << ": warning: "
4964 		 << "returning 'bx for undefined array access "
4965 		 << net->name() << as_indices(unpacked_indices)
4966 		 << "." << endl;
4967 
4968       } else if (idx_flags.variable) {
4969 	    ivl_assert(*this, unpacked_indices.size() == net->unpacked_dimensions());
4970 	    canon_index = normalize_variable_unpacked(net, unpacked_indices);
4971 
4972       } else {
4973 	    ivl_assert(*this, unpacked_indices_const.size() == net->unpacked_dimensions());
4974 	    canon_index = normalize_variable_unpacked(net, unpacked_indices_const);
4975 
4976 	    if (canon_index == 0) {
4977 		  cerr << get_fileline() << ": warning: "
4978 		       << "returning 'bx for out of bounds array access "
4979 		       << net->name() << as_indices(unpacked_indices_const)
4980 		       << "." << endl;
4981 	    }
4982       }
4983 
4984       if (canon_index == 0) {
4985 	    NetEConst*xxx = make_const_x(net->vector_width());
4986 	    xxx->set_line(*this);
4987 	    return xxx;
4988       }
4989       canon_index->set_line(*this);
4990 
4991       NetESignal*res = new NetESignal(net, canon_index);
4992       res->set_line(*this);
4993 
4994 	// Detect that the word has a bit/part select as well.
4995 
4996       index_component_t::ctype_t word_sel = index_component_t::SEL_NONE;
4997       if (name_tail.index.size() > net->unpacked_dimensions())
4998 	    word_sel = name_tail.index.back().sel;
4999 
5000       if (net->get_scalar() &&
5001           word_sel != index_component_t::SEL_NONE) {
5002 	    cerr << get_fileline() << ": error: can not select part of ";
5003 	    if (res->expr_type() == IVL_VT_REAL) cerr << "real";
5004 	    else cerr << "scalar";
5005 	    cerr << " array word: " << net->name()
5006 		 << as_indices(unpacked_indices) << endl;
5007 	    des->errors += 1;
5008 	    delete res;
5009 	    return 0;
5010       }
5011 
5012       if (word_sel == index_component_t::SEL_PART)
5013 	    return elaborate_expr_net_part_(des, scope, res, found_in,
5014                                             expr_wid);
5015 
5016       if (word_sel == index_component_t::SEL_IDX_UP)
5017 	    return elaborate_expr_net_idx_up_(des, scope, res, found_in,
5018                                               need_const);
5019 
5020       if (word_sel == index_component_t::SEL_IDX_DO)
5021 	    return elaborate_expr_net_idx_do_(des, scope, res, found_in,
5022                                               need_const);
5023 
5024       if (word_sel == index_component_t::SEL_BIT)
5025 	    return elaborate_expr_net_bit_(des, scope, res, found_in,
5026                                            need_const);
5027 
5028       ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
5029 
5030       return res;
5031 }
5032 
5033 /*
5034  * Handle part selects of NetNet identifiers.
5035  */
elaborate_expr_net_part_(Design * des,NetScope * scope,NetESignal * net,NetScope *,unsigned expr_wid) const5036 NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
5037 				           NetESignal*net, NetScope*,
5038                                            unsigned expr_wid) const
5039 {
5040       list<long> prefix_indices;
5041       bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
5042       if (!rc)
5043 	    return 0;
5044 
5045       long msv, lsv;
5046       bool parts_defined_flag;
5047       bool flag = calculate_parts_(des, scope, msv, lsv, parts_defined_flag);
5048       if (!flag)
5049 	    return 0;
5050 
5051 	/* The indices of part selects are signed integers, so allow
5052 	   negative values. However, the width that they represent is
5053 	   unsigned. Remember that any order is possible,
5054 	   i.e., [1:0], [-4:6], etc. */
5055       unsigned long wid = 1 + labs(msv-lsv);
5056 	/* But wait... if the part select expressions are not fully
5057 	   defined, then fall back on the tested width. */
5058       if (!parts_defined_flag) {
5059 	    if (warn_ob_select) {
5060 		  const index_component_t&psel = path_.back().index.back();
5061 		  cerr << get_fileline() << ": warning: "
5062 		          "Undefined part select [" << *(psel.msb) << ":"
5063 		       << *(psel.lsb) << "] for ";
5064 		  if (net->word_index()) cerr << "array word";
5065 		  else cerr << "vector";
5066 		  cerr << " '" << net->name();
5067 		  if (net->word_index()) cerr << "[]";
5068 		  cerr << "'." << endl;
5069 		  cerr << get_fileline() << ":        : "
5070 		          "Replacing select with a constant 'bx." << endl;
5071 	    }
5072 
5073 	    NetEConst*tmp = new NetEConst(verinum(verinum::Vx, expr_wid, true));
5074 	    tmp->set_line(*this);
5075 	    return tmp;
5076       }
5077       long sb_lsb, sb_msb;
5078       if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
5079 	      // Here we have a slice that doesn't have enough indices
5080 	      // to get to a single slice. For example:
5081 	      //    wire [9:0][5:1] foo
5082 	      //      ... foo[4:3] ...
5083 	      // Make this work by finding the indexed slices and
5084 	      // creating a generated slice that spans the whole
5085 	      // range.
5086 	    long loff, moff;
5087 	    unsigned long lwid, mwid;
5088 	    bool lrc;
5089 	    lrc = net->sig()->sb_to_slice(prefix_indices, lsv, loff, lwid);
5090 	    ivl_assert(*this, lrc);
5091 	    lrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
5092 	    ivl_assert(*this, lrc);
5093 	    ivl_assert(*this, lwid == mwid);
5094 
5095 	    if (moff > loff) {
5096 		  sb_lsb = loff;
5097 		  sb_msb = moff + mwid - 1;
5098 	    } else {
5099 		  sb_lsb = moff;
5100 		  sb_msb = loff + lwid - 1;
5101 	    }
5102 	    wid = sb_msb - sb_lsb + 1;
5103       } else {
5104 	      // This case, the prefix indices are enough to index
5105 	      // down to a single bit/slice.
5106 	    ivl_assert(*this, prefix_indices.size()+1 == net->sig()->packed_dims().size());
5107 	    sb_lsb = net->sig()->sb_to_idx(prefix_indices, lsv);
5108 	    sb_msb = net->sig()->sb_to_idx(prefix_indices, msv);
5109       }
5110 
5111       if (sb_msb < sb_lsb) {
5112 	    cerr << get_fileline() << ": error: part select " << net->name();
5113 	    if (net->word_index()) cerr << "[]";
5114 	    cerr << "[" << msv << ":" << lsv << "] is out of order." << endl;
5115 	    des->errors += 1;
5116 	      //delete lsn;
5117 	      //delete msn;
5118 	    return net;
5119       }
5120 
5121       if (warn_ob_select) {
5122 	    if ((sb_lsb >= (signed) net->vector_width()) ||
5123 	        (sb_msb >= (signed) net->vector_width())) {
5124 		  cerr << get_fileline() << ": warning: "
5125 		          "Part select " << "[" << msv << ":" << lsv
5126 		       << "] is selecting after the ";
5127 		  if (net->word_index()) cerr << "array word ";
5128 		  else cerr << "vector ";
5129 		  cerr << net->name();
5130 		  if (net->word_index()) cerr << "[]";
5131 		  cerr << "[" << net->msi() << ":" << net->lsi() << "]."
5132 		       << endl;
5133 		  cerr << get_fileline() << ":        : "
5134 		       << "Replacing the out of bound bits with 'bx." << endl;
5135 	    }
5136 	    if ((sb_msb < 0) || (sb_lsb < 0)) {
5137 		  cerr << get_fileline() << ": warning: "
5138 		          "Part select " << "[" << msv << ":" << lsv
5139 		       << "] is selecting before the ";
5140 		  if (net->word_index()) cerr << "array word ";
5141 		  else cerr << "vector ";
5142 		  cerr << net->name();
5143 		  if (net->word_index()) cerr << "[]";
5144 		  cerr << "[" << net->msi() << ":" << net->lsi() << "]."
5145 		       << endl;
5146 		  cerr << get_fileline() << ":        : "
5147 		          "Replacing the out of bound bits with 'bx." << endl;
5148 	    }
5149       }
5150 
5151 	// If the part select covers exactly the entire
5152 	// vector, then do not bother with it. Return the
5153 	// signal itself, casting to unsigned if necessary.
5154       if (sb_lsb == 0 && wid == net->vector_width()) {
5155 	    net->cast_signed(false);
5156 	    return net;
5157       }
5158 
5159 	// If the part select covers NONE of the vector, then return a
5160 	// constant X.
5161 
5162       if ((sb_lsb >= (signed) net->vector_width()) || (sb_msb < 0)) {
5163 	    NetEConst*tmp = make_const_x(wid);
5164 	    tmp->set_line(*this);
5165 	    return tmp;
5166       }
5167 
5168       NetExpr*ex = new NetEConst(verinum(sb_lsb));
5169       NetESelect*ss = new NetESelect(net, ex, wid);
5170       ss->set_line(*this);
5171       return ss;
5172 }
5173 
5174 /*
5175  * Part select indexed up, i.e. net[<m> +: <l>]
5176  */
elaborate_expr_net_idx_up_(Design * des,NetScope * scope,NetESignal * net,NetScope *,bool need_const) const5177 NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
5178 				             NetESignal*net, NetScope*,
5179                                              bool need_const) const
5180 {
5181       list<long>prefix_indices;
5182       bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
5183       if (!rc)
5184 	    return 0;
5185 
5186       NetExpr*base = calculate_up_do_base_(des, scope, need_const);
5187 
5188 	// Use the part select width already calculated by test_width().
5189       unsigned long wid = min_width_;
5190 
5191 	// Handle the special case that the base is constant as
5192 	// well. In this case it can be converted to a conventional
5193 	// part select.
5194       if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
5195 	    NetExpr*ex;
5196 	    if (base_c->value().is_defined()) {
5197 		  long lsv = base_c->value().as_long();
5198 		  long offset = 0;
5199 		    // Get the signal range.
5200 		  const vector<netrange_t>&packed = net->sig()->packed_dims();
5201 		  ivl_assert(*this, packed.size() == prefix_indices.size()+1);
5202 
5203 		    // We want the last range, which is where we work.
5204 		  const netrange_t&rng = packed.back();
5205 		  if (rng.get_msb() < rng.get_lsb()) {
5206 			offset = -wid + 1;
5207 		  }
5208 
5209 		  long rel_base = net->sig()->sb_to_idx(prefix_indices, lsv);
5210 
5211 		    // If the part select covers exactly the entire
5212 		    // vector, then do not bother with it. Return the
5213 		    // signal itself.
5214 		  if (rel_base == 0 && wid == net->vector_width()) {
5215 			delete base;
5216 			net->cast_signed(false);
5217 			return net;
5218 		  }
5219 
5220 		    // Otherwise, make a part select that covers the right
5221 		    // range.
5222 		  ex = new NetEConst(verinum(rel_base + offset));
5223 		  if (warn_ob_select) {
5224 			if (rel_base < 0) {
5225 			      cerr << get_fileline() << ": warning: "
5226 			           << net->name();
5227 			      if (net->word_index()) cerr << "[]";
5228 			      cerr << "[" << lsv << "+:" << wid
5229 			           << "] is selecting before vector." << endl;
5230 			}
5231 			if (rel_base + wid > net->vector_width()) {
5232 			      cerr << get_fileline() << ": warning: "
5233 			           << net->name();
5234 			      if (net->word_index()) cerr << "[]";
5235 			      cerr << "[" << lsv << "+:" << wid
5236 			           << "] is selecting after vector." << endl;
5237 			}
5238 		  }
5239 	    } else {
5240 		    // Return 'bx for an undefined base.
5241 		  ex = new NetEConst(verinum(verinum::Vx, wid, true));
5242 		  ex->set_line(*this);
5243 		  delete base;
5244 		  if (warn_ob_select) {
5245 			cerr << get_fileline() << ": warning: " << net->name();
5246 			if (net->word_index()) cerr << "[]";
5247 			cerr << "['bx+:" << wid
5248 			     << "] is always outside vector." << endl;
5249 		  }
5250 		  return ex;
5251 	    }
5252 	    NetESelect*ss = new NetESelect(net, ex, wid);
5253 	    ss->set_line(*this);
5254 
5255 	    delete base;
5256 	    return ss;
5257       }
5258 
5259 
5260       ivl_assert(*this, prefix_indices.size()+1 == net->sig()->packed_dims().size());
5261 
5262 	// Convert the non-constant part select index expression into
5263 	// an expression that returns a canonical base.
5264       base = normalize_variable_part_base(prefix_indices, base, net->sig(), wid, true);
5265 
5266       NetESelect*ss = new NetESelect(net, base, wid, IVL_SEL_IDX_UP);
5267       ss->set_line(*this);
5268 
5269       if (debug_elaborate) {
5270 	    cerr << get_fileline() << ": debug: Elaborate part "
5271 		 << "select base="<< *base << ", wid="<< wid << endl;
5272       }
5273 
5274       return ss;
5275 }
5276 
5277 /*
5278  * Part select indexed down, i.e. net[<m> -: <l>]
5279  */
elaborate_expr_net_idx_do_(Design * des,NetScope * scope,NetESignal * net,NetScope *,bool need_const) const5280 NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
5281 					     NetESignal*net, NetScope*,
5282                                              bool need_const) const
5283 {
5284       list<long>prefix_indices;
5285       bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
5286       if (!rc)
5287 	    return 0;
5288 
5289       NetExpr*base = calculate_up_do_base_(des, scope, need_const);
5290 
5291 	// Use the part select width already calculated by test_width().
5292       unsigned long wid = min_width_;
5293 
5294 	// Handle the special case that the base is constant as
5295 	// well. In this case it can be converted to a conventional
5296 	// part select.
5297       if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
5298 	    NetExpr*ex;
5299 	    if (base_c->value().is_defined()) {
5300 		  long lsv = base_c->value().as_long();
5301 
5302 		    // If the part select covers exactly the entire
5303 		    // vector, then do not bother with it. Return the
5304 		    // signal itself.
5305 		  if (net->sig()->sb_to_idx(prefix_indices,lsv) == (signed) (wid-1) &&
5306 		      wid == net->vector_width()) {
5307 			delete base;
5308 			net->cast_signed(false);
5309 			return net;
5310 		  }
5311 
5312 		  long offset = 0;
5313 		  if (net->msi() > net->lsi()) {
5314 			offset = -wid + 1;
5315 		  }
5316 		    // Otherwise, make a part select that covers the right
5317 		    // range.
5318 		  ex = new NetEConst(verinum(net->sig()->sb_to_idx(prefix_indices,lsv) + offset));
5319 		  if (warn_ob_select) {
5320 			long rel_base = net->sig()->sb_to_idx(prefix_indices,lsv) + offset;
5321 			if (rel_base < 0) {
5322 			      cerr << get_fileline() << ": warning: "
5323 			           << net->name();
5324 			      if (net->word_index()) cerr << "[]";
5325 			      cerr << "[" << lsv << "+:" << wid
5326 			           << "] is selecting before vector." << endl;
5327 			}
5328 			if (rel_base + wid > net->vector_width()) {
5329 			      cerr << get_fileline() << ": warning: "
5330 			           << net->name();
5331 			      if (net->word_index()) cerr << "[]";
5332 			      cerr << "[" << lsv << "-:" << wid
5333 			           << "] is selecting after vector." << endl;
5334 			}
5335 		  }
5336 	    } else {
5337 		    // Return 'bx for an undefined base.
5338 		  ex = new NetEConst(verinum(verinum::Vx, wid, true));
5339 		  ex->set_line(*this);
5340 		  delete base;
5341 		  if (warn_ob_select) {
5342 			cerr << get_fileline() << ": warning: " << net->name();
5343 			if (net->word_index()) cerr << "[]";
5344 			cerr << "['bx-:" << wid
5345 			     << "] is always outside vector." << endl;
5346 		  }
5347 		  return ex;
5348 	    }
5349 	    NetESelect*ss = new NetESelect(net, ex, wid);
5350 	    ss->set_line(*this);
5351 
5352 	    delete base;
5353 	    return ss;
5354       }
5355 
5356       base = normalize_variable_base(base, net->msi(), net->lsi(), wid, false);
5357 
5358       NetESelect*ss = new NetESelect(net, base, wid, IVL_SEL_IDX_DOWN);
5359       ss->set_line(*this);
5360 
5361       if (debug_elaborate) {
5362 	    cerr << get_fileline() << ": debug: Elaborate part "
5363 		 << "select base="<< *base << ", wid="<< wid << endl;
5364       }
5365 
5366       return ss;
5367 }
5368 
elaborate_expr_net_bit_(Design * des,NetScope * scope,NetESignal * net,NetScope *,bool need_const) const5369 NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
5370 				          NetESignal*net, NetScope*,
5371                                           bool need_const) const
5372 {
5373       list<long>prefix_indices;
5374       bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
5375       if (!rc)
5376 	    return 0;
5377 
5378       const name_component_t&name_tail = path_.back();
5379       ivl_assert(*this, !name_tail.index.empty());
5380 
5381       const index_component_t&index_tail = name_tail.index.back();
5382       ivl_assert(*this, index_tail.msb != 0);
5383       ivl_assert(*this, index_tail.lsb == 0);
5384 
5385       NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
5386       if (!mux)
5387 	    return 0;
5388 
5389       if (const netdarray_t*darray = net->sig()->darray_type()) {
5390 	      // Special case: This is a select of a dynamic
5391 	      // array. Generate a NetESelect and attach it to
5392 	      // the NetESignal. This should be interpreted as
5393 	      // an array word select downstream.
5394 	    if (debug_elaborate) {
5395 		  cerr << get_fileline() << ": debug: "
5396 		       << "Bit select of a dynamic array becomes NetESelect." << endl;
5397 	    }
5398 	    NetESelect*res = new NetESelect(net, mux, darray->element_width());
5399 	    res->set_line(*net);
5400 	    return res;
5401       }
5402 
5403 	// If the bit select is constant, then treat it similar
5404 	// to the part select, so that I save the effort of
5405 	// making a mux part in the netlist.
5406       if (NetEConst*msc = dynamic_cast<NetEConst*> (mux)) {
5407 
5408 	    if (debug_elaborate) {
5409 		  cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
5410 		       << "mux is constant=" << *msc
5411 		       << ", packed_dims()=" << net->sig()->packed_dims()
5412 		       << ", packed_dims().size()=" << net->sig()->packed_dims().size()
5413 		       << ", prefix_indices.size()=" << prefix_indices.size()
5414 		       << endl;
5415 	    }
5416 
5417 	      // Special case: The bit select expression is constant
5418 	      // x/z. The result of the expression is 1'bx.
5419 	    if (! msc->value().is_defined()) {
5420 		  if (warn_ob_select) {
5421 			cerr << get_fileline() << ": warning: "
5422 			        "Constant bit select [" << msc->value()
5423 			      << "] is undefined for ";
5424 			if (net->word_index()) cerr << "array word";
5425 			else cerr << "vector";
5426 			cerr << " '" << net->name();
5427 			if (net->word_index()) cerr << "[]";
5428 			cerr  << "'." << endl;
5429 			cerr << get_fileline() << ":        : "
5430 			     << "Replacing select with a constant 1'bx."
5431 			     << endl;
5432 		  }
5433 
5434 		    // FIXME: Should I be using slice_width() here?
5435 		  NetEConst*tmp = make_const_x(1);
5436 		  tmp->set_line(*this);
5437 		  delete mux;
5438 		  return tmp;
5439 	    }
5440 
5441 	    long msv = msc->value().as_long();
5442 
5443 	    const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
5444 	    if (prefix_indices.size()+2 <= sig_packed.size()) {
5445 		    // Special case: this is a slice of a multi-dimensional
5446 		    // packed array. For example:
5447 		    //   reg [3:0][7:0] x;
5448 		    //   ... x[2] ...
5449 		    // This shows up as the prefix_indices being too short
5450 		    // for the packed dimensions of the vector. What we do
5451 		    // here is convert to a "slice" of the vector.
5452 		  unsigned long lwid;
5453 		  long idx;
5454 		  rc = net->sig()->sb_to_slice(prefix_indices, msv, idx, lwid);
5455 		  ivl_assert(*this, rc);
5456 
5457 		    // Make an expression out of the index
5458 		  NetEConst*idx_c = new NetEConst(verinum(idx));
5459 		  idx_c->set_line(*net);
5460 
5461 		  NetESelect*res = new NetESelect(net, idx_c, lwid);
5462 		  res->set_line(*net);
5463 		  return res;
5464 	    }
5465 
5466 	    if (net->sig()->data_type()==IVL_VT_STRING && (msv < 0)) {
5467 		    // Special case: This is a constant bit select of
5468 		    // a string, and the index is < 0. For example:
5469 		    //   string foo;
5470 		    //   ... foo[-1] ...
5471 		    // This is known to be 8'h00.
5472 		  NetEConst*tmp = make_const_0(8);
5473 		  tmp->set_line(*this);
5474 		  delete mux;
5475 		  return tmp;
5476 	    }
5477 
5478 	    if (net->sig()->data_type()==IVL_VT_STRING) {
5479 		    // Special case: This is a select of a string
5480 		    // variable. Generate a NetESelect and attach it
5481 		    // to the NetESignal. This should be interpreted
5482 		    // as a character select downstream.
5483 		  if (debug_elaborate) {
5484 			cerr << get_fileline() << ": debug: "
5485 			     << "Bit select of string becomes NetESelect." << endl;
5486 		  }
5487 		  NetESelect*res = new NetESelect(net, mux, 8);
5488 		  res->set_line(*net);
5489 		  return res;
5490 	    }
5491 
5492 	    long idx = net->sig()->sb_to_idx(prefix_indices,msv);
5493 
5494 	    if (idx >= (long)net->vector_width() || idx < 0) {
5495 		    /* The bit select is out of range of the
5496 		       vector. This is legal, but returns a
5497 		       constant 1'bx value. */
5498 		  if (warn_ob_select) {
5499 			cerr << get_fileline() << ": warning: "
5500 			        "Constant bit select [" << msv
5501 			      << "] is ";
5502 			if (idx < 0) cerr << "before ";
5503 			else cerr << "after ";
5504 			if (net->word_index()) cerr << "array word ";
5505 			else cerr << "vector ";
5506 			cerr << net->name();
5507 			if (net->word_index()) cerr << "[]";
5508 			cerr  << net->sig()->packed_dims() << "." << endl;
5509 			cerr << get_fileline() << ":        : "
5510 			     << "Replacing select with a constant 1'bx."
5511 			     << endl;
5512 		  }
5513 
5514 		  NetEConst*tmp = make_const_x(1);
5515 		  tmp->set_line(*this);
5516 
5517 		  delete mux;
5518 		  return tmp;
5519 	    }
5520 
5521 	      // If the vector is only one bit, we are done. The
5522 	      // bit select will return the scalar itself.
5523 	    if (net->vector_width() == 1)
5524 		  return net;
5525 
5526 	    if (debug_elaborate) {
5527 		  cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
5528 		       << "Make bit select idx=" << idx
5529 		       << endl;
5530 	    }
5531 
5532 	      // Make an expression out of the index
5533 	    NetEConst*idx_c = new NetEConst(verinum(idx));
5534 	    idx_c->set_line(*net);
5535 
5536 	      // Make a bit select with the canonical index
5537 	    NetESelect*res = new NetESelect(net, idx_c, 1);
5538 	    res->set_line(*net);
5539 
5540 	    return res;
5541       }
5542 
5543       const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
5544       if (prefix_indices.size()+2 <= sig_packed.size()) {
5545 	      // Special case: this is a slice of a multi-dimensional
5546 	      // packed array. For example:
5547 	      //   reg [3:0][7:0] x;
5548 	      //   x[2] = ...
5549 	      // This shows up as the prefix_indices being too short
5550 	      // for the packed dimensions of the vector. What we do
5551 	      // here is convert to a "slice" of the vector.
5552 	    unsigned long lwid;
5553 	    mux = normalize_variable_slice_base(prefix_indices, mux,
5554 						net->sig(), lwid);
5555 	    mux->set_line(*net);
5556 
5557 	      // Make a PART select with the canonical index
5558 	    NetESelect*res = new NetESelect(net, mux, lwid);
5559 	    res->set_line(*net);
5560 
5561 	    return res;
5562       }
5563 
5564       if (net->sig()->data_type() == IVL_VT_STRING) {
5565 	      // Special case: This is a select of a string.
5566 	      // This should be interpreted as a byte select.
5567 	    if (debug_elaborate) {
5568 		  cerr << get_fileline() << ": debug: "
5569 		       << "Bit select of a string becomes NetESelect." << endl;
5570 	    }
5571 	    NetESelect*res = new NetESelect(net, mux, 8);
5572 	    res->set_line(*net);
5573 	    return res;
5574       }
5575 
5576 	// Non-constant bit select? punt and make a subsignal
5577 	// device to mux the bit in the net. This is a fairly
5578 	// complicated task because we need to generate
5579 	// expressions to convert calculated bit select
5580 	// values to canonical values that are used internally.
5581       mux = normalize_variable_bit_base(prefix_indices, mux, net->sig());
5582 
5583       NetESelect*ss = new NetESelect(net, mux, 1);
5584       ss->set_line(*this);
5585       return ss;
5586 }
5587 
elaborate_expr_net_bit_last_(Design *,NetScope *,NetESignal * net,NetScope *,bool need_const) const5588 NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*, NetScope*,
5589 					       NetESignal*net,
5590 					       NetScope* /* found_in */,
5591 					       bool need_const) const
5592 {
5593       if (need_const) {
5594 	    cerr << get_fileline() << ": error: "
5595 		 << "Expression with \"[$]\" is not constant." << endl;
5596 	    return 0;
5597       }
5598 
5599       unsigned use_width = 1;
5600       if (const netdarray_t*darray = net->sig()->darray_type()) {
5601 	    use_width = darray->element_width();
5602       }
5603 
5604       NetELast*mux = new NetELast(net->sig());
5605       mux->set_line(*this);
5606       NetESelect*ss = new NetESelect(net, mux, use_width);
5607       ss->set_line(*this);
5608       return ss;
5609 }
5610 
elaborate_expr_net(Design * des,NetScope * scope,NetNet * net,NetScope * found_in,unsigned expr_wid,unsigned flags) const5611 NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
5612 				     NetNet*net, NetScope*found_in,
5613                                      unsigned expr_wid,
5614 				     unsigned flags) const
5615 {
5616       if (debug_elaborate) {
5617 	    cerr << get_fileline() << ": PEIdent::elaborate_expr_net: "
5618 		 << "net=" << net->name()
5619 		 << ", net->unpacked_dimensions()=" << net->unpacked_dimensions()
5620 		 << ", net->get_scalar()=" << (net->get_scalar()?"true":"false")
5621 		 << ", net->net_type()=" << *net->net_type()
5622 		 << endl;
5623       }
5624 
5625       if (net->unpacked_dimensions() > 0)
5626 	    return elaborate_expr_net_word_(des, scope, net, found_in,
5627                                             expr_wid, flags);
5628 
5629       bool need_const = NEED_CONST & flags;
5630 
5631       NetESignal*node = new NetESignal(net);
5632       node->set_line(*this);
5633 
5634       index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
5635       if (! path_.back().index.empty())
5636 	    use_sel = path_.back().index.back().sel;
5637 
5638       if (net->get_scalar() && use_sel != index_component_t::SEL_NONE) {
5639 	    cerr << get_fileline() << ": error: can not select part of ";
5640 	    if (node->expr_type() == IVL_VT_REAL) cerr << "real: ";
5641 	    else cerr << "scalar: ";
5642 	    cerr << net->name() << endl;
5643 	    des->errors += 1;
5644 	    return 0;
5645       }
5646 
5647       list<long> prefix_indices;
5648       bool rc = evaluate_index_prefix(des, scope, prefix_indices, path_.back().index);
5649       if (!rc) return 0;
5650 
5651 	// If this is a part select of a signal, then make a new
5652 	// temporary signal that is connected to just the
5653 	// selected bits. The lsb_ and msb_ expressions are from
5654 	// the foo[msb:lsb] expression in the original.
5655       if (use_sel == index_component_t::SEL_PART)
5656 	    return elaborate_expr_net_part_(des, scope, node, found_in,
5657                                             expr_wid);
5658 
5659       if (use_sel == index_component_t::SEL_IDX_UP)
5660 	    return elaborate_expr_net_idx_up_(des, scope, node, found_in,
5661                                               need_const);
5662 
5663       if (use_sel == index_component_t::SEL_IDX_DO)
5664 	    return elaborate_expr_net_idx_do_(des, scope, node, found_in,
5665                                               need_const);
5666 
5667       if (use_sel == index_component_t::SEL_BIT)
5668 	    return elaborate_expr_net_bit_(des, scope, node, found_in,
5669                                            need_const);
5670 
5671       if (use_sel == index_component_t::SEL_BIT_LAST)
5672 	    return elaborate_expr_net_bit_last_(des, scope, node, found_in,
5673 						need_const);
5674 
5675 	// It's not anything else, so this must be a simple identifier
5676 	// expression with no part or bit select. Return the signal
5677 	// itself as the expression.
5678       assert(use_sel == index_component_t::SEL_NONE);
5679 
5680       return node;
5681 }
5682 
test_width(Design *,NetScope *,width_mode_t &)5683 unsigned PENewArray::test_width(Design*, NetScope*, width_mode_t&)
5684 {
5685       expr_type_  = IVL_VT_DARRAY;
5686       expr_width_ = 1;
5687       min_width_  = 1;
5688       signed_flag_= false;
5689       return 1;
5690 }
5691 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const5692 NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope,
5693 				    ivl_type_t ntype, unsigned flags) const
5694 {
5695 	// Elaborate the size expression.
5696       width_mode_t mode = LOSSLESS;
5697       unsigned use_wid = size_->test_width(des, scope, mode);
5698       NetExpr*size = size_->elaborate_expr(des, scope, use_wid, flags);
5699       NetExpr*init_val = 0;
5700 
5701       if (dynamic_cast<PEAssignPattern*> (init_)) {
5702 	      // Special case: the initial value expression is an
5703 	      // array_pattern. Elaborate the expression like the
5704 	      // r-value to an assignment to array.
5705 	    init_val = init_->elaborate_expr(des, scope, ntype, flags);
5706 
5707       } else if (init_) {
5708 	      // Regular case: The initial value is an
5709 	      // expression. Elaborate the expression as an element
5710 	      // type. The run-time will assign this value to each element.
5711 	    const netarray_t*array_type = dynamic_cast<const netarray_t*> (ntype);
5712 
5713 	    init_val = init_->elaborate_expr(des, scope, array_type, flags);
5714       }
5715 
5716       NetENew*tmp = new NetENew(ntype, size, init_val);
5717       tmp->set_line(*this);
5718 
5719       return tmp;
5720 }
5721 
elaborate_expr(Design * des,NetScope *,unsigned,unsigned) const5722 NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*, unsigned, unsigned) const
5723 {
5724       cerr << get_fileline() << ": error: The new array constructor may "
5725               "only be used in an assignment to a dynamic array." << endl;
5726       des->errors += 1;
5727       return 0;
5728 }
5729 
test_width(Design *,NetScope *,width_mode_t &)5730 unsigned PENewClass::test_width(Design*, NetScope*, width_mode_t&)
5731 {
5732       expr_type_  = IVL_VT_CLASS;
5733       expr_width_ = 1;
5734       min_width_  = 1;
5735       signed_flag_= false;
5736       return 1;
5737 }
5738 
5739 /*
5740  * This elaborates the constructor for a class. This arranges for the
5741  * call of class constructor, if present, and also
5742  * initializers in front of an explicit constructor.
5743  *
5744  * The derived argument is the type of the class derived from the
5745  * current one. This is used to get chained constructor arguments, if necessary.
5746  */
elaborate_expr_constructor_(Design * des,NetScope * scope,const netclass_t * ctype,NetExpr * obj,unsigned) const5747 NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
5748 						 const netclass_t*ctype,
5749 						 NetExpr*obj, unsigned /*flags*/) const
5750 {
5751       ivl_assert(*this, ctype);
5752 
5753 	// If there is an initializer function, then pass the object
5754 	// through that function first. Note that the initializer
5755 	// function has no arguments other than the object itself.
5756       if (NetScope*new1_scope = ctype->method_from_name(perm_string::literal("new@"))) {
5757 	    NetFuncDef*def1 = new1_scope->func_def();
5758 	    ivl_assert(*this, def1);
5759 	    ivl_assert(*this, def1->port_count()==1);
5760 	    vector<NetExpr*> parms1 (1);
5761 	    parms1[0] = obj;
5762 
5763 	      // The return value of the initializer is the "this"
5764 	      // variable, instead of the "new&" scope name.
5765 	    NetNet*res1 = new1_scope->find_signal(perm_string::literal("@"));
5766 	    ivl_assert(*this, res1);
5767 
5768 	    NetESignal*eres = new NetESignal(res1);
5769 	    NetEUFunc*tmp = new NetEUFunc(scope, new1_scope, eres, parms1, true);
5770 	    tmp->set_line(*this);
5771 	    obj = tmp;
5772       }
5773 
5774 
5775       NetScope*new_scope = ctype->method_from_name(perm_string::literal("new"));
5776       if (new_scope == 0) {
5777 	      // No constructor.
5778 	    if (parms_.size() > 0) {
5779 		  cerr << get_fileline() << ": error: "
5780 		       << "Class " << ctype->get_name()
5781 		       << " has no constructor, but you passed " << parms_.size()
5782 		       << " arguments to the new operator." << endl;
5783 		  des->errors += 1;
5784 	    }
5785 	    return obj;
5786       }
5787 
5788 
5789       NetFuncDef*def = new_scope->func_def();
5790       if (def == 0) {
5791 	    cerr << get_fileline() << ": internal error: "
5792 		 << "Scope " << scope_path(new_scope)
5793 		 << " is missing constructor definition." << endl;
5794 	    des->errors += 1;
5795       }
5796       ivl_assert(*this, def);
5797 
5798 	// Are there too many arguments passed to the function. If so,
5799 	// generate an error message. The case of too few arguments
5800 	// will be handled below, when we run out of arguments.
5801       if ((parms_.size()+1) > def->port_count()) {
5802 	    cerr << get_fileline() << ": error: Parm count mismatch"
5803 		 << " passing " << parms_.size() << " arguments "
5804 		 << " to constructor expecting " << (def->port_count()-1)
5805 		 << " arguments." << endl;
5806 	    des->errors += 1;
5807       }
5808 
5809       vector<NetExpr*> parms (def->port_count());
5810       parms[0] = obj;
5811 
5812       int missing_parms = 0;
5813       int parm_errors = 0;
5814       for (size_t idx = 1 ; idx < parms.size() ; idx += 1) {
5815 	      // While there are default arguments, check them.
5816 	    if (idx <= parms_.size() && parms_[idx-1]) {
5817 		  PExpr*tmp = parms_[idx-1];
5818 		  parms[idx] = elaborate_rval_expr(des, scope,
5819 						   def->port(idx)->net_type(),
5820 						   def->port(idx)->data_type(),
5821 						   def->port(idx)->vector_width(),
5822 						   tmp, false);
5823 		  if (parms[idx] == 0)
5824 			parm_errors += 1;
5825 
5826 		  continue;
5827 	    }
5828 
5829 	      // Ran out of explicit arguments. Is there a default
5830 	      // argument we can use?
5831 	    if (NetExpr*tmp = def->port_defe(idx)) {
5832 		  parms[idx] = tmp;
5833 		  continue;
5834 	    }
5835 
5836 	      // If we run out of passed expressions, and there is no
5837 	      // default value for this port, then we will need to
5838 	      // report an error that we are missing parameters.
5839 	    missing_parms += 1;
5840 	    parms[idx] = 0;
5841       }
5842 
5843       if (missing_parms > 0) {
5844 	    cerr << get_fileline() << ": error: The " << scope_path(new_scope)
5845 		 << " constructor call is missing arguments." << endl;
5846 	    parm_errors += 1;
5847 	    des->errors += 1;
5848       }
5849 
5850 	// The return value for the constructor is actually the "this"
5851 	// variable, instead of the "new" scope name.
5852       NetNet*res = new_scope->find_signal(perm_string::literal("@"));
5853       ivl_assert(*this, res);
5854 
5855       NetESignal*eres = new NetESignal(res);
5856       NetEUFunc*con = new NetEUFunc(scope, new_scope, eres, parms, true);
5857       con->set_line(*this);
5858 
5859       return con;
5860 }
5861 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t ntype,unsigned flags) const5862 NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
5863 				    ivl_type_t ntype, unsigned flags) const
5864 {
5865       NetExpr*obj = new NetENew(ntype);
5866       obj->set_line(*this);
5867 
5868 	// Find the constructor for the class. If there is no
5869 	// constructor then the result of this expression is the
5870 	// allocation alone.
5871       const netclass_t*ctype = dynamic_cast<const netclass_t*> (ntype);
5872 
5873       obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags);
5874       return obj;
5875 }
5876 
test_width(Design *,NetScope *,width_mode_t &)5877 unsigned PENewCopy::test_width(Design*, NetScope*, width_mode_t&)
5878 {
5879       expr_type_  = IVL_VT_CLASS;
5880       expr_width_ = 1;
5881       min_width_  = 1;
5882       signed_flag_= false;
5883       return 1;
5884 }
5885 
elaborate_expr(Design * des,NetScope * scope,ivl_type_t obj_type,unsigned) const5886 NetExpr* PENewCopy::elaborate_expr(Design*des, NetScope*scope, ivl_type_t obj_type, unsigned) const
5887 {
5888       NetExpr*copy_arg = src_->elaborate_expr(des, scope, obj_type, 0);
5889       if (copy_arg == 0)
5890 	    return 0;
5891 
5892       NetENew*obj_new = new NetENew(obj_type);
5893       obj_new->set_line(*this);
5894 
5895       NetEShallowCopy*copy = new NetEShallowCopy(obj_new, copy_arg);
5896       copy->set_line(*this);
5897 
5898       return copy;
5899 }
5900 
5901 /*
5902  * A "null" expression represents class objects/handles. This brings
5903  * up a ton of special cases, but we handle it here by setting the
5904  * expr_type_ and expr_width_ to fixed values.
5905  */
test_width(Design *,NetScope *,width_mode_t &)5906 unsigned PENull::test_width(Design*, NetScope*, width_mode_t&)
5907 {
5908       expr_type_   = IVL_VT_CLASS;
5909       expr_width_  = 1;
5910       min_width_   = 1;
5911       signed_flag_ = false;
5912       return expr_width_;
5913 }
5914 
elaborate_expr(Design *,NetScope *,ivl_type_t,unsigned) const5915 NetExpr* PENull::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned) const
5916 {
5917       NetENull*tmp = new NetENull;
5918       tmp->set_line(*this);
5919       return tmp;
5920 }
5921 
elaborate_expr(Design *,NetScope *,unsigned,unsigned) const5922 NetExpr* PENull::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
5923 {
5924       NetENull*tmp = new NetENull;
5925       tmp->set_line(*this);
5926       return tmp;
5927 }
5928 
test_width(Design *,NetScope *,width_mode_t & mode)5929 unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
5930 {
5931       expr_type_   = IVL_VT_LOGIC;
5932       expr_width_  = value_->len();
5933       min_width_   = expr_width_;
5934       signed_flag_ = value_->has_sign();
5935 
5936       if (!value_->has_len() && !value_->is_single()) {
5937             if (gn_strict_expr_width_flag) {
5938                   expr_width_ = integer_width;
5939                   mode = UNSIZED;
5940             } else if (mode < LOSSLESS) {
5941 		  if (expr_width_ < integer_width) {
5942 			expr_width_ = integer_width;
5943 			if (mode < UNSIZED)
5944 			      mode = UNSIZED;
5945 		  } else {
5946 			mode = LOSSLESS;
5947 		  }
5948             }
5949       }
5950 
5951       if (debug_elaborate) {
5952 	    cerr << get_fileline() << ": PENumber::test_width: "
5953 		 << "Value=" << *value_
5954 		 << ", width=" << expr_width_
5955 		 << ", output mode=" << width_mode_name(mode) << endl;
5956       }
5957 
5958       return expr_width_;
5959 }
5960 
elaborate_expr(Design * des,NetScope *,ivl_type_t ntype,unsigned) const5961 NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const
5962 {
5963         // Icarus allows dynamic arrays to be initialised with a single value.
5964       if (const netdarray_t*array_type = dynamic_cast<const netdarray_t*> (ntype))
5965             ntype = array_type->element_type();
5966 
5967       const netvector_t*use_type = dynamic_cast<const netvector_t*> (ntype);
5968       if (use_type == 0) {
5969 	    cerr << get_fileline() << ": internal error: "
5970 		 << "I don't know how cast numbers to this type."
5971 		 << endl;
5972 	    des->errors += 1;
5973 	    return 0;
5974       }
5975 
5976 	// Special case: If the context type is REAL, then cast the
5977 	// vector value to a real and return a NetECReal.
5978       if (ntype->base_type() == IVL_VT_REAL) {
5979 	    verireal val (value_->as_long());
5980 	    NetECReal*tmp = new NetECReal(val);
5981 	    tmp->set_line(*this);
5982 	    return tmp;
5983       }
5984 
5985       verinum use_val = value();
5986       use_val .has_sign( use_type->get_signed() );
5987       use_val = cast_to_width(use_val, use_type->packed_width());
5988 
5989       NetEConst*tmp = new NetEConst(use_val);
5990       tmp->set_line(*this);
5991 
5992       return tmp;
5993 }
5994 
elaborate_expr(Design *,NetScope *,unsigned expr_wid,unsigned) const5995 NetEConst* PENumber::elaborate_expr(Design*, NetScope*,
5996 				    unsigned expr_wid, unsigned) const
5997 {
5998       assert(value_);
5999       verinum val = *value_;
6000       if (val.has_len())
6001             val.has_sign(signed_flag_);
6002       val = cast_to_width(val, expr_wid);
6003       NetEConst*tmp = new NetEConst(val);
6004       tmp->cast_signed(signed_flag_);
6005       tmp->set_line(*this);
6006 
6007       return tmp;
6008 }
6009 
test_width(Design *,NetScope *,width_mode_t &)6010 unsigned PEString::test_width(Design*, NetScope*, width_mode_t&)
6011 {
6012       expr_type_   = IVL_VT_BOOL;
6013       expr_width_  = text_ ? verinum(text_).len() : 0;
6014       min_width_   = expr_width_;
6015       signed_flag_ = false;
6016 
6017       return expr_width_;
6018 }
6019 
elaborate_expr(Design *,NetScope *,ivl_type_t,unsigned) const6020 NetEConst* PEString::elaborate_expr(Design*, NetScope*, ivl_type_t, unsigned)const
6021 {
6022       verinum val(value());
6023       NetEConst*tmp = new NetEConst(val);
6024       tmp->cast_signed(signed_flag_);
6025       tmp->set_line(*this);
6026 
6027       return tmp;
6028 }
6029 
elaborate_expr(Design *,NetScope *,unsigned expr_wid,unsigned) const6030 NetEConst* PEString::elaborate_expr(Design*, NetScope*,
6031 				    unsigned expr_wid, unsigned) const
6032 {
6033       verinum val(value());
6034       val = pad_to_width(val, expr_wid);
6035       NetEConst*tmp = new NetEConst(val);
6036       tmp->cast_signed(signed_flag_);
6037       tmp->set_line(*this);
6038 
6039       return tmp;
6040 }
6041 
test_width(Design * des,NetScope * scope,width_mode_t & mode)6042 unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
6043 {
6044 	// The condition of the ternary is self-determined, so
6045 	// we will test its width when we elaborate it.
6046 
6047         // Test the width of the true and false clauses.
6048       unsigned tru_width = tru_->test_width(des, scope, mode);
6049 
6050       width_mode_t saved_mode = mode;
6051 
6052       unsigned fal_width = fal_->test_width(des, scope, mode);
6053 
6054         // If the width mode changed, retest the true clause, as it
6055         // may choose a different width if it is in a lossless context.
6056       if ((mode >= LOSSLESS) && (saved_mode < LOSSLESS)) {
6057 	    tru_width = tru_->test_width(des, scope, mode);
6058       }
6059 
6060 	// If either of the alternatives is IVL_VT_REAL, then the
6061 	// expression as a whole is IVL_VT_REAL. Otherwise, if either
6062 	// of the alternatives is IVL_VT_LOGIC, then the expression as
6063 	// a whole is IVL_VT_LOGIC. The fallback assumes that the
6064 	// types are the same and we take that.
6065       ivl_variable_type_t tru_type = tru_->expr_type();
6066       ivl_variable_type_t fal_type = fal_->expr_type();
6067 
6068       if (tru_type == IVL_VT_REAL || fal_type == IVL_VT_REAL) {
6069 	    expr_type_ = IVL_VT_REAL;
6070       } else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) {
6071 	    expr_type_ = IVL_VT_LOGIC;
6072       } else {
6073 	    expr_type_ = tru_type;
6074       }
6075       if (expr_type_ == IVL_VT_REAL) {
6076 	    expr_width_  = 1;
6077             min_width_   = 1;
6078             signed_flag_ = true;
6079       } else {
6080 	    expr_width_  = max(tru_width, fal_width);
6081             min_width_   = max(tru_->min_width(), fal_->min_width());
6082             signed_flag_ = tru_->has_sign() && fal_->has_sign();
6083 
6084               // If the alternatives are different types, the expression
6085               // is forced to unsigned. In this case the lossless width
6086               // calculation is unreliable and we need to make sure the
6087               // final expression width is at least integer_width.
6088             if ((mode == LOSSLESS) && (tru_->has_sign() != fal_->has_sign()))
6089                   mode = UPSIZE;
6090       }
6091 
6092       if (debug_elaborate)
6093 	    cerr << get_fileline() << ": debug: "
6094 		 << "Ternary expression type=" << expr_type_
6095 		 << ", width=" << expr_width_
6096 		 << " (tru_type=" << tru_type
6097 		 << ", fal_type=" << fal_type << ")" << endl;
6098 
6099       return fix_width_(mode);
6100 }
6101 
test_operand_compat(ivl_variable_type_t l,ivl_variable_type_t r)6102 bool NetETernary::test_operand_compat(ivl_variable_type_t l,
6103 				      ivl_variable_type_t r)
6104 {
6105       if (l == IVL_VT_LOGIC && r == IVL_VT_BOOL)
6106 	    return true;
6107       if (l == IVL_VT_BOOL && r == IVL_VT_LOGIC)
6108 	    return true;
6109 
6110       if (l == IVL_VT_REAL && (r == IVL_VT_LOGIC || r == IVL_VT_BOOL))
6111 	    return true;
6112       if (r == IVL_VT_REAL && (l == IVL_VT_LOGIC || l == IVL_VT_BOOL))
6113 	    return true;
6114 
6115       if (l == r)
6116 	    return true;
6117 
6118       return false;
6119 }
6120 
6121 /*
6122  * Elaborate the Ternary operator. I know that the expressions were
6123  * parsed so I can presume that they exist, and call elaboration
6124  * methods. If any elaboration fails, then give up and return 0.
6125  */
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const6126 NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
6127 				  unsigned expr_wid, unsigned flags) const
6128 {
6129       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
6130 
6131       ivl_assert(*this, expr_);
6132       ivl_assert(*this, tru_);
6133       ivl_assert(*this, fal_);
6134 
6135 	// Elaborate and evaluate the condition expression. Note that
6136 	// it is always self-determined.
6137       NetExpr*con = elab_and_eval(des, scope, expr_, -1, NEED_CONST & flags);
6138       if (con == 0)
6139 	    return 0;
6140 
6141 	/* Make sure the condition expression reduces to a single bit. */
6142       con = condition_reduce(con);
6143 
6144 	// Verilog doesn't say that we must do short circuit
6145 	// evaluation of ternary expressions, but it doesn't disallow
6146 	// it. The disadvantage of doing this is that semantic errors
6147 	// in the unused clause will be missed, but people don't seem
6148 	// to mind, and do appreciate the optimization available here.
6149       if (NetEConst*tmp = dynamic_cast<NetEConst*> (con)) {
6150 	    verinum cval = tmp->value();
6151 	    ivl_assert(*this, cval.len()==1);
6152 
6153 	      // Condition is constant TRUE, so we only need the true clause.
6154 	    if (cval.get(0) == verinum::V1) {
6155 		  if (debug_elaborate)
6156 			cerr << get_fileline() << ": debug: Short-circuit "
6157 			        "elaborate TRUE clause of ternary."
6158 			     << endl;
6159 
6160 		  return elab_and_eval_alternative_(des, scope, tru_,
6161                                                     expr_wid, flags, true);
6162 	    }
6163 
6164 	      // Condition is constant FALSE, so we only need the
6165 	      // false clause.
6166 	    if (cval.get(0) == verinum::V0) {
6167 		  if (debug_elaborate)
6168 			cerr << get_fileline() << ": debug: Short-circuit "
6169 			        "elaborate FALSE clause of ternary."
6170 			<< endl;
6171 
6172 		  return elab_and_eval_alternative_(des, scope, fal_,
6173                                                     expr_wid, flags, true);
6174 	    }
6175 
6176 	      // X and Z conditions need to blend both results, so we
6177 	      // can't short-circuit.
6178       }
6179 
6180       NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_,
6181 					       expr_wid, flags, false);
6182       if (tru == 0) {
6183 	    delete con;
6184 	    return 0;
6185       }
6186 
6187       NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_,
6188 					       expr_wid, flags, false);
6189       if (fal == 0) {
6190 	    delete con;
6191 	    delete tru;
6192 	    return 0;
6193       }
6194 
6195       if (! NetETernary::test_operand_compat(tru->expr_type(), fal->expr_type())) {
6196 	    cerr << get_fileline() << ": error: Data types "
6197 		 << tru->expr_type() << " and "
6198 		 << fal->expr_type() << " of ternary"
6199 		 << " do not match." << endl;
6200 	    des->errors += 1;
6201 	    return 0;
6202       }
6203 
6204       NetETernary*res = new NetETernary(con, tru, fal, expr_wid, signed_flag_);
6205       res->set_line(*this);
6206       return res;
6207 }
6208 
6209 /*
6210  * When elaborating the true or false alternative expression of a
6211  * ternary, take into account the overall expression type. If the type
6212  * is not vectorable, then the alternative expression is evaluated as
6213  * self-determined.
6214  */
elab_and_eval_alternative_(Design * des,NetScope * scope,PExpr * expr,unsigned expr_wid,unsigned flags,bool short_cct) const6215 NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
6216 					       PExpr*expr, unsigned expr_wid,
6217                                                unsigned flags, bool short_cct) const
6218 {
6219       int context_wid = expr_wid;
6220       if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) {
6221 	    expr_wid = expr->expr_width();
6222             context_wid = -1;
6223       } else {
6224             expr->cast_signed(signed_flag_);
6225       }
6226       NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, flags);
6227       if (tmp == 0) return 0;
6228 
6229       if (short_cct && (expr_type_ == IVL_VT_REAL)
6230           && (expr->expr_type() != IVL_VT_REAL))
6231 	    tmp = cast_to_real(tmp);
6232 
6233       eval_expr(tmp, context_wid);
6234 
6235       return tmp;
6236 }
6237 
6238 /*
6239  * A typename expression is only legal in very narrow cases. This is
6240  * just a placeholder.
6241  */
test_width(Design * des,NetScope *,width_mode_t &)6242 unsigned PETypename::test_width(Design*des, NetScope*, width_mode_t&)
6243 {
6244       cerr << get_fileline() << ": error: "
6245 	   << "Type names are not valid expressions here." << endl;
6246       des->errors += 1;
6247 
6248       expr_type_   = IVL_VT_NO_TYPE;
6249       expr_width_  = 1;
6250       min_width_   = 1;
6251       signed_flag_ = false;
6252       return expr_width_;
6253 }
6254 
elaborate_expr(Design * des,NetScope *,ivl_type_t,unsigned) const6255 NetExpr*PETypename::elaborate_expr(Design*des, NetScope*,
6256 				   ivl_type_t, unsigned) const
6257 {
6258       cerr << get_fileline() << ": error: Type name not a valid expression here." << endl;
6259       des->errors += 1;
6260       return 0;
6261 }
6262 
test_width(Design * des,NetScope * scope,width_mode_t & mode)6263 unsigned PEUnary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
6264 {
6265       switch (op_) {
6266 	  case '&': // Reduction AND
6267 	  case '|': // Reduction OR
6268 	  case '^': // Reduction XOR
6269 	  case 'A': // Reduction NAND (~&)
6270 	  case 'N': // Reduction NOR (~|)
6271 	  case 'X': // Reduction NXOR (~^)
6272 	  case '!':
6273 	    {
6274 		  width_mode_t sub_mode = SIZED;
6275 		  unsigned sub_width = expr_->test_width(des, scope, sub_mode);
6276 
6277 		  expr_type_   = expr_->expr_type();
6278 	          expr_width_  = 1;
6279 	          min_width_   = 1;
6280                   signed_flag_ = false;
6281 
6282                   if ((op_ == '!') && (expr_type_ != IVL_VT_BOOL))
6283                         expr_type_ = IVL_VT_LOGIC;
6284 
6285 		  if (debug_elaborate)
6286 			cerr << get_fileline() << ": debug: "
6287 			     << "Test width of sub-expression of " << op_
6288 			     << " returns " << sub_width << "." << endl;
6289 
6290 	    }
6291             return expr_width_;
6292       }
6293 
6294       expr_width_  = expr_->test_width(des, scope, mode);
6295       expr_type_   = expr_->expr_type();
6296       min_width_   = expr_->min_width();
6297       signed_flag_ = expr_->has_sign();
6298 
6299       return fix_width_(mode);
6300 }
6301 
6302 
elaborate_expr(Design * des,NetScope * scope,unsigned expr_wid,unsigned flags) const6303 NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
6304 				 unsigned expr_wid, unsigned flags) const
6305 {
6306       flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
6307       ivl_variable_type_t t;
6308 
6309       unsigned sub_width = expr_wid;
6310       switch (op_) {
6311             // Reduction operators and ! always have a self determined width.
6312 	  case '!':
6313 	  case '&': // Reduction AND
6314 	  case '|': // Reduction OR
6315 	  case '^': // Reduction XOR
6316 	  case 'A': // Reduction NAND (~&)
6317 	  case 'N': // Reduction NOR (~|)
6318 	  case 'X': // Reduction NXOR (~^)
6319 	    sub_width = expr_->expr_width();
6320 	    break;
6321 
6322             // Other operators have context determined operands, so propagate
6323             // the expression type (signed/unsigned) down to the operands.
6324 	  default:
6325             expr_->cast_signed(signed_flag_);
6326 	    break;
6327       }
6328       NetExpr*ip = expr_->elaborate_expr(des, scope, sub_width, flags);
6329       if (ip == 0) return 0;
6330 
6331       ivl_assert(*expr_, expr_type_ != IVL_VT_NO_TYPE);
6332 
6333       NetExpr*tmp;
6334       switch (op_) {
6335 	  case 'i':
6336 	  case 'I':
6337 	  case 'D':
6338 	  case 'd':
6339 		t = ip->expr_type();
6340 		if (expr_wid != expr_->expr_width()) {
6341 			/*
6342 			 * TODO: Need to modify draw_unary_expr() to support
6343 			 * increment/decrement operations on slice of vector.
6344 			 */
6345 			cerr << get_fileline() << ": sorry: "
6346 				<< human_readable_op(op_, true)
6347 				<< " operation is not yet supported on "
6348 				<< "vector slice." << endl;
6349 			des->errors += 1;
6350 			return 0;
6351 		} else if (t == IVL_VT_LOGIC || t == IVL_VT_BOOL ||
6352 				t == IVL_VT_REAL) {
6353 
6354 			if (dynamic_cast<NetEConst *> (ip) ||
6355 				dynamic_cast<NetECReal*> (ip)) {
6356 				/*
6357 				 * invalid operand: operand is a constant
6358 				 * or real number
6359 				 */
6360 				cerr << get_fileline() << ": error: "
6361 					<< "inappropriate use of "
6362 					<< human_readable_op(op_, true)
6363 					<< " operator." << endl;
6364 				des->errors += 1;
6365 				return 0;
6366 			}
6367 
6368 			/*
6369 			 * **** Valid use of operator ***
6370 			 * For REAL variables draw_unary_real() is invoked during
6371 			 * evaluation and for LOGIC/BOOLEAN draw_unary_expr()
6372 			 * is called for evaluation.
6373 			 */
6374 			tmp = new NetEUnary(op_, ip, expr_wid, signed_flag_);
6375 			tmp->set_line(*this);
6376 		} else {
6377 			cerr << get_fileline() << ": error: "
6378 				<< "inappropriate use of "
6379 				<< human_readable_op(op_, true)
6380 				<< " operator." << endl;
6381 			des->errors += 1;
6382 			return 0;
6383 		}
6384 		break;
6385 
6386 	  default:
6387 	    tmp = new NetEUnary(op_, ip, expr_wid, signed_flag_);
6388 	    tmp->set_line(*this);
6389 	    break;
6390 
6391 	  case '-':
6392 	    if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
6393 
6394 		  verinum val = - ipc->value();
6395 		  tmp = new NetEConst(val);
6396 		  tmp->cast_signed(signed_flag_);
6397 		  tmp->set_line(*this);
6398 		  delete ip;
6399 
6400 	    } else if (NetECReal*ipr = dynamic_cast<NetECReal*>(ip)) {
6401 
6402 		    /* When taking the - of a real, fold this into the
6403 		       constant value. */
6404 		  verireal val = - ipr->value();
6405 		  tmp = new NetECReal(val);
6406 		  tmp->set_line(*this);
6407 		  delete ip;
6408 
6409 	    } else {
6410 		  tmp = new NetEUnary(op_, ip, expr_wid, signed_flag_);
6411 		  tmp->set_line(*this);
6412 	    }
6413 	    break;
6414 
6415 	  case '+':
6416 	    tmp = ip;
6417 	    break;
6418 
6419 	  case '!': // Logical NOT
6420 	      /* If the operand to unary ! is a constant, then I can
6421 		 evaluate this expression here and return a logical
6422 		 constant in its place. */
6423 	    if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
6424 		  verinum val = ipc->value();
6425 		  unsigned v1 = 0;
6426 		  unsigned vx = 0;
6427 		  for (unsigned idx = 0 ;  idx < val.len() ;  idx += 1)
6428 			switch (val[idx]) {
6429 			    case verinum::V0:
6430 			      break;
6431 			    case verinum::V1:
6432 			      v1 += 1;
6433 			      break;
6434 			    default:
6435 			      vx += 1;
6436 			      break;
6437 			}
6438 
6439 		  verinum::V res;
6440 		  if (v1 > 0)
6441 			res = verinum::V0;
6442 		  else if (vx > 0)
6443 			res = verinum::Vx;
6444 		  else
6445 			res = verinum::V1;
6446 
6447 		  verinum vres (res, 1, true);
6448 		  tmp = new NetEConst(vres);
6449 		  tmp->set_line(*this);
6450 		  delete ip;
6451 	    } else if (NetECReal*ipr = dynamic_cast<NetECReal*>(ip)) {
6452 		  verinum::V res;
6453 		  if (ipr->value().as_double() == 0.0) res = verinum::V1;
6454 		  else res = verinum::V0;
6455 		  verinum vres (res, 1, true);
6456 		  tmp = new NetEConst(vres);
6457 		  tmp->set_line(*this);
6458 		  delete ip;
6459 	    } else {
6460 		  if (ip->expr_type() == IVL_VT_REAL) {
6461 			tmp = new NetEBComp('e', ip,
6462 			                    new NetECReal(verireal(0.0)));
6463 		  } else {
6464 			tmp = new NetEUReduce(op_, ip);
6465 		  }
6466 		  tmp->set_line(*this);
6467 	    }
6468             tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
6469 	    break;
6470 
6471 	  case '&': // Reduction AND
6472 	  case '|': // Reduction OR
6473 	  case '^': // Reduction XOR
6474 	  case 'A': // Reduction NAND (~&)
6475 	  case 'N': // Reduction NOR (~|)
6476 	  case 'X': // Reduction NXOR (~^)
6477 	    if (ip->expr_type() == IVL_VT_REAL) {
6478 		  cerr << get_fileline() << ": error: "
6479 		       << human_readable_op(op_, true)
6480 		       << " operator may not have a REAL operand." << endl;
6481 		  des->errors += 1;
6482 		  return 0;
6483 	    }
6484 	    tmp = new NetEUReduce(op_, ip);
6485 	    tmp->set_line(*this);
6486             tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
6487 	    break;
6488 
6489 	  case '~':
6490 	    tmp = elaborate_expr_bits_(ip, expr_wid);
6491 	    break;
6492       }
6493 
6494       return tmp;
6495 }
6496 
elaborate_expr_bits_(NetExpr * operand,unsigned expr_wid) const6497 NetExpr* PEUnary::elaborate_expr_bits_(NetExpr*operand, unsigned expr_wid) const
6498 {
6499 	// Handle the special case that the operand is a
6500 	// constant. Simply calculate the constant results of the
6501 	// expression and return that.
6502       if (NetEConst*ctmp = dynamic_cast<NetEConst*> (operand)) {
6503 	    verinum value = ctmp->value();
6504 
6505 	      // The only operand that I know can get here is the
6506 	      // unary not (~).
6507 	    ivl_assert(*this, op_ == '~');
6508 	    value = ~value;
6509 
6510 	    ctmp = new NetEConst(value);
6511 	    ctmp->set_line(*this);
6512 	    delete operand;
6513 	    return ctmp;
6514       }
6515 
6516       NetEUBits*tmp = new NetEUBits(op_, operand, expr_wid, signed_flag_);
6517       tmp->set_line(*this);
6518       return tmp;
6519 }
6520 
elaborate_expr(Design *,NetScope *,unsigned,unsigned) const6521 NetExpr* PEVoid::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
6522 {
6523       return 0;
6524 }
6525 
find_discipline_reference(ivl_discipline_t dis,NetScope * scope)6526 NetNet* Design::find_discipline_reference(ivl_discipline_t dis, NetScope*scope)
6527 {
6528       NetNet*gnd = discipline_references_[dis->name()];
6529 
6530       if (gnd) return gnd;
6531 
6532       string name = string(dis->name()) + "$gnd";
6533       netvector_t*gnd_vec = new netvector_t(IVL_VT_REAL,0,0);
6534       gnd = new NetNet(scope, lex_strings.make(name), NetNet::WIRE, gnd_vec);
6535       gnd->set_discipline(dis);
6536       discipline_references_[dis->name()] = gnd;
6537 
6538       if (debug_elaborate)
6539 	    cerr << gnd->get_fileline() << ": debug: "
6540 		 << "Create an implicit reference terminal"
6541 		 << " for discipline=" << dis->name()
6542 		 << " in scope=" << scope_path(scope) << endl;
6543 
6544       return gnd;
6545 }
6546