Fix for assertion error when expanding macro.
[iverilog.git] / eval.cc
blob69cbd795b4461a48d0b017af9beffd6a9e197c6b
1 /*
2 * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
27 # include "PExpr.h"
28 # include "netlist.h"
29 # include "netmisc.h"
30 # include "compiler.h"
32 verinum* PExpr::eval_const(Design*, NetScope*) const
34 return 0;
37 verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
39 verinum*l = left_->eval_const(des, scope);
40 if (l == 0) return 0;
41 verinum*r = right_->eval_const(des, scope);
42 if (r == 0) {
43 delete l;
44 return 0;
46 verinum*res;
48 switch (op_) {
49 case '+': {
50 if (l->is_defined() && r->is_defined()) {
51 res = new verinum(*l + *r);
52 } else {
53 res = new verinum(verinum::Vx, l->len());
55 break;
57 case '-': {
58 if (l->is_defined() && r->is_defined()) {
59 res = new verinum(*l - *r);
60 } else {
61 res = new verinum(verinum::Vx, l->len());
63 break;
65 case '*': {
66 if (l->is_defined() && r->is_defined()) {
67 res = new verinum(*l * *r);
68 } else {
69 res = new verinum(verinum::Vx, l->len());
71 break;
73 case '/': {
74 if (l->is_defined() && r->is_defined()) {
75 long lv = l->as_long();
76 long rv = r->as_long();
77 res = new verinum(lv / rv, l->len());
78 } else {
79 res = new verinum(verinum::Vx, l->len());
81 break;
83 case '%': {
84 if (l->is_defined() && r->is_defined()) {
85 long lv = l->as_long();
86 long rv = r->as_long();
87 res = new verinum(lv % rv, l->len());
88 } else {
89 res = new verinum(verinum::Vx, l->len());
91 break;
93 case '>': {
94 if (l->is_defined() && r->is_defined()) {
95 long lv = l->as_long();
96 long rv = r->as_long();
97 res = new verinum(lv > rv, l->len());
98 } else {
99 res = new verinum(verinum::Vx, l->len());
101 break;
103 case '<': {
104 if (l->is_defined() && r->is_defined()) {
105 long lv = l->as_long();
106 long rv = r->as_long();
107 res = new verinum(lv < rv, l->len());
108 } else {
109 res = new verinum(verinum::Vx, l->len());
111 break;
113 case 'l': { // left shift (<<)
114 assert(r->is_defined());
115 unsigned long rv = r->as_ulong();
116 res = new verinum(verinum::V0, l->len());
117 if (rv < res->len()) {
118 unsigned cnt = res->len() - rv;
119 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
120 res->set(idx+rv, l->get(idx));
122 break;
124 case 'r': { // right shift (>>)
125 assert(r->is_defined());
126 unsigned long rv = r->as_ulong();
127 res = new verinum(verinum::V0, l->len());
128 if (rv < res->len()) {
129 unsigned cnt = res->len() - rv;
130 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
131 res->set(idx, l->get(idx+rv));
133 break;
136 default:
137 delete l;
138 delete r;
139 return 0;
142 delete l;
143 delete r;
144 return res;
146 verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
148 verinum*accum = parms_[0]->eval_const(des, scope);
149 if (accum == 0)
150 return 0;
152 for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
154 verinum*tmp = parms_[idx]->eval_const(des, scope);
155 if (tmp == 0) {
156 delete accum;
157 return 0;
159 assert(tmp);
161 *accum = concat(*accum, *tmp);
162 delete tmp;
165 return accum;
170 * Evaluate an identifier as a constant expression. This is only
171 * possible if the identifier is that of a parameter.
173 verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
175 assert(scope);
176 NetNet*net;
177 NetEvent*eve;
178 const NetExpr*expr;
180 const name_component_t&name_tail = path_.back();
182 // Handle the special case that this ident is a genvar
183 // variable name. In that case, the genvar meaning preempts
184 // everything and we just return that value immediately.
185 if (scope->genvar_tmp
186 && strcmp(name_tail.name,scope->genvar_tmp) == 0) {
187 return new verinum(scope->genvar_tmp_val);
190 symbol_search(des, scope, path_, net, expr, eve);
192 if (expr == 0)
193 return 0;
195 const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
196 if (eval == 0) {
197 cerr << get_line() << ": internal error: Unable to evaluate "
198 << "constant expression (parameter=" << path_
199 << "): " << *expr << endl;
200 return 0;
203 assert(eval);
205 if (!name_tail.index.empty())
206 return 0;
209 return new verinum(eval->value());
212 verinum* PEFNumber::eval_const(Design*, NetScope*) const
214 long val = value_->as_long();
215 return new verinum(val);
218 verinum* PENumber::eval_const(Design*, NetScope*) const
220 return new verinum(value());
223 verinum* PEString::eval_const(Design*, NetScope*) const
225 return new verinum(string(text_));
228 verinum* PETernary::eval_const(Design*des, NetScope*scope) const
230 verinum*test = expr_->eval_const(des, scope);
231 if (test == 0)
232 return 0;
234 verinum::V bit = test->get(0);
235 delete test;
236 switch (bit) {
237 case verinum::V0:
238 return fal_->eval_const(des, scope);
239 case verinum::V1:
240 return tru_->eval_const(des, scope);
241 default:
242 return 0;
243 // XXXX It is possible to handle this case if both fal_
244 // and tru_ are constant. Someday...
248 verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
250 verinum*val = expr_->eval_const(des, scope);
251 if (val == 0)
252 return 0;
254 switch (op_) {
255 case '+':
256 return val;
258 case '-': {
259 /* We need to expand the value a bit if we are
260 taking the 2's complement so that we are
261 guaranteed to not overflow. */
262 verinum tmp ((uint64_t)0, val->len()+1);
263 for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
264 tmp.set(idx, val->get(idx));
266 *val = v_not(tmp) + verinum(verinum::V1, 1);
267 val->has_sign(true);
268 return val;
272 delete val;
273 return 0;
278 * $Log: eval.cc,v $
279 * Revision 1.47 2007/06/04 19:14:06 steve
280 * Build errors in picky GCC compilers.
282 * Revision 1.46 2007/05/24 04:07:12 steve
283 * Rework the heirarchical identifier parse syntax and pform
284 * to handle more general combinations of heirarch and bit selects.
286 * Revision 1.45 2007/03/07 00:38:15 steve
287 * Lint fixes.
289 * Revision 1.44 2007/01/16 05:44:15 steve
290 * Major rework of array handling. Memories are replaced with the
291 * more general concept of arrays. The NetMemory and NetEMemory
292 * classes are removed from the ivl core program, and the IVL_LPM_RAM
293 * lpm type is removed from the ivl_target API.
295 * Revision 1.43 2006/08/08 05:11:37 steve
296 * Handle 64bit delay constants.
298 * Revision 1.42 2006/05/19 04:07:24 steve
299 * eval_const is not strict.
301 * Revision 1.41 2006/05/17 16:49:30 steve
302 * Error message if concat expression cannot evaluate.
304 * Revision 1.40 2006/04/10 00:37:42 steve
305 * Add support for generate loops w/ wires and gates.
307 * Revision 1.39 2005/12/07 04:04:23 steve
308 * Allow constant concat expressions.
310 * Revision 1.38 2005/11/27 17:01:57 steve
311 * Fix for stubborn compiler.
313 * Revision 1.37 2005/11/27 05:56:20 steve
314 * Handle bit select of parameter with ranges.
316 * Revision 1.36 2003/06/21 01:21:43 steve
317 * Harmless fixup of warnings.
319 * Revision 1.35 2003/04/14 03:40:21 steve
320 * Make some effort to preserve bits while
321 * operating on constant values.
323 * Revision 1.34 2003/03/26 06:16:18 steve
324 * Evaluate > and < in constant expressions.
326 * Revision 1.33 2003/03/10 23:40:53 steve
327 * Keep parameter constants for the ivl_target API.
329 * Revision 1.32 2002/10/19 22:59:49 steve
330 * Redo the parameter vector support to allow
331 * parameter names in range expressions.
333 * Revision 1.31 2002/10/13 05:01:07 steve
334 * More verbose eval_const assert message.
336 * Revision 1.30 2002/08/12 01:34:59 steve
337 * conditional ident string using autoconfig.
339 * Revision 1.29 2002/06/07 02:57:54 steve
340 * Simply give up on constants with indices.
342 * Revision 1.28 2002/06/06 18:57:04 steve
343 * Better error for identifier index eval.
345 * Revision 1.27 2002/05/23 03:08:51 steve
346 * Add language support for Verilog-2001 attribute
347 * syntax. Hook this support into existing $attribute
348 * handling, and add number and void value types.
350 * Add to the ivl_target API new functions for access
351 * of complex attributes attached to gates.
353 * Revision 1.26 2001/12/29 22:10:10 steve
354 * constant eval of arithmetic with x and z.
356 * Revision 1.25 2001/12/29 00:43:55 steve
357 * Evaluate constant right shifts.
359 * Revision 1.24 2001/12/03 04:47:15 steve
360 * Parser and pform use hierarchical names as hname_t
361 * objects instead of encoded strings.
363 * Revision 1.23 2001/11/07 04:01:59 steve
364 * eval_const uses scope instead of a string path.
366 * Revision 1.22 2001/11/06 06:11:55 steve
367 * Support more real arithmetic in delay constants.
369 * Revision 1.21 2001/07/25 03:10:49 steve
370 * Create a config.h.in file to hold all the config
371 * junk, and support gcc 3.0. (Stephan Boettcher)
373 * Revision 1.20 2001/02/09 02:49:59 steve
374 * Be more clear about scope of failure.
376 * Revision 1.19 2001/01/27 05:41:48 steve
377 * Fix sign extension of evaluated constants. (PR#91)
379 * Revision 1.18 2001/01/14 23:04:56 steve
380 * Generalize the evaluation of floating point delays, and
381 * get it working with delay assignment statements.
383 * Allow parameters to be referenced by hierarchical name.
385 * Revision 1.17 2001/01/04 04:47:51 steve
386 * Add support for << is signal indices.
388 * Revision 1.16 2000/12/10 22:01:36 steve
389 * Support decimal constants in behavioral delays.
391 * Revision 1.15 2000/09/07 22:38:13 steve
392 * Support unary + and - in constants.