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 |