Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | mjames | 1 | /* expression.h */ |
2 | /* contains the type declarations for expression handling information */ |
||
3 | /* |
||
4 | * $Id: expression.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $ |
||
5 | * |
||
6 | * $Log: expression.c,v $ |
||
7 | * Revision 1.1.1.1 2003/11/04 23:34:57 mjames |
||
8 | * Imported into local repositrory |
||
9 | * |
||
10 | * Revision 1.11 2002/09/30 13:22:38 MJAMES |
||
11 | * Altered the use and creation of partition |
||
12 | * generics (at evaluation time of expressions within the partition ) |
||
13 | * This still needs checking, as evaluation of the expression may well be |
||
14 | * delayed until after when the partition generics need to be defined. |
||
15 | * |
||
16 | * Revision 1.10 2002/09/09 15:15:37 mjames |
||
17 | * Altered expression to copy properly |
||
18 | * |
||
19 | * Revision 1.8 2001/11/30 22:19:27 mjames |
||
20 | * Corrected some missing conversion of LBRK to '('. |
||
21 | * Initialised a variable to satisfy GCC. |
||
22 | * Enhanced an error message to give some context. |
||
23 | * |
||
24 | * Revision 1.7 2001/10/31 22:20:04 mjames |
||
25 | * Tidying up problematical comments caused by CVS |
||
26 | * 'intelligent' comment guessing |
||
27 | * |
||
28 | * Revision 1.6 2001/06/06 12:10:23 mjames |
||
29 | * Move from HPUX |
||
30 | * |
||
31 | * Revision 1.5 2001/04/09 14:58:29 mjames |
||
32 | * Added capability to delete generics from specific sockets. |
||
33 | * |
||
34 | * Revision 1.4 2001/04/06 22:47:02 mjames |
||
35 | * Added doc2, the creator of documentation to Vertical scripts uses PERL |
||
36 | * |
||
37 | * |
||
38 | * Also correcting generic behaviour and the printing of Verilog. |
||
39 | * |
||
40 | * Revision 1.3 2000/12/04 13:14:02 mjames |
||
41 | * Imported all of the PCB syntax readers. |
||
42 | * |
||
43 | * Converted "a/b" to mean "a" divided by "b" insted of a single string |
||
44 | * "a/b" in Verilog |
||
45 | * |
||
46 | * Revision 1.2 2000/11/29 21:51:18 mjames |
||
47 | * Fine tuning of software |
||
48 | * |
||
49 | * Revision 1.1.1.1 2000/10/19 21:58:37 mjames |
||
50 | * Mike put it here |
||
51 | * |
||
52 | * |
||
53 | * Revision 1.20 2000/10/12 15:32:18 15:32:18 mjames (Mike James) |
||
54 | * Removed <cr> |
||
55 | * |
||
56 | * Revision 1.19 2000/10/04 10:37:04 10:37:04 mjames (Mike James) |
||
57 | * Modified for Vertical2 : support COMPONENTS and SIGNALS |
||
58 | * |
||
59 | * Revision 1.19 2000/10/04 10:37:04 10:37:04 mjames (Mike James) |
||
60 | * Part of Release PSAVAT01 |
||
61 | * |
||
62 | * Revision 1.18 2000/10/02 11:04:12 11:04:12 mjames (Mike James) |
||
63 | * new_vhdl |
||
64 | * |
||
65 | * Revision 1.17 2000/09/27 14:42:12 14:42:12 mjames (Mike James) |
||
66 | * Part of Release Sep_27_ST_2000 |
||
67 | * |
||
68 | * Revision 1.16 2000/09/21 10:15:42 10:15:42 mjames (Mike James) |
||
69 | * Part of Release Sep21Alpha |
||
70 | * |
||
71 | * Revision 1.15 2000/08/25 09:57:10 09:57:10 mjames (Mike James) |
||
72 | * Part of Release Aug25_alpha |
||
73 | * |
||
74 | * Revision 1.14 2000/08/16 08:57:27 08:57:27 mjames (Mike James) |
||
75 | * Part of Release CD01_Aug2000 |
||
76 | * |
||
77 | * Revision 1.13 2000/08/14 14:45:08 14:45:08 mjames (Mike James) |
||
78 | * Part of Release Aug_14_2000 |
||
79 | * |
||
80 | * Revision 1.12 2000/08/11 08:30:28 08:30:28 mjames (Mike James) |
||
81 | * Part of Release Aug_11_2000 |
||
82 | * |
||
83 | * Revision 1.11 2000/08/09 10:31:42 10:31:42 mjames (Mike James) |
||
84 | * Part of Release Aug__9_2000 |
||
85 | * |
||
86 | * Revision 1.10 2000/05/31 11:42:50 11:42:50 mjames (Mike James) |
||
87 | * Part of Release May_31_2000 |
||
88 | * |
||
89 | * Revision 1.9 2000/05/08 17:01:34 17:01:34 mjames (Mike James) |
||
90 | * Part of Release May__8_2000 |
||
91 | * |
||
92 | * Revision 1.8 2000/05/08 16:59:27 16:59:27 mjames (Mike James) |
||
93 | * Part of Release May__8_2000 |
||
94 | * |
||
95 | * Revision 1.7 2000/05/08 16:57:03 16:57:03 mjames (Mike James) |
||
96 | * Part of Release May__8_2000 |
||
97 | * |
||
98 | * Revision 1.6 2000/03/08 16:18:56 16:18:56 mjames (Mike James) |
||
99 | * New version including PC |
||
100 | * |
||
101 | * Revision 1.3 2000/01/20 15:58:42 15:58:42 mjames (Mike James) |
||
102 | * Part of Release R22 |
||
103 | * |
||
104 | * Revision 1.2 99/12/22 11:15:23 11:15:23 mjames (Mike James) |
||
105 | * Part of Release Dec_22_1999 |
||
106 | * |
||
107 | * Revision 1.1 99/06/25 14:34:45 14:34:45 mjames (Mike James) |
||
108 | * Initial revision |
||
109 | * |
||
110 | * */ |
||
111 | |||
112 | #include "expression.h" |
||
113 | |||
114 | #include "acf_yacc.h" |
||
115 | #include "cmdlog.h" |
||
116 | #include "cmdparse.h" |
||
117 | #include "database.h" |
||
118 | #include "generic.h" |
||
119 | #include "vertcl_main.h" |
||
120 | |||
121 | #include <stdio.h> |
||
122 | #include <stdlib.h> |
||
123 | #include <string.h> |
||
124 | |||
125 | /* place reference to a 'C' variable at the end of the tree branch */ |
||
126 | expression_t *compile_variable_reference (int *v, char *s) |
||
127 | { |
||
128 | expression_t *p; |
||
129 | p = calloc (1, sizeof (expression_t)); |
||
130 | |||
131 | if (p) |
||
132 | { |
||
133 | p->opcode = EXP_VAR_REF; |
||
134 | p->left.ip = v; |
||
135 | p->right.s = s; |
||
136 | } |
||
137 | return p; |
||
138 | } |
||
139 | |||
140 | /* place an integer constant at the end of the tree branch */ |
||
141 | expression_t *compile_constant (int k) |
||
142 | { |
||
143 | expression_t *p; |
||
144 | p = calloc (1, sizeof (expression_t)); |
||
145 | |||
146 | if (p) |
||
147 | { |
||
148 | p->opcode = EXP_CONSTANT; |
||
149 | p->left.i = k; |
||
150 | p->right.s = NULL; |
||
151 | } |
||
152 | return p; |
||
153 | } |
||
154 | /* place a boolean constant at the end of the tree branch */ |
||
155 | expression_t *compile_boolean_constant (int k) |
||
156 | { |
||
157 | expression_t *p; |
||
158 | p = calloc (1, sizeof (expression_t)); |
||
159 | |||
160 | if (p) |
||
161 | { |
||
162 | p->opcode = EXP_BOOLEAN; |
||
163 | p->left.i = k; |
||
164 | p->right.s = NULL; |
||
165 | } |
||
166 | return p; |
||
167 | } |
||
168 | |||
169 | /* this is where the user types some arbitrary string which is a numeric constant */ |
||
170 | expression_t *compile_constant_string (int k, char *s) |
||
171 | { |
||
172 | expression_t *p; |
||
173 | p = calloc (1, sizeof (expression_t)); |
||
174 | |||
175 | if (p) |
||
176 | { |
||
177 | p->opcode = EXP_CONSTANT; |
||
178 | p->left.i = k; |
||
179 | p->right.s = ISNULLSTR (s) ? NULL : strdup (s); |
||
180 | } |
||
181 | return p; |
||
182 | } |
||
183 | /* this is where the user types some arbitrary string which is a boolean constant */ |
||
184 | expression_t *compile_boolean_constant_string (int k, char *s) |
||
185 | { |
||
186 | expression_t *p; |
||
187 | p = calloc (1, sizeof (expression_t)); |
||
188 | |||
189 | if (p) |
||
190 | { |
||
191 | p->opcode = EXP_BOOLEAN; |
||
192 | p->left.i = k; |
||
193 | p->right.s = ISNULLSTR (s) ? NULL : strdup (s); |
||
194 | } |
||
195 | return p; |
||
196 | } |
||
197 | |||
198 | /* this compiles a reference to the variable */ |
||
199 | expression_t *compile_variable (generic_info_t *generic, char *valname) |
||
200 | { |
||
201 | expression_t *p; |
||
202 | p = calloc (1, sizeof (expression_t)); |
||
203 | |||
204 | if (p) |
||
205 | { |
||
206 | p->opcode = EXP_VARIABLE; |
||
207 | p->left.g = generic; |
||
208 | p->right.s = valname; |
||
209 | } |
||
210 | return p; |
||
211 | } |
||
212 | |||
213 | expression_t *compile_string (char *s) |
||
214 | { |
||
215 | expression_t *p; |
||
216 | p = (expression_t *) calloc (1, sizeof (expression_t)); |
||
217 | |||
218 | if (p) |
||
219 | { |
||
220 | p->opcode = EXP_STRING; |
||
221 | p->left.s = ISNULLSTR (s) ? NULL : strdup (s); |
||
222 | } |
||
223 | return p; |
||
224 | } |
||
225 | |||
226 | expression_t *compile_char (char c) |
||
227 | { |
||
228 | expression_t *p; |
||
229 | p = (expression_t *) calloc (1, sizeof (expression_t)); |
||
230 | |||
231 | if (p) |
||
232 | { |
||
233 | p->opcode = EXP_CHAR; |
||
234 | p->left.i = c; |
||
235 | } |
||
236 | return p; |
||
237 | } |
||
238 | |||
239 | expression_t *compile_reference (char *s) |
||
240 | { |
||
241 | expression_t *p; |
||
242 | p = (expression_t *) calloc (1, sizeof (expression_t)); |
||
243 | |||
244 | if (p) |
||
245 | { |
||
246 | p->opcode = EXP_UNDEF_VAR; |
||
247 | p->right.s = ISNULLSTR (s) ? NULL : strdup (s); |
||
248 | } |
||
249 | return p; |
||
250 | } |
||
251 | |||
252 | expression_t *compile_expression (int opcode, expression_t *l, expression_t *r) |
||
253 | { |
||
254 | expression_t *p; |
||
255 | p = (expression_t *) calloc (1, sizeof (expression_t)); |
||
256 | if (p) |
||
257 | { |
||
258 | p->opcode = opcode; |
||
259 | p->left.e = l; |
||
260 | p->right.e = r; |
||
261 | } |
||
262 | return p; |
||
263 | } |
||
264 | |||
265 | void print_expression (FILE *f, expression_t *e, generic_print_style recurse_generics) |
||
266 | { |
||
267 | if (!e) |
||
268 | { |
||
269 | fprintf (f, "(NULL)"); |
||
270 | return; |
||
271 | } |
||
272 | switch (e->opcode) |
||
273 | { |
||
274 | case EXP_UNDEF_VAR: |
||
275 | if (e->right.s) |
||
276 | fprintf (f, "%s", e->right.s); |
||
277 | break; |
||
278 | case EXP_STRING: |
||
279 | if (e->left.s) |
||
280 | fprintf (f, "\"%s\"", e->left.s); |
||
281 | break; |
||
282 | case EXP_CHAR: |
||
283 | fprintf (f, "\'%c\'", e->left.i); |
||
284 | break; |
||
285 | case EXP_CONSTANT: |
||
286 | if (e->right.s) |
||
287 | fprintf (f, "%s", e->right.s); |
||
288 | else |
||
289 | fprintf (f, "%d", e->left.i); |
||
290 | break; |
||
291 | case EXP_VAR_REF: |
||
292 | /* if (e->right.s) |
||
293 | fprintf(f,"%s",e->right.s); |
||
294 | else */ |
||
295 | fprintf (f, "%d", *(e->left.ip)); |
||
296 | break; |
||
297 | case EXP_BOOLEAN: |
||
298 | if (e->right.s) |
||
299 | fprintf (f, "%s", e->right.s); |
||
300 | else |
||
301 | fprintf (f, "%s", e->left.i ? "true" : "false"); |
||
302 | break; |
||
303 | case EXP_VARIABLE: |
||
304 | if (e->left.g) |
||
305 | { |
||
306 | if (recurse_generics != NO_RECURSE && e->left.g->expr && |
||
307 | (recurse_generics == RECURSE_NUMBER || |
||
308 | e->left.g->expr->opcode != EXP_CONSTANT)) |
||
309 | { |
||
310 | fprintf (f, "("); |
||
311 | print_expression (f, e->left.g->expr, recurse_generics); |
||
312 | fprintf (f, ")"); |
||
313 | } |
||
314 | else |
||
315 | fprintf (f, "%s", e->right.s); |
||
316 | } |
||
317 | else |
||
318 | fprintf (f, "((%s))", e->right.s); |
||
319 | |||
320 | break; |
||
321 | case UMINUS: |
||
322 | fprintf (f, "(-"); |
||
323 | if (e->left.e->opcode != EXP_CONSTANT) |
||
324 | fprintf (f, "("); |
||
325 | print_expression (f, e->left.e, recurse_generics); |
||
326 | if (e->left.e->opcode != EXP_CONSTANT) |
||
327 | fprintf (f, ")"); |
||
328 | fprintf (f, ")"); |
||
329 | break; |
||
330 | case '~': |
||
331 | fprintf (f, "(~"); |
||
332 | if (e->left.e->opcode != EXP_CONSTANT) |
||
333 | fprintf (f, "("); |
||
334 | print_expression (f, e->left.e, recurse_generics); |
||
335 | if (e->left.e->opcode != EXP_CONSTANT) |
||
336 | fprintf (f, ")"); |
||
337 | fprintf (f, ")"); |
||
338 | break; |
||
339 | case '!': |
||
340 | fprintf (f, "(!"); |
||
341 | if (e->left.e->opcode != EXP_CONSTANT) |
||
342 | fprintf (f, "("); |
||
343 | print_expression (f, e->left.e, recurse_generics); |
||
344 | if (e->left.e->opcode != EXP_CONSTANT) |
||
345 | fprintf (f, ")"); |
||
346 | fprintf (f, ")"); |
||
347 | break; |
||
348 | case '(': |
||
349 | fprintf (f, "("); |
||
350 | print_expression (f, e->left.e, recurse_generics); |
||
351 | fprintf (f, ")"); |
||
352 | break; |
||
353 | case '+': |
||
354 | case '-': |
||
355 | case '*': |
||
356 | case '/': |
||
357 | case '%': |
||
358 | case '^': |
||
359 | case '?': |
||
360 | case ':': |
||
361 | case '>': |
||
362 | case '<': |
||
363 | case '&': |
||
364 | case '|': |
||
365 | |||
366 | print_expression (f, e->left.e, recurse_generics); |
||
367 | fprintf (f, "%c", e->opcode); |
||
368 | print_expression (f, e->right.e, recurse_generics); |
||
369 | |||
370 | break; |
||
371 | case SHL: |
||
372 | print_expression (f, e->left.e, recurse_generics); |
||
373 | fprintf (f, "<<"); |
||
374 | print_expression (f, e->right.e, recurse_generics); |
||
375 | break; |
||
376 | case SHR: |
||
377 | print_expression (f, e->left.e, recurse_generics); |
||
378 | fprintf (f, ">>"); |
||
379 | print_expression (f, e->right.e, recurse_generics); |
||
380 | break; |
||
381 | case EQ_EQ: |
||
382 | print_expression (f, e->left.e, recurse_generics); |
||
383 | fprintf (f, "=="); |
||
384 | print_expression (f, e->right.e, recurse_generics); |
||
385 | break; |
||
386 | case N_EQ: |
||
387 | print_expression (f, e->left.e, recurse_generics); |
||
388 | fprintf (f, "!="); |
||
389 | print_expression (f, e->right.e, recurse_generics); |
||
390 | break; |
||
391 | case LOG_AND: |
||
392 | print_expression (f, e->left.e, recurse_generics); |
||
393 | fprintf (f, "&&"); |
||
394 | print_expression (f, e->right.e, recurse_generics); |
||
395 | break; |
||
396 | case LOG_OR: |
||
397 | print_expression (f, e->left.e, recurse_generics); |
||
398 | fprintf (f, "||"); |
||
399 | print_expression (f, e->right.e, recurse_generics); |
||
400 | break; |
||
401 | case TO_POW: |
||
402 | print_expression (f, e->left.e, recurse_generics); |
||
403 | fprintf (f, "**"); |
||
404 | print_expression (f, e->right.e, recurse_generics); |
||
405 | break; |
||
406 | default: |
||
407 | fprintf (f, "(?? expression ERROR : OPCODE 0x%X)", e->opcode); |
||
408 | } |
||
409 | } |
||
410 | |||
411 | /* a range is permitted at the top level of an expression */ |
||
412 | /* if there is no expression return */ |
||
413 | void print_range_expression (FILE *f, expression_t *e, generic_print_style recurse_generics) |
||
414 | { |
||
415 | if (!e) |
||
416 | return; |
||
417 | switch (e->opcode) |
||
418 | { |
||
419 | case TO: |
||
420 | fprintf (f, "("); |
||
421 | print_expression (f, e->left.e, recurse_generics); |
||
422 | fprintf (f, " TO "); |
||
423 | print_expression (f, e->right.e, recurse_generics); |
||
424 | fprintf (f, ")"); |
||
425 | break; |
||
426 | |||
427 | case DOWNTO: |
||
428 | fprintf (f, "("); |
||
429 | print_expression (f, e->left.e, recurse_generics); |
||
430 | fprintf (f, " DOWNTO "); |
||
431 | print_expression (f, e->right.e, recurse_generics); |
||
432 | fprintf (f, ")"); |
||
433 | break; |
||
434 | |||
435 | case EXP_VARIABLE: |
||
436 | if (e->left.g) |
||
437 | { |
||
438 | if (recurse_generics != NO_RECURSE) |
||
439 | print_range_expression (f, e->left.g->expr, recurse_generics); |
||
440 | else |
||
441 | fprintf (f, "(%s)", e->right.s); |
||
442 | } |
||
443 | else |
||
444 | fprintf (f, "((??%s))", e->right.s); |
||
445 | |||
446 | break; |
||
447 | |||
448 | default: |
||
449 | /* handle the expressions down each level of the hierarchy */ |
||
450 | /* fprintf(f,"("); */ |
||
451 | print_expression (f, e, recurse_generics); |
||
452 | /* fprintf(f,")"); */ |
||
453 | } |
||
454 | } |
||
455 | |||
456 | void print_msg_expression (FILE *f, char *s, expression_t *e) |
||
457 | { |
||
458 | fprintf (f, "%s '", s); |
||
459 | print_range_expression (f, e, NO_RECURSE); |
||
460 | fprintf (f, "'\n"); |
||
461 | } |
||
462 | |||
463 | /* evaluate an integer expression : checking local generics if they are available */ |
||
464 | int eval_expression (expression_t *e, generic_info_t **chip_generics) |
||
465 | { |
||
466 | int r = 0; |
||
467 | if (!e) |
||
468 | return 0; |
||
469 | |||
470 | switch (e->opcode) |
||
471 | { |
||
472 | case EXP_CONSTANT: |
||
473 | case EXP_BOOLEAN: |
||
474 | r = e->left.i; |
||
475 | break; |
||
476 | case EXP_VAR_REF: |
||
477 | r = *(e->left.ip); |
||
478 | break; |
||
479 | /* when evaluating expression, if a generic in scope is found then the |
||
480 | generic will be updated : ends up creating and cross-linking a |
||
481 | partition generic */ |
||
482 | case EXP_UNDEF_VAR: |
||
483 | { |
||
484 | generic_info_t *gen; |
||
485 | gen = NULL; |
||
486 | if (chip_generics) |
||
487 | { |
||
488 | gen = get_generic_ref (chip_generics, e->right.s); |
||
489 | } |
||
490 | /* search outwards */ |
||
491 | if (!gen) |
||
492 | { |
||
493 | gen = get_generic_ref (&global_generics, e->right.s); |
||
494 | } |
||
495 | if (!gen) |
||
496 | { /* scope is external not local */ |
||
497 | expr_ref_t *link; |
||
498 | gen = get_generic_ref (&partition_generics, e->right.s); |
||
499 | /* if no partition generic appears, make one */ |
||
500 | if (!gen) |
||
501 | { |
||
502 | generic_info_t newgen; |
||
503 | newgen.typename = "integer"; |
||
504 | newgen.name = e->right.s; |
||
505 | |||
506 | newgen.valid = 1; |
||
507 | newgen.expr = compile_constant (0); |
||
508 | newgen.g_type = IS_INTEGER; |
||
509 | newgen.g_class = DEFINED; |
||
510 | |||
511 | gen = set_generic_value (&partition_generics, &newgen); |
||
512 | } |
||
513 | if (gen) |
||
514 | { |
||
515 | link = calloc (1, sizeof (expr_ref_t)); |
||
516 | } |
||
517 | if (gen && link) |
||
518 | { |
||
519 | link->expr_ref = gen->expr_ref; |
||
520 | gen->expr_ref = link; |
||
521 | link->expr = e; |
||
522 | } |
||
523 | } |
||
524 | if (gen) |
||
525 | { |
||
526 | e->opcode = EXP_VARIABLE; |
||
527 | e->left.g = gen; |
||
528 | /* having located a valid generic then try to link it up */ |
||
529 | |||
530 | /* duplicate code borrowed from below. Avoiding 'goto' !! */ |
||
531 | eval_gen_expression (gen); |
||
532 | if (gen->g_type == IS_ATTRIBUTE || gen->g_type == IS_INTEGER) |
||
533 | { |
||
534 | r = eval_expression (gen->expr, chip_generics); |
||
535 | #if defined DEBUG_EXPRESSION |
||
536 | printf ("eval %s = %d\n", gen->name, r); |
||
537 | #endif |
||
538 | } |
||
539 | else |
||
540 | { |
||
541 | Log ( |
||
542 | LOG_ERROR, |
||
543 | "#Error : generic %s has non integer type (code %d)\n", |
||
544 | gen->name, |
||
545 | gen->g_type); |
||
546 | r = 0; |
||
547 | } |
||
548 | } |
||
549 | else |
||
550 | { |
||
551 | Log (LOG_ERROR, "# symbol '%s' is not defined\n", e->right.s); |
||
552 | } |
||
553 | } |
||
554 | break; |
||
555 | case EXP_VARIABLE: |
||
556 | { |
||
557 | generic_info_t *gen; |
||
558 | gen = e->left.g; |
||
559 | |||
560 | if (gen) |
||
561 | { |
||
562 | eval_gen_expression (gen); |
||
563 | if (gen->g_type == IS_ATTRIBUTE || gen->g_type == IS_INTEGER) |
||
564 | { |
||
565 | r = eval_expression (gen->expr, chip_generics); |
||
566 | #if defined DEBUG_EXPRESSION |
||
567 | printf ("eval %s = %d\n", gen->name, r); |
||
568 | #endif |
||
569 | } |
||
570 | else |
||
571 | { |
||
572 | Log ( |
||
573 | LOG_ERROR, |
||
574 | "#Error : generic %s has non integer type (code %d)\n", |
||
575 | gen->name, |
||
576 | gen->g_type); |
||
577 | r = 0; |
||
578 | } |
||
579 | } |
||
580 | |||
581 | else |
||
582 | Log (LOG_ERROR, "#Error : generic '%s' not found\n", e->right.s); |
||
583 | } |
||
584 | break; |
||
585 | case EXP_CHAR: |
||
586 | r = e->left.i; |
||
587 | break; |
||
588 | case EXP_STRING: |
||
589 | r = 0; |
||
590 | break; |
||
591 | case '(': |
||
592 | r = eval_expression (e->left.e, chip_generics); |
||
593 | break; |
||
594 | case UMINUS: |
||
595 | r = 0 - eval_expression (e->left.e, chip_generics); |
||
596 | break; |
||
597 | case '~': |
||
598 | r = ~eval_expression (e->left.e, chip_generics); |
||
599 | break; |
||
600 | case '!': |
||
601 | r = !eval_expression (e->left.e, chip_generics); |
||
602 | break; |
||
603 | case '+': |
||
604 | r = eval_expression (e->left.e, chip_generics) + |
||
605 | eval_expression (e->right.e, chip_generics); |
||
606 | break; |
||
607 | case '-': |
||
608 | r = eval_expression (e->left.e, chip_generics) - |
||
609 | eval_expression (e->right.e, chip_generics); |
||
610 | break; |
||
611 | case '*': |
||
612 | r = eval_expression (e->left.e, chip_generics) * |
||
613 | eval_expression (e->right.e, chip_generics); |
||
614 | break; |
||
615 | case '/': |
||
616 | { |
||
617 | int rhs; |
||
618 | rhs = eval_expression (e->right.e, chip_generics); |
||
619 | if (rhs) |
||
620 | { |
||
621 | r = eval_expression (e->left.e, chip_generics) / rhs; |
||
622 | } |
||
623 | else |
||
624 | { |
||
625 | Log (LOG_ERROR, "# ERROR: Division by 0\n"); |
||
626 | r = 0; |
||
627 | }; |
||
628 | } |
||
629 | break; |
||
630 | case '%': |
||
631 | { |
||
632 | int rhs; |
||
633 | rhs = eval_expression (e->right.e, chip_generics); |
||
634 | if (rhs) |
||
635 | { |
||
636 | r = eval_expression (e->left.e, chip_generics) % rhs; |
||
637 | } |
||
638 | else |
||
639 | { |
||
640 | Log (LOG_ERROR, "# ERROR: Modulus by 0\n"); |
||
641 | r = 0; |
||
642 | }; |
||
643 | } |
||
644 | break; |
||
645 | case '^': |
||
646 | r = eval_expression (e->left.e, chip_generics) ^ |
||
647 | eval_expression (e->right.e, chip_generics); |
||
648 | break; |
||
649 | case '|': |
||
650 | r = eval_expression (e->left.e, chip_generics) | |
||
651 | eval_expression (e->right.e, chip_generics); |
||
652 | break; |
||
653 | case '&': |
||
654 | r = eval_expression (e->left.e, chip_generics) & |
||
655 | eval_expression (e->right.e, chip_generics); |
||
656 | break; |
||
657 | case '>': |
||
658 | r = eval_expression (e->left.e, chip_generics) > |
||
659 | eval_expression (e->right.e, chip_generics); |
||
660 | break; |
||
661 | case '<': |
||
662 | r = eval_expression (e->left.e, chip_generics) < |
||
663 | eval_expression (e->right.e, chip_generics); |
||
664 | break; |
||
665 | case EQ_EQ: |
||
666 | r = eval_expression (e->left.e, chip_generics) == |
||
667 | eval_expression (e->right.e, chip_generics); |
||
668 | break; |
||
669 | case N_EQ: |
||
670 | r = eval_expression (e->left.e, chip_generics) != |
||
671 | eval_expression (e->right.e, chip_generics); |
||
672 | break; |
||
673 | case LOG_OR: |
||
674 | r = eval_expression (e->left.e, chip_generics) || |
||
675 | eval_expression (e->right.e, chip_generics); |
||
676 | break; |
||
677 | case LOG_AND: |
||
678 | r = eval_expression (e->left.e, chip_generics) && |
||
679 | eval_expression (e->right.e, chip_generics); |
||
680 | break; |
||
681 | case SHL: |
||
682 | r = eval_expression (e->left.e, chip_generics) |
||
683 | << eval_expression (e->right.e, chip_generics); |
||
684 | break; |
||
685 | case SHR: |
||
686 | r = eval_expression (e->left.e, chip_generics) >> |
||
687 | eval_expression (e->right.e, chip_generics); |
||
688 | break; |
||
689 | case '?': |
||
690 | r = eval_expression (e->left.e, chip_generics) |
||
691 | ? eval_expression (e->right.e->left.e, chip_generics) |
||
692 | : eval_expression (e->right.e->right.e, chip_generics); |
||
693 | break; |
||
694 | case TO_POW: |
||
695 | { |
||
696 | int i, y, x; |
||
697 | x = eval_expression (e->left.e, chip_generics); |
||
698 | y = eval_expression (e->right.e, chip_generics); |
||
699 | if (y == 0) /* x**0 = 1 */ |
||
700 | r = 1; |
||
701 | else if (y < 0) /* negative powers */ |
||
702 | r = 0; |
||
703 | else |
||
704 | { |
||
705 | i = y; /* limit power */ |
||
706 | if (i > 32) |
||
707 | { |
||
708 | Log ( |
||
709 | LOG_ERROR, |
||
710 | "arithmetic power of: %d ** %d : %d > 32: limited to 32\n", |
||
711 | x, |
||
712 | y, |
||
713 | y); |
||
714 | i = 32; |
||
715 | } |
||
716 | r = x; |
||
717 | while (--i) |
||
718 | r *= x; |
||
719 | } |
||
720 | } |
||
721 | break; |
||
722 | default: |
||
723 | Log (LOG_ERROR, "#Error : expression : illegal operator (%d)\n", e->opcode); |
||
724 | } |
||
725 | /* printf("(%d)",r); */ |
||
726 | return r; |
||
727 | } |
||
728 | |||
729 | int eval_vhdl_expression (expression_t *expr, int *high, int *low) |
||
730 | { |
||
731 | int rc; |
||
732 | |||
733 | generic_info_t **chip_generics = |
||
734 | NULL; /* no local search scope, order of declaration should ensure that |
||
735 | generics are defined before use */ |
||
736 | |||
737 | if (!expr) |
||
738 | return 0; |
||
739 | /* my be range at top level in variable */ |
||
740 | if (expr->opcode == EXP_VARIABLE) |
||
741 | expr = expr->left.g->expr; |
||
742 | |||
743 | if (!expr) |
||
744 | return 0; |
||
745 | |||
746 | switch (expr->opcode) |
||
747 | { |
||
748 | case TO: |
||
749 | *high = eval_expression (expr->left.e, chip_generics); |
||
750 | *low = eval_expression (expr->right.e, chip_generics); |
||
751 | rc = TO; |
||
752 | break; |
||
753 | |||
754 | case DOWNTO: |
||
755 | *high = eval_expression (expr->left.e, chip_generics); |
||
756 | *low = eval_expression (expr->right.e, chip_generics); |
||
757 | rc = DOWNTO; |
||
758 | break; |
||
759 | |||
760 | default: |
||
761 | /* handle the expressions down each level of the hierarchy */ |
||
762 | *high = eval_expression (expr, chip_generics); |
||
763 | *low = *high; |
||
764 | rc = IS_INTEGER; |
||
765 | break; |
||
766 | } |
||
767 | #if defined DEBUG_EXPRESSION |
||
768 | print_msg_expression (stdout, "eval vhdl ", expr); |
||
769 | printf ("high %d low %d rc %d\n", *high, *low, rc); |
||
770 | #endif |
||
771 | return rc; |
||
772 | } |
||
773 | |||
774 | int eval_gen_expression (generic_info_t *gen) |
||
775 | { |
||
776 | #if defined NEED_EVAL_GEN |
||
777 | expression_t *exp; |
||
778 | if (gen) |
||
779 | { |
||
780 | exp = gen->expr; |
||
781 | /* printf("Ptr %p: ",exp); */ |
||
782 | if (exp) |
||
783 | { |
||
784 | switch (exp->opcode) |
||
785 | { |
||
786 | case EXP_STRING: |
||
787 | gen->valuename = exp->left.s; |
||
788 | gen->g_type = IS_STRING; |
||
789 | gen->valid = 1; |
||
790 | break; |
||
791 | case TO: |
||
792 | gen->valid = 1; |
||
793 | gen->g_type = TO; |
||
794 | |||
795 | break; |
||
796 | |||
797 | case DOWNTO: |
||
798 | gen->valid = 1; |
||
799 | gen->g_type = DOWNTO; |
||
800 | break; |
||
801 | default: |
||
802 | /* handle the expressions down each level of the hierarchy */ |
||
803 | gen->valid = 1; |
||
804 | gen->g_type = IS_INTEGER; |
||
805 | } |
||
806 | gen->g_class = DEFINED; |
||
807 | return gen->g_type; |
||
808 | } |
||
809 | } |
||
810 | |||
811 | return NO_VALUE; |
||
812 | #else |
||
813 | return gen->g_type; |
||
814 | #endif |
||
815 | } |
||
816 | |||
817 | /* delete any expression pointed to */ |
||
818 | void free_expression (expression_t *ptr) |
||
819 | { |
||
820 | if (!ptr) |
||
821 | return; |
||
822 | switch (ptr->opcode) |
||
823 | { |
||
824 | case EXP_STRING: |
||
825 | if (ptr->left.s) |
||
826 | free (ptr->left.s); |
||
827 | case EXP_CONSTANT: |
||
828 | case EXP_BOOLEAN: |
||
829 | case EXP_VARIABLE: |
||
830 | case EXP_VAR_REF: |
||
831 | if (ptr->right.s) |
||
832 | free (ptr->right.s); /* remove string */ |
||
833 | break; |
||
834 | default: |
||
835 | if (ptr->left.e) |
||
836 | free_expression (ptr->left.e); |
||
837 | if (ptr->right.e) |
||
838 | free_expression (ptr->right.e); |
||
839 | break; |
||
840 | } |
||
841 | free (ptr); |
||
842 | } |
||
843 | /* copy the expression, fixing up the references to local generic constants |
||
844 | at the same time . Need to */ |
||
845 | expression_t *copy_expression (expression_t *ptr, socket_t *skt) |
||
846 | { |
||
847 | expression_t *copy; |
||
848 | if (!ptr) |
||
849 | return NULL; |
||
850 | switch (ptr->opcode) |
||
851 | { |
||
852 | case EXP_CONSTANT: |
||
853 | case EXP_BOOLEAN: |
||
854 | case EXP_STRING: |
||
855 | case EXP_VAR_REF: |
||
856 | case EXP_VARIABLE: |
||
857 | case EXP_CHAR: |
||
858 | return ptr; /* no copy needed as this is a terminal node that cannot change */ |
||
859 | break; |
||
860 | /* duplicate undefined references so each induvidual expression is fixed up */ |
||
861 | case EXP_UNDEF_VAR: |
||
862 | copy = calloc (1, sizeof (expression_t)); |
||
863 | *copy = *ptr; |
||
864 | return copy; |
||
865 | break; |
||
866 | default: |
||
867 | return compile_expression ( |
||
868 | ptr->opcode, |
||
869 | copy_expression (ptr->left.e, skt), |
||
870 | copy_expression (ptr->right.e, skt)); |
||
871 | break; |
||
872 | } |
||
873 | return NULL; |
||
874 | } |
||
875 | |||
876 | struct vhdl *copy_vhdl (vhdl_t *vhdl, socket_t *skt) |
||
877 | { |
||
878 | vhdl_t *new_vhdl; |
||
879 | if (!vhdl) |
||
880 | return NULL; |
||
881 | new_vhdl = calloc (1, sizeof (vhdl_t)); |
||
882 | *new_vhdl = *vhdl; |
||
883 | new_vhdl->expr = copy_expression (vhdl->expr, skt); |
||
884 | new_vhdl->default_expr = copy_expression (vhdl->default_expr, skt); |
||
885 | #if defined DEBUG_EXPRESSION |
||
886 | printf ("Type = %s\n", vhdl->basetype); |
||
887 | print_msg_expression (stdout, "Copied expr", new_vhdl->expr); |
||
888 | print_msg_expression (stdout, "Copied default", new_vhdl->default_expr); |
||
889 | #endif |
||
890 | return new_vhdl; |
||
891 | } |