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)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
30 # include "compiler.h"
32 verinum
* PExpr::eval_const(Design
*, NetScope
*) const
37 verinum
* PEBinary::eval_const(Design
*des
, NetScope
*scope
) const
39 verinum
*l
= left_
->eval_const(des
, scope
);
41 verinum
*r
= right_
->eval_const(des
, scope
);
50 if (l
->is_defined() && r
->is_defined()) {
51 res
= new verinum(*l
+ *r
);
53 res
= new verinum(verinum::Vx
, l
->len());
58 if (l
->is_defined() && r
->is_defined()) {
59 res
= new verinum(*l
- *r
);
61 res
= new verinum(verinum::Vx
, l
->len());
66 if (l
->is_defined() && r
->is_defined()) {
67 res
= new verinum(*l
* *r
);
69 res
= new verinum(verinum::Vx
, l
->len());
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());
79 res
= new verinum(verinum::Vx
, l
->len());
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());
89 res
= new verinum(verinum::Vx
, l
->len());
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());
99 res
= new verinum(verinum::Vx
, l
->len());
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());
109 res
= new verinum(verinum::Vx
, l
->len());
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
));
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
));
146 verinum
* PEConcat::eval_const(Design
*des
, NetScope
*scope
) const
148 verinum
*accum
= parms_
[0]->eval_const(des
, scope
);
152 for (unsigned idx
= 1 ; idx
< parms_
.count() ; idx
+= 1) {
154 verinum
*tmp
= parms_
[idx
]->eval_const(des
, scope
);
161 *accum
= concat(*accum
, *tmp
);
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
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
);
195 const NetEConst
*eval
= dynamic_cast<const NetEConst
*>(expr
);
197 cerr
<< get_line() << ": internal error: Unable to evaluate "
198 << "constant expression (parameter=" << path_
199 << "): " << *expr
<< endl
;
205 if (!name_tail
.index
.empty())
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
);
234 verinum::V bit
= test
->get(0);
238 return fal_
->eval_const(des
, scope
);
240 return tru_
->eval_const(des
, scope
);
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
);
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);
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
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.