URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [branches/] [stable_0_1_x/] [or1ksim/] [profiler.c] - Rev 533
Go to most recent revision | Compare with Previous | Blame | View Log
/* Command line utility, that displays profiling information, generated by or1ksim. (use -profile option at command line, when running or1ksim. GNU License (C) Marko Mlinar 2001. */ #include <stdio.h> #define MAX_STACK 1024 #define MAX_FUNCS 1024 struct stack_struct { /* Function address */ unsigned int addr; /* Cycles of function start; cycles of subfunctions are added later */ unsigned int cycles; /* Return address */ unsigned int raddr; /* Name of the function */ char name[33]; } stack[MAX_STACK]; struct func_struct { /* Start address of function */ unsigned int addr; /* Name of the function */ char name[33]; /* Total cycles spent in function */ long cum_cycles; /* Calls to this function */ long calls; } func[MAX_FUNCS]; /* Total number of functions */ int nfuncs = 0; /* Current depth */ int nstack = 0; /* Max depth */ int maxstack = 0; /* Number of total calls */ int ntotcalls = 0; /* Number of covered calls */ int nfunccalls = 0; /* Current cycles */ static int cycles = 0; /* Whether we are in cumulative mode */ static int cumulative = 0; /* Whether we should not report warnings */ static int quiet = 0; /* File to read from */ static FILE *fprof = 0; int main (int argc, char *argv[]) { char fprofname[50] = "sim.profile"; int line = 0; if (argc > 4 || argc < 2) { fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--quiet|-q] --generate|-g [profile_file_name]\n"); exit(1); } argv++; argc--; while (argc > 0) { if (!strcmp(argv[0], "-q") || !strcmp(argv[0], "--quiet")) { quiet = 1; argv++; argc--; } else if (!strcmp(argv[0], "-c") || !strcmp(argv[0], "--cumulative")) { cumulative = 1; argv++; argc--; } else if (strcmp(argv[0], "-g") && strcmp(argv[0], "--generate")) { fprintf (stderr, "USAGE: profiler [--cumulative|-c] [--generate|-g] [profile_file_name]\n"); exit(1); } else { argv++; argc--; if (argv[0] && argv[0][0] != '-') { strcpy (&fprofname[0], argv[0]); argv++; argc--; } } } fprof = fopen (&fprofname[0], "rt"); if (!fprof) { fprintf (stderr, "Cannot open profile file: %s\n", &fprofname[0]); exit(1); } while (1) { char dir = fgetc (fprof); line++; if (dir == '+') { if (fscanf (fprof, "%08X %08X %08X %s\n", &stack[nstack].cycles, &stack[nstack].raddr, &stack[nstack].addr, &stack[nstack].name[0]) != 4) fprintf (stderr, "Error reading line #%i\n", line); else { cycles = stack[nstack].cycles; nstack++; if (nstack > maxstack) maxstack = nstack; } ntotcalls++; } else if (dir == '-') { struct stack_struct s; if (fscanf (fprof, "%08X %08X\n", &s.cycles, &s.raddr) != 2) fprintf (stderr, "Error reading line #%i\n", line); else { int i; cycles = s.cycles; for (i = nstack - 1; i >= 0; i--) if (stack[i].raddr == s.raddr) break; if (i >= 0) { /* pop everything above current from stack, if more than one, something went wrong */ while (nstack > i) { int j; long time; nstack--; time = s.cycles - stack[nstack].cycles; if (!quiet && time < 0) { fprintf (stderr, "WARNING: Negative time at %s (return addr = %08X).\n", stack[i].name, stack[i].raddr); time = 0; } /* Whether in normal mode, we must substract called function from execution time. */ if (!cumulative) for (j = 0; j < nstack; j++) stack[j].cycles += time; if (!quiet && i != nstack) fprintf (stderr, "WARNING: Missaligned return call for %s (%08X) (found %s @ %08X), closing.\n", stack[nstack].name, stack[nstack].raddr, stack[i].name, stack[i].raddr); for (j = 0; j < nfuncs; j++) if (stack[nstack].addr == func[j].addr) { /* function exists, append. */ func[j].cum_cycles += time; func[j].calls++; nfunccalls++; break; } if (j >= nfuncs) { /* function does not yet exist, create new. */ func[nfuncs].cum_cycles = time; func[nfuncs].calls = 1; nfunccalls++; func[nfuncs].addr = stack[nstack].addr; strcpy (func[nfuncs].name, stack[nstack].name); nfuncs++; } } } else if (!quiet) fprintf (stderr, "WARNING: Cannot find return call for (%08X), ignoring.\n", s.raddr); } } else break; } fclose(fprof); /* Now we have all data acquired. Print out. */ { int i, j; if (cumulative) printf ("CUMULATIVE TIMES\n"); printf ("---------------------------------------------------------------------------\n"); printf ("|function name |addr |# calls |avg cycles |total cyles |\n"); printf ("|-------------------------+--------+--------+------------+----------------|\n"); for (j = 0; j < nfuncs; j++) { int bestcyc = 0, besti = 0; for (i = 0; i < nfuncs; i++) if (func[i].cum_cycles > bestcyc) { bestcyc = func[i].cum_cycles; besti = i; } i = besti; printf ("| %-24s|%08X|%8i|%12.1f|%11i,%3.0f%%|\n", func[i].name, func[i].addr, func[i].calls, ((double)func[i].cum_cycles / func[i].calls), func[i].cum_cycles, (100. * func[i].cum_cycles / cycles)); func[i].cum_cycles = -1; } printf ("---------------------------------------------------------------------------\n"); } printf ("Total %i functions, %i cycles.\n", nfuncs, cycles); printf ("Total function calls %i/%i (max depth %i).\n", nfunccalls, ntotcalls, maxstack); return 0; }
Go to most recent revision | Compare with Previous | Blame | View Log