2 * Copyright (c) 2003-2005 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_real.c,v 1.22 2007/06/12 02:36:58 steve Exp $"
24 * This file includes functions for evaluating REAL expressions.
26 # include "vvp_priv.h"
35 static unsigned long word_alloc_mask
= 0x0f;
40 int max
= 8*sizeof(word_alloc_mask
);
42 while (res
< max
&& (1U << res
) & word_alloc_mask
)
46 word_alloc_mask
|= 1U << res
;
50 void clr_word(int res
)
52 int max
= 8*sizeof(word_alloc_mask
);
54 word_alloc_mask
&= ~ (1U << res
);
58 static int draw_binary_real(ivl_expr_t exp
)
62 l
= draw_eval_real(ivl_expr_oper1(exp
));
63 r
= draw_eval_real(ivl_expr_oper2(exp
));
65 switch (ivl_expr_opcode(exp
)) {
68 fprintf(vvp_out
, " %%add/wr %d, %d;\n", l
, r
);
72 fprintf(vvp_out
, " %%sub/wr %d, %d;\n", l
, r
);
76 fprintf(vvp_out
, " %%mul/wr %d, %d;\n", l
, r
);
80 fprintf(vvp_out
, " %%div/wr %d, %d;\n", l
, r
);
84 fprintf(vvp_out
, " %%mod/wr %d, %d;\n", l
, r
);
88 { struct vector_info res
= draw_eval_expr(exp
, STUFF_OK_XZ
);
90 fprintf(vvp_out
, " %%ix/get %d, %u, %u;\n",
91 l
, res
.base
, res
.wid
);
92 fprintf(vvp_out
, " %%cvt/ri %d, %d;\n", l
, l
);
98 fprintf(stderr
, "XXXX draw_binary_real(%c)\n",
99 ivl_expr_opcode(exp
));
103 if (r
>= 0) clr_word(r
);
108 static int draw_number_real(ivl_expr_t exp
)
111 int res
= allocate_word();
112 const char*bits
= ivl_expr_bits(exp
);
113 unsigned wid
= ivl_expr_width(exp
);
114 unsigned long mant
= 0, mask
= -1UL;
117 for (idx
= 0 ; idx
< wid
; idx
+= 1) {
119 if (bits
[idx
] == '1')
123 /* If this is actually a negative number, then get the
124 positive equivalent, and set the sign bit in the exponent
127 To get the positive equivilent of mant we need to take the
128 negative of the mantissa (0-mant) but also be aware that
129 the bits may not have been as many bits as the width of the
130 mant variable. This would lead to spurious '1' bits in the
131 high bits of mant that are masked by ~((-1UL)<<wid). */
132 if (ivl_expr_signed(exp
) && (bits
[wid
-1] == '1')) {
133 mant
= (0-mant
) & ~(mask
);
137 fprintf(vvp_out
, " %%loadi/wr %d, %lu, %d; load(num)= %c%lu\n",
138 res
, mant
, vexp
, (vexp
&0x4000)? '-' : '+', mant
);
142 static int draw_realnum_real(ivl_expr_t exp
)
144 int res
= allocate_word();
145 double value
= ivl_expr_dvalue(exp
);
152 /* Handle the special case that the value is +-inf. */
155 fprintf(vvp_out
, " %%loadi/wr %d, 0, %d; load=+inf\n",
158 fprintf(vvp_out
, " %%loadi/wr %d, 0, %d; load=-inf\n",
168 fract
= frexp(value
, &expo
);
169 fract
= ldexp(fract
, 31);
173 vexp
= expo
+ 0x1000;
175 assert(vexp
< 0x2000);
178 fprintf(vvp_out
, " %%loadi/wr %d, %lu, %d; load=%f\n",
179 res
, mant
, vexp
, ivl_expr_dvalue(exp
));
181 /* Capture the residual bits, if there are any. Note that an
182 IEEE754 mantissa has 52 bits, 31 of which were accounted
184 fract
-= floor(fract
);
185 fract
= ldexp(fract
, 22);
189 vexp
= expo
+ 0x1000;
191 assert(vexp
< 0x2000);
195 int tmp_word
= allocate_word();
196 fprintf(vvp_out
, " %%loadi/wr %d, %lu, %d; load=%f\n",
197 tmp_word
, mant
, vexp
, ivl_expr_dvalue(exp
));
198 fprintf(vvp_out
, " %%add/wr %d, %d;\n", res
, tmp_word
);
205 static int draw_sfunc_real(ivl_expr_t exp
)
207 struct vector_info sv
;
209 const char*sign_flag
= "";
211 switch (ivl_expr_value(exp
)) {
214 if (ivl_expr_parms(exp
) == 0) {
215 res
= allocate_word();
216 fprintf(vvp_out
, " %%vpi_func/r \"%s\", %d;\n",
217 ivl_expr_name(exp
), res
);
220 res
= draw_vpi_rfunc_call(exp
);
225 /* If the value of the sfunc is a vector, then evaluate
226 it as a vector, then convert the result to a real
227 (via an index register) for the result. */
228 sv
= draw_eval_expr(exp
, 0);
231 if (ivl_expr_signed(exp
))
234 res
= allocate_word();
235 fprintf(vvp_out
, " %%ix/get%s %d, %u, %u;\n",
236 sign_flag
, res
, sv
.base
, sv
.wid
);
238 fprintf(vvp_out
, " %%cvt/ri %d, %d;\n", res
, res
);
250 * The real value of a signal is the integer value of a signal
253 static int draw_signal_real_logic(ivl_expr_t exp
)
255 int res
= allocate_word();
256 struct vector_info sv
= draw_eval_expr(exp
, 0);
257 const char*sign_flag
= ivl_expr_signed(exp
)? "/s" : "";
259 fprintf(vvp_out
, " %%ix/get%s %d, %u, %u; logic signal as real\n",
260 sign_flag
, res
, sv
.base
, sv
.wid
);
263 fprintf(vvp_out
, " %%cvt/ri %d, %d;\n", res
, res
);
268 static int draw_signal_real_real(ivl_expr_t exp
)
270 ivl_signal_t sig
= ivl_expr_signal(exp
);
271 int res
= allocate_word();
272 unsigned long word
= 0;
274 if (ivl_signal_array_count(sig
) > 1) {
275 ivl_expr_t ix
= ivl_expr_oper1(exp
);
276 if (!number_is_immediate(ix
, 8*sizeof(word
))) {
277 /* XXXX Need to generate a %load/ar instruction. */
282 /* The index is constant, so we can return to direct
283 readout with the specific word selected. */
284 word
= get_number_immediate(ix
);
287 fprintf(vvp_out
, " %%load/wr %d, v%p_%lu;\n", res
, sig
, word
);
292 static int draw_signal_real(ivl_expr_t exp
)
294 ivl_signal_t sig
= ivl_expr_signal(exp
);
295 switch (ivl_signal_data_type(sig
)) {
297 return draw_signal_real_logic(exp
);
299 return draw_signal_real_real(exp
);
301 fprintf(stderr
, "internal error: signal_data_type=%d\n",
302 ivl_signal_data_type(sig
));
308 static int draw_ternary_real(ivl_expr_t exp
)
310 ivl_expr_t cond
= ivl_expr_oper1(exp
);
311 ivl_expr_t true_ex
= ivl_expr_oper2(exp
);
312 ivl_expr_t false_ex
= ivl_expr_oper3(exp
);
314 struct vector_info tst
;
316 unsigned lab_true
= local_count
++;
317 unsigned lab_false
= local_count
++;
320 int res
= allocate_word();
322 tst
= draw_eval_expr(cond
, STUFF_OK_XZ
|STUFF_OK_RO
);
323 if ((tst
.base
>= 4) && (tst
.wid
> 1)) {
324 struct vector_info tmp
;
326 fprintf(vvp_out
, " %%or/r %u, %u, %u;\n",
327 tst
.base
, tst
.base
, tst
.wid
);
337 fprintf(vvp_out
, " %%jmp/0 T_%d.%d, %u;\n",
338 thread_count
, lab_true
, tst
.base
);
340 tru
= draw_eval_real(true_ex
);
341 fprintf(vvp_out
, " %%mov/wr %d, %d;\n", res
, tru
);
342 fprintf(vvp_out
, " %%jmp T_%d.%d;\n", thread_count
, lab_false
);
345 fprintf(vvp_out
, "T_%d.%d ;\n", thread_count
, lab_true
);
347 fal
= draw_eval_real(false_ex
);
348 fprintf(vvp_out
, " %%mov/wr %d, %d;\n", res
, fal
);
351 fprintf(vvp_out
, "T_%d.%d ;\n", thread_count
, lab_false
);
358 static int draw_unary_real(ivl_expr_t exp
)
360 ivl_expr_t sube
= ivl_expr_oper1(exp
);
361 int sub
= draw_eval_real(sube
);
363 if (ivl_expr_opcode(exp
) == '+')
366 if (ivl_expr_opcode(exp
) == '-') {
367 int res
= allocate_word();
368 fprintf(vvp_out
, " %%loadi/wr %d, 0, 0; load 0.0\n", res
);
369 fprintf(vvp_out
, " %%sub/wr %d, %d;\n", res
, sub
);
375 fprintf(vvp_out
, "; XXXX unary (%c)\n", ivl_expr_opcode(exp
));
376 fprintf(stderr
, "XXXX evaluate unary (%c)\n", ivl_expr_opcode(exp
));
380 int draw_eval_real(ivl_expr_t exp
)
384 switch (ivl_expr_type(exp
)) {
387 res
= draw_binary_real(exp
);
391 res
= draw_number_real(exp
);
395 res
= draw_realnum_real(exp
);
399 res
= draw_sfunc_real(exp
);
403 res
= draw_signal_real(exp
);
407 res
= draw_ternary_real(exp
);
411 res
= draw_ufunc_real(exp
);
415 res
= draw_unary_real(exp
);
419 if (ivl_expr_value(exp
) == IVL_VT_VECTOR
) {
420 struct vector_info sv
= draw_eval_expr(exp
, 0);
421 const char*sign_flag
= ivl_expr_signed(exp
)? "/s" : "";
424 res
= allocate_word();
426 fprintf(vvp_out
, " %%ix/get%s %d, %u, %u;\n",
427 sign_flag
, res
, sv
.base
, sv
.wid
);
429 fprintf(vvp_out
, " %%cvt/ri %d, %d;\n", res
, res
);
432 fprintf(stderr
, "XXXX Evaluate real expression (%d)\n",
434 fprintf(vvp_out
, " ; XXXX Evaluate real expression (%d)\n",
446 * $Log: eval_real.c,v $
447 * Revision 1.22 2007/06/12 02:36:58 steve
448 * handle constant inf values.
450 * Revision 1.21 2007/06/07 03:20:15 steve
451 * Properly handle signed conversion to real
453 * Revision 1.20 2007/02/26 19:49:50 steve
454 * Spelling fixes (larry doolittle)
456 * Revision 1.19 2007/02/20 05:58:36 steve
457 * Handle unary minus of real valued expressions.
459 * Revision 1.18 2007/02/14 05:59:46 steve
460 * Handle type of ternary expressions properly.
462 * Revision 1.17 2007/01/16 05:44:16 steve
463 * Major rework of array handling. Memories are replaced with the
464 * more general concept of arrays. The NetMemory and NetEMemory
465 * classes are removed from the ivl core program, and the IVL_LPM_RAM
466 * lpm type is removed from the ivl_target API.
468 * Revision 1.16 2006/10/10 23:54:28 steve
469 * Fix rendering of signed numbers in real expressions.
471 * Revision 1.15 2006/08/09 05:19:08 steve
472 * Add support for real valued modulus.
474 * Revision 1.14 2005/07/13 04:52:31 steve
475 * Handle functions with real values.
477 * Revision 1.13 2005/07/11 16:56:51 steve
478 * Remove NetVariable and ivl_variable_t structures.
480 * Revision 1.12 2005/07/07 16:22:50 steve
481 * Generalize signals to carry types.
483 * Revision 1.11 2004/10/04 01:10:57 steve
484 * Clean up spurious trailing white space.
486 * Revision 1.10 2003/12/19 01:27:10 steve
487 * Fix various unsigned compare warnings.
489 * Revision 1.9 2003/05/25 02:50:08 steve
490 * Add % in real expressions.
492 * Revision 1.8 2003/04/23 02:22:47 steve
493 * Fix word register leak.
495 * Revision 1.7 2003/03/28 02:33:56 steve
496 * Add support for division of real operands.
498 * Revision 1.6 2003/03/15 04:45:18 steve
499 * Allow real-valued vpi functions to have arguments.
501 * Revision 1.5 2003/03/08 01:04:01 steve
502 * Excess precision breaks some targets.
504 * Revision 1.4 2003/02/07 02:46:16 steve
505 * Handle real value subtract and comparisons.
507 * Revision 1.3 2003/01/28 04:15:50 steve
508 * Deliver residual bits of real value.
510 * Revision 1.2 2003/01/27 00:14:37 steve
511 * Support in various contexts the $realtime
514 * Revision 1.1 2003/01/26 21:16:00 steve
515 * Rework expression parsing and elaboration to
516 * accommodate real/realtime values and expressions.