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 const NetExpr
*expr_msb
;
1175 const NetExpr
*expr_lsb
;
1176 const NetExpr
*expr
= scope_
->get_parameter(name_
, expr_msb
, expr_lsb
);
1178 cerr
<< get_fileline() << ": internal error: Unable to match "
1179 << "parameter " << name_
<< " in scope "
1180 << scope_path(scope_
) << endl
;
1186 NetExpr
*nexpr
= expr
->dup_expr();
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);
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);
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();
1211 cerr
<< get_fileline() << ": internal error: Unable to evaluate "
1212 << "parameter " << name_
<< " expression: "
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
);
1222 cerr
<< get_fileline() << ": internal error: Could not "
1223 << "replace parameter expression for " << name_
<< endl
;
1227 /* Return as a result a NetEConstParam or NetECRealParam
1228 object, depending on the type of the expression. */
1230 switch (res
->expr_type()) {
1234 { NetEConst
*tmp
= dynamic_cast<NetEConst
*>(res
);
1236 cerr
<< get_fileline() << ": internal error: parameter "
1237 << name_
<< " evaluates to incomprehensible "
1238 << *res
<< "." << endl
;
1244 verinum val
= tmp
->value();
1245 NetEConstParam
*ptmp
= new NetEConstParam(scope_
, name_
, val
);
1251 { NetECReal
*tmp
= dynamic_cast<NetECReal
*>(res
);
1253 cerr
<< get_fileline() << ": internal error: parameter "
1254 << name_
<< " evaluates to incomprehensible "
1255 << *res
<< "." << endl
;
1261 verireal val
= tmp
->value();
1262 NetECRealParam
*ptmp
= new NetECRealParam(scope_
, name_
, val
);
1273 NetEConst
* NetESelect::eval_tree(int prune_to_width
)
1276 NetEConst
*expr
= dynamic_cast<NetEConst
*>(expr_
);
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
;
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
));
1311 oval
.set(idx
, pad_bit
);
1316 oval
.has_sign(has_sign());
1318 NetEConst
*res
= new NetEConst(oval
);
1323 static void print_ternary_cond(NetExpr
*expr
)
1325 if (NetEConst
*c
= dynamic_cast<NetEConst
*>(expr
)) {
1326 cerr
<< c
->value() << endl
;
1329 if (NetECReal
*c
= dynamic_cast<NetECReal
*>(expr
)) {
1330 cerr
<< c
->value() << endl
;
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
)
1346 switch (const_logical(cond_
)) {
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
) {
1361 if (get_real_arg_(false_val_
, f
)) {
1362 NetECReal
*rc
= new NetECReal(f
);
1363 rc
->set_line(*this);
1368 return false_val_
->dup_expr();
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
) {
1383 if (get_real_arg_(true_val_
, t
)) {
1384 NetECReal
*rc
= new NetECReal(t
);
1385 rc
->set_line(*this);
1390 return true_val_
->dup_expr();
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) {
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);
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 "
1451 NetEConst
*rc
= new NetEConst(val
);
1452 rc
->set_line(*this);
1456 NetExpr
* NetEUnary::eval_tree_real_()
1458 NetECReal
*val
= dynamic_cast<NetECReal
*> (expr_
), *res
;
1459 if (val
== 0) return 0;
1463 res
= new NetECReal(val
->value());
1464 res
->set_line(*this);
1468 res
= new NetECReal(-(val
->value()));
1469 res
->set_line(*this);
1477 NetExpr
* NetEUnary::eval_tree(int prune_to_width
)
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();
1490 /* Unary + is a no-op. */
1491 return new NetEConst(val
);
1494 if (val
.is_defined()) {
1496 verinum
tmp (verinum::V0
, val
.len());
1497 tmp
.has_sign(val
.has_sign());
1501 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1502 val
.set(idx
, verinum::Vx
);
1505 return new NetEConst(val
);
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
)) {
1515 val
.set(idx
, verinum::V1
);
1518 val
.set(idx
, verinum::V0
);
1521 val
.set(idx
, verinum::Vx
);
1524 return new NetEConst(val
);
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
)
1543 NetEConst
*rval
= dynamic_cast<NetEConst
*>(expr_
);
1544 if (rval
== 0) return 0;
1546 verinum val
= rval
->value();
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
)) {
1572 res
= v1
? verinum::V0
: (vx
? verinum::Vx
: verinum::V1
);
1578 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1579 res
= res
& val
.get(idx
);
1585 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1586 res
= res
| val
.get(idx
);
1591 /* Reduction XOR. */
1592 unsigned ones
= 0, unknown
= 0;
1593 for (unsigned idx
= 0 ; idx
< val
.len() ; idx
+= 1)
1594 switch (val
.get(idx
)) {
1606 return new NetEConst(verinum(verinum::Vx
,1,true));
1608 return new NetEConst(verinum(verinum::V1
,1,true));
1609 return new NetEConst(verinum(verinum::V0
,1,true));
1616 return new NetEConst(verinum(res
, 1));