Add file and line information for parameters, etc.
[sverilog.git] / eval_tree.cc
blobf6608e7b7ec8e29239685dfeb0d4adafd17d3d2a
1 /*
2 * Copyright (c) 1999-2008 Stephen Williams (steve@icarus.com)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "config.h"
21 # include "compiler.h"
23 # include <iostream>
24 # include <cstdlib>
26 # include "netlist.h"
27 # include "ivl_assert.h"
28 # include "netmisc.h"
30 NetExpr* NetExpr::eval_tree(int prune_to_width)
32 return 0;
35 static bool get_real_arg_(NetExpr*expr, verireal&val)
37 switch (expr->expr_type()) {
38 case IVL_VT_REAL: {
39 NetECReal*c = dynamic_cast<NetECReal*> (expr);
40 if (c == 0) return false;
41 val = c->value();
42 break;
45 case IVL_VT_BOOL:
46 case IVL_VT_LOGIC: {
47 NetEConst*c = dynamic_cast<NetEConst*>(expr);
48 if (c == 0) return false;
49 verinum tmp = c->value();
50 val = verireal(tmp.as_double());
51 break;
54 default:
55 assert(0);
58 return true;
61 bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
63 if (!get_real_arg_(left_, lval)) return false;
64 if (!get_real_arg_(right_, rval)) return false;
66 return true;
69 NetExpr* NetEBAdd::eval_tree(int prune_to_width)
71 eval_expr(left_, prune_to_width);
72 eval_expr(right_, prune_to_width);
74 if (left_->expr_type() == IVL_VT_REAL || right_->expr_type()==IVL_VT_REAL)
75 return eval_tree_real_();
77 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
78 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
80 /* If both operands are constant, then replace the entire
81 expression with a constant value. */
82 if (lc != 0 && rc != 0) {
83 verinum lval = lc->value();
84 verinum rval = rc->value();
86 verinum val;
87 switch (op_) {
88 case '+':
89 val = lval + rval;
90 break;
91 case '-':
92 val = lval - rval;
93 break;
94 default:
95 return 0;
98 if (debug_eval_tree) {
99 cerr << get_fileline() << ": debug: Evaluate expr=" << *this
100 << " --- prune=" << prune_to_width
101 << " has_width=" << (has_width()? "true" : "false") << endl;
104 /* Result might have known width. */
105 if (has_width()) {
106 unsigned lwid = lc->expr_width();
107 unsigned rwid = rc->expr_width();
108 unsigned wid = (rwid > lwid) ? rwid : lwid;
109 if (prune_to_width < 0)
110 wid += 1;
111 verinum val2=verinum(val,wid);
112 val=val2;
113 } else {
114 /* No fixed width, so trim the bits losslessly. */
115 verinum val2 = trim_vnum(val);
116 val = val2;
119 return new NetEConst(val);
122 /* Try to combine a right constant value with the right
123 constant value of a sub-expression add. For example, the
124 expression (a + 2) - 1 can be rewritten as a + 1. */
126 NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
127 lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
129 if (lc != 0 && rc != 0) {
130 assert(se != 0);
131 verinum lval = lc->value();
132 verinum rval = rc->value();
134 verinum val;
135 if (op_ == se->op_) {
136 /* (a + lval) + rval --> a + (rval+lval) */
137 /* (a - lval) - rval --> a - (rval+lval) */
138 val = rval + lval;
139 } else {
140 /* (a - lval) + rval --> a + (rval-lval) */
141 /* (a + lval) - rval --> a - (rval-lval) */
142 val = rval - lval;
145 NetEConst*tmp = new NetEConst(val);
146 left_ = se->left_->dup_expr();
147 delete se;
148 tmp->set_line(*right_);
149 delete right_;
150 right_ = tmp;
151 /* We've changed the subexpression, but the result is
152 still not constant, so return nil here anyhow. */
153 return 0;
156 /* Nothing more to be done, the value is not constant. */
157 return 0;
160 NetECReal* NetEBAdd::eval_tree_real_()
162 verireal lval;
163 verireal rval;
164 bool flag = get_real_arguments_(lval, rval);
165 if (!flag) return 0;
167 verireal res_val;
169 switch (op()) {
170 case '+':
171 res_val = lval + rval;
172 break;
173 case '-':
174 res_val = lval - rval;
175 break;
176 default:
177 ivl_assert(*this, 0);
180 NetECReal*res = new NetECReal( res_val );
181 res->set_line(*this);
182 return res;
185 NetEConst* NetEBBits::eval_tree(int prune_to_width)
187 eval_expr(left_);
188 eval_expr(right_);
190 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
191 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
192 if (lc == 0 || rc == 0) return 0;
194 /* Notice the special case where one of the operands is 0 and
195 this is a bitwise &. If this happens, then the result is
196 known to be 0. */
197 if ((op() == '&') && (lc->value() == verinum(0))) {
198 verinum res (verinum::V0, expr_width());
199 return new NetEConst(res);
202 if ((op() == '&') && (rc->value() == verinum(0))) {
203 verinum res (verinum::V0, expr_width());
204 return new NetEConst(res);
207 verinum lval = lc->value();
208 verinum rval = rc->value();
210 unsigned lwid = lc->expr_width();
211 if (lwid == 0) lwid = lval.len();
213 unsigned rwid = rc->expr_width();
214 if (rwid == 0) rwid = rval.len();
216 unsigned wid = expr_width();
217 if (wid == 0)
218 wid = (rwid > lwid)? rwid : lwid;
220 verinum res (verinum::V0, wid);
222 if (lwid > wid)
223 lwid = wid;
224 if (rwid > wid)
225 rwid = wid;
227 // Sub-expressions of bitwise operators need to be the same
228 // width. Pad them out if necessary.
229 if (lwid < wid) {
230 lval = pad_to_width(lval, wid);
231 lwid = wid;
233 if (rwid < wid) {
234 rval = pad_to_width(rval, wid);
235 rwid = wid;
238 switch (op()) {
240 case '|': {
241 unsigned cnt = lwid;
242 if (cnt > wid) cnt = wid;
243 if (cnt > rwid) cnt = rwid;
244 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
245 res.set(idx, lval.get(idx) | rval.get(idx));
247 if (lwid < rwid)
248 for (unsigned idx = lwid ; idx < rwid ; idx += 1)
249 res.set(idx, rval.get(idx));
251 if (rwid < lwid)
252 for (unsigned idx = rwid ; idx < lwid ; idx += 1)
253 res.set(idx, lval.get(idx));
255 break;
258 case '&': {
259 unsigned cnt = lwid;
260 if (cnt > wid) cnt = wid;
261 if (cnt > rwid) cnt = rwid;
262 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
263 res.set(idx, lval.get(idx) & rval.get(idx));
265 break;
268 case '^': {
269 unsigned cnt = lwid;
270 if (cnt > wid) cnt = wid;
271 if (cnt > rwid) cnt = rwid;
272 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
273 res.set(idx, lval.get(idx) ^ rval.get(idx));
275 if (lwid < rwid)
276 for (unsigned idx = lwid ; idx < rwid ; idx += 1)
277 res.set(idx, rval.get(idx));
279 if (rwid < lwid)
280 for (unsigned idx = rwid ; idx < lwid ; idx += 1)
281 res.set(idx, lval.get(idx));
283 break;
286 default:
287 return 0;
290 return new NetEConst(res);
294 NetEConst* NetEBComp::eval_less_()
296 if (right_->expr_type() == IVL_VT_REAL)
297 return eval_leeq_real_(left_, right_, false);
298 if (left_->expr_type() == IVL_VT_REAL)
299 return eval_leeq_real_(left_, right_, false);
301 NetEConst*r = dynamic_cast<NetEConst*>(right_);
302 if (r == 0) return 0;
304 verinum rv = r->value();
305 if (! rv.is_defined()) {
306 verinum result(verinum::Vx, 1);
307 return new NetEConst(result);
310 if (NetEConst*tmp = must_be_leeq_(left_, rv, false)) {
311 return tmp;
314 /* Now go on to the normal test of the values. */
315 NetEConst*l = dynamic_cast<NetEConst*>(left_);
316 if (l == 0) return 0;
317 verinum lv = l->value();
318 if (! lv.is_defined()) {
319 verinum result(verinum::Vx, 1);
320 return new NetEConst(result);
323 if (lv < rv) {
324 verinum result(verinum::V1, 1);
325 return new NetEConst(result);
326 } else {
327 verinum result(verinum::V0, 1);
328 return new NetEConst(result);
332 NetEConst* NetEBComp::eval_leeq_real_(NetExpr*le, NetExpr*ri, bool eq_flag)
334 NetEConst*vtmp;
335 NetECReal*rtmp;
336 double lv, rv;
338 switch (le->expr_type()) {
339 case IVL_VT_REAL:
340 rtmp = dynamic_cast<NetECReal*> (le);
341 if (rtmp == 0)
342 return 0;
344 lv = rtmp->value().as_double();
345 break;
347 case IVL_VT_LOGIC:
348 case IVL_VT_BOOL:
349 vtmp = dynamic_cast<NetEConst*> (le);
350 if (vtmp == 0)
351 return 0;
353 lv = vtmp->value().as_long();
354 break;
356 default:
357 cerr << get_fileline() << ": internal error: "
358 << "Unexpected expression type? " << le->expr_type() << endl;
359 assert(0);
363 switch (ri->expr_type()) {
364 case IVL_VT_REAL:
365 rtmp = dynamic_cast<NetECReal*> (ri);
366 if (rtmp == 0)
367 return 0;
369 rv = rtmp->value().as_double();
370 break;
372 case IVL_VT_LOGIC:
373 case IVL_VT_BOOL:
374 vtmp = dynamic_cast<NetEConst*> (ri);
375 if (vtmp == 0)
376 return 0;
378 rv = vtmp->value().as_long();
379 break;
381 default:
382 cerr << get_fileline() << ": internal error: "
383 << "Unexpected expression type? " << ri->expr_type() << endl;
384 assert(0);
387 bool test = false;
388 if (lv < rv) test = true;
389 if (test == false && eq_flag && lv == rv) test = true;
391 verinum result(test? verinum::V1 : verinum::V0, 1);
392 vtmp = new NetEConst(result);
393 vtmp->set_line(*this);
395 return vtmp;
398 NetEConst* NetEBComp::must_be_leeq_(NetExpr*le, const verinum&rv, bool eq_flag)
400 assert(le->expr_width() > 0);
401 verinum lv (verinum::V1, le->expr_width());
402 if (le->has_sign() && rv.has_sign()) {
403 // If the expression is signed, then the largest
404 // possible value for the left_ needs to have a 0 in the
405 // sign position.
406 lv.set(lv.len()-1, verinum::V0);
407 lv.has_sign(true);
410 if (lv < rv || (eq_flag && (lv == rv))) {
411 verinum result(verinum::V1, 1);
412 return new NetEConst(result);
415 return 0;
418 NetEConst* NetEBComp::eval_leeq_()
420 if (right_->expr_type() == IVL_VT_REAL)
421 return eval_leeq_real_(left_, right_, true);
422 if (left_->expr_type() == IVL_VT_REAL)
423 return eval_leeq_real_(left_, right_, true);
425 NetEConst*r = dynamic_cast<NetEConst*>(right_);
426 if (r == 0) return 0;
428 verinum rv = r->value();
429 if (! rv.is_defined()) {
430 verinum result(verinum::Vx, 1);
431 return new NetEConst(result);
434 if (left_->expr_width() == 0) {
435 cerr << get_fileline() << ": internal error: Something wrong "
436 << "with the left side width of <= ?" << endl;
437 cerr << get_fileline() << ": : " << *this << endl;
440 if (NetEConst*tmp = must_be_leeq_(left_, rv, true)) {
441 return tmp;
444 /* Now go on to the normal test of the values. */
445 NetEConst*l = dynamic_cast<NetEConst*>(left_);
446 if (l == 0) return 0;
447 verinum lv = l->value();
448 if (! lv.is_defined()) {
449 verinum result(verinum::Vx, 1);
450 return new NetEConst(result);
453 if (lv <= rv) {
454 verinum result(verinum::V1, 1);
455 return new NetEConst(result);
456 } else {
457 verinum result(verinum::V0, 1);
458 return new NetEConst(result);
462 NetEConst* NetEBComp::eval_gt_()
464 if (right_->expr_type() == IVL_VT_REAL)
465 return eval_leeq_real_(right_, left_, false);
466 if (left_->expr_type() == IVL_VT_REAL)
467 return eval_leeq_real_(right_, left_, false);
469 NetEConst*l = dynamic_cast<NetEConst*>(left_);
470 if (l == 0) return 0;
472 verinum lv = l->value();
473 if (! lv.is_defined()) {
474 verinum result(verinum::Vx, 1);
475 return new NetEConst(result);
478 if (NetEConst*tmp = must_be_leeq_(right_, lv, false)) {
479 return tmp;
482 /* Compare with a real value. Do it as double precision. */
483 if (right_->expr_type() == IVL_VT_REAL) {
484 NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
485 if (tmp == 0)
486 return 0;
488 double rr = tmp->value().as_double();
489 double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
491 verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
492 return new NetEConst(result);
495 /* Now go on to the normal test of the values. */
496 NetEConst*r = dynamic_cast<NetEConst*>(right_);
497 if (r == 0) return 0;
498 verinum rv = r->value();
499 if (! rv.is_defined()) {
500 verinum result(verinum::Vx, 1);
501 return new NetEConst(result);
504 if (lv > rv) {
505 verinum result(verinum::V1, 1);
506 return new NetEConst(result);
507 } else {
508 verinum result(verinum::V0, 1);
509 return new NetEConst(result);
513 NetEConst* NetEBComp::eval_gteq_()
515 if (right_->expr_type() == IVL_VT_REAL)
516 return eval_leeq_real_(right_, left_, true);
517 if (left_->expr_type() == IVL_VT_REAL)
518 return eval_leeq_real_(right_, left_, true);
520 NetEConst*l = dynamic_cast<NetEConst*>(left_);
521 if (l == 0) return 0;
523 verinum lv = l->value();
524 if (! lv.is_defined()) {
525 verinum result(verinum::Vx, 1);
526 return new NetEConst(result);
529 if (NetEConst*tmp = must_be_leeq_(right_, lv, true)) {
530 return tmp;
533 /* Compare with a real value. Do it as double precision. */
534 if (right_->expr_type() == IVL_VT_REAL) {
535 NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
536 if (tmp == 0)
537 return 0;
539 double rr = tmp->value().as_double();
540 double ll = lv.has_sign()? lv.as_long() : lv.as_ulong();
542 verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
543 return new NetEConst(result);
546 /* Now go on to the normal test of the values. */
547 NetEConst*r = dynamic_cast<NetEConst*>(right_);
548 if (r == 0) return 0;
549 verinum rv = r->value();
550 if (! rv.is_defined()) {
551 verinum result(verinum::Vx, 1);
552 return new NetEConst(result);
555 if (lv >= rv) {
556 verinum result(verinum::V1, 1);
557 return new NetEConst(result);
558 } else {
559 verinum result(verinum::V0, 1);
560 return new NetEConst(result);
564 NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
566 NetEConst*l = dynamic_cast<NetEConst*>(left_);
567 if (l == 0) return 0;
568 NetEConst*r = dynamic_cast<NetEConst*>(right_);
569 if (r == 0) return 0;
571 const verinum&lv = l->value();
572 const verinum&rv = r->value();
574 const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
575 const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
577 verinum::V res = eq_res;
578 unsigned top = lv.len();
579 if (rv.len() < top)
580 top = rv.len();
582 for (unsigned idx = 0 ; idx < top ; idx += 1) {
584 switch (lv.get(idx)) {
586 case verinum::Vx:
587 case verinum::Vz:
588 res = verinum::Vx;
589 break;
591 default:
592 break;
595 switch (rv.get(idx)) {
597 case verinum::Vx:
598 case verinum::Vz:
599 res = verinum::Vx;
600 break;
602 default:
603 break;
606 if (res == verinum::Vx)
607 break;
609 if (rv.get(idx) != lv.get(idx))
610 res = ne_res;
613 if (res != verinum::Vx) {
614 verinum::V lpad = verinum::V0;
615 verinum::V rpad = verinum::V0;
617 if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
618 lpad = verinum::V1;
619 if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
620 rpad = verinum::V1;
622 for (unsigned idx = top ; idx < lv.len() ; idx += 1)
623 switch (lv.get(idx)) {
625 case verinum::Vx:
626 case verinum::Vz:
627 res = verinum::Vx;
628 break;
630 case verinum::V0:
631 if (res != verinum::Vx && rpad != verinum::V0)
632 res = ne_res;
633 break;
635 case verinum::V1:
636 if (res != verinum::Vx && rpad != verinum::V1)
637 res = ne_res;
638 break;
640 default:
641 break;
644 for (unsigned idx = top ; idx < rv.len() ; idx += 1)
645 switch (rv.get(idx)) {
647 case verinum::Vx:
648 case verinum::Vz:
649 res = verinum::Vx;
650 break;
652 case verinum::V0:
653 if (res != verinum::Vx && lpad != verinum::V0)
654 res = ne_res;
655 break;
657 case verinum::V1:
658 if (res != verinum::Vx && lpad != verinum::V1)
659 res = ne_res;
660 break;
662 default:
663 break;
667 return new NetEConst(verinum(res));
670 NetEConst* NetEBComp::eval_eqeqeq_()
672 NetEConst*l = dynamic_cast<NetEConst*>(left_);
673 if (l == 0) return 0;
674 NetEConst*r = dynamic_cast<NetEConst*>(right_);
675 if (r == 0) return 0;
677 const verinum&lv = l->value();
678 const verinum&rv = r->value();
680 verinum::V res = verinum::V1;
682 unsigned cnt = lv.len();
683 if (cnt > rv.len())
684 cnt = rv.len();
686 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
687 if (lv.get(idx) != rv.get(idx))
688 res = verinum::V0;
690 for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
691 if (lv.get(idx) != verinum::V0)
692 res = verinum::V0;
694 for (unsigned idx = cnt ; idx < rv.len() ; idx += 1)
695 if (rv.get(idx) != verinum::V0)
696 res = verinum::V0;
698 return new NetEConst(verinum(res, 1));
701 NetEConst* NetEBComp::eval_neeqeq_()
703 NetEConst*tmp = eval_eqeqeq_();
704 if (tmp == 0)
705 return 0;
707 NetEConst*res;
709 if (tmp->value().get(0) == verinum::V0)
710 res = new NetEConst(verinum(verinum::V1,1));
711 else
712 res = new NetEConst(verinum(verinum::V0,1));
714 delete tmp;
715 res->set_line(*this);
716 return res;
719 NetEConst* NetEBComp::eval_tree(int prune_to_width)
721 eval_expr(left_);
722 eval_expr(right_);
724 switch (op_) {
725 case 'E': // Case equality (===)
726 return eval_eqeqeq_();
728 case 'e': // Equality (==)
729 return eval_eqeq_(false);
731 case 'G': // >=
732 return eval_gteq_();
734 case 'L': // <=
735 return eval_leeq_();
737 case 'N': // Case inequality (!==)
738 return eval_neeqeq_();
740 case 'n': // not-equal (!=)
741 return eval_eqeq_(true);
743 case '<': // Less than
744 return eval_less_();
746 case '>': // Greater than
747 return eval_gt_();
749 default:
750 return 0;
755 * The NetEBDiv operator includes the / and % operators. First evaluate
756 * the sub-expressions, then perform the required operation.
758 NetExpr* NetEBDiv::eval_tree(int prune_to_width)
760 eval_expr(left_);
761 eval_expr(right_);
763 if (expr_type() == IVL_VT_REAL) {
764 NetECReal*lc = dynamic_cast<NetECReal*>(left_);
765 if (lc == 0) return 0;
767 verireal lval = lc->value();
769 if (NetECReal*rc = dynamic_cast<NetECReal*>(right_)) {
770 NetECReal*tmp = 0;
771 verireal rval = rc->value();
773 switch (op_) {
774 case '/':
775 tmp = new NetECReal(lval / rval);
776 break;
778 case '%':
779 tmp = new NetECReal(lval % rval);
782 assert(tmp);
783 tmp->set_line(*this);
784 return tmp;
786 } else if (NetEConst*rc = dynamic_cast<NetEConst*>(right_)) {
788 NetECReal*tmp = 0;
789 verinum rval = rc->value();
791 switch (op_) {
792 case '/':
793 tmp = new NetECReal(lval / rval);
794 break;
796 case '%':
797 tmp = new NetECReal(lval % rval);
800 assert(tmp);
801 tmp->set_line(*this);
802 return tmp;
807 } else {
808 assert(expr_type() == IVL_VT_LOGIC);
809 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
810 if (lc == 0) return 0;
811 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
812 if (rc == 0) return 0;
814 verinum lval = lc->value();
815 verinum rval = rc->value();
817 NetExpr*tmp = 0;
818 switch (op_) {
819 case '/':
820 tmp = new NetEConst(lval / rval);
821 break;
822 case '%':
823 tmp = new NetEConst(lval % rval);
824 break;
826 ivl_assert(*this, tmp);
827 tmp->set_line(*this);
828 return tmp;
831 return 0;
834 NetEConst* NetEBLogic::eval_tree(int prune_to_width)
836 eval_expr(left_);
837 eval_expr(right_);
839 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
840 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
841 if (lc == 0 || rc == 0) return 0;
843 verinum::V lv = verinum::V0;
844 verinum::V rv = verinum::V0;
846 verinum v = lc->value();
847 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
848 if (v.get(idx) == verinum::V1)
849 lv = verinum::V1;
851 if (lv == verinum::V0)
852 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
853 if (v.get(idx) != verinum::V0)
854 lv = verinum::Vx;
856 v = rc->value();
857 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
858 if (v.get(idx) == verinum::V1)
859 rv = verinum::V1;
861 if (rv == verinum::V0)
862 for (unsigned idx = 0 ; idx < v.len() ; idx += 1)
863 if (v.get(idx) != verinum::V0)
864 rv = verinum::Vx;
866 verinum::V res;
867 switch (op_) {
868 case 'a': { // Logical AND (&&)
869 if ((lv == verinum::V0) || (rv == verinum::V0))
870 res = verinum::V0;
872 else if ((lv == verinum::V1) && (rv == verinum::V1))
873 res = verinum::V1;
875 else
876 res = verinum::Vx;
878 break;
881 case 'o': { // Logical OR (||)
882 if ((lv == verinum::V1) || (rv == verinum::V1))
883 res = verinum::V1;
885 else if ((lv == verinum::V0) && (rv == verinum::V0))
886 res = verinum::V0;
888 else
889 res = verinum::Vx;
891 break;
894 default:
895 return 0;
898 return new NetEConst(verinum(res, 1));
902 NetExpr* NetEBMult::eval_tree_real_()
904 verireal lval;
905 verireal rval;
907 bool flag = get_real_arguments_(lval, rval);
908 if (! flag) return 0;
911 NetECReal*res = new NetECReal(lval * rval);
912 res->set_line(*this);
913 return res;
916 NetExpr* NetEBMult::eval_tree(int prune_to_width)
918 eval_expr(left_);
919 eval_expr(right_);
921 if (expr_type() == IVL_VT_REAL)
922 return eval_tree_real_();
924 assert(expr_type() == IVL_VT_LOGIC);
926 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
927 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
928 if (lc == 0 || rc == 0) return 0;
930 verinum lval = lc->value();
931 verinum rval = rc->value();
933 NetEConst*tmp = new NetEConst(lval * rval);
935 if (debug_eval_tree)
936 cerr << get_fileline() << ": debug: Evaluate "
937 << lval << " * " << rval << " --> " << *tmp << endl;
939 return tmp;
942 NetExpr* NetEBPow::eval_tree_real_()
944 verireal lval;
945 verireal rval;
947 bool flag = get_real_arguments_(lval, rval);
948 if (! flag) return 0;
950 NetECReal*res = new NetECReal( pow(lval,rval) );
951 res->set_line(*this);
952 return res;
955 NetExpr* NetEBPow::eval_tree(int prune_to_width)
957 eval_expr(left_);
958 eval_expr(right_);
960 if (expr_type() == IVL_VT_REAL)
961 return eval_tree_real_();
963 assert(expr_type() == IVL_VT_LOGIC);
965 NetEConst*lc = dynamic_cast<NetEConst*>(left_);
966 NetEConst*rc = dynamic_cast<NetEConst*>(right_);
967 if (lc == 0 || rc == 0) return 0;
969 verinum lval = lc->value();
970 verinum rval = rc->value();
972 return new NetEConst( pow(lval,rval) );
976 * Evaluate the shift operator if possible. For this to work, both
977 * operands must be constant.
979 NetEConst* NetEBShift::eval_tree(int prune_to_width)
981 eval_expr(left_);
982 eval_expr(right_);
984 NetEConst*le = dynamic_cast<NetEConst*>(left_);
985 NetEConst*re = dynamic_cast<NetEConst*>(right_);
986 if (le == 0 || re == 0) return 0;
988 NetEConst*res;
990 verinum rv = re->value();
991 verinum lv = le->value();
993 /* Make an early estimate of the expression width. */
994 unsigned wid = expr_width();
996 if (rv.is_defined()) {
998 unsigned shift = rv.as_ulong();
1000 if (debug_eval_tree) {
1001 cerr << get_fileline() << ": debug: "
1002 << "Evaluate " << lv << "<<" << op() << ">> "
1003 << rv << ", wid=" << wid << ", shift=" << shift
1004 << ", lv.has_len()=" << lv.has_len() << endl;
1007 if ((wid == 0) || ! lv.has_len()) {
1008 /* If the caller doesn't care what the width is,
1009 then calculate a width from the trimmed left
1010 expression, plus the shift. This avoids
1011 data loss. */
1012 lv = trim_vnum(lv);
1013 wid = lv.len();
1014 if (op() == 'l')
1015 wid = lv.len() + shift;
1018 if (prune_to_width > 0 && wid > (unsigned)prune_to_width)
1019 wid = prune_to_width;
1021 assert(wid);
1022 verinum::V pad = verinum::V0;
1023 if (op() == 'R' && has_sign()) {
1024 pad = lv[lv.len()-1];
1026 verinum nv (pad, wid, lv.has_len());
1028 if (op() == 'r' || op() == 'R') {
1029 unsigned cnt = wid;
1030 if (cnt > nv.len())
1031 cnt = nv.len();
1032 if (shift >= lv.len())
1033 cnt = 0;
1034 else if (cnt > (lv.len()-shift))
1035 cnt = (lv.len()-shift);
1036 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
1037 nv.set(idx, lv[idx+shift]);
1039 } else {
1040 unsigned cnt = wid;
1041 if (cnt > lv.len())
1042 cnt = lv.len();
1043 if (shift >= nv.len())
1044 cnt = 0;
1045 else if (cnt > (nv.len()-shift))
1046 cnt = nv.len() - shift;
1048 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
1049 nv.set(idx+shift, lv[idx]);
1052 res = new NetEConst(nv);
1054 } else {
1055 if (wid == 0) wid = left_->expr_width();
1057 verinum nv (verinum::Vx, wid);
1058 res = new NetEConst(nv);
1061 return res;
1064 NetEConst* NetEConcat::eval_tree(int prune_to_width)
1066 unsigned repeat_val = repeat();
1067 unsigned local_errors = 0;
1069 if (debug_eval_tree) {
1070 cerr << get_fileline() << ": debug: Evaluate expr=" << *this
1071 << ", prune_to_width=" << prune_to_width << endl;
1074 unsigned gap = 0;
1075 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
1077 // Parameter not here? This is an error, but presumably
1078 // already caught and we are here just to catch more.
1079 if (parms_[idx] == 0) continue;
1081 // If this parameter is already a constant, all is well
1082 // so go on.
1083 if (dynamic_cast<NetEConst*>(parms_[idx])) {
1084 gap += parms_[idx]->expr_width();
1085 continue;
1088 // Finally, try to evaluate the parameter expression
1089 // that is here. If I succeed, reset the parameter to
1090 // the evaluated value.
1091 assert(parms_[idx]);
1092 NetExpr*expr = parms_[idx]->eval_tree(0);
1093 if (expr) {
1094 expr->set_line(*parms_[idx]);
1095 delete parms_[idx];
1096 parms_[idx] = expr;
1098 if (! expr->has_width()) {
1099 cerr << get_fileline() << ": error: concatenation "
1100 << "operand has indefinite width: "
1101 << *parms_[idx] << endl;
1102 local_errors += 1;
1103 } else if (expr->expr_width() == 0) {
1104 cerr << expr->get_fileline() << ": internal error: "
1105 << "Operand of concatenation has no width: "
1106 << *expr << endl;
1107 local_errors += 1;
1110 gap += expr->expr_width();
1115 if (local_errors > 0) return 0;
1117 // Handle the special case that the repeat expression is
1118 // zero. In this case, just return a 0 value with the expected
1119 // width.
1120 if (repeat_val == 0) {
1121 verinum val (verinum::V0, expr_width());
1122 NetEConst*res = new NetEConst(val);
1123 res->set_width(val.len());
1124 return res;
1127 // At this point, the "gap" is the width of a single repeat of
1128 // the concatenation. The total width of the result is the gap
1129 // times the repeat count.
1130 verinum val (verinum::Vx, repeat_val * gap);
1132 // build up the result from least significant to most.
1134 unsigned cur = 0;
1135 bool is_string_flag = true;
1136 for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
1137 NetEConst*expr = dynamic_cast<NetEConst*>(parms_[idx-1]);
1138 if (expr == 0)
1139 return 0;
1141 verinum tmp = expr->value();
1142 for (unsigned bit = 0; bit < tmp.len(); bit += 1, cur += 1)
1143 for (unsigned rep = 0 ; rep < repeat_val ; rep += 1)
1144 val.set(rep*gap+cur, tmp[bit]);
1146 is_string_flag = is_string_flag && tmp.is_string();
1149 /* If all the values were strings, then re-stringify this
1150 constant. This might be useful information in the code
1151 generator or other optimizer steps. */
1152 if (is_string_flag) {
1153 val = verinum(val.as_string());
1156 NetEConst*res = new NetEConst(val);
1157 res->set_width(val.len());
1158 return res;
1161 NetExpr* NetEParam::eval_tree(int prune_to_width)
1163 if (des_ == 0) {
1164 assert(scope_ == 0);
1165 return 0;
1168 if (debug_eval_tree) {
1169 cerr << get_fileline() << ": debug: evaluating expression: "
1170 << *this << endl;
1173 assert(scope_);
1174 const NetExpr*expr_msb;
1175 const NetExpr*expr_lsb;
1176 const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
1177 if (expr == 0) {
1178 cerr << get_fileline() << ": internal error: Unable to match "
1179 << "parameter " << name_ << " in scope "
1180 << scope_path(scope_) << endl;
1181 return 0;
1184 assert(expr);
1186 NetExpr*nexpr = expr->dup_expr();
1187 assert(nexpr);
1189 // If the parameter that I refer to is already evaluated, then
1190 // return the constant value.
1191 if (NetEConst*tmp = dynamic_cast<NetEConst*>(nexpr)) {
1192 verinum val = tmp->value();
1193 NetEConstParam*ptmp = new NetEConstParam(scope_, name_, val);
1194 ptmp->set_line(*this);
1195 delete nexpr;
1196 return ptmp;
1199 if (NetECReal*tmp = dynamic_cast<NetECReal*>(nexpr)) {
1200 verireal val = tmp->value();
1201 NetECRealParam*ptmp = new NetECRealParam(scope_, name_, val);
1202 ptmp->set_line(*this);
1203 delete nexpr;
1204 return ptmp;
1207 // Try to evaluate the expression. If I cannot, then the
1208 // expression is not a constant expression and I fail here.
1209 NetExpr*res = nexpr->eval_tree();
1210 if (res == 0) {
1211 cerr << get_fileline() << ": internal error: Unable to evaluate "
1212 << "parameter " << name_ << " expression: "
1213 << *nexpr << endl;
1214 delete nexpr;
1215 return 0;
1218 // The result can be saved as the value of the parameter for
1219 // future reference, and return a copy to the caller.
1220 bool flag = scope_->replace_parameter(name_, res);
1221 if (!flag) {
1222 cerr << get_fileline() << ": internal error: Could not "
1223 << "replace parameter expression for " << name_ << endl;
1224 return 0;
1227 /* Return as a result a NetEConstParam or NetECRealParam
1228 object, depending on the type of the expression. */
1230 switch (res->expr_type()) {
1232 case IVL_VT_BOOL:
1233 case IVL_VT_LOGIC:
1234 { NetEConst*tmp = dynamic_cast<NetEConst*>(res);
1235 if (tmp == 0) {
1236 cerr << get_fileline() << ": internal error: parameter "
1237 << name_ << " evaluates to incomprehensible "
1238 << *res << "." << endl;
1239 return 0;
1242 assert(tmp);
1244 verinum val = tmp->value();
1245 NetEConstParam*ptmp = new NetEConstParam(scope_, name_, val);
1247 return ptmp;
1250 case IVL_VT_REAL:
1251 { NetECReal*tmp = dynamic_cast<NetECReal*>(res);
1252 if (tmp == 0) {
1253 cerr << get_fileline() << ": internal error: parameter "
1254 << name_ << " evaluates to incomprehensible "
1255 << *res << "." << endl;
1256 return 0;
1259 assert(tmp);
1261 verireal val = tmp->value();
1262 NetECRealParam*ptmp = new NetECRealParam(scope_, name_, val);
1264 return ptmp;
1267 default:
1268 assert(0);
1269 return 0;
1273 NetEConst* NetESelect::eval_tree(int prune_to_width)
1275 eval_expr(expr_);
1276 NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
1278 long bval = 0;
1279 if (base_) {
1280 eval_expr(base_);
1281 NetEConst*base = dynamic_cast<NetEConst*>(base_);
1283 if (base == 0) return 0;
1285 bval = base->value().as_long();
1288 if (expr == 0) return 0;
1290 verinum eval = expr->value();
1291 verinum oval (verinum::V0, expr_width(), true);
1293 verinum::V pad_bit = verinum::Vx;
1294 if (base_ == 0) {
1296 /* If the base is NULL (different from 0) the this
1297 select is here for sign extension. So calculate a
1298 proper pad bit. Extend x or z or 0, and sign extend 1
1299 if this is signed. */
1300 unsigned top = expr->expr_width()-1;
1302 pad_bit = eval.get(top);
1303 if (pad_bit==verinum::V1 && !has_sign())
1304 pad_bit = verinum::V0;
1307 for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
1308 if ((bval >= 0) && ((unsigned long) bval < eval.len()))
1309 oval.set(idx, eval.get(bval));
1310 else
1311 oval.set(idx, pad_bit);
1313 bval += 1;
1316 oval.has_sign(has_sign());
1318 NetEConst*res = new NetEConst(oval);
1319 return res;
1323 static void print_ternary_cond(NetExpr*expr)
1325 if (NetEConst*c = dynamic_cast<NetEConst*>(expr)) {
1326 cerr << c->value() << endl;
1327 return;
1329 if (NetECReal*c = dynamic_cast<NetECReal*>(expr)) {
1330 cerr << c->value() << endl;
1331 return;
1333 assert(0);
1337 * A ternary expression evaluation is controlled by the condition
1338 * expression. If the condition evaluates to true or false, then
1339 * return the evaluated true or false expression. If the condition
1340 * evaluates to x or z, then merge the constant bits of the true and
1341 * false expressions.
1343 NetExpr* NetETernary::eval_tree(int prune_to_width)
1345 eval_expr(cond_);
1346 switch (const_logical(cond_)) {
1347 case C_0:
1348 eval_expr(false_val_);
1349 if (debug_eval_tree) {
1351 cerr << get_fileline() << ": debug: Evaluate ternary with "
1352 << "constant condition value: ";
1353 print_ternary_cond(cond_);
1354 cerr << get_fileline() << ": : Selecting false case: "
1355 << *false_val_ << endl;
1358 if (expr_type() == IVL_VT_REAL &&
1359 false_val_->expr_type() != IVL_VT_REAL) {
1360 verireal f;
1361 if (get_real_arg_(false_val_, f)) {
1362 NetECReal*rc = new NetECReal(f);
1363 rc->set_line(*this);
1364 return rc;
1368 return false_val_->dup_expr();
1370 case C_1:
1371 eval_expr(true_val_);
1372 if (debug_eval_tree) {
1373 cerr << get_fileline() << ": debug: Evaluate ternary with "
1374 << "constant condition value: ";
1375 print_ternary_cond(cond_);
1376 cerr << get_fileline() << ": : Selecting true case: "
1377 << *true_val_ << endl;
1380 if (expr_type() == IVL_VT_REAL &&
1381 true_val_->expr_type() != IVL_VT_REAL) {
1382 verireal t;
1383 if (get_real_arg_(true_val_, t)) {
1384 NetECReal*rc = new NetECReal(t);
1385 rc->set_line(*this);
1386 return rc;
1390 return true_val_->dup_expr();
1392 case C_X:
1393 break;
1395 default:
1396 return 0;
1399 /* Here we have a more complex case. We need to evaluate both
1400 expressions down to constants then compare the values to
1401 build up a constant result. */
1403 eval_expr(true_val_);
1404 eval_expr(false_val_);
1406 NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
1407 NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
1408 if (t == 0 || f == 0) {
1409 verireal tv, fv;
1410 if (!get_real_arg_(true_val_, tv)) return 0;
1411 if (!get_real_arg_(false_val_, fv)) return 0;
1413 verireal val = verireal(0.0);
1414 if (tv.as_double() == fv.as_double()) val = tv;
1416 if (debug_eval_tree) {
1417 cerr << get_fileline() << ": debug: Evaluate ternary with "
1418 << "constant condition value: ";
1419 print_ternary_cond(cond_);
1420 cerr << get_fileline() << ": : Blending real cases "
1421 << "to get " << val << endl;
1424 NetECReal*rc = new NetECReal(val);
1425 rc->set_line(*this);
1426 return rc;
1429 unsigned tsize = t->expr_width();
1430 unsigned fsize = f->expr_width();
1431 /* Size of the result is the size of the widest operand. */
1432 unsigned rsize = tsize > fsize? tsize : fsize;
1434 verinum val (verinum::V0, rsize);
1435 for (unsigned idx = 0 ; idx < rsize ; idx += 1) {
1436 verinum::V tv = idx < tsize? t->value().get(idx) : verinum::V0;
1437 verinum::V fv = idx < fsize? f->value().get(idx) : verinum::V0;
1439 if (tv == fv) val.set(idx, tv);
1440 else val.set(idx, verinum::Vx);
1443 if (debug_eval_tree) {
1444 cerr << get_fileline() << ": debug: Evaluate ternary with "
1445 << "constant condition value: ";
1446 print_ternary_cond(cond_);
1447 cerr << get_fileline() << ": : Blending cases to get "
1448 << val << endl;
1451 NetEConst*rc = new NetEConst(val);
1452 rc->set_line(*this);
1453 return rc;
1456 NetExpr* NetEUnary::eval_tree_real_()
1458 NetECReal*val= dynamic_cast<NetECReal*> (expr_), *res;
1459 if (val == 0) return 0;
1461 switch (op_) {
1462 case '+':
1463 res = new NetECReal(val->value());
1464 res->set_line(*this);
1465 return res;
1467 case '-':
1468 res = new NetECReal(-(val->value()));
1469 res->set_line(*this);
1470 return res;
1472 default:
1473 return 0;
1477 NetExpr* NetEUnary::eval_tree(int prune_to_width)
1479 eval_expr(expr_);
1480 if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
1482 NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
1483 if (rval == 0) return 0;
1485 verinum val = rval->value();
1487 switch (op_) {
1489 case '+':
1490 /* Unary + is a no-op. */
1491 return new NetEConst(val);
1493 case '-': {
1494 if (val.is_defined()) {
1496 verinum tmp (verinum::V0, val.len());
1497 tmp.has_sign(val.has_sign());
1498 val = tmp - val;
1500 } else {
1501 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1502 val.set(idx, verinum::Vx);
1505 return new NetEConst(val);
1508 case '~': {
1509 /* Bitwise not is even simpler then logical
1510 not. Just invert all the bits of the operand and
1511 make the new value with the same dimensions. */
1512 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1513 switch (val.get(idx)) {
1514 case verinum::V0:
1515 val.set(idx, verinum::V1);
1516 break;
1517 case verinum::V1:
1518 val.set(idx, verinum::V0);
1519 break;
1520 default:
1521 val.set(idx, verinum::Vx);
1524 return new NetEConst(val);
1527 case '!':
1528 assert(0);
1529 default:
1530 return 0;
1535 NetExpr* NetEUBits::eval_tree(int prune_to_width)
1537 return NetEUnary::eval_tree(prune_to_width);
1540 NetEConst* NetEUReduce::eval_tree(int prune_to_width)
1542 eval_expr(expr_);
1543 NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
1544 if (rval == 0) return 0;
1546 verinum val = rval->value();
1547 verinum::V res;
1549 switch (op_) {
1551 case '!': {
1552 /* Evaluate the unary logical not by first scanning
1553 the operand value for V1 and Vx bits. If we find
1554 any V1 bits we know that the value is TRUE, so
1555 the result of ! is V0. If there are no V1 bits
1556 but there are some Vx/Vz bits, the result is
1557 unknown. Otherwise, the result is V1. */
1558 unsigned v1 = 0, vx = 0;
1559 for (unsigned idx = 0 ; idx < val.len() ; idx += 1) {
1560 switch (val.get(idx)) {
1561 case verinum::V0:
1562 break;
1563 case verinum::V1:
1564 v1 += 1;
1565 break;
1566 default:
1567 vx += 1;
1568 break;
1572 res = v1? verinum::V0 : (vx? verinum::Vx : verinum::V1);
1573 break;
1576 case '&': {
1577 res = verinum::V1;
1578 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1579 res = res & val.get(idx);
1580 break;
1583 case '|': {
1584 res = verinum::V0;
1585 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1586 res = res | val.get(idx);
1587 break;
1590 case '^': {
1591 /* Reduction XOR. */
1592 unsigned ones = 0, unknown = 0;
1593 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1594 switch (val.get(idx)) {
1595 case verinum::V0:
1596 break;
1597 case verinum::V1:
1598 ones += 1;
1599 break;
1600 default:
1601 unknown += 1;
1602 break;
1605 if (unknown)
1606 return new NetEConst(verinum(verinum::Vx,1,true));
1607 if (ones%2)
1608 return new NetEConst(verinum(verinum::V1,1,true));
1609 return new NetEConst(verinum(verinum::V0,1,true));
1612 default:
1613 return 0;
1616 return new NetEConst(verinum(res, 1));