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