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