Merge branch 'master' into verilog-ams
[sverilog.git] / eval_tree.cc
blob7cc7b9ac87b78b3f09a82789a56815a75f7e9767
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 perm_string name = (*reference_).first;
1175 const NetExpr*expr = (*reference_).second.expr;
1176 ivl_assert(*this, expr);
1178 NetExpr*nexpr = expr->dup_expr();
1179 assert(nexpr);
1181 // If the parameter that I refer to is already evaluated, then
1182 // return the constant value.
1183 if (NetEConst*tmp = dynamic_cast<NetEConst*>(nexpr)) {
1184 verinum val = tmp->value();
1185 NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
1186 ptmp->set_line(*this);
1187 delete nexpr;
1188 return ptmp;
1191 if (NetECReal*tmp = dynamic_cast<NetECReal*>(nexpr)) {
1192 verireal val = tmp->value();
1193 NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
1194 ptmp->set_line(*this);
1195 delete nexpr;
1196 return ptmp;
1199 // Try to evaluate the expression. If I cannot, then the
1200 // expression is not a constant expression and I fail here.
1201 NetExpr*res = nexpr->eval_tree();
1202 if (res == 0) {
1203 cerr << get_fileline() << ": internal error: Unable to evaluate "
1204 << "parameter " << name << " expression: "
1205 << *nexpr << endl;
1206 delete nexpr;
1207 return 0;
1210 // The result can be saved as the value of the parameter for
1211 // future reference, and return a copy to the caller.
1212 bool flag = scope_->replace_parameter(name, res);
1213 if (!flag) {
1214 cerr << get_fileline() << ": internal error: Could not "
1215 << "replace parameter expression for " << name << endl;
1216 return 0;
1219 /* Return as a result a NetEConstParam or NetECRealParam
1220 object, depending on the type of the expression. */
1222 switch (res->expr_type()) {
1224 case IVL_VT_BOOL:
1225 case IVL_VT_LOGIC:
1226 { NetEConst*tmp = dynamic_cast<NetEConst*>(res);
1227 if (tmp == 0) {
1228 cerr << get_fileline() << ": internal error: parameter "
1229 << name << " evaluates to incomprehensible "
1230 << *res << "." << endl;
1231 return 0;
1234 assert(tmp);
1236 verinum val = tmp->value();
1237 NetEConstParam*ptmp = new NetEConstParam(scope_, name, val);
1239 return ptmp;
1242 case IVL_VT_REAL:
1243 { NetECReal*tmp = dynamic_cast<NetECReal*>(res);
1244 if (tmp == 0) {
1245 cerr << get_fileline() << ": internal error: parameter "
1246 << name << " evaluates to incomprehensible "
1247 << *res << "." << endl;
1248 return 0;
1251 assert(tmp);
1253 verireal val = tmp->value();
1254 NetECRealParam*ptmp = new NetECRealParam(scope_, name, val);
1256 return ptmp;
1259 default:
1260 assert(0);
1261 return 0;
1265 NetEConst* NetESelect::eval_tree(int prune_to_width)
1267 eval_expr(expr_);
1268 NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
1270 long bval = 0;
1271 if (base_) {
1272 eval_expr(base_);
1273 NetEConst*base = dynamic_cast<NetEConst*>(base_);
1275 if (base == 0) return 0;
1277 bval = base->value().as_long();
1280 if (expr == 0) return 0;
1282 verinum eval = expr->value();
1283 verinum oval (verinum::V0, expr_width(), true);
1285 verinum::V pad_bit = verinum::Vx;
1286 if (base_ == 0) {
1288 /* If the base is NULL (different from 0) the this
1289 select is here for sign extension. So calculate a
1290 proper pad bit. Extend x or z or 0, and sign extend 1
1291 if this is signed. */
1292 unsigned top = expr->expr_width()-1;
1294 pad_bit = eval.get(top);
1295 if (pad_bit==verinum::V1 && !has_sign())
1296 pad_bit = verinum::V0;
1299 for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
1300 if ((bval >= 0) && ((unsigned long) bval < eval.len()))
1301 oval.set(idx, eval.get(bval));
1302 else
1303 oval.set(idx, pad_bit);
1305 bval += 1;
1308 oval.has_sign(has_sign());
1310 NetEConst*res = new NetEConst(oval);
1311 return res;
1315 static void print_ternary_cond(NetExpr*expr)
1317 if (NetEConst*c = dynamic_cast<NetEConst*>(expr)) {
1318 cerr << c->value() << endl;
1319 return;
1321 if (NetECReal*c = dynamic_cast<NetECReal*>(expr)) {
1322 cerr << c->value() << endl;
1323 return;
1325 assert(0);
1329 * A ternary expression evaluation is controlled by the condition
1330 * expression. If the condition evaluates to true or false, then
1331 * return the evaluated true or false expression. If the condition
1332 * evaluates to x or z, then merge the constant bits of the true and
1333 * false expressions.
1335 NetExpr* NetETernary::eval_tree(int prune_to_width)
1337 eval_expr(cond_);
1338 switch (const_logical(cond_)) {
1339 case C_0:
1340 eval_expr(false_val_);
1341 if (debug_eval_tree) {
1343 cerr << get_fileline() << ": debug: Evaluate ternary with "
1344 << "constant condition value: ";
1345 print_ternary_cond(cond_);
1346 cerr << get_fileline() << ": : Selecting false case: "
1347 << *false_val_ << endl;
1350 if (expr_type() == IVL_VT_REAL &&
1351 false_val_->expr_type() != IVL_VT_REAL) {
1352 verireal f;
1353 if (get_real_arg_(false_val_, f)) {
1354 NetECReal*rc = new NetECReal(f);
1355 rc->set_line(*this);
1356 return rc;
1360 return false_val_->dup_expr();
1362 case C_1:
1363 eval_expr(true_val_);
1364 if (debug_eval_tree) {
1365 cerr << get_fileline() << ": debug: Evaluate ternary with "
1366 << "constant condition value: ";
1367 print_ternary_cond(cond_);
1368 cerr << get_fileline() << ": : Selecting true case: "
1369 << *true_val_ << endl;
1372 if (expr_type() == IVL_VT_REAL &&
1373 true_val_->expr_type() != IVL_VT_REAL) {
1374 verireal t;
1375 if (get_real_arg_(true_val_, t)) {
1376 NetECReal*rc = new NetECReal(t);
1377 rc->set_line(*this);
1378 return rc;
1382 return true_val_->dup_expr();
1384 case C_X:
1385 break;
1387 default:
1388 return 0;
1391 /* Here we have a more complex case. We need to evaluate both
1392 expressions down to constants then compare the values to
1393 build up a constant result. */
1395 eval_expr(true_val_);
1396 eval_expr(false_val_);
1398 NetEConst*t = dynamic_cast<NetEConst*>(true_val_);
1399 NetEConst*f = dynamic_cast<NetEConst*>(false_val_);
1400 if (t == 0 || f == 0) {
1401 verireal tv, fv;
1402 if (!get_real_arg_(true_val_, tv)) return 0;
1403 if (!get_real_arg_(false_val_, fv)) return 0;
1405 verireal val = verireal(0.0);
1406 if (tv.as_double() == fv.as_double()) val = tv;
1408 if (debug_eval_tree) {
1409 cerr << get_fileline() << ": debug: Evaluate ternary with "
1410 << "constant condition value: ";
1411 print_ternary_cond(cond_);
1412 cerr << get_fileline() << ": : Blending real cases "
1413 << "to get " << val << endl;
1416 NetECReal*rc = new NetECReal(val);
1417 rc->set_line(*this);
1418 return rc;
1421 unsigned tsize = t->expr_width();
1422 unsigned fsize = f->expr_width();
1423 /* Size of the result is the size of the widest operand. */
1424 unsigned rsize = tsize > fsize? tsize : fsize;
1426 verinum val (verinum::V0, rsize);
1427 for (unsigned idx = 0 ; idx < rsize ; idx += 1) {
1428 verinum::V tv = idx < tsize? t->value().get(idx) : verinum::V0;
1429 verinum::V fv = idx < fsize? f->value().get(idx) : verinum::V0;
1431 if (tv == fv) val.set(idx, tv);
1432 else val.set(idx, verinum::Vx);
1435 if (debug_eval_tree) {
1436 cerr << get_fileline() << ": debug: Evaluate ternary with "
1437 << "constant condition value: ";
1438 print_ternary_cond(cond_);
1439 cerr << get_fileline() << ": : Blending cases to get "
1440 << val << endl;
1443 NetEConst*rc = new NetEConst(val);
1444 rc->set_line(*this);
1445 return rc;
1448 NetExpr* NetEUnary::eval_tree_real_()
1450 NetECReal*val= dynamic_cast<NetECReal*> (expr_), *res;
1451 if (val == 0) return 0;
1453 switch (op_) {
1454 case '+':
1455 res = new NetECReal(val->value());
1456 res->set_line(*this);
1457 return res;
1459 case '-':
1460 res = new NetECReal(-(val->value()));
1461 res->set_line(*this);
1462 return res;
1464 default:
1465 return 0;
1469 NetExpr* NetEUnary::eval_tree(int prune_to_width)
1471 eval_expr(expr_);
1472 if (expr_type() == IVL_VT_REAL) return eval_tree_real_();
1474 NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
1475 if (rval == 0) return 0;
1477 verinum val = rval->value();
1479 switch (op_) {
1481 case '+':
1482 /* Unary + is a no-op. */
1483 return new NetEConst(val);
1485 case '-': {
1486 if (val.is_defined()) {
1488 verinum tmp (verinum::V0, val.len());
1489 tmp.has_sign(val.has_sign());
1490 val = tmp - val;
1492 } else {
1493 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1494 val.set(idx, verinum::Vx);
1497 return new NetEConst(val);
1500 case '~': {
1501 /* Bitwise not is even simpler then logical
1502 not. Just invert all the bits of the operand and
1503 make the new value with the same dimensions. */
1504 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1505 switch (val.get(idx)) {
1506 case verinum::V0:
1507 val.set(idx, verinum::V1);
1508 break;
1509 case verinum::V1:
1510 val.set(idx, verinum::V0);
1511 break;
1512 default:
1513 val.set(idx, verinum::Vx);
1516 return new NetEConst(val);
1519 case '!':
1520 assert(0);
1521 default:
1522 return 0;
1527 NetExpr* NetEUBits::eval_tree(int prune_to_width)
1529 return NetEUnary::eval_tree(prune_to_width);
1532 NetEConst* NetEUReduce::eval_tree(int prune_to_width)
1534 eval_expr(expr_);
1535 NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
1536 if (rval == 0) return 0;
1538 verinum val = rval->value();
1539 verinum::V res;
1541 switch (op_) {
1543 case '!': {
1544 /* Evaluate the unary logical not by first scanning
1545 the operand value for V1 and Vx bits. If we find
1546 any V1 bits we know that the value is TRUE, so
1547 the result of ! is V0. If there are no V1 bits
1548 but there are some Vx/Vz bits, the result is
1549 unknown. Otherwise, the result is V1. */
1550 unsigned v1 = 0, vx = 0;
1551 for (unsigned idx = 0 ; idx < val.len() ; idx += 1) {
1552 switch (val.get(idx)) {
1553 case verinum::V0:
1554 break;
1555 case verinum::V1:
1556 v1 += 1;
1557 break;
1558 default:
1559 vx += 1;
1560 break;
1564 res = v1? verinum::V0 : (vx? verinum::Vx : verinum::V1);
1565 break;
1568 case '&': {
1569 res = verinum::V1;
1570 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1571 res = res & val.get(idx);
1572 break;
1575 case '|': {
1576 res = verinum::V0;
1577 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1578 res = res | val.get(idx);
1579 break;
1582 case '^': {
1583 /* Reduction XOR. */
1584 unsigned ones = 0, unknown = 0;
1585 for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
1586 switch (val.get(idx)) {
1587 case verinum::V0:
1588 break;
1589 case verinum::V1:
1590 ones += 1;
1591 break;
1592 default:
1593 unknown += 1;
1594 break;
1597 if (unknown)
1598 return new NetEConst(verinum(verinum::Vx,1,true));
1599 if (ones%2)
1600 return new NetEConst(verinum(verinum::V1,1,true));
1601 return new NetEConst(verinum(verinum::V0,1,true));
1604 default:
1605 return 0;
1608 return new NetEConst(verinum(res, 1));