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