1 /*
2 * Copyright (c) 1999-2020 Stephen Williams (steve@icarus.com)
3 *
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "config.h"
21 # include "compiler.h"
22
23 # include <iostream>
24 # include <cstdlib>
25 # include <cstring>
26 # include <cmath>
27
28 # include "netlist.h"
29 # include "ivl_assert.h"
30 # include "netmisc.h"
31
eval_tree()32 NetExpr* NetExpr::eval_tree()
33 {
34 return 0;
35 }
36
eval_debug(const NetExpr * expr,NetExpr * res,bool is_real)37 static void eval_debug(const NetExpr*expr, NetExpr*res, bool is_real)
38 {
39 if (res != 0) {
40 res->set_line(*expr);
41 if (debug_eval_tree) {
42 cerr << expr->get_fileline() << ": debug: Evaluated";
43 if (is_real) cerr << " (real)";
44 cerr << ": " << *expr << " --> " << *res << endl;
45 }
46 }
47 }
48
get_real_arg_(const NetExpr * expr,verireal & val)49 static bool get_real_arg_(const NetExpr*expr, verireal&val)
50 {
51 switch (expr->expr_type()) {
52 case IVL_VT_REAL: {
53 const NetECReal*c = dynamic_cast<const NetECReal*> (expr);
54 if (c == 0) return false;
55 val = c->value();
56 break;
57 }
58
59 case IVL_VT_BOOL:
60 case IVL_VT_LOGIC: {
61 const NetEConst*c = dynamic_cast<const NetEConst*>(expr);
62 if (c == 0) return false;
63 verinum tmp = c->value();
64 val = verireal(tmp.as_double());
65 break;
66 }
67
68 case IVL_VT_DARRAY:
69 return false;
70
71 default:
72 assert(0);
73 }
74
75 return true;
76 }
77
get_real_arguments(const NetExpr * le,const NetExpr * re,double & lval,double & rval)78 static bool get_real_arguments(const NetExpr*le, const NetExpr*re,
79 double&lval, double&rval)
80 {
81 verireal val;
82
83 if (!get_real_arg_(le, val)) return false;
84 lval = val.as_double();
85
86 if (!get_real_arg_(re, val)) return false;
87 rval = val.as_double();
88
89 return true;
90 }
91
eval_tree()92 NetExpr* NetEBinary::eval_tree()
93 {
94 eval_expr(left_);
95 eval_expr(right_);
96
97 return eval_arguments_(left_, right_);
98 }
99
eval_arguments_(const NetExpr *,const NetExpr *) const100 NetExpr* NetEBinary::eval_arguments_(const NetExpr*, const NetExpr*) const
101 {
102 // this method should be overridden in all sub-classes
103 ivl_assert(*this, 0);
104 return 0;
105 }
106
eval_tree_real_(const NetExpr * l,const NetExpr * r) const107 NetECReal* NetEBAdd::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
108 {
109 double lval;
110 double rval;
111
112 bool flag = get_real_arguments(l, r, lval, rval);
113 if (!flag) return 0;
114
115 double res_val;
116
117 switch (op()) {
118 case '+':
119 res_val = lval + rval;
120 break;
121 case '-':
122 res_val = lval - rval;
123 break;
124 default:
125 ivl_assert(*this, 0);
126 }
127
128 NetECReal*res = new NetECReal( verireal(res_val) );
129 ivl_assert(*this, res);
130 eval_debug(this, res, true);
131 return res;
132 }
133
eval_tree()134 NetExpr* NetEBAdd::eval_tree()
135 {
136 eval_expr(left_);
137 eval_expr(right_);
138
139 // First try to elaborate the expression completely.
140 NetExpr*res = eval_arguments_(left_,right_);
141 if (res != 0) return res;
142
143 // If the expression type is real, then do not attempt the
144 // following alternative processing.
145 if (expr_type() == IVL_VT_REAL)
146 return 0;
147
148 // The expression has not evaluated to a constant. Let's still
149 // try to optimize by trying to combine a right constant value
150 // with the right constant value of a sub-expression add. For
151 // example, the expression (a + 2) - 1 can be rewritten as a + 1.
152
153 NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
154 NetEConst*lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
155 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
156
157 if (lc != 0 && rc != 0) {
158 ivl_assert(*this, se != 0);
159
160 if (debug_eval_tree) {
161 cerr << get_fileline() << ": debug: "
162 << "Partially evaluate " << *this
163 << " using (a+2)-1 --> (a+1) transform." << endl;
164 }
165
166 verinum lval = lc->value();
167 verinum rval = rc->value();
168
169 unsigned wid = expr_width();
170 ivl_assert(*this, wid > 0);
171 ivl_assert(*this, lval.len() == wid);
172 ivl_assert(*this, rval.len() == wid);
173
174 verinum val;
175 if (op_ == se->op_) {
176 /* (a + lval) + rval --> a + (rval+lval) */
177 /* (a - lval) - rval --> a - (rval+lval) */
178 val = cast_to_width(rval + lval, wid);
179 } else {
180 /* (a - lval) + rval --> a + (rval-lval) */
181 /* (a + lval) - rval --> a - (rval-lval) */
182 val = cast_to_width(rval - lval, wid);
183 }
184
185 NetEConst*tmp = new NetEConst(val);
186 left_ = se->left_->dup_expr();
187 delete se;
188 tmp->set_line(*right_);
189 delete right_;
190 right_ = tmp;
191 }
192
193 // We may have changed the subexpression, but the result is
194 // still not constant, so return nil here anyhow.
195 return 0;
196 }
197
eval_arguments_(const NetExpr * l,const NetExpr * r) const198 NetExpr* NetEBAdd::eval_arguments_(const NetExpr*l, const NetExpr*r) const
199 {
200 if (expr_type() == IVL_VT_REAL)
201 return eval_tree_real_(l,r);
202
203 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
204 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
205
206 /* If both operands are constant, then replace the entire
207 expression with a constant value. */
208 if (lc != 0 && rc != 0) {
209 verinum lval = lc->value();
210 verinum rval = rc->value();
211
212 unsigned wid = expr_width();
213 ivl_assert(*this, wid > 0);
214 ivl_assert(*this, lval.len() == wid);
215 ivl_assert(*this, rval.len() == wid);
216
217 verinum val;
218 switch (op_) {
219 case '+':
220 val = cast_to_width(lval + rval, wid);
221 break;
222 case '-':
223 val = cast_to_width(lval - rval, wid);
224 break;
225 default:
226 return 0;
227 }
228
229 NetEConst *res = new NetEConst(val);
230 ivl_assert(*this, res);
231 eval_debug(this, res, false);
232 return res;
233 }
234
235
236 /* Nothing more to be done, the value is not constant. */
237 return 0;
238 }
239
eval_arguments_(const NetExpr * l,const NetExpr * r) const240 NetEConst* NetEBBits::eval_arguments_(const NetExpr*l, const NetExpr*r) const
241 {
242 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
243 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
244 if (lc == 0 || rc == 0) return 0;
245
246 /* Notice the special case where one of the operands is 0 and
247 this is a bitwise &. If this happens, then the result is
248 known to be 0. */
249 if ((op() == '&') && (lc->value() == verinum(0))) {
250 verinum res (verinum::V0, expr_width());
251 res.has_sign(has_sign());
252 NetEConst*tmp = new NetEConst(res);
253 ivl_assert(*this, tmp);
254 eval_debug(this, tmp, false);
255 return tmp;
256 }
257
258 if ((op() == '&') && (rc->value() == verinum(0))) {
259 verinum res (verinum::V0, expr_width());
260 res.has_sign(has_sign());
261 NetEConst*tmp = new NetEConst(res);
262 ivl_assert(*this, tmp);
263 eval_debug(this, tmp, false);
264 return tmp;
265 }
266
267 verinum lval = lc->value();
268 verinum rval = rc->value();
269
270 unsigned wid = expr_width();
271 ivl_assert(*this, wid > 0);
272 ivl_assert(*this, lval.len() == wid);
273 ivl_assert(*this, rval.len() == wid);
274
275 verinum res (verinum::V0, wid);
276
277 switch (op()) {
278
279 case '|': {
280 for (unsigned idx = 0 ; idx < wid ; idx += 1)
281 res.set(idx, lval.get(idx) | rval.get(idx));
282
283 break;
284 }
285
286 case '&': {
287 for (unsigned idx = 0 ; idx < wid ; idx += 1)
288 res.set(idx, lval.get(idx) & rval.get(idx));
289
290 break;
291 }
292
293 case 'X': {
294 for (unsigned idx = 0 ; idx < wid ; idx += 1)
295 res.set(idx, ~(lval.get(idx) ^ rval.get(idx)));
296
297 break;
298 }
299
300 case '^': {
301 for (unsigned idx = 0 ; idx < wid ; idx += 1)
302 res.set(idx, lval.get(idx) ^ rval.get(idx));
303
304 break;
305 }
306
307 default:
308 return 0;
309 }
310
311 res.has_sign(has_sign());
312 NetEConst*tmp = new NetEConst(res);
313 ivl_assert(*this, tmp);
314 eval_debug(this, tmp, false);
315 return tmp;
316 }
317
eval_less_(const NetExpr * le,const NetExpr * re) const318 NetEConst* NetEBComp::eval_less_(const NetExpr*le, const NetExpr*re) const
319 {
320 if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
321 return eval_leeq_real_(le, re, false);
322
323 const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
324 if (rc == 0) return 0;
325
326 verinum rv = rc->value();
327 if (! rv.is_defined()) {
328 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
329 ivl_assert(*this, res);
330 return res;
331 }
332
333 if (NetEConst*tmp = must_be_leeq_(le, rv, false)) {
334 return tmp;
335 }
336
337 /* Now go on to the normal test of the values. */
338 const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
339 if (lc == 0) return 0;
340
341 verinum lv = lc->value();
342 if (! lv.is_defined()) {
343 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
344 ivl_assert(*this, res);
345 return res;
346 }
347
348 if (lv < rv) {
349 NetEConst*res = new NetEConst(verinum(verinum::V1, 1));
350 ivl_assert(*this, res);
351 return res;
352 } else {
353 NetEConst*res = new NetEConst(verinum(verinum::V0, 1));
354 ivl_assert(*this, res);
355 return res;
356 }
357 }
358
must_be_leeq_(const NetExpr * le,const verinum & rv,bool eq_flag) const359 NetEConst* NetEBComp::must_be_leeq_(const NetExpr*le, const verinum&rv, bool eq_flag) const
360 {
361 // The following optimization is not valid if le can contain 'x'
362 // or 'z' values.
363 if (le->expr_type() == IVL_VT_LOGIC) return 0;
364
365 assert(le->expr_width() > 0);
366 verinum lv (verinum::V1, le->expr_width());
367 if (le->has_sign() && rv.has_sign()) {
368 // If the expression is signed, then the largest
369 // possible value for the left_ needs to have a 0 in the
370 // sign position.
371 lv.set(lv.len()-1, verinum::V0);
372 lv.has_sign(true);
373 }
374
375 if (lv < rv || (eq_flag && (lv == rv))) {
376 NetEConst*res = new NetEConst(verinum(verinum::V1, 1));
377 ivl_assert(*this, res);
378 return res;
379 }
380
381 return 0;
382 }
383
eval_leeq_real_(const NetExpr * le,const NetExpr * re,bool eq_flag) const384 NetEConst* NetEBComp::eval_leeq_real_(const NetExpr*le, const NetExpr*re, bool eq_flag) const
385 {
386 double lval;
387 double rval;
388
389 bool flag = get_real_arguments(le, re, lval, rval);
390 if (! flag) return 0;
391
392 bool tmp = false;
393 if (lval < rval) tmp = true;
394 if (tmp == false && eq_flag && lval == rval) tmp = true;
395
396 verinum result(tmp ? verinum::V1 : verinum::V0, 1);
397 NetEConst*res = new NetEConst(result);
398 ivl_assert(*this, res);
399
400 return res;
401 }
402
eval_leeq_(const NetExpr * le,const NetExpr * re) const403 NetEConst* NetEBComp::eval_leeq_(const NetExpr*le, const NetExpr*re) const
404 {
405 if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
406 return eval_leeq_real_(le, re, true);
407 // assert(expr_type() == IVL_VT_LOGIC);
408
409 const NetEConst*r = dynamic_cast<const NetEConst*>(re);
410 if (r == 0) return 0;
411
412 verinum rv = r->value();
413 if (! rv.is_defined()) {
414 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
415 ivl_assert(*this, res);
416 return res;
417 }
418
419 if (le->expr_width() == 0) {
420 cerr << get_fileline() << ": internal error: Something wrong "
421 << "with the left side width of <= ?" << endl;
422 cerr << get_fileline() << ": : " << *this << endl;
423 }
424
425 if (NetEConst*tmp = must_be_leeq_(le, rv, true)) {
426 return tmp;
427 }
428
429 /* Now go on to the normal test of the values. */
430 const NetEConst*l = dynamic_cast<const NetEConst*>(le);
431 if (l == 0) return 0;
432
433 verinum lv = l->value();
434 if (! lv.is_defined()) {
435 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
436 ivl_assert(*this, res);
437 return res;
438 }
439
440 if (lv <= rv) {
441 NetEConst*res = new NetEConst(verinum(verinum::V1, 1));
442 ivl_assert(*this, res);
443 return res;
444 } else {
445 NetEConst*res = new NetEConst(verinum(verinum::V0, 1));
446 ivl_assert(*this, res);
447 return res;
448 }
449 }
450
eval_gt_(const NetExpr * le,const NetExpr * re) const451 NetEConst* NetEBComp::eval_gt_(const NetExpr*le, const NetExpr*re) const
452 {
453 if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
454 return eval_leeq_real_(re, le, false);
455
456 const NetEConst*l = dynamic_cast<const NetEConst*>(le);
457 if (l == 0) return 0;
458
459 verinum lv = l->value();
460 if (! lv.is_defined()) {
461 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
462 ivl_assert(*this, res);
463 return res;
464 }
465
466 if (NetEConst*tmp = must_be_leeq_(re, lv, false)) {
467 return tmp;
468 }
469
470 /* Now go on to the normal test of the values. */
471 const NetEConst*r = dynamic_cast<const NetEConst*>(re);
472 if (r == 0) return 0;
473
474 verinum rv = r->value();
475 if (! rv.is_defined()) {
476 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
477 ivl_assert(*this, res);
478 return res;
479 }
480
481 if (lv > rv) {
482 NetEConst*res = new NetEConst(verinum(verinum::V1, 1));
483 ivl_assert(*this, res);
484 return res;
485 } else {
486 NetEConst*res = new NetEConst(verinum(verinum::V0, 1));
487 ivl_assert(*this, res);
488 return res;
489 }
490 }
491
eval_gteq_(const NetExpr * le,const NetExpr * re) const492 NetEConst* NetEBComp::eval_gteq_(const NetExpr*le, const NetExpr*re) const
493 {
494 if (le->expr_type() == IVL_VT_REAL || re->expr_type() == IVL_VT_REAL)
495 return eval_leeq_real_(re, le, true);
496
497 const NetEConst*l = dynamic_cast<const NetEConst*>(le);
498 if (l == 0) return 0;
499
500 verinum lv = l->value();
501 if (! lv.is_defined()) {
502 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
503 ivl_assert(*this, res);
504 return res;
505 }
506
507 if (NetEConst*tmp = must_be_leeq_(re, lv, true)) {
508 return tmp;
509 }
510
511 /* Now go on to the normal test of the values. */
512 const NetEConst*r = dynamic_cast<const NetEConst*>(re);
513 if (r == 0) return 0;
514
515 verinum rv = r->value();
516 if (! rv.is_defined()) {
517 NetEConst*res = new NetEConst(verinum(verinum::Vx, 1));
518 ivl_assert(*this, res);
519 return res;
520 }
521
522 if (lv >= rv) {
523 NetEConst*res = new NetEConst(verinum(verinum::V1, 1));
524 ivl_assert(*this, res);
525 return res;
526 } else {
527 NetEConst*res = new NetEConst(verinum(verinum::V0, 1));
528 ivl_assert(*this, res);
529 return res;
530 }
531 }
532
533 /*
534 * Evaluate <A>==<B> or <A>!=<B>. The equality operator checks all the
535 * bits and returns true(false) if there are any bits in the vector
536 * that are defined (0 or 1) and different. If all the defined bits
537 * are equal, but there are are x/z bits, then the situation is
538 * ambiguous so the result is x.
539 */
eval_eqeq_real_(bool ne_flag,const NetExpr * le,const NetExpr * re) const540 NetEConst* NetEBComp::eval_eqeq_real_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
541 {
542 double lval;
543 double rval;
544
545 bool flag = get_real_arguments(le, re, lval, rval);
546 if (! flag) return 0;
547
548 verinum result(((lval == rval) != ne_flag) ?
549 verinum::V1 : verinum::V0, 1);
550 NetEConst*res = new NetEConst(result);
551 ivl_assert(*this, res);
552
553 return res;
554 }
555
eval_eqeq_(bool ne_flag,const NetExpr * le,const NetExpr * re) const556 NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
557 {
558 if (le->expr_type() == IVL_VT_REAL ||
559 re->expr_type() == IVL_VT_REAL)
560 return eval_eqeq_real_(ne_flag, le, re);
561
562 const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
563 const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
564 if (lc == 0 || rc == 0) return 0;
565
566 const verinum&lv = lc->value();
567 const verinum&rv = rc->value();
568
569 const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
570 const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
571
572 verinum::V res = eq_res;
573
574 // The two expressions should already be padded to the same size.
575 ivl_assert(*this, lv.len() == rv.len());
576
577 for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
578
579 bool x_bit_present = false;
580
581 switch (lv.get(idx)) {
582
583 case verinum::Vx:
584 case verinum::Vz:
585 res = verinum::Vx;
586 x_bit_present = true;
587 break;
588
589 default:
590 break;
591 }
592
593 switch (rv.get(idx)) {
594
595 case verinum::Vx:
596 case verinum::Vz:
597 res = verinum::Vx;
598 x_bit_present = true;
599 break;
600
601 default:
602 break;
603 }
604
605 if (x_bit_present)
606 continue;
607
608 if (rv.get(idx) != lv.get(idx)) {
609 res = ne_res;
610 break;
611 }
612 }
613
614 NetEConst*result = new NetEConst(verinum(res, 1));
615 ivl_assert(*this, result);
616 return result;
617 }
618
eval_eqeqeq_(bool ne_flag,const NetExpr * le,const NetExpr * re) const619 NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
620 {
621 const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
622 const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
623 if (lc == 0 || rc == 0) return 0;
624
625 const verinum&lv = lc->value();
626 const verinum&rv = rc->value();
627
628 verinum::V res = verinum::V1;
629
630 // The two expressions should already be padded to the same size.
631 ivl_assert(*this, lv.len() == rv.len());
632
633 for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
634 if (lv.get(idx) != rv.get(idx)) {
635 res = verinum::V0;
636 break;
637 }
638
639 if (ne_flag) {
640 if (res == verinum::V0) res = verinum::V1;
641 else res = verinum::V0;
642 }
643
644 NetEConst*result = new NetEConst(verinum(res, 1));
645 ivl_assert(*this, result);
646 return result;
647 }
648
eval_weqeq_(bool ne_flag,const NetExpr * le,const NetExpr * re) const649 NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const
650 {
651 const NetEConst*lc = dynamic_cast<const NetEConst*>(le);
652 const NetEConst*rc = dynamic_cast<const NetEConst*>(re);
653 if (lc == 0 || rc == 0) return 0;
654
655 const verinum&lv = lc->value();
656 const verinum&rv = rc->value();
657
658 const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1;
659 const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0;
660
661 verinum::V res = eq_res;
662
663 // The two expressions should already be padded to the same size.
664 ivl_assert(*this, lv.len() == rv.len());
665
666 for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
667 // An X or Z in the R-value matches any L-value.
668 switch (rv.get(idx)) {
669 case verinum::Vx:
670 case verinum::Vz:
671 continue;
672 default:
673 break;
674 }
675
676 // An X or Z in the L-value that is not matches by an R-value X/Z returns undefined.
677 switch (lv.get(idx)) {
678 case verinum::Vx:
679 case verinum::Vz:
680 res = verinum::Vx;
681 continue;
682 default:
683 break;
684 }
685
686 // A hard (0/1) mismatch gives a not-equal result.
687 if (rv.get(idx) != lv.get(idx)) {
688 res = ne_res;
689 break;
690 }
691 }
692
693 NetEConst*result = new NetEConst(verinum(res, 1));
694 ivl_assert(*this, result);
695 return result;
696 }
697
eval_arguments_(const NetExpr * l,const NetExpr * r) const698 NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const
699 {
700 NetEConst*res = 0;
701
702 switch (op_) {
703 case 'E': // Case equality (===)
704 res = eval_eqeqeq_(false, l, r);
705 break;
706
707 case 'e': // Equality (==)
708 res = eval_eqeq_(false, l, r);
709 break;
710
711 case 'w': // Wild equality (==?)
712 res = eval_weqeq_(false, l, r);
713 break;
714
715 case 'G': // >=
716 res = eval_gteq_(l, r);
717 break;
718
719 case 'L': // <=
720 res = eval_leeq_(l, r);
721 break;
722
723 case 'N': // Case inequality (!==)
724 res = eval_eqeqeq_(true, l, r);
725 break;
726
727 case 'n': // not-equal (!=)
728 res = eval_eqeq_(true, l, r);
729 break;
730
731 case 'W': // Wild not-equal (!=?)
732 res = eval_weqeq_(true, l, r);
733 break;
734
735 case '<': // Less than
736 res = eval_less_(l, r);
737 break;
738
739 case '>': // Greater than
740 res = eval_gt_(l, r);
741 break;
742
743 }
744 eval_debug(this, res, l->expr_type() == IVL_VT_REAL ||
745 r->expr_type() == IVL_VT_REAL);
746 return res;
747 }
748
eval_tree_real_(const NetExpr * l,const NetExpr * r) const749 NetExpr* NetEBDiv::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
750 {
751 double lval;
752 double rval;
753
754 bool flag = get_real_arguments(l, r, lval, rval);
755 if (! flag) return 0;
756
757 double res_val = 0.0;
758 switch (op_) {
759 case '/':
760 res_val = lval / rval;
761 break;
762
763 case '%':
764 // Since this could/may be called early we don't want to
765 // leak functionality.
766 if (!gn_icarus_misc_flag) return 0;
767 res_val = fmod(lval, rval);
768 break;
769 }
770 NetECReal*res = new NetECReal( verireal(res_val) );
771 ivl_assert(*this, res);
772 eval_debug(this, res, true);
773 return res;
774 }
775
eval_arguments_(const NetExpr * l,const NetExpr * r) const776 NetExpr* NetEBDiv::eval_arguments_(const NetExpr*l, const NetExpr*r) const
777 {
778 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
779 assert(expr_type() == IVL_VT_LOGIC);
780
781 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
782 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
783 if (lc == 0 || rc == 0) return 0;
784
785 verinum lval = lc->value();
786 verinum rval = rc->value();
787
788 unsigned wid = expr_width();
789 ivl_assert(*this, wid > 0);
790 ivl_assert(*this, lval.len() == wid);
791 ivl_assert(*this, rval.len() == wid);
792
793 verinum val;
794 switch (op_) {
795 case '/':
796 val = cast_to_width(lval / rval, wid);
797 break;
798 case '%':
799 val = cast_to_width(lval % rval, wid);
800 break;
801 default:
802 return 0;
803 }
804
805 NetExpr*tmp = new NetEConst(val);
806 ivl_assert(*this, tmp);
807 eval_debug(this, tmp, false);
808 return tmp;
809 }
810
eval_arguments_(const NetExpr * l,const NetExpr * r) const811 NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
812 {
813 // NetEBLogic arguments should have already been reduced so real is not possible.
814 ivl_assert(*this, (l->expr_type() != IVL_VT_REAL) && (r->expr_type() != IVL_VT_REAL));
815 assert(expr_type() == IVL_VT_LOGIC);
816
817 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
818 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
819 if (lc == 0 || rc == 0) return 0;
820
821 verinum::V lv = verinum::V0;
822 verinum::V rv = verinum::V0;
823
824 verinum v = lc->value();
825 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
826 if (v.get(idx) == verinum::V1) {
827 lv = verinum::V1;
828 break;
829 }
830
831 if (lv == verinum::V0 && ! v.is_defined()) lv = verinum::Vx;
832
833 v = rc->value();
834 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
835 if (v.get(idx) == verinum::V1) {
836 rv = verinum::V1;
837 break;
838 }
839
840 if (rv == verinum::V0 && ! v.is_defined()) rv = verinum::Vx;
841
842 verinum::V res;
843 switch (op_) {
844 case 'a': // Logical AND (&&)
845 if ((lv == verinum::V0) || (rv == verinum::V0))
846 res = verinum::V0;
847 else if ((lv == verinum::V1) && (rv == verinum::V1))
848 res = verinum::V1;
849 else
850 res = verinum::Vx;
851 break;
852
853 case 'o': // Logical OR (||)
854 if ((lv == verinum::V1) || (rv == verinum::V1))
855 res = verinum::V1;
856 else if ((lv == verinum::V0) && (rv == verinum::V0))
857 res = verinum::V0;
858 else
859 res = verinum::Vx;
860 break;
861
862 case 'q': // Logical implication (->)
863 if ((lv == verinum::V0) || (rv == verinum::V1))
864 res = verinum::V1;
865 else if ((lv == verinum::V1) && (rv == verinum::V0))
866 res = verinum::V0;
867 else
868 res = verinum::Vx;
869 break;
870
871 case 'Q': // Logical equivalence (<->)
872 if (((lv == verinum::V0) && (rv == verinum::V0)) ||
873 ((lv == verinum::V1) && (rv == verinum::V1)))
874 res = verinum::V1;
875 else if (((lv == verinum::V0) && (rv == verinum::V1)) ||
876 ((lv == verinum::V1) && (rv == verinum::V0)))
877 res = verinum::V0;
878 else
879 res = verinum::Vx;
880 break;
881
882 default:
883 return 0;
884 }
885
886 NetEConst*tmp = new NetEConst(verinum(res, 1));
887 ivl_assert(*this, tmp);
888 eval_debug(this, tmp, false);
889 return tmp;
890 }
891
eval_tree_real_(const NetExpr * l,const NetExpr * r) const892 NetExpr* NetEBMinMax::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
893 {
894 double lval;
895 double rval;
896
897 bool flag = get_real_arguments(l, r, lval, rval);
898 if (! flag) return 0;
899
900 double res_val;
901 switch (op()) {
902 case 'm':
903 res_val = lval < rval ? lval : rval;
904 break;
905 case 'M':
906 res_val = lval > rval ? lval : rval;
907 break;
908 default:
909 ivl_assert(*this, 0);
910 }
911
912 NetECReal*res = new NetECReal( verireal(res_val) );
913 ivl_assert(*this, res);
914 eval_debug(this, res, true);
915 return res;
916 }
917
eval_arguments_(const NetExpr * l,const NetExpr * r) const918 NetExpr* NetEBMinMax::eval_arguments_(const NetExpr*l, const NetExpr*r) const
919 {
920 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
921 assert(expr_type() == IVL_VT_LOGIC);
922
923 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
924 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
925 if (lc == 0 || rc == 0) return 0;
926
927 verinum lval = lc->value();
928 verinum rval = rc->value();
929
930 unsigned wid = expr_width();
931 ivl_assert(*this, wid > 0);
932 ivl_assert(*this, lval.len() == wid);
933 ivl_assert(*this, rval.len() == wid);
934
935 verinum res_val;
936 if (lval.is_defined() && rval.is_defined()) {
937 switch (op()) {
938 case 'm':
939 res_val = lval < rval ? lval : rval;
940 break;
941 case 'M':
942 res_val = lval > rval ? lval : rval;
943 break;
944 default:
945 ivl_assert(*this, 0);
946 }
947 } else {
948 res_val = verinum(verinum::Vx, wid);
949 }
950 res_val.has_sign(has_sign());
951 NetEConst*res = new NetEConst(res_val);
952 ivl_assert(*this, res);
953 eval_debug(this, res, false);
954 return res;
955 }
956
eval_tree_real_(const NetExpr * l,const NetExpr * r) const957 NetExpr* NetEBMult::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
958 {
959 double lval;
960 double rval;
961
962 bool flag = get_real_arguments(l, r, lval, rval);
963 if (! flag) return 0;
964
965 NetECReal*res = new NetECReal( verireal(lval * rval) );
966 ivl_assert(*this, res);
967 eval_debug(this, res, true);
968 return res;
969 }
970
eval_arguments_(const NetExpr * l,const NetExpr * r) const971 NetExpr* NetEBMult::eval_arguments_(const NetExpr*l, const NetExpr*r) const
972 {
973 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
974 assert(expr_type() == IVL_VT_LOGIC);
975
976 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
977 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
978 if (lc == 0 || rc == 0) return 0;
979
980 verinum lval = lc->value();
981 verinum rval = rc->value();
982
983 unsigned wid = expr_width();
984 ivl_assert(*this, wid > 0);
985 ivl_assert(*this, lval.len() == wid);
986 ivl_assert(*this, rval.len() == wid);
987
988 verinum val = cast_to_width(lval * rval, wid);
989 NetEConst*tmp = new NetEConst(val);
990 ivl_assert(*this, tmp);
991 eval_debug(this, tmp, false);
992 return tmp;
993 }
994
eval_tree_real_(const NetExpr * l,const NetExpr * r) const995 NetExpr* NetEBPow::eval_tree_real_(const NetExpr*l, const NetExpr*r) const
996 {
997 double lval;
998 double rval;
999
1000 bool flag = get_real_arguments(l, r, lval, rval);
1001 if (! flag) return 0;
1002
1003 NetECReal*res = new NetECReal( verireal( pow(lval,rval) ) );
1004 ivl_assert(*this, res);
1005 eval_debug(this, res, true);
1006 return res;
1007 }
1008
eval_arguments_(const NetExpr * l,const NetExpr * r) const1009 NetExpr* NetEBPow::eval_arguments_(const NetExpr*l, const NetExpr*r) const
1010 {
1011 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(l,r);
1012 assert(expr_type() == IVL_VT_LOGIC);
1013
1014 const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
1015 const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
1016 if (lc == 0 || rc == 0) return 0;
1017
1018 verinum lval = lc->value();
1019 verinum rval = rc->value();
1020
1021 unsigned wid = expr_width();
1022 ivl_assert(*this, wid > 0);
1023 ivl_assert(*this, lval.len() == wid);
1024
1025 verinum val = cast_to_width(pow(lval, rval), wid);
1026 NetEConst*res = new NetEConst(val);
1027 ivl_assert(*this, res);
1028 eval_debug(this, res, false);
1029 return res;
1030 }
1031
eval_arguments_(const NetExpr * l,const NetExpr * r) const1032 NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const
1033 {
1034 const NetEConst*le = dynamic_cast<const NetEConst*>(l);
1035 const NetEConst*re = dynamic_cast<const NetEConst*>(r);
1036 if (le == 0 || re == 0) return 0;
1037
1038 NetEConst*res;
1039
1040 verinum lv = le->value();
1041 verinum rv = re->value();
1042
1043 unsigned wid = expr_width();
1044 ivl_assert(*this, wid > 0);
1045 ivl_assert(*this, lv.len() == wid);
1046
1047 verinum val;
1048 if (rv.is_defined()) {
1049 unsigned shift = rv.as_unsigned();
1050
1051 switch (op_) {
1052 case 'l':
1053 val = cast_to_width(lv << shift, wid);
1054 break;
1055 case 'r':
1056 lv.has_sign(false);
1057 // fallthrough
1058 case 'R':
1059 val = cast_to_width(lv >> shift, wid);
1060 break;
1061 default:
1062 return 0;
1063 }
1064 } else {
1065 val = verinum(verinum::Vx, wid);
1066 }
1067 val.has_sign(has_sign());
1068 res = new NetEConst(val);
1069 ivl_assert(*this, res);
1070 eval_debug(this, res, false);
1071 return res;
1072 }
1073
eval_tree()1074 NetEConst* NetEConcat::eval_tree()
1075 {
1076 unsigned local_errors = 0;
1077
1078 unsigned gap = 0;
1079 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
1080
1081 // Parameter not here? This is an error, but presumably
1082 // already caught and we are here just to catch more.
1083 if (parms_[idx] == 0) continue;
1084
1085 // If this parameter is already a constant, all is well
1086 // so go on.
1087 if (dynamic_cast<NetEConst*>(parms_[idx])) {
1088 gap += parms_[idx]->expr_width();
1089 continue;
1090 }
1091
1092 // Finally, try to evaluate the parameter expression
1093 // that is here. If I succeed, reset the parameter to
1094 // the evaluated value.
1095 assert(parms_[idx]);
1096 NetExpr*expr = parms_[idx]->eval_tree();
1097 if (expr) {
1098 expr->set_line(*parms_[idx]);
1099 delete parms_[idx];
1100 parms_[idx] = expr;
1101
1102 if (! expr->has_width()) {
1103 cerr << get_fileline() << ": error: concatenation "
1104 << "operand has indefinite width: "
1105 << *parms_[idx] << endl;
1106 local_errors += 1;
1107 } else if (expr->expr_width() == 0) {
1108 cerr << expr->get_fileline() << ": internal error: "
1109 << "Operand of concatenation has no width: "
1110 << *expr << endl;
1111 local_errors += 1;
1112 }
1113
1114 gap += expr->expr_width();
1115 }
1116
1117 }
1118
1119 if (local_errors > 0) return 0;
1120
1121 return eval_arguments_(parms_, gap);
1122 }
1123
eval_arguments_(const vector<NetExpr * > & vals,unsigned gap) const1124 NetEConst* NetEConcat::eval_arguments_(const vector<NetExpr*>&vals,
1125 unsigned gap) const
1126 {
1127 unsigned repeat_val = repeat();
1128
1129 // At this point, the "gap" is the width of a single repeat of
1130 // the concatenation. The total width of the result is the gap
1131 // times the repeat count.
1132 verinum val (verinum::Vx, repeat_val * gap);
1133
1134 // build up the result from least significant to most.
1135
1136 unsigned cur = 0;
1137 bool is_string_flag = true;
1138 for (unsigned idx = vals.size() ; idx > 0 ; idx -= 1) {
1139 const NetEConst*expr = dynamic_cast<NetEConst*>(vals[idx-1]);
1140 if (expr == 0)
1141 return 0;
1142
1143 verinum tmp = expr->value();
1144 for (unsigned bit = 0; bit < tmp.len(); bit += 1, cur += 1)
1145 for (unsigned rep = 0 ; rep < repeat_val ; rep += 1)
1146 val.set(rep*gap+cur, tmp[bit]);
1147
1148 is_string_flag = is_string_flag && tmp.is_string();
1149 }
1150
1151 /* If all the values were strings, then re-stringify this
1152 constant. This might be useful information in the code
1153 generator or other optimizer steps. */
1154 if (is_string_flag) {
1155 val = verinum(val.as_string());
1156 }
1157
1158 // Normally, concatenations are unsigned. However, the
1159 // $signed() function works by marking the expression as
1160 // signed, so we really have to check.
1161 val.has_sign( this->has_sign() );
1162
1163 NetEConst*res = new NetEConst(val);
1164 ivl_assert(*this, res);
1165 eval_debug(this, res, false);
1166 return res;
1167 }
1168
eval_tree()1169 NetEConst* NetESelect::eval_tree()
1170 {
1171 eval_expr(expr_);
1172 NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
1173
1174 long bval = 0;
1175 if (base_) {
1176 eval_expr(base_);
1177 NetEConst*base = dynamic_cast<NetEConst*>(base_);
1178
1179 if (base == 0) return 0;
1180
1181 bval = base->value().as_long();
1182 }
1183
1184 if (expr == 0) return 0;
1185
1186 verinum eval = expr->value();
1187 verinum oval (verinum::V0, expr_width(), true);
1188
1189 verinum::V pad_bit = verinum::Vx;
1190 if (base_ == 0) {
1191
1192 /* If the base is NULL (different from 0) then this
1193 select is here for zero or sign extension. So
1194 calculate a proper pad bit. */
1195 if (has_sign())
1196 pad_bit = eval.get(expr->expr_width()-1);
1197 else
1198 pad_bit = verinum::V0;
1199 }
1200
1201 for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
1202 if ((bval >= 0) && ((unsigned long) bval < eval.len()))
1203 oval.set(idx, eval.get(bval));
1204 else
1205 oval.set(idx, pad_bit);
1206
1207 bval += 1;
1208 }
1209
1210 oval.has_sign(has_sign());
1211
1212 NetEConst*res = new NetEConst(oval);
1213 eval_debug(this, res, false);
1214 return res;
1215 }
1216
1217
print_ternary_cond(NetExpr * expr)1218 static void print_ternary_cond(NetExpr*expr)
1219 {
1220 if (NetEConst*c = dynamic_cast<NetEConst*>(expr)) {
1221 cerr << c->value() << endl;
1222 return;
1223 }
1224 if (NetECReal*c = dynamic_cast<NetECReal*>(expr)) {
1225 cerr << c->value() << endl;
1226 return;
1227 }
1228 assert(0);
1229 }
1230
1231 /*
1232 * A ternary expression evaluation is controlled by the condition
1233 * expression. If the condition evaluates to true or false, then
1234 * return the evaluated true or false expression. If the condition
1235 * evaluates to x or z, then merge the constant bits of the true and
1236 * false expressions.
1237 */
eval_tree()1238 NetExpr* NetETernary::eval_tree()
1239 {
1240 eval_expr(cond_);
1241 switch (const_logical(cond_)) {
1242 case C_0:
1243 eval_expr(false_val_);
1244 if (debug_eval_tree) {
1245
1246 cerr << get_fileline() << ": debug: Evaluate ternary with "
1247 << "constant condition value: ";
1248 print_ternary_cond(cond_);
1249 cerr << get_fileline() << ": : Selecting false case: "
1250 << *false_val_ << endl;
1251 }
1252
1253 if (expr_type() == IVL_VT_REAL &&
1254 false_val_->expr_type() != IVL_VT_REAL) {
1255 verireal f;
1256 if (get_real_arg_(false_val_, f)) {
1257 NetECReal*rc = new NetECReal(f);
1258 rc->set_line(*this);
1259 return rc;
1260 }
1261 }
1262
1263 return false_val_->dup_expr();
1264
1265 case C_1:
1266 eval_expr(true_val_);
1267 if (debug_eval_tree) {
1268 cerr << get_fileline() << ": debug: Evaluate ternary with "
1269 << "constant condition value: ";
1270 print_ternary_cond(cond_);
1271 cerr << get_fileline() << ": : Selecting true case: "
1272 << *true_val_ << endl;
1273 }
1274
1275 if (expr_type() == IVL_VT_REAL &&
1276 true_val_->expr_type() != IVL_VT_REAL) {
1277 verireal t;
1278 if (get_real_arg_(true_val_, t)) {
1279 NetECReal*rc = new NetECReal(t);
1280 rc->set_line(*this);
1281 return rc;
1282 }
1283 }
1284
1285 return true_val_->dup_expr();
1286
1287 case C_X:
1288 break;
1289
1290 default:
1291 return 0;
1292 }
1293
1294 /* Here we have a more complex case. We need to evaluate both
1295 expressions down to constants then compare the values to
1296 build up a constant result. */
1297
1298 eval_expr(true_val_);
1299 eval_expr(false_val_);
1300
1301 return blended_arguments_(true_val_, false_val_);
1302 }
1303
blended_arguments_(const NetExpr * te,const NetExpr * fe) const1304 NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) const
1305 {
1306
1307 const NetEConst*t = dynamic_cast<const NetEConst*>(te);
1308 const NetEConst*f = dynamic_cast<const NetEConst*>(fe);
1309 if (t == 0 || f == 0) {
1310 verireal tv, fv;
1311 if (!get_real_arg_(te, tv)) return 0;
1312 if (!get_real_arg_(fe, fv)) return 0;
1313
1314 verireal val = verireal(0.0);
1315 if (tv.as_double() == fv.as_double()) val = tv;
1316
1317 if (debug_eval_tree) {
1318 cerr << get_fileline() << ": debug: Evaluate ternary with "
1319 << "constant condition value: ";
1320 print_ternary_cond(cond_);
1321 cerr << get_fileline() << ": : Blending real cases "
1322 << "true=" << tv.as_double()
1323 << ", false=" << fv.as_double()
1324 << ", to get " << val << endl;
1325 }
1326
1327 NetECReal*rc = new NetECReal(val);
1328 rc->set_line(*this);
1329 return rc;
1330 }
1331
1332 unsigned tsize = t->expr_width();
1333 unsigned fsize = f->expr_width();
1334 /* Size of the result is the size of the widest operand. */
1335 unsigned rsize = tsize > fsize? tsize : fsize;
1336
1337 verinum val (verinum::V0, rsize);
1338 for (unsigned idx = 0 ; idx < rsize ; idx += 1) {
1339 verinum::V tv = idx < tsize? t->value().get(idx) : verinum::V0;
1340 verinum::V fv = idx < fsize? f->value().get(idx) : verinum::V0;
1341
1342 if (tv == fv) val.set(idx, tv);
1343 else val.set(idx, verinum::Vx);
1344 }
1345 val.has_sign(has_sign());
1346
1347 if (debug_eval_tree) {
1348 cerr << get_fileline() << ": debug: Evaluate ternary with "
1349 << "constant condition value: ";
1350 print_ternary_cond(cond_);
1351 cerr << get_fileline() << ": : Blending cases to get "
1352 << val << endl;
1353 }
1354
1355 NetEConst*rc = new NetEConst(val);
1356 rc->set_line(*this);
1357 return rc;
1358 }
1359
eval_tree()1360 NetExpr* NetEUnary::eval_tree()
1361 {
1362 eval_expr(expr_);
1363 return eval_arguments_(expr_);
1364 }
1365
eval_tree_real_(const NetExpr * ex) const1366 NetExpr* NetEUnary::eval_tree_real_(const NetExpr*ex) const
1367 {
1368 const NetECReal*val= dynamic_cast<const NetECReal*> (ex);
1369 if (val == 0) return 0;
1370
1371 double res_val = val->value().as_double();
1372 switch (op_) {
1373 case '+':
1374 break;
1375
1376 case '-':
1377 res_val = -res_val;
1378 break;
1379
1380 case 'm':
1381 if (res_val < 0.0) res_val = -res_val;
1382 break;
1383
1384 default:
1385 return 0;
1386 }
1387 NetECReal *res = new NetECReal( verireal(res_val) );
1388 ivl_assert(*this, res);
1389 eval_debug(this, res, true);
1390 return res;
1391 }
1392
eval_arguments_(const NetExpr * ex) const1393 NetExpr* NetEUnary::eval_arguments_(const NetExpr*ex) const
1394 {
1395 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(ex);
1396
1397 const NetEConst*rval = dynamic_cast<const NetEConst*>(ex);
1398 if (rval == 0) return 0;
1399
1400 verinum val = rval->value();
1401
1402 switch (op_) {
1403
1404 case '+':
1405 /* Unary + is a no-op. */
1406 break;
1407
1408 case '-':
1409 val = -val;
1410 break;
1411
1412 case 'm':
1413 if (!val.is_defined()) {
1414 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1415 val.set(idx, verinum::Vx);
1416 } else if (val.is_negative()) {
1417 val = -val;
1418 }
1419 break;
1420
1421 case '~':
1422 /* Bitwise not is even simpler than logical
1423 not. Just invert all the bits of the operand and
1424 make the new value with the same dimensions. */
1425 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1426 switch (val.get(idx)) {
1427 case verinum::V0:
1428 val.set(idx, verinum::V1);
1429 break;
1430 case verinum::V1:
1431 val.set(idx, verinum::V0);
1432 break;
1433 default:
1434 val.set(idx, verinum::Vx);
1435 }
1436
1437 break;
1438
1439 case '!':
1440 assert(0);
1441 default:
1442 return 0;
1443 }
1444
1445 NetEConst *res = new NetEConst(val);
1446 ivl_assert(*this, res);
1447 eval_debug(this, res, false);
1448 return res;
1449 }
1450
1451
eval_tree_real_(const NetExpr * ex) const1452 NetEConst* NetEUReduce::eval_tree_real_(const NetExpr*ex) const
1453 {
1454 ivl_assert(*this, op_ == '!');
1455
1456 const NetECReal*val= dynamic_cast<const NetECReal*> (ex);
1457 if (val == 0) return 0;
1458
1459 verinum::V res = val->value().as_double() == 0.0 ? verinum::V1 :
1460 verinum::V0;
1461
1462 NetEConst*tmp = new NetEConst(verinum(res, 1));
1463 ivl_assert(*this, tmp);
1464 eval_debug(this, tmp, true);
1465 return tmp;
1466 }
1467
eval_arguments_(const NetExpr * ex) const1468 NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const
1469 {
1470 if (expr_type() == IVL_VT_REAL) return eval_tree_real_(ex);
1471
1472 const NetEConst*rval = dynamic_cast<const NetEConst*>(ex);
1473 if (rval == 0) return 0;
1474
1475 verinum val = rval->value();
1476
1477 verinum::V res;
1478 bool invert = false;
1479
1480 switch (op_) {
1481
1482 case '!': {
1483 /* Evaluate the unary logical not by first scanning
1484 the operand value for V1 and Vx bits. If we find
1485 any V1 bits we know that the value is TRUE, so
1486 the result of ! is V0. If there are no V1 bits
1487 but there are some Vx/Vz bits, the result is
1488 unknown. Otherwise, the result is V1. */
1489 bool v1 = false, vx = false;
1490 for (unsigned idx = 0 ; idx < val.len() && !v1 ; idx += 1) {
1491 switch (val.get(idx)) {
1492 case verinum::V0:
1493 break;
1494 case verinum::V1:
1495 v1 = true;
1496 break;
1497 default:
1498 vx = true;
1499 break;
1500 }
1501 }
1502
1503 res = v1? verinum::V0 : (vx? verinum::Vx : verinum::V1);
1504 break;
1505 }
1506
1507 case 'A':
1508 invert = true;
1509 // fallthrough
1510 case '&': {
1511 res = verinum::V1;
1512 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1513 res = res & val.get(idx);
1514 break;
1515 }
1516
1517 case 'N':
1518 invert = true;
1519 // fallthrough
1520 case '|': {
1521 res = verinum::V0;
1522 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1523 res = res | val.get(idx);
1524 break;
1525 }
1526
1527 case 'X':
1528 invert = true;
1529 // fallthrough
1530 case '^': {
1531 /* Reduction XOR. */
1532 unsigned ones = 0, unknown = 0;
1533 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1534 switch (val.get(idx)) {
1535 case verinum::V0:
1536 break;
1537 case verinum::V1:
1538 ones += 1;
1539 break;
1540 default:
1541 unknown += 1;
1542 break;
1543 }
1544
1545 if (unknown) res = verinum::Vx;
1546 else if (ones%2) res = verinum::V1;
1547 else res = verinum::V0;
1548 break;
1549 }
1550
1551 default:
1552 return 0;
1553 }
1554
1555 if (invert) res = ~res;
1556
1557 NetEConst*tmp = new NetEConst(verinum(res, 1));
1558 ivl_assert(*this, tmp);
1559 eval_debug(this, tmp, false);
1560 return tmp;
1561 }
1562
eval_arguments_(const NetExpr * ex) const1563 NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const
1564 {
1565 NetExpr*res = 0;
1566 switch (op_) {
1567 case 'r':
1568 if (const NetEConst*val = dynamic_cast<const NetEConst*>(ex)) {
1569 verireal res_val(val->value().as_double());
1570 res = new NetECReal(res_val);
1571 }
1572 break;
1573 case '2':
1574 if (const NetEConst*val = dynamic_cast<const NetEConst*>(ex)) {
1575 verinum res_val(val->value());
1576 res_val.cast_to_int2();
1577 if (expr_width() > 0)
1578 res_val = cast_to_width(res_val, expr_width());
1579 res = new NetEConst(res_val);
1580 }
1581 // fallthrough
1582 case 'v':
1583 if (const NetECReal*val = dynamic_cast<const NetECReal*>(ex)) {
1584 verinum res_val(val->value().as_double(), false);
1585 if (expr_width() > 0)
1586 res_val = cast_to_width(res_val, expr_width());
1587 res = new NetEConst(res_val);
1588 }
1589 break;
1590 default:
1591 ivl_assert(*this, 0);
1592 return 0;
1593 }
1594 if (res == 0) return 0;
1595
1596 ivl_assert(*this, res);
1597 eval_debug(this, res, op_ == 'r');
1598 return res;
1599 }
1600
evaluate_clog2_(const NetExpr * arg_) const1601 NetEConst* NetESFunc::evaluate_clog2_(const NetExpr*arg_) const
1602 {
1603 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
1604 const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
1605
1606 if (tmpi == 0 && tmpr == 0) return 0;
1607
1608 verinum arg;
1609 if (tmpi) {
1610 arg = tmpi->value();
1611 } else {
1612 arg = verinum(tmpr->value().as_double(), true);
1613 }
1614
1615 NetEConst*rtn;
1616
1617 /* If we have an x in the verinum we return 'bx. */
1618 if (!arg.is_defined()) {
1619 verinum tmp (verinum::Vx, integer_width);
1620 tmp.has_sign(true);
1621
1622 rtn = new NetEConst(tmp);
1623 ivl_assert(*this, rtn);
1624 } else {
1625 bool is_neg = false;
1626 uint64_t res = 0;
1627
1628 if (arg.is_negative()) {
1629 is_neg = true;
1630 // If the length is not defined, then work with
1631 // the trimmed version of the number.
1632 if (! arg.has_len())
1633 arg = trim_vnum(arg);
1634 }
1635 arg.has_sign(false); // $unsigned()
1636
1637 if (!arg.is_zero()) {
1638 arg = arg - verinum((uint64_t)1, 1);
1639 while (!arg.is_zero()) {
1640 res += 1;
1641 arg = arg >> 1;
1642 }
1643 }
1644
1645 if (is_neg && res < integer_width)
1646 res = integer_width;
1647
1648 verinum tmp (res, integer_width);
1649 tmp.has_sign(true);
1650
1651 rtn = new NetEConst(tmp);
1652 ivl_assert(*this, rtn);
1653 }
1654
1655 eval_debug(this, rtn, false);
1656 return rtn;
1657 }
1658
evaluate_rtoi_(const NetExpr * arg_) const1659 NetEConst* NetESFunc::evaluate_rtoi_(const NetExpr*arg_) const
1660 {
1661 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
1662 const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
1663
1664 if (tmpi == 0 && tmpr == 0) return 0;
1665
1666 /* If the argument is already a bit based value just extend/trim it
1667 * to the integer width and translate all undefined bits to zero. */
1668 if (tmpi) {
1669 verinum arg = verinum(tmpi->value(), integer_width);
1670 arg.cast_to_int2();
1671 return new NetEConst(arg);
1672 }
1673
1674 /* Get the value of the real argument as a bit based value and then
1675 * extend/trim it to the integer width. */
1676 double arg = tmpr->value().as_double();
1677 if (arg >= 0.0) arg = floor(arg);
1678 else arg = ceil(arg);
1679 return new NetEConst(verinum(verinum(arg, false), integer_width));
1680 }
1681
evaluate_itor_(const NetExpr * arg_) const1682 NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_) const
1683 {
1684 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
1685 const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
1686
1687 if (tmpi == 0 && tmpr == 0) return 0;
1688
1689 /* If the argument is already a real value round it, but NaN and
1690 * +/- infinity need to be translated to 0.0. */
1691 if (tmpr) {
1692 double arg = tmpr->value().as_double();
1693 /* Convert a NaN or +/- infinity to 0.0 since these convert
1694 * to 'bz which is then translated to 0.0. */
1695 if (arg != arg || (arg && (arg == 0.5*arg))) {
1696 return new NetECReal(verireal(0.0));
1697 }
1698
1699 if (arg >= 0.0) arg = floor(arg + 0.5);
1700 else arg = ceil(arg - 0.5);
1701
1702 return new NetECReal(verireal(arg));
1703 }
1704
1705 /* Convert the bit based value to a real value. */
1706 double arg = tmpi->value().as_double();
1707 return new NetECReal(verireal(arg));
1708 }
1709
evaluate_math_one_arg_(ID id,const NetExpr * arg_) const1710 NetECReal* NetESFunc::evaluate_math_one_arg_(ID id, const NetExpr*arg_) const
1711 {
1712 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
1713 const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
1714
1715 NetECReal*res = 0;
1716
1717 if (tmpi || tmpr) {
1718 double arg;
1719 if (tmpi) {
1720 arg = tmpi->value().as_double();
1721 } else {
1722 arg = tmpr->value().as_double();
1723 }
1724
1725 switch (id) {
1726 case LN:
1727 res = new NetECReal(verireal(log(arg)));
1728 break;
1729 case LOG10:
1730 res = new NetECReal(verireal(log10(arg)));
1731 break;
1732 case EXP:
1733 res = new NetECReal(verireal(exp(arg)));
1734 break;
1735 case SQRT:
1736 res = new NetECReal(verireal(sqrt(arg)));
1737 break;
1738 case FLOOR:
1739 res = new NetECReal(verireal(floor(arg)));
1740 break;
1741 case CEIL:
1742 res = new NetECReal(verireal(ceil(arg)));
1743 break;
1744 case SIN:
1745 res = new NetECReal(verireal(sin(arg)));
1746 break;
1747 case COS:
1748 res = new NetECReal(verireal(cos(arg)));
1749 break;
1750 case TAN:
1751 res = new NetECReal(verireal(tan(arg)));
1752 break;
1753 case ASIN:
1754 res = new NetECReal(verireal(asin(arg)));
1755 break;
1756 case ACOS:
1757 res = new NetECReal(verireal(acos(arg)));
1758 break;
1759 case ATAN:
1760 res = new NetECReal(verireal(atan(arg)));
1761 break;
1762 case SINH:
1763 res = new NetECReal(verireal(sinh(arg)));
1764 break;
1765 case COSH:
1766 res = new NetECReal(verireal(cosh(arg)));
1767 break;
1768 case TANH:
1769 res = new NetECReal(verireal(tanh(arg)));
1770 break;
1771 case ASINH:
1772 res = new NetECReal(verireal(asinh(arg)));
1773 break;
1774 case ACOSH:
1775 res = new NetECReal(verireal(acosh(arg)));
1776 break;
1777 case ATANH:
1778 res = new NetECReal(verireal(atanh(arg)));
1779 break;
1780 default:
1781 ivl_assert(*this, 0);
1782 break;
1783 }
1784 ivl_assert(*this, res);
1785 }
1786
1787 eval_debug(this, res, true);
1788 return res;
1789 }
1790
evaluate_math_two_arg_(ID id,const NetExpr * arg0_,const NetExpr * arg1_) const1791 NetECReal* NetESFunc::evaluate_math_two_arg_(ID id, const NetExpr*arg0_,
1792 const NetExpr*arg1_) const
1793 {
1794 const NetEConst*tmpi0 = dynamic_cast<const NetEConst*>(arg0_);
1795 const NetECReal*tmpr0 = dynamic_cast<const NetECReal*>(arg0_);
1796 const NetEConst*tmpi1 = dynamic_cast<const NetEConst*>(arg1_);
1797 const NetECReal*tmpr1 = dynamic_cast<const NetECReal*>(arg1_);
1798
1799 NetECReal*res = 0;
1800
1801 if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
1802 double arg0, arg1;
1803 if (tmpi0) {
1804 arg0 = tmpi0->value().as_double();
1805 } else {
1806 arg0 = tmpr0->value().as_double();
1807 }
1808 if (tmpi1) {
1809 arg1 = tmpi1->value().as_double();
1810 } else {
1811 arg1 = tmpr1->value().as_double();
1812 }
1813
1814 switch (id) {
1815 case POW:
1816 res = new NetECReal(verireal(pow(arg0, arg1)));
1817 break;
1818 case ATAN2:
1819 res = new NetECReal(verireal(atan2(arg0, arg1)));
1820 break;
1821 case HYPOT:
1822 res = new NetECReal(verireal(hypot(arg0, arg1)));
1823 break;
1824 default:
1825 ivl_assert(*this, 0);
1826 break;
1827 }
1828 ivl_assert(*this, res);
1829 }
1830
1831 eval_debug(this, res, true);
1832 return res;
1833 }
1834
evaluate_abs_(const NetExpr * arg_) const1835 NetExpr* NetESFunc::evaluate_abs_(const NetExpr*arg_) const
1836 {
1837 NetExpr*res = 0;
1838
1839 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
1840 const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
1841 if (tmpi || tmpr) {
1842 double arg;
1843 if (tmpi) {
1844 arg = tmpi->value().as_double();
1845 } else {
1846 arg = tmpr->value().as_double();
1847 }
1848 res = new NetECReal(verireal(fabs(arg)));
1849 ivl_assert(*this, res);
1850 }
1851
1852 eval_debug(this, res, true);
1853 return res;
1854 }
1855
evaluate_min_max_(ID id,const NetExpr * arg0_,const NetExpr * arg1_) const1856 NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
1857 const NetExpr*arg1_) const
1858 {
1859 const NetEConst*tmpi0 = dynamic_cast<const NetEConst*>(arg0_);
1860 const NetECReal*tmpr0 = dynamic_cast<const NetECReal*>(arg0_);
1861 const NetEConst*tmpi1 = dynamic_cast<const NetEConst*>(arg1_);
1862 const NetECReal*tmpr1 = dynamic_cast<const NetECReal*>(arg1_);
1863
1864 NetExpr*res = 0;
1865
1866 if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
1867 double arg0, arg1;
1868 if (tmpi0) {
1869 arg0 = tmpi0->value().as_double();
1870 } else {
1871 arg0 = tmpr0->value().as_double();
1872 }
1873 if (tmpi1) {
1874 arg1 = tmpi1->value().as_double();
1875 } else {
1876 arg1 = tmpr1->value().as_double();
1877 }
1878 switch (id) {
1879 case MIN:
1880 res = new NetECReal(verireal(arg0 < arg1 ? arg0 : arg1));
1881 break;
1882 case MAX:
1883 res = new NetECReal(verireal(arg0 < arg1 ? arg1 : arg0));
1884 break;
1885 default:
1886 ivl_assert(*this, 0);
1887 break;
1888 }
1889 ivl_assert(*this, res);
1890 }
1891
1892 eval_debug(this, res, true);
1893 return res;
1894 }
1895
no_string_arg(const NetESFunc * info,unsigned arg_num)1896 static void no_string_arg(const NetESFunc*info, unsigned arg_num)
1897 {
1898 cerr << info->get_fileline() << ": error: constant function "
1899 << info->name() << "() does not support a string argument ("
1900 << arg_num+1 << ")." << endl;
1901 }
1902
evaluate_countbits_() const1903 NetEConst* NetESFunc::evaluate_countbits_() const
1904 {
1905 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(parms_[0]);
1906
1907 NetEConst*res = 0;
1908
1909 if (tmpi) {
1910 verinum value = tmpi->value();
1911
1912 if (value.is_string()) {
1913 no_string_arg(this, 0);
1914 return 0;
1915 }
1916
1917 /* Find which values need to be counted. */
1918 bool count_0 = false;
1919 bool count_1 = false;
1920 bool count_z = false;
1921 bool count_x = false;
1922 for (unsigned arg=1; arg < parms_.size(); ++arg) {
1923 const NetEConst*argi = dynamic_cast<const NetEConst*>(parms_[arg]);
1924 if (! argi) return 0;
1925 verinum check_for = argi->value();
1926 if (check_for.is_string()) {
1927 no_string_arg(this, arg);
1928 return 0;
1929 }
1930 switch (check_for[0]) {
1931 case verinum::V0:
1932 count_0 = true;
1933 break;
1934 case verinum::V1:
1935 count_1 = true;
1936 break;
1937 case verinum::Vz:
1938 count_z = true;
1939 break;
1940 case verinum::Vx:
1941 count_x = true;
1942 break;
1943 }
1944 }
1945
1946 /* Search each bit of the vector looking for the values to
1947 * be counted. */
1948 int count = 0;
1949 for (unsigned bit=0; bit < value.len(); ++bit) {
1950 switch (value[bit]) {
1951 case verinum::V0:
1952 if (count_0) ++count;
1953 break;
1954 case verinum::V1:
1955 if (count_1) ++count;
1956 break;
1957 case verinum::Vz:
1958 if (count_z) ++count;
1959 break;
1960 case verinum::Vx:
1961 if (count_x) ++count;
1962 break;
1963 }
1964 }
1965
1966 verinum tmp (count, integer_width);
1967 tmp.has_sign(true);
1968 res = new NetEConst(tmp);
1969 ivl_assert(*this, res);
1970 }
1971
1972 return res;
1973 }
1974
evaluate_countones_(const NetExpr * arg) const1975 NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const
1976 {
1977 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
1978
1979 NetEConst*res = 0;
1980
1981 if (tmpi) {
1982 verinum value = tmpi->value();
1983 int count = 0;
1984
1985 if (value.is_string()) {
1986 no_string_arg(this, 0);
1987 return 0;
1988 }
1989
1990 for (unsigned bit=0; bit < value.len(); ++bit) {
1991 if (value[bit] == verinum::V1) ++count;
1992 }
1993
1994 verinum tmp (count, integer_width);
1995 tmp.has_sign(true);
1996 res = new NetEConst(tmp);
1997 ivl_assert(*this, res);
1998 }
1999
2000 return res;
2001 }
2002
2003 /* Get the total number of dimensions for the given expression. */
evaluate_dimensions_(const NetExpr * arg) const2004 NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const
2005 {
2006 const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
2007 long res = 0;
2008 if (esig != 0) {
2009 const NetNet *sig = esig->sig();
2010 res = sig->packed_dimensions() + sig->unpacked_dimensions();
2011 /* Icarus does not think a string has a packed size so to
2012 * make these routines work correct add one if this is a
2013 * string data type. */
2014 if (sig->data_type() == IVL_VT_STRING) {
2015 assert(sig->packed_dimensions() == 0);
2016 res += 1;
2017 }
2018 }
2019 /* Return the result as an integer sized constant. */
2020 return new NetEConst(verinum(verinum(res), integer_width));
2021 }
2022
evaluate_isunknown_(const NetExpr * arg) const2023 NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
2024 {
2025 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
2026
2027 NetEConst*res = 0;
2028
2029 if (tmpi) {
2030 verinum value = tmpi->value();
2031 unsigned is_unknown = 1;
2032
2033 if (value.is_string()) {
2034 no_string_arg(this, 0);
2035 return 0;
2036 }
2037
2038 if (value.is_defined()) is_unknown = 0;
2039
2040 verinum tmp (is_unknown, 1U);
2041 tmp.has_sign(false);
2042 res = new NetEConst(tmp);
2043 ivl_assert(*this, res);
2044 }
2045
2046 return res;
2047 }
2048
is_onehot(verinum & value,bool zero_is_okay)2049 static bool is_onehot(verinum&value, bool zero_is_okay)
2050 {
2051 bool found_a_one = false;
2052
2053 for (unsigned bit=0; bit < value.len(); ++bit) {
2054 if (value[bit] == verinum::V1) {
2055 if (found_a_one) return false;
2056 found_a_one = true;
2057 }
2058 }
2059
2060 /* If no one bit was found return true if zero is okay. */
2061 if (zero_is_okay) found_a_one = true;
2062 return found_a_one;
2063 }
2064
evaluate_onehot_(const NetExpr * arg) const2065 NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const
2066 {
2067 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
2068
2069 NetEConst*res = 0;
2070
2071 if (tmpi) {
2072 verinum value = tmpi->value();
2073
2074 if (value.is_string()) {
2075 no_string_arg(this, 0);
2076 return 0;
2077 }
2078
2079 verinum tmp (is_onehot(value, false), 1U);
2080 tmp.has_sign(false);
2081 res = new NetEConst(tmp);
2082 ivl_assert(*this, res);
2083 }
2084
2085 return res;
2086 }
2087
evaluate_onehot0_(const NetExpr * arg) const2088 NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
2089 {
2090 const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg);
2091
2092 NetEConst*res = 0;
2093
2094 if (tmpi) {
2095 verinum value = tmpi->value();
2096
2097 if (value.is_string()) {
2098 no_string_arg(this, 0);
2099 return 0;
2100 }
2101
2102 verinum tmp (is_onehot(value, true), 1U);
2103 tmp.has_sign(false);
2104 res = new NetEConst(tmp);
2105 ivl_assert(*this, res);
2106 }
2107
2108 return res;
2109 }
2110
2111 /* Get the number of unpacked dimensions for the given expression. */
evaluate_unpacked_dimensions_(const NetExpr * arg) const2112 NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg) const
2113 {
2114 const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
2115 long res = 0;
2116 if (esig != 0) {
2117 const NetNet *sig = esig->sig();
2118 res = sig->unpacked_dimensions();
2119 }
2120 /* Return the result as an integer sized constant. */
2121 return new NetEConst(verinum(verinum(res), integer_width));
2122 }
2123
2124 /* This code assumes that the dimension value will fit in a long.
2125 * Return true if no constant dimension value is available. */
check_dimension(const NetExpr * dim_expr,long & dim)2126 static bool check_dimension(const NetExpr*dim_expr, long &dim)
2127 {
2128 const NetEConst*dimi = dynamic_cast<const NetEConst*>(dim_expr);
2129 const NetECReal*dimr = dynamic_cast<const NetECReal*>(dim_expr);
2130 if (dimi == 0 && dimr == 0) return true;
2131
2132 if (dimi) dim = dimi->value().as_long();
2133 if (dimr) dim = dimr->value().as_long();
2134 return false;
2135 }
2136
2137 /* Get the left and right values for the argument at the given dimension
2138 * if it exists. Return true if no values are available. Set defer to true
2139 * if this should be handled in the run time. */
get_array_info(const NetExpr * arg,long dim,long & left,long & right,bool & defer)2140 static bool get_array_info(const NetExpr*arg, long dim,
2141 long &left, long &right, bool&defer)
2142 {
2143 if (const NetEConstParam*param = dynamic_cast<const NetEConstParam*>(arg)) {
2144 assert(dim == 1);
2145 left = param->expr_width() - 1;
2146 right = 0;
2147 return false;
2148 }
2149 /* The argument must be a signal that has enough dimensions. */
2150 const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
2151 if (esig == 0) return true;
2152 const NetNet *sig = esig->sig();
2153 /* A string or dynamic array must be handled by the run time. */
2154 switch (sig->data_type()) {
2155 case IVL_VT_DARRAY:
2156 case IVL_VT_QUEUE:
2157 case IVL_VT_STRING:
2158 defer = true;
2159 return true;
2160 break;
2161 default:
2162 break;
2163 }
2164 long pdims = sig->packed_dimensions();
2165 long updims = sig->unpacked_dimensions();
2166 if (dim > (pdims + updims)) return true;
2167 /* Get the appropriate unpacked or packed dimension information. */
2168 if (dim > updims) {
2169 const vector<netrange_t>&dim_vals = sig->packed_dims();
2170 const netrange_t&range = dim_vals[dim-updims-1];
2171 left = range.get_msb();
2172 right = range.get_lsb();
2173 } else {
2174 const vector<netrange_t>&dim_vals = sig->unpacked_dims();
2175 const netrange_t&range = dim_vals[dim-1];
2176 left = range.get_msb();
2177 right = range.get_lsb();
2178 }
2179 return false;
2180 }
2181
2182 /* Calculate the array property functions. */
evaluate_array_funcs_(ID id,const NetExpr * arg0,const NetExpr * arg1) const2183 NetEConst* NetESFunc::evaluate_array_funcs_(ID id,
2184 const NetExpr*arg0,
2185 const NetExpr*arg1) const
2186 {
2187 long dim = 0;
2188 /* Check to see if the dimension argument is constant. */
2189 if (check_dimension(arg1, dim)) return 0;
2190 /* If dimension is less than 1 return undefined. */
2191 if (dim < 1) {
2192 return new NetEConst(verinum(verinum::Vx, integer_width));
2193 }
2194 /* Get the left/right information for this dimension if it exists. */
2195 long left = 0;
2196 long right = 0;
2197 bool defer = false;
2198 if (get_array_info(arg0, dim, left, right, defer)) {
2199 /* If this is a string or dynamic array defer this function
2200 * call since the left/right information is dynamic and is
2201 * not available yet. */
2202 if (defer) return 0;
2203 return new NetEConst(verinum(verinum::Vx, integer_width));
2204 }
2205 /* Calculate the appropriate array function result. */
2206 long res;
2207 switch (id) {
2208 case HIGH:
2209 res = (right > left) ? right : left;
2210 break;
2211 case INCR:
2212 res = (right > left) ? -1 : 1;
2213 break;
2214 case LEFT:
2215 res = left;
2216 break;
2217 case LOW:
2218 res = (right > left) ? left : right;
2219 break;
2220 case RIGHT:
2221 res = right;
2222 break;
2223 case SIZE:
2224 res = (right > left) ? right - left : left - right;
2225 res += 1;
2226 break;
2227 default:
2228 res = 0;
2229 assert(0);
2230 }
2231 /* Return the result as an integer sized constant. */
2232 return new NetEConst(verinum(verinum(res), integer_width));
2233 }
2234
2235 /* Make a constant one value that can be used by the one argument
2236 * array properties calls. */
2237 const NetEConst* NetESFunc::const_one_ = new NetEConst(verinum(1U, 32U));
2238
evaluate_one_arg_(ID id,const NetExpr * arg) const2239 NetExpr* NetESFunc::evaluate_one_arg_(ID id, const NetExpr*arg) const
2240 {
2241 switch (id) {
2242 case ABS:
2243 return evaluate_abs_(arg);
2244 case CLOG2:
2245 return evaluate_clog2_(arg);
2246 case CTONES:
2247 return evaluate_countones_(arg);
2248 case DIMS:
2249 return evaluate_dimensions_(arg);
2250 /* The array functions are handled together. */
2251 case HIGH:
2252 case INCR:
2253 case LEFT:
2254 case LOW:
2255 case RIGHT:
2256 case SIZE:
2257 return evaluate_array_funcs_(id, arg, const_one_);
2258 case ISUNKN:
2259 return evaluate_isunknown_(arg);
2260 case ITOR:
2261 return evaluate_itor_(arg);
2262 case ONEHT:
2263 return evaluate_onehot_(arg);
2264 case ONEHT0:
2265 return evaluate_onehot0_(arg);
2266 case RTOI:
2267 return evaluate_rtoi_(arg);
2268 case UPDIMS:
2269 return evaluate_unpacked_dimensions_(arg);
2270 default:
2271 return evaluate_math_one_arg_(id, arg);
2272 }
2273 }
2274
evaluate_two_arg_(ID id,const NetExpr * arg0,const NetExpr * arg1) const2275 NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
2276 const NetExpr*arg1) const
2277 {
2278 switch (id) {
2279 case CTBITS:
2280 return evaluate_countbits_();
2281 /* The array functions are handled together. */
2282 case HIGH:
2283 case INCR:
2284 case LEFT:
2285 case LOW:
2286 case RIGHT:
2287 case SIZE:
2288 return evaluate_array_funcs_(id, arg0, arg1);
2289 case MAX:
2290 case MIN:
2291 return evaluate_min_max_(id, arg0, arg1);
2292 default:
2293 return evaluate_math_two_arg_(id, arg0, arg1);
2294 }
2295 }
2296
built_in_id_() const2297 NetESFunc::ID NetESFunc::built_in_id_() const
2298 {
2299 static map<string,ID> built_in_func;
2300 static bool funcs_need_init = true;
2301
2302 /* These functions are always available. */
2303 if (funcs_need_init) {
2304 built_in_func["$itor"] = ITOR;
2305 built_in_func["$rtoi"] = RTOI;
2306 }
2307
2308 /* These are available in 1364-2005 and later or if the Icarus misc
2309 * flag was given. */
2310 if (funcs_need_init && ((generation_flag >= GN_VER2005) ||
2311 gn_icarus_misc_flag)) {
2312 built_in_func["$acos" ] = ACOS;
2313 built_in_func["$acosh"] = ACOSH;
2314 built_in_func["$asin" ] = ASIN;
2315 built_in_func["$asinh"] = ASINH;
2316 built_in_func["$atan" ] = ATAN;
2317 built_in_func["$atanh"] = ATANH;
2318 built_in_func["$atan2"] = ATAN2;
2319 built_in_func["$ceil" ] = CEIL;
2320 built_in_func["$clog2"] = CLOG2;
2321 built_in_func["$cos" ] = COS;
2322 built_in_func["$cosh" ] = COSH;
2323 built_in_func["$exp" ] = EXP;
2324 built_in_func["$floor"] = FLOOR;
2325 built_in_func["$hypot"] = HYPOT;
2326 built_in_func["$ln" ] = LN;
2327 built_in_func["$log10"] = LOG10;
2328 built_in_func["$pow" ] = POW;
2329 built_in_func["$sin" ] = SIN;
2330 built_in_func["$sinh" ] = SINH;
2331 built_in_func["$sqrt" ] = SQRT;
2332 built_in_func["$tan" ] = TAN;
2333 built_in_func["$tanh" ] = TANH;
2334 }
2335
2336 /* These are available in 1800-2005 and later. */
2337 if (funcs_need_init && (generation_flag >= GN_VER2005_SV)) {
2338 built_in_func["$dimensions" ] = DIMS;
2339 built_in_func["$high" ] = HIGH;
2340 built_in_func["$increment" ] = INCR;
2341 built_in_func["$isunknown" ] = ISUNKN;
2342 built_in_func["$left" ] = LEFT;
2343 built_in_func["$low" ] = LOW;
2344 built_in_func["$onehot" ] = ONEHT;
2345 built_in_func["$onehot0" ] = ONEHT0;
2346 built_in_func["$right" ] = RIGHT;
2347 built_in_func["$size" ] = SIZE;
2348 built_in_func["$unpacked_dimensions" ] = UPDIMS;
2349 }
2350
2351 /* This is available in 1800-2009 and later. */
2352 if (funcs_need_init && (generation_flag >= GN_VER2009)) {
2353 built_in_func["$countones" ] = CTONES;
2354 }
2355
2356 /* This is available in 1800-2012 and later. */
2357 if (funcs_need_init && (generation_flag >= GN_VER2012)) {
2358 built_in_func["$countbits" ] = CTBITS;
2359 }
2360
2361 /* These are available in Verilog-A as Icarus extensions or if the
2362 * Icarus misc flag was given. */
2363 if (funcs_need_init && (gn_verilog_ams_flag || gn_icarus_misc_flag)) {
2364 built_in_func["$abs"] = ABS;
2365 built_in_func["$max"] = MAX;
2366 built_in_func["$min"] = MIN;
2367 }
2368
2369 /* The function table has been initialized at this point. */
2370 funcs_need_init = false;
2371
2372 /* Look for the given function and if it is not available return
2373 * NOT_BUILT_IN otherwise return the ID for the function. */
2374 map<string,ID>::iterator idx = built_in_func.find(name_);
2375
2376 if (idx == built_in_func.end()) return NOT_BUILT_IN;
2377
2378 return idx->second;
2379 }
2380
eval_tree()2381 NetExpr* NetESFunc::eval_tree()
2382 {
2383 /* We don't support evaluating overridden functions. */
2384 if (is_overridden_)
2385 return 0;
2386
2387 /* Get the ID for this system function if it can be used as a
2388 * constant function. */
2389 ID id = built_in_id_();
2390 if (id == NOT_BUILT_IN) return 0;
2391
2392 switch (parms_.size()) {
2393 case 1:
2394 if (! takes_nargs_(id, 1)) {
2395 cerr << get_fileline() << ": error: constant function "
2396 << name_ << "() does not support a single argument."
2397 << endl;
2398 return 0;
2399 }
2400 eval_expr(parms_[0]);
2401 return evaluate_one_arg_(id, parms_[0]);
2402
2403 case 2:
2404 if (! takes_nargs_(id, 2)) {
2405 cerr << get_fileline() << ": error: constant function "
2406 << name_ << "() does not support two arguments."
2407 << endl;
2408 return 0;
2409 }
2410 eval_expr(parms_[0]);
2411 eval_expr(parms_[1]);
2412 return evaluate_two_arg_(id, parms_[0], parms_[1]);
2413
2414 default:
2415 /* Check to see if the function was called correctly. */
2416 if (! takes_nargs_(id, parms_.size())) {
2417 cerr << get_fileline() << ": error: constant function "
2418 << name_ << "() does not support " << parms_.size()
2419 << " arguments." << endl;
2420 return 0;
2421 }
2422 if (id == CTBITS) {
2423 for (unsigned bit = 0; bit < parms_.size(); ++bit) {
2424 eval_expr(parms_[bit]);
2425 }
2426 return evaluate_countbits_();
2427 } else {
2428 cerr << get_fileline() << ": sorry: constant functions with "
2429 << parms_.size() << " arguments are not supported: "
2430 << name_ << "()." << endl;
2431 }
2432 return 0;
2433 }
2434 }
2435
eval_tree()2436 NetExpr* NetEUFunc::eval_tree()
2437 {
2438 // If we know the function cannot be evaluated as a constant,
2439 // give up now.
2440 if (!func()->is_const_func() || (func()->calls_sys_task() && !need_const_))
2441 return 0;
2442
2443 // If we neither want nor need to evaluate the function at
2444 // compile time, give up now.
2445 if (!opt_const_func && !need_const_)
2446 return 0;
2447
2448 // Variables inside static functions can be accessed from outside
2449 // the function, so we can't be sure they are constant unless the
2450 // function was called in a constant context or the user has told
2451 // us this is safe.
2452 if (!func()->is_auto() && !need_const_ && (opt_const_func < 2))
2453 return 0;
2454
2455 // Run through the input parameters to check they are constants.
2456 for (unsigned idx = 0; idx < parm_count(); idx += 1) {
2457 if (dynamic_cast<const NetEConst*> (parm(idx)))
2458 continue;
2459 if (dynamic_cast<const NetECReal*> (parm(idx)))
2460 continue;
2461 return 0;
2462 }
2463
2464 NetFuncDef*def = func_->func_def();
2465 ivl_assert(*this, def);
2466
2467 vector<NetExpr*>args(parms_.size());
2468 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
2469 args[idx] = parms_[idx]->dup_expr();
2470
2471 NetExpr*res = def->evaluate_function(*this, args);
2472 return res;
2473 }
2474