void analyse_statements(Stmts *statements, sym_table *table, char *scope_id) { while (statements != NULL) { Stmt *statement = statements->first; StmtKind kind = statement->kind; SInfo *info = &(statement->info); int line_no = statement->lineno; // Switch on kind of statement and print appropriately switch (kind) { case STMT_ASSIGN: analyse_assign(&info->assign, table, scope_id, line_no); break; case STMT_COND: analyse_if(&info->cond, table, scope_id, line_no); break; case STMT_READ: analyse_read(info->read, table, scope_id, line_no); break; case STMT_WHILE: analyse_while(&info->loop, table, scope_id, line_no); break; case STMT_WRITE: analyse_write(info->write, table, scope_id, line_no); break; case STMT_FUNC: analyse_function(info->func, table, scope_id, line_no); break; } statements = statements->rest; } }
void main_cuc (char *filename) { int i, j; char tmp1[256]; char filename_cut[256]; #if 0 /* Select prefix, based on binary program name */ for (i = 0; i < sizeof (filename_cut); i++) { if (isalpha (filename[i])) filename_cut[i] = filename[i]; else { filename_cut[i] = '\0'; break; } } #else strcpy (filename_cut, "cu"); #endif PRINTF ("Entering OpenRISC Custom Unit Compiler command prompt\n"); PRINTF ("Using profile file \"%s\" and memory profile file \"%s\".\n", config.sim.prof_fn, config.sim.mprof_fn); sprintf (tmp1, "%s.log", filename_cut); PRINTF ("Analyzing. (log file \"%s\").\n", tmp1); assert (flog = fopen (tmp1, "wt+")); /* Loads in the specified timings table */ PRINTF ("Using timings from \"%s\" at %s\n", config.cuc.timings_fn, generate_time_pretty (tmp1, config.sim.clkcycle_ps)); load_timing_table (config.cuc.timings_fn); runtime.cuc.cycle_duration = 1000. * config.sim.clkcycle_ps; PRINTF ("Multicycle logic %s, bursts %s, %s memory order.\n", config.cuc.no_multicycle ? "OFF" : "ON", config.cuc.enable_bursts ? "ON" : "OFF", config.cuc.memory_order == MO_NONE ? "no" : config.cuc.memory_order == MO_WEAK ? "weak" : config.cuc.memory_order == MO_STRONG ? "strong" : "exact"); prof_set (1, 0); assert (prof_acquire (config.sim.prof_fn) == 0); if (config.cuc.calling_convention) PRINTF ("Assuming OpenRISC standard calling convention.\n"); /* Try all functions except "total" */ for (i = 0; i < prof_nfuncs - 1; i++) { long orig_time; unsigned long start_addr, end_addr; orig_time = prof_func[i].cum_cycles; start_addr = prof_func[i].addr; /* Extract the function from the binary */ sprintf (tmp1, "%s.bin", prof_func[i].name); end_addr = extract_function (tmp1, start_addr); log ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name, start_addr, end_addr); PRINTF ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name, start_addr, end_addr); func[i] = analyse_function (prof_func[i].name, orig_time, start_addr, end_addr, config.cuc.memory_order, prof_func[i].calls); func_v[i] = 0; } set_func_deps (); while (1) { char *s; wait_command: PRINTF ("(cuc) "); fflush (stdout); wait_command_empty: s = fgets (tmp1, sizeof tmp1, stdin); usleep (100); if (!s) goto wait_command_empty; for (s = tmp1; *s != '\0' && *s != '\n' && *s != '\r'; s++); *s = '\0'; /* quit command */ if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0) { /* Delete temporary files */ for (i = 0; i < prof_nfuncs - 1; i++) { sprintf (tmp1, "%s.bin", prof_func[i].name); log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK"); sprintf (tmp1, "%s.bin.bb", prof_func[i].name); log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK"); } break; /* profile command */ } else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0) { int ntime = 0; int size = 0; PRINTF ("-----------------------------------------------------------------------------\n"); PRINTF ("|function name |calls|avg cycles |old%%| max. f. | impr. f.| options |\n"); PRINTF ("|--------------------+-----+------------+----+----------|---------+---------|\n"); for (j = 0; j < prof_nfuncs; j++) { int bestcyc = 0, besti = 0; char tmp[100]; for (i = 0; i < prof_nfuncs; i++) if (prof_func[i].cum_cycles > bestcyc) { bestcyc = prof_func[i].cum_cycles; besti = i; } i = besti; PRINTF ("|%-20s|%5li|%12.1f|%3.0f%%| ", strstrip (tmp, prof_func[i].name, 20), prof_func[i].calls, ((double) prof_func[i].cum_cycles / prof_func[i].calls), (100. * prof_func[i].cum_cycles / prof_cycles)); if (func[i]) { double f = 1.0; if (func_v[i]) { int nt = calc_cycles (func[i]); int s = calc_size (func[i]); f = 1. * func[i]->orig_time / nt; ntime += nt; size += s; } else ntime += prof_func[i].cum_cycles; PRINTF ("%8.1f |%8.1f | %-8s|\n", 1.f * prof_func[i].cum_cycles / func[i]->timings.new_time, f, format_func_options (tmp, func[i])); } else { PRINTF (" N/A | N/A | N/A |\n"); ntime += prof_func[i].cum_cycles; } prof_func[i].cum_cycles = -prof_func[i].cum_cycles; } for (i = 0; i < prof_nfuncs; i++) prof_func[i].cum_cycles = -prof_func[i].cum_cycles; PRINTF ("-----------------------------------------------------------------------------\n"); PRINTF ("Total %i cycles (was %i), total added gates = %i. Speed factor %.1f\n", ntime, prof_cycles, size, 1. * prof_cycles / ntime); /* debug command */ } else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0) { sscanf (tmp1, "%*s %i", &cuc_debug); if (cuc_debug < 0) cuc_debug = 0; if (cuc_debug > 9) cuc_debug = 9; /* generate command */ } else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0) { /* check for function dependencies */ for (i = 0; i < prof_nfuncs; i++) if (func[i]) func[i]->tmp = func_v[i]; for (i = 0; i < prof_nfuncs; i++) if (func[i]) for (j = 0; j < func[i]->nfdeps; j++) if (!func[i]->fdeps[j] || !func[i]->fdeps[j]->tmp) { PRINTF ("Function %s must be selected for translation (required by %s)\n", prof_func[j].name, prof_func[i].name); goto wait_command; } for (i = 0; i < prof_nfuncs; i++) if (func[i] && func_v[i]) generate_function (func[i], prof_func[i].name, filename_cut); generate_main (prof_nfuncs, func, filename_cut); /* list command */ } else if (strcmp (tmp1, "l") == 0 || strcmp (tmp1, "list") == 0) { /* check for function dependencies */ for (i = 0; i < prof_nfuncs; i++) if (func_v[i]) { PRINTF ("%s\n", prof_func[i].name); } /* selectall command */ } else if (strcmp (tmp1, "sa") == 0 || strcmp (tmp1, "selectall") == 0) { int f; for (f = 0; f < prof_nfuncs; f++) if (func[f]) { func_v[f] = 1; PRINTF ("Function %s selected for translation.\n", prof_func[f].name); } /* select command */ } else if (strncmp (tmp1, "s", 1) == 0 || strncmp (tmp1, "select", 6) == 0) { char tmp[50], ch; int p, o, b, f; p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch); if (p < 1) PRINTF ("Invalid parameters.\n"); else { /* Check if we have valid option */ for (f = 0; f < prof_nfuncs; f++) if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break; if (f < prof_nfuncs) { if (p == 1) { if (func[f]) { func_v[f] = 1; PRINTF ("Function %s selected for translation.\n", prof_func[f].name); } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name); } else { if (!func_v[f]) PRINTF ("Function %s not yet selected for translation.\n", prof_func[f].name); if (p < 3) goto invalid_option; for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++); if (!option_char[o]) goto invalid_option; if (b < 0 || b >= func[f]->num_bb) goto invalid_option; if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option; /* select an option */ func[f]->bb[b].selected_tim = o; if (func[f]->bb[b].tim[o].nshared) { PRINTF ("Option has shared instructions: "); print_shared (func[f], func[f]->bb[b].tim[o].shared, func[f]->bb[b].tim[o].nshared); PRINTF ("\n"); } goto wait_command; invalid_option: PRINTF ("Invalid option.\n"); } } else PRINTF ("Invalid function.\n"); } /* unselect command */ } else if (strncmp (tmp1, "u", 1) == 0 || strncmp (tmp1, "unselect", 8) == 0) { char tmp[50], ch; int p, o, b, f; p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch); if (p < 1) PRINTF ("Invalid parameters.\n"); else { /* Check if we have valid option */ for (f = 0; f < prof_nfuncs; f++) if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break; if (f < prof_nfuncs) { if (p == 1) { if (func[f]) { func_v[f] = 0; PRINTF ("Function %s unselected for translation.\n", prof_func[f].name); } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name); } else { if (p < 3) goto invalid_option; for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++); if (!option_char[o]) goto invalid_option; if (b < 0 || b >= func[f]->num_bb) goto invalid_option; if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option; /* select an option */ func[f]->bb[b].selected_tim = -1; } } else PRINTF ("Invalid function.\n"); } /* options command */ } else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0) { int any = 0; PRINTF ("Available options:\n"); for (i = 0; i < prof_nfuncs; i++) if (func[i]) { options_cmd (i, func[i]); any = 1; } if (any) PRINTF ("-----------------------------------------------------------------------------\n"); else PRINTF ("Sorry. No available options.\n"); /* Ignore empty string */ } else if (strcmp (tmp1, "") == 0) { /* help command */ } else { if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0) PRINTF ("Unknown command.\n"); PRINTF ("OpenRISC Custom Unit Compiler command prompt\n"); PRINTF ("Available commands:\n"); PRINTF (" h | help displays this help\n"); PRINTF (" q | quit returns to or1ksim prompt\n"); PRINTF (" p | profile displays function profiling\n"); PRINTF (" d | debug # sets debug level (0-9)\n"); PRINTF (" o | options displays available options\n"); PRINTF (" s | select func [option] selects an option/function\n"); PRINTF (" u | unselect func [option] unselects an option/function\n"); PRINTF (" g | generate generates verilog file\n"); PRINTF (" l | list displays selected functions\n"); } } /* Dispose memory */ for (i = 0; i < prof_nfuncs - 1; i++) if (func[i]) free_func (func[i]); fclose (flog); }