My omnium-gatherom of scripts and source code.
at main 703 lines 15 kB view raw
1/* Functions to generate C or Verilog code from HCL */ 2/* This file maintains a parse tree representation of expressions */ 3 4#include <stdio.h> 5#include <stdlib.h> 6#include <string.h> 7#include <unistd.h> 8#include <ctype.h> 9 10#include "node.h" 11#include "outgen.h" 12 13#define MAXBUF 1024 14 15void yyerror(const char *str); 16void yyserror(const char *str, char *other); 17 18/* For error reporting */ 19static char* show_expr(node_ptr expr); 20 21/* The symbol table */ 22#define SYM_LIM 100 23static node_ptr sym_tab[2][SYM_LIM]; 24static int sym_count = 0; 25 26/* Optional simulator name */ 27char simname[MAXBUF] = ""; 28 29#ifdef UCLID 30int annotate = 0; 31/* Keep list of argument names encountered in node definition */ 32char *arg_names[SYM_LIM]; 33int arg_cnt = 0; 34#endif 35 36 37extern FILE *outfile; 38 39/* 40 * usage - print helpful diagnostic information 41 */ 42static void usage(char *name) 43{ 44#ifdef VLOG 45 fprintf(stderr, "Usage: %s [-h] < HCL_file > verilog_file\n", name); 46#else 47#ifdef UCLID 48 fprintf(stderr, "Usage: %s [-ah] < HCL_file > uclid_file\n", name); 49 fprintf(stderr, " -a Add define/use annotations\n"); 50#else /* !UCLID */ 51 fprintf(stderr, "Usage: %s [-h][-n NAM] < HCL_file > C_file\n", name); 52#endif /* UCLID */ 53#endif /* VLOG */ 54 fprintf(stderr, " -h Print this message\n"); 55 fprintf(stderr, " -n NAM Specify processor name\n"); 56 exit(0); 57} 58 59 60/* Initialization */ 61void init_node(int argc, char **argv) 62{ 63 int c; 64 int max_column = 75; 65 int first_indent = 4; 66 int other_indents = 2; 67 68 /* Parse the command line arguments */ 69 while ((c = getopt(argc, argv, "hna")) != -1) { 70 switch(c) { 71 case 'h': 72 usage(argv[0]); 73 break; 74 case 'n': /* Optional simulator name */ 75 strcpy(simname, argv[optind]); 76 break; 77#ifdef UCLID 78 case 'a': 79 annotate = 1; 80 break; 81#endif 82 default: 83 printf("Invalid option '%c'\n", c); 84 usage(argv[0]); 85 break; 86 } 87 } 88 89#if !defined(VLOG) && !defined(UCLID) 90 /* Define and initialize the simulator name */ 91 if (!strcmp(simname, "")) 92 printf("char simname[] = \"Y86-64 Processor\";\n"); 93 else 94 printf("char simname[] = \"Y86-64 Processor: %s\";\n", simname); 95#endif 96 outgen_init(outfile, max_column, first_indent, other_indents); 97} 98 99static void add_symbol(node_ptr name, node_ptr val) 100{ 101 if (sym_count >= SYM_LIM) { 102 yyerror("Symbol table limit exceeded"); 103 return; 104 } 105 sym_tab[0][sym_count] = name; 106 sym_tab[1][sym_count] = val; 107 sym_count++; 108} 109 110 111static char *node_names[] = 112 {"quote", "var", "num", "and", "or", "not", "comp", "ele", "case"}; 113 114static void show_node(node_ptr node) 115{ 116 printf("Node type: %s, Boolean ? %c, String value: %s\n", 117 node_names[node->type], node->isbool ? 'Y':'N', node->sval); 118} 119 120 121void finish_node(int check_ref) 122{ 123 if (check_ref) { 124 int i; 125 for (i = 0; i < sym_count; i++) 126 if (!sym_tab[0][i]->ref) { 127 fprintf(stderr, "Warning, argument '%s' not referenced\n", 128 sym_tab[0][i]->sval); 129 } 130 } 131} 132 133static node_ptr find_symbol(char *name) 134{ 135 int i; 136 for (i = 0; i < sym_count; i++) { 137 if (strcmp(name, sym_tab[0][i]->sval) == 0) { 138 node_ptr result = sym_tab[1][i]; 139 sym_tab[0][i]->ref++; 140 return result; 141 } 142 } 143 yyserror("Symbol %s not found", name); 144 return NULL; 145} 146 147#ifdef UCLID 148/* See if string should be considered argument. 149 Currently, omit strings that are all upper case */ 150static int is_arg(char *name) 151{ 152 int upper = 1; 153 int c; 154 while ((c=*name++) != '\0') 155 upper = upper && isupper(c); 156 return !upper; 157} 158 159/* See if string is part of current argument list */ 160static void check_for_arg(char *name) 161{ 162 int i; 163 if (!is_arg(name)) 164 return; 165 for (i = 0; i < arg_cnt; i++) 166 if (strcmp(arg_names[i], name) == 0) 167 return; 168 arg_names[arg_cnt++] = name; 169} 170#endif 171 172static node_ptr new_node(node_type_t t, int isbool, 173 char *s, node_ptr a1, node_ptr a2) 174{ 175 node_ptr result = malloc(sizeof(node_rec)); 176 result->type = t; 177 result->isbool = isbool; 178 result->sval = s; 179 result->arg1 = a1; 180 result->arg2 = a2; 181 result->ref = 0; 182 result->next = NULL; 183 return result; 184} 185 186/* Concatenate two lists */ 187node_ptr concat(node_ptr n1, node_ptr n2) 188{ 189 node_ptr tail = n1; 190 if (!n1) 191 return n2; 192 while (tail->next) 193 tail = tail->next; 194 tail->next = n2; 195 return n1; 196} 197 198static void free_node(node_ptr n) 199{ 200 free(n->sval); 201 free(n); 202} 203 204node_ptr make_quote(char *qstring) 205{ 206 207 /* Quoted string still has quotes around it */ 208 int len = strlen(qstring)-2; 209 char *sname = malloc(len+1); 210 strncpy(sname, qstring+1, len); 211 sname[len] = '\0'; 212 return new_node(N_QUOTE, 0, sname, NULL, NULL); 213} 214 215node_ptr make_var(char *name) 216{ 217 char *sname = malloc(strlen(name)+1); 218 strcpy(sname, name); 219 /* Initially assume var is not Boolean */ 220 return new_node(N_VAR, 0, sname, NULL, NULL); 221} 222 223node_ptr make_num(char *name) 224{ 225 char *sname = malloc(strlen(name)+1); 226 strcpy(sname, name); 227 return new_node(N_NUM, 0, sname, NULL, NULL); 228} 229 230void set_bool(node_ptr varnode) 231{ 232 if (!varnode) 233 yyerror("Null node encountered"); 234 varnode->isbool = 1; 235} 236 237/* Make sure argument is OK */ 238static int check_arg(node_ptr arg, int wantbool) 239{ 240 if (!arg) { 241 yyerror("Null node encountered"); 242 return 0; 243 } 244 if (arg->type == N_VAR) { 245 node_ptr qval = find_symbol(arg->sval); 246 if (!qval) { 247 yyserror("Variable '%s' not found", arg->sval); 248 return 0; 249 } 250 if (wantbool != qval->isbool) { 251 if (wantbool) 252 yyserror("Variable '%s' not Boolean", arg->sval); 253 else 254 yyserror("Variable '%s' not integer", arg->sval); 255 return 0; 256 } 257 return 1; 258 } 259 if (arg->type == N_NUM) { 260 if (wantbool && strcmp(arg->sval,"0") != 0 && 261 strcmp(arg->sval,"1") != 0) { 262 yyserror("Value '%s' not Boolean", arg->sval); 263 return 0; 264 } 265 return 1; 266 } 267 if (wantbool && !arg->isbool) 268 yyserror("Non Boolean argument '%s'", show_expr(arg)); 269 if (!wantbool && arg->isbool) 270 yyserror("Non integer argument '%s'", show_expr(arg)); 271 return (wantbool == arg->isbool); 272} 273 274node_ptr make_not(node_ptr arg) 275{ 276 check_arg(arg, 1); 277 return new_node(N_NOT, 1, "!", arg, NULL); 278} 279 280node_ptr make_and(node_ptr arg1, node_ptr arg2) 281{ 282 check_arg(arg1, 1); 283 check_arg(arg2, 1); 284 return new_node(N_AND, 1, "&", arg1, arg2); 285} 286 287node_ptr make_or(node_ptr arg1, node_ptr arg2) 288{ 289 check_arg(arg1, 1); 290 check_arg(arg2, 1); 291 return new_node(N_OR, 1, "|", arg1, arg2); 292} 293 294node_ptr make_comp(node_ptr op, node_ptr arg1, node_ptr arg2) 295{ 296 check_arg(arg1, 0); 297 check_arg(arg2, 0); 298 return new_node(N_COMP, 1, op->sval, arg1, arg2); 299} 300 301node_ptr make_ele(node_ptr arg1, node_ptr arg2) 302{ 303 node_ptr ele; 304 check_arg(arg1, 0); 305 for (ele = arg1; ele; ele = ele->next) 306 check_arg(ele, 0); 307 return new_node(N_ELE, 1, "in", arg1, arg2); 308} 309 310node_ptr make_case(node_ptr arg1, node_ptr arg2) 311{ 312 check_arg(arg1, 1); 313 check_arg(arg2, 0); 314 return new_node(N_CASE, 0, ":", arg1, arg2); 315} 316 317void insert_code(node_ptr qstring) 318{ 319 if (!qstring) 320 yyerror("Null node"); 321 else { 322#if !defined(VLOG) && !defined(UCLID) 323 fputs(qstring->sval, outfile); 324 fputs("\n", outfile); 325#endif 326 } 327} 328 329void add_arg(node_ptr var, node_ptr qstring, int isbool) 330{ 331 if (!var || !qstring) { 332 yyerror("Null node"); 333 return; 334 } 335 add_symbol(var, qstring); 336 if (isbool) { 337 set_bool(var); 338 set_bool(qstring); 339 } 340} 341 342static char expr_buf[1024]; 343static int errlen = 0; 344#define MAXERRLEN 80 345 346/* Recursively display expression for error reporting */ 347static void show_expr_helper(node_ptr expr) 348{ 349 switch(expr->type) { 350 int len; 351 node_ptr ele; 352 case N_QUOTE: 353 len = strlen(expr->sval) + 2; 354 if (len + errlen < MAXERRLEN) { 355 sprintf(expr_buf+errlen, "'%s'", expr->sval); 356 errlen += len; 357 } 358 break; 359 case N_VAR: 360 len = strlen(expr->sval); 361 if (len + errlen < MAXERRLEN) { 362 sprintf(expr_buf+errlen, "%s", expr->sval); 363 errlen += len; 364 } 365 break; 366 case N_NUM: 367 len = strlen(expr->sval); 368 if (len + errlen < MAXERRLEN) { 369 sprintf(expr_buf+errlen, "%s", expr->sval); 370 errlen += len; 371 } 372 break; 373 case N_AND: 374 if (errlen < MAXERRLEN) { 375 sprintf(expr_buf+errlen, "("); 376 errlen+=1; 377 show_expr_helper(expr->arg1); 378 sprintf(expr_buf+errlen, " & "); 379 errlen+=3; 380 } 381 if (errlen < MAXERRLEN) { 382 show_expr_helper(expr->arg2); 383 sprintf(expr_buf+errlen, ")"); 384 errlen+=1; 385 } 386 break; 387 case N_OR: 388 if (errlen < MAXERRLEN) { 389 sprintf(expr_buf+errlen, "("); 390 errlen+=1; 391 show_expr_helper(expr->arg1); 392 sprintf(expr_buf+errlen, " | "); 393 errlen+=3; 394 } 395 if (errlen < MAXERRLEN) { 396 show_expr_helper(expr->arg2); 397 sprintf(expr_buf+errlen, ")"); 398 errlen+=1; 399 } 400 break; 401 case N_NOT: 402 if (errlen < MAXERRLEN) { 403 sprintf(expr_buf+errlen, "!"); 404 errlen+=1; 405 show_expr_helper(expr->arg1); 406 } 407 break; 408 case N_COMP: 409 if (errlen < MAXERRLEN) { 410 sprintf(expr_buf+errlen, "("); 411 errlen+=1; 412 show_expr_helper(expr->arg1); 413 sprintf(expr_buf+errlen, " %s ", expr->sval); 414 errlen+=4; 415 } 416 if (errlen < MAXERRLEN) { 417 show_expr_helper(expr->arg2); 418 sprintf(expr_buf+errlen, ")"); 419 errlen+=1; 420 } 421 break; 422 case N_ELE: 423 if (errlen < MAXERRLEN) { 424 sprintf(expr_buf+errlen, "("); 425 errlen+=1; 426 show_expr_helper(expr->arg1); 427 sprintf(expr_buf+errlen, " in {"); 428 errlen+=5; 429 } 430 for (ele = expr->arg2; ele; ele=ele->next) { 431 if (errlen < MAXERRLEN) { 432 show_expr_helper(ele); 433 if (ele->next) { 434 sprintf(expr_buf+errlen, ", "); 435 errlen+=2; 436 } 437 } 438 } 439 if (errlen < MAXERRLEN) { 440 sprintf(expr_buf+errlen, "})"); 441 errlen+=2; 442 } 443 break; 444 case N_CASE: 445 if (errlen < MAXERRLEN) { 446 sprintf(expr_buf+errlen, "[ "); 447 errlen+=2; 448 } 449 for (ele = expr; errlen < MAXERRLEN && ele; ele=ele->next) { 450 show_expr_helper(ele->arg1); 451 sprintf(expr_buf+errlen, " : "); 452 errlen += 3; 453 show_expr_helper(ele->arg2); 454 } 455 if (errlen < MAXERRLEN) { 456 sprintf(expr_buf+errlen, " ]"); 457 errlen+=2; 458 } 459 break; 460 default: 461 if (errlen < MAXERRLEN) { 462 sprintf(expr_buf+errlen, "??"); 463 errlen+=2; 464 } 465 break; 466 } 467} 468 469static char *show_expr(node_ptr expr) 470{ 471 errlen = 0; 472 show_expr_helper(expr); 473 if (errlen >= MAXERRLEN) 474 sprintf(expr_buf+errlen, "..."); 475 return expr_buf; 476} 477 478/* Recursively generate code for function */ 479static void gen_expr(node_ptr expr) 480{ 481 node_ptr ele; 482 switch(expr->type) { 483 case N_QUOTE: 484 yyserror("Unexpected quoted string", expr->sval); 485 break; 486 case N_VAR: 487 { 488 node_ptr qstring = find_symbol(expr->sval); 489 if (qstring) 490#if defined(VLOG) || defined(UCLID) 491 outgen_print("%s", expr->sval); 492#else 493 outgen_print("(%s)", qstring->sval); 494#endif 495 else 496 yyserror("Invalid variable '%s'", expr->sval); 497#ifdef UCLID 498 check_for_arg(expr->sval); 499#endif 500 501 } 502 break; 503 case N_NUM: 504#ifdef UCLID 505 { 506 long long int val = atoll(expr->sval); 507 if (val < -1) 508 outgen_print("pred^%d(CZERO)", -val); 509 else if (val == -1) 510 outgen_print("pred(CZERO)"); 511 else if (val == 0) 512 outgen_print("CZERO"); 513 else if (val == 1) 514 outgen_print("succ(CZERO)"); 515 else 516 outgen_print("succ^%d(CZERO)", val); 517 } 518#else /* !UCLID */ 519 fputs(expr->sval, outfile); 520#endif /* UCLID */ 521 break; 522 case N_AND: 523 outgen_print("("); 524 outgen_upindent(); 525 gen_expr(expr->arg1); 526 outgen_print(" & "); 527 gen_expr(expr->arg2); 528 outgen_print(")"); 529 outgen_downindent(); 530 break; 531 case N_OR: 532 outgen_print("("); 533 outgen_upindent(); 534 gen_expr(expr->arg1); 535 outgen_print(" | "); 536 gen_expr(expr->arg2); 537 outgen_print(")"); 538 outgen_downindent(); 539 break; 540 case N_NOT: 541#if defined(VLOG) || defined(UCLID) 542 outgen_print("~"); 543#else 544 outgen_print("!"); 545#endif 546 gen_expr(expr->arg1); 547 break; 548 case N_COMP: 549 outgen_print("("); 550 outgen_upindent(); 551 gen_expr(expr->arg1); 552#ifdef UCLID 553 { 554 char *cval = expr->sval; 555 if (strcmp(cval, "==") == 0) 556 cval = "="; 557 outgen_print(" %s ", cval); 558 } 559#else /* !UCLID */ 560 outgen_print(" %s ", expr->sval); 561#endif /* UCLID */ 562 gen_expr(expr->arg2); 563 outgen_print(")"); 564 outgen_downindent(); 565 break; 566 case N_ELE: 567 outgen_print("("); 568 outgen_upindent(); 569 for (ele = expr->arg2; ele; ele=ele->next) { 570 gen_expr(expr->arg1); 571#ifdef UCLID 572 outgen_print(" = "); 573#else 574 outgen_print(" == "); 575#endif 576 gen_expr(ele); 577 if (ele->next) 578#if defined(VLOG) || defined(UCLID) 579 outgen_print(" | "); 580#else 581 outgen_print(" || "); 582#endif 583 } 584 outgen_print(")"); 585 outgen_downindent(); 586 break; 587 case N_CASE: 588#ifdef UCLID 589 outgen_print("case"); 590 outgen_terminate(); 591 { 592 /* Use this to keep track of last case when no default is given */ 593 node_ptr last_arg2 = NULL; 594 for (ele = expr; ele; ele=ele->next) { 595 outgen_print(" "); 596 if (ele->arg1->type == N_NUM && atoll(ele->arg1->sval) == 1) { 597 outgen_print("default"); 598 last_arg2 = NULL; 599 } 600 else { 601 gen_expr(ele->arg1); 602 last_arg2 = ele->arg2; 603 } 604 outgen_print(" : "); 605 gen_expr(ele->arg2); 606 outgen_print(";"); 607 outgen_terminate(); 608 } 609 if (last_arg2) { 610 /* Use final case as default */ 611 outgen_print(" default : "); 612 gen_expr(last_arg2); 613 outgen_print(";"); 614 outgen_terminate(); 615 } 616 } 617 outgen_print(" esac"); 618#else /* !UCLID */ 619 outgen_print("("); 620 outgen_upindent(); 621 int done = 0; 622 for (ele = expr; ele && !done; ele=ele->next) { 623 if (ele->arg1->type == N_NUM && atoll(ele->arg1->sval) == 1) { 624 gen_expr(ele->arg2); 625 done = 1; 626 } else { 627 gen_expr(ele->arg1); 628 outgen_print(" ? "); 629 gen_expr(ele->arg2); 630 outgen_print(" : "); 631 } 632 } 633 if (!done) 634 outgen_print("0"); 635 outgen_print(")"); 636 outgen_downindent(); 637#endif 638 break; 639 default: 640 yyerror("Unknown node type"); 641 break; 642 } 643} 644 645 646/* Generate code defining function for var */ 647void gen_funct(node_ptr var, node_ptr expr, int isbool) 648{ 649 if (!var || !expr) { 650 yyerror("Null node"); 651 return; 652 } 653 check_arg(expr, isbool); 654#ifdef VLOG 655 outgen_print("assign %s = ", var->sval); 656 outgen_terminate(); 657 outgen_print(" "); 658 gen_expr(expr); 659 outgen_print(";"); 660 outgen_terminate(); 661 outgen_terminate(); 662#else /* !VLOG */ 663#ifdef UCLID 664 if (annotate) { 665 /* Print annotation information*/ 666 outgen_print("(* $define %s *)", var->sval); 667 outgen_terminate(); 668 } 669 outgen_print("%s := ", var->sval); 670 outgen_terminate(); 671 outgen_print(" "); 672 if (isbool && expr->type == N_NUM) { 673 outgen_print("%d", atoll(var->sval)); 674 } else 675 gen_expr(expr); 676 outgen_print(";"); 677 outgen_terminate(); 678 if (annotate) { 679 int i; 680 outgen_print("(* $args"); 681 for (i = 0; i < arg_cnt; i++) 682 outgen_print("%c%s", i == 0 ? ' ' : ':', arg_names[i]); 683 outgen_print(" *)"); 684 outgen_terminate(); 685 arg_cnt = 0; 686 } 687 outgen_terminate(); 688#else /* !UCLID */ 689 /* Print function header */ 690 outgen_print("long long gen_%s()", var->sval); 691 outgen_terminate(); 692 outgen_print("{"); 693 outgen_terminate(); 694 outgen_print(" return "); 695 gen_expr(expr); 696 outgen_print(";"); 697 outgen_terminate(); 698 outgen_print("}"); 699 outgen_terminate(); 700 outgen_terminate(); 701#endif /* UCLID */ 702#endif /* VLOG */ 703}