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)
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
21 # include "compiler.h"
27 # include "ivl_assert.h"
30 NetExpr
* NetExpr::eval_tree(int prune_to_width
)
35 static bool get_real_arg_(NetExpr
*expr
, verireal
&val
)
37 switch (expr
->expr_type()) {
39 NetECReal
*c
= dynamic_cast<NetECReal
*> (expr
);
40 if (c
== 0) return false;
47 NetEConst
*c
= dynamic_cast<NetEConst
*>(expr
);
48 if (c
== 0) return false;
49 verinum tmp
= c
->value();
50 val
= verireal(tmp
.as_double());
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;
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();
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. */
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)
111 verinum val2
=verinum(val
,wid
);
114 /* No fixed width, so trim the bits losslessly. */
115 verinum val2
= trim_vnum(val
);
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) {
131 verinum lval
= lc
->value();
132 verinum rval
= rc
->value();
135 if (op_
== se
->op_
) {
136 /* (a + lval) + rval --> a + (rval+lval) */
137 /* (a - lval) - rval --> a - (rval+lval) */
140 /* (a - lval) + rval --> a + (rval-lval) */
141 /* (a + lval) - rval --> a - (rval-lval) */
145 NetEConst
*tmp
= new NetEConst(val
);
146 left_
= se
->left_
->dup_expr();
148 tmp
->set_line(*right_
);
151 /* We've changed the subexpression, but the result is
152 still not constant, so return nil here anyhow. */
156 /* Nothing more to be done, the value is not constant. */
160 NetECReal
* NetEBAdd::eval_tree_real_()
164 bool flag
= get_real_arguments_(lval
, rval
);
171 res_val
= lval
+ rval
;
174 res_val
= lval
- rval
;
177 ivl_assert(*this, 0);
180 NetECReal
*res
= new NetECReal( res_val
);
181 res
->set_line(*this);
185 NetEConst
* NetEBBits::eval_tree(int prune_to_width
)
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
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();
218 wid
= (rwid
> lwid
)? rwid
: lwid
;
220 verinum
res (verinum::V0
, wid
);
227 // Sub-expressions of bitwise operators need to be the same
228 // width. Pad them out if necessary.
230 lval
= pad_to_width(lval
, wid
);
234 rval
= pad_to_width(rval
, wid
);
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
));
248 for (unsigned idx
= lwid
; idx
< rwid
; idx
+= 1)
249 res
.set(idx
, rval
.get(idx
));
252 for (unsigned idx
= rwid
; idx
< lwid
; idx
+= 1)
253 res
.set(idx
, lval
.get(idx
));
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
));
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
));
276 for (unsigned idx
= lwid
; idx
< rwid
; idx
+= 1)
277 res
.set(idx
, rval
.get(idx
));
280 for (unsigned idx
= rwid
; idx
< lwid
; idx
+= 1)
281 res
.set(idx
, lval
.get(idx
));
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)) {
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
);
324 verinum
result(verinum::V1
, 1);
325 return new NetEConst(result
);
327 verinum
result(verinum::V0
, 1);
328 return new NetEConst(result
);
332 NetEConst
* NetEBComp::eval_leeq_real_(NetExpr
*le
, NetExpr
*ri
, bool eq_flag
)
338 switch (le
->expr_type()) {
340 rtmp
= dynamic_cast<NetECReal
*> (le
);
344 lv
= rtmp
->value().as_double();
349 vtmp
= dynamic_cast<NetEConst
*> (le
);
353 lv
= vtmp
->value().as_long();
357 cerr
<< get_fileline() << ": internal error: "
358 << "Unexpected expression type? " << le
->expr_type() << endl
;
363 switch (ri
->expr_type()) {
365 rtmp
= dynamic_cast<NetECReal
*> (ri
);
369 rv
= rtmp
->value().as_double();
374 vtmp
= dynamic_cast<NetEConst
*> (ri
);
378 rv
= vtmp
->value().as_long();
382 cerr
<< get_fileline() << ": internal error: "
383 << "Unexpected expression type? " << ri
->expr_type() << endl
;
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);
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
406 lv
.set(lv
.len()-1, verinum::V0
);
410 if (lv
< rv
|| (eq_flag
&& (lv
== rv
))) {
411 verinum
result(verinum::V1
, 1);
412 return new NetEConst(result
);
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)) {
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
);
454 verinum
result(verinum::V1
, 1);
455 return new NetEConst(result
);
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)) {
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_
);
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
);
505 verinum
result(verinum::V1
, 1);
506 return new NetEConst(result
);
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)) {
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_
);
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
);
556 verinum
result(verinum::V1
, 1);
557 return new NetEConst(result
);
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();
582 for (unsigned idx
= 0 ; idx
< top
; idx
+= 1) {
584 switch (lv
.get(idx
)) {
595 switch (rv
.get(idx
)) {
606 if (res
== verinum::Vx
)
609 if (rv
.get(idx
) != lv
.get(idx
))
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
)
619 if (rv
.has_sign() && rv
.get(rv
.len()-1) == verinum::V1
)
622 for (unsigned idx
= top
; idx
< lv
.len() ; idx
+= 1)
623 switch (lv
.get(idx
)) {
631 if (res
!= verinum::Vx
&& rpad
!= verinum::V0
)
636 if (res
!= verinum::Vx
&& rpad
!= verinum::V1
)
644 for (unsigned idx
= top
; idx
< rv
.len() ; idx
+= 1)
645 switch (rv
.get(idx
)) {
653 if (res
!= verinum::Vx
&& lpad
!= verinum::V0
)
658 if (res
!= verinum::Vx
&& lpad
!= verinum::V1
)
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();
686 for (unsigned idx
= 0 ; idx
< cnt
; idx
+= 1)
687 if (lv
.get(idx
) != rv
.get(idx
))
690 for (unsigned idx
= cnt
; idx
< lv
.len() ; idx
+= 1)
691 if (lv
.get(idx
) != verinum::V0
)
694 for (unsigned idx
= cnt
; idx
< rv
.len() ; idx
+= 1)
695 if (rv
.get(idx
) != verinum::V0
)
698 return new NetEConst(verinum(res
, 1));
701 NetEConst
* NetEBComp::eval_neeqeq_()
703 NetEConst
*tmp
= eval_eqeqeq_();
709 if (tmp
->value().get(0) == verinum::V0
)
710 res
= new NetEConst(verinum(verinum::V1
,1));
712 res
= new NetEConst(verinum(verinum::V0
,1));
715 res
->set_line(*this);
719 NetEConst
* NetEBComp::eval_tree(int prune_to_width
)
725 case 'E': // Case equality (===)
726 return eval_eqeqeq_();
728 case 'e': // Equality (==)
729 return eval_eqeq_(false);
737 case 'N': // Case inequality (!==)
738 return eval_neeqeq_();
740 case 'n': // not-equal (!=)
741 return eval_eqeq_(true);
743 case '<': // Less than
746 case '>': // Greater than
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
)
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_
)) {
771 verireal rval
= rc
->value();
775 tmp
= new NetECReal(lval
/ rval
);
779 tmp
= new NetECReal(lval
% rval
);
783 tmp
->set_line(*this);
786 } else if (NetEConst
*rc
= dynamic_cast<NetEConst
*>(right_
)) {
789 verinum rval
= rc
->value();
793 tmp
= new NetECReal(lval
/ rval
);
797 tmp
= new NetECReal(lval
% rval
);
801 tmp
->set_line(*this);
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();
820 tmp
= new NetEConst(lval
/ rval
);
823 tmp
= new NetEConst(lval
% rval
);
826 ivl_assert(*this, tmp
);
827 tmp
->set_line(*this);
834 NetEConst
* NetEBLogic::eval_tree(int prune_to_width
)
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
)
851 if (lv
== verinum::V0
)
852 for (unsigned idx
= 0 ; idx
< v
.len() ; idx
+= 1)
853 if (v
.get(idx
) != verinum::V0
)
857 for (unsigned idx
= 0 ; idx
< v
.len() ; idx
+= 1)
858 if (v
.get(idx
) == verinum::V1
)
861 if (rv
== verinum::V0
)
862 for (unsigned idx
= 0 ; idx
< v
.len() ; idx
+= 1)
863 if (v
.get(idx
) != verinum::V0
)
868 case 'a': { // Logical AND (&&)
869 if ((lv
== verinum::V0
) || (rv
== verinum::V0
))
872 else if ((lv
== verinum::V1
) && (rv
== verinum::V1
))
881 case 'o': { // Logical OR (||)
882 if ((lv
== verinum::V1
) || (rv
== verinum::V1
))
885 else if ((lv
== verinum::V0
) && (rv
== verinum::V0
))
898 return new NetEConst(verinum(res
, 1));
902 NetExpr
* NetEBMult::eval_tree_real_()
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);
916 NetExpr
* NetEBMult::eval_tree(int prune_to_width
)
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
);
936 cerr
<< get_fileline() << ": debug: Evaluate "
937 << lval
<< " * " << rval
<< " --> " << *tmp
<< endl
;
942 NetExpr
* NetEBPow::eval_tree_real_()
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);
955 NetExpr
* NetEBPow::eval_tree(int prune_to_width
)
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
)
984 NetEConst
*le
= dynamic_cast<NetEConst
*>(left_
);
985 NetEConst
*re
= dynamic_cast<NetEConst
*>(right_
);
986 if (le
== 0 || re
== 0) return 0;
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
1015 wid
= lv
.len() + shift
;
1018 if (prune_to_width
> 0 && wid
> (unsigned)prune_to_width
)
1019 wid
= prune_to_width
;
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') {
1032 if (shift
>= lv
.len())
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
]);
1043 if (shift
>= nv
.len())
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
);
1055 if (wid
== 0) wid
= left_
->expr_width();
1057 verinum
nv (verinum::Vx
, wid
);
1058 res
= new NetEConst(nv
);
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
;
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
1083 if (dynamic_cast<NetEConst
*>(parms_
[idx
])) {
1084 gap
+= parms_
[idx
]->expr_width();
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);
1094 expr
->set_line(*parms_
[idx
]);
1098 if (! expr
->has_width()) {
1099 cerr
<< get_fileline() << ": error: concatenation "
1100 << "operand has indefinite width: "
1101 << *parms_
[idx
] << endl
;
1103 } else if (expr
->expr_width() == 0) {
1104 cerr
<< expr
->get_fileline() << ": internal error: "
1105 << "Operand of concatenation has no width: "
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
1120 if (repeat_val
== 0) {
1121 verinum
val (verinum::V0
, expr_width());
1122 NetEConst
*res
= new NetEConst(val
);
1123 res
->set_width(val
.len());
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.
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]);
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());
1161 NetExpr
* NetEParam::eval_tree(int prune_to_width
)
1164 assert(scope_
== 0);
1168 if (debug_eval_tree
) {
1169 cerr
<< get_fileline() << ": debug: evaluating expression: "
1174 perm_string name
= (*reference_
).first
;
1175 const NetExpr
*expr
= (*reference_
).second
.expr
;
1176 ivl_assert(*this, expr
);
1178 NetExpr
*nexpr
= expr
->dup_expr();
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);
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);
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();
1203 cerr
<< get_fileline() << ": internal error: Unable to evaluate "
1204 << "parameter " << name
<< " expression: "
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
);
1214 cerr
<< get_fileline() << ": internal error: Could not "
1215 << "replace parameter expression for " << name
<< endl
;
1219 /* Return as a result a NetEConstParam or NetECRealParam
1220 object, depending on the type of the expression. */
1222 switch (res
->expr_type()) {
1226 { NetEConst
*tmp
= dynamic_cast<NetEConst
*>(res
);
1228 cerr
<< get_fileline() << ": internal error: parameter "
1229 << name
<< " evaluates to incomprehensible "
1230 << *res
<< "." << endl
;
1236 verinum val
= tmp
->value();
1237 NetEConstParam
*ptmp
= new NetEConstParam(scope_
, name
, val
);
1243 { NetECReal
*tmp
= dynamic_cast<NetECReal
*>(res
);
1245 cerr
<< get_fileline() << ": internal error: parameter "
1246 << name
<< " evaluates to incomprehensible "
1247 << *res
<< "." << endl
;
1253 verireal val
= tmp
->value();
1254 NetECRealParam
*ptmp
= new NetECRealParam(scope_
, name
, val
);
1265 NetEConst
* NetESelect::eval_tree(int prune_to_width
)
1268 NetEConst
*expr
= dynamic_cast<NetEConst
*>(expr_
);
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
;
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
));
1303 oval
.set(idx
, pad_bit
);
1308 oval
.has_sign(has_sign());
1310 NetEConst
*res
= new NetEConst(oval
);
1315 static void print_ternary_cond(NetExpr
*expr
)
1317 if (NetEConst
*c
= dynamic_cast<NetEConst
*>(expr
)) {
1318 cerr
<< c
->value() << endl
;
1321 if (NetECReal
*c
= dynamic_cast<NetECReal
*>(expr
)) {
1322 cerr
<< c
->value() << endl
;
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
)
1338 switch (const_logical(cond_
)) {
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
) {
1353 if (get_real_arg_(false_val_
, f
)) {
1354 NetECReal
*rc
= new NetECReal(f
);
1355 rc
->set_line(*this);
1360 return false_val_
->dup_expr();
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
) {
1375 if (get_real_arg_(true_val_
, t
)) {
1376 NetECReal
*rc
= new NetECReal(t
);
1377 rc
->set_line(*this);
1382 return true_val_
->dup_expr();
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) {
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);
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 "
1443 NetEConst
*rc
= new NetEConst(val
);
1444 rc
->set_line(*this);
1448 NetExpr
* NetEUnary::eval_tree_real_()
1450 NetECReal
*val
= dynamic_cast<NetECReal
*> (expr_
), *res
;
1451 if (val
== 0) return 0;
1455 res
= new NetECReal(val
->value());
1456 res
->set_line(*this);
1460 res
= new NetECReal(-(val
->value()));
1461 res
->set_line(*this);
1469 NetExpr
* NetEUnary::eval_tree(int prune_to_width
)
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();
1482 /* Unary + is a no-op. */
1483 return new NetEConst(val
);
1486 if (val
.is_defined()) {
1488 verinum
tmp (verinum::V0
, val
.len());
1489 tmp
.has_sign(val
.has_sign());
1493 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1494 val
.set(idx
, verinum::Vx
);
1497 return new NetEConst(val
);
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
)) {
1507 val
.set(idx
, verinum::V1
);
1510 val
.set(idx
, verinum::V0
);
1513 val
.set(idx
, verinum::Vx
);
1516 return new NetEConst(val
);
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
)
1535 NetEConst
*rval
= dynamic_cast<NetEConst
*>(expr_
);
1536 if (rval
== 0) return 0;
1538 verinum val
= rval
->value();
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
)) {
1564 res
= v1
? verinum::V0
: (vx
? verinum::Vx
: verinum::V1
);
1570 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1571 res
= res
& val
.get(idx
);
1577 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1578 res
= res
| val
.get(idx
);
1583 /* Reduction XOR. */
1584 unsigned ones
= 0, unknown
= 0;
1585 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1586 switch (val
.get(idx
)) {
1598 return new NetEConst(verinum(verinum::Vx
,1,true));
1600 return new NetEConst(verinum(verinum::V1
,1,true));
1601 return new NetEConst(verinum(verinum::V0
,1,true));
1608 return new NetEConst(verinum(res
, 1));