X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fcommon%2Fsim-profile.c;h=ff53f71d775bc2decd80343f1ce62a83047b3a43;hb=80dbae7a49c0b633be93dabe7908312db3e61060;hp=5a9805ba5dd1898c3b2f10728cdb73611085057a;hpb=b61e2e146a85a1d93d1ad78f923005c8e4e2d7e4;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/common/sim-profile.c b/sim/common/sim-profile.c index 5a9805ba5d..ff53f71d77 100644 --- a/sim/common/sim-profile.c +++ b/sim/common/sim-profile.c @@ -1,5 +1,5 @@ /* Default profiling support. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB, the GNU debugger. @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif #endif +#include #define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n)) @@ -48,6 +49,7 @@ enum { OPTION_PROFILE_MODEL, OPTION_PROFILE_FILE, OPTION_PROFILE_CORE, + OPTION_PROFILE_CPU_FREQUENCY, OPTION_PROFILE_PC, OPTION_PROFILE_PC_RANGE, OPTION_PROFILE_PC_GRANULARITY, @@ -56,28 +58,32 @@ enum { }; static const OPTION profile_options[] = { - { {"profile", no_argument, NULL, 'p'}, - 'p', NULL, "Perform profiling", + { {"profile", optional_argument, NULL, 'p'}, + 'p', "on|off", "Perform profiling", profile_option_handler }, - { {"profile-insn", no_argument, NULL, OPTION_PROFILE_INSN}, - '\0', NULL, "Perform instruction profiling", + { {"profile-insn", optional_argument, NULL, OPTION_PROFILE_INSN}, + '\0', "on|off", "Perform instruction profiling", profile_option_handler }, - { {"profile-memory", no_argument, NULL, OPTION_PROFILE_MEMORY}, - '\0', NULL, "Perform memory profiling", + { {"profile-memory", optional_argument, NULL, OPTION_PROFILE_MEMORY}, + '\0', "on|off", "Perform memory profiling", profile_option_handler }, - { {"profile-core", no_argument, NULL, OPTION_PROFILE_CORE}, - '\0', NULL, "Perform CORE profiling", + { {"profile-core", optional_argument, NULL, OPTION_PROFILE_CORE}, + '\0', "on|off", "Perform CORE profiling", profile_option_handler }, - { {"profile-model", no_argument, NULL, OPTION_PROFILE_MODEL}, - '\0', NULL, "Perform model profiling", + { {"profile-model", optional_argument, NULL, OPTION_PROFILE_MODEL}, + '\0', "on|off", "Perform model profiling", + profile_option_handler }, + { {"profile-cpu-frequency", required_argument, NULL, + OPTION_PROFILE_CPU_FREQUENCY}, + '\0', "CPU FREQUENCY", "Specify the speed of the simulated cpu clock", profile_option_handler }, { {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE}, '\0', "FILE NAME", "Specify profile output file", profile_option_handler }, - { {"profile-pc", no_argument, NULL, OPTION_PROFILE_PC}, - '\0', NULL, "Perform PC profiling", + { {"profile-pc", optional_argument, NULL, OPTION_PROFILE_PC}, + '\0', "on|off", "Perform PC profiling", profile_option_handler }, { {"profile-pc-frequency", required_argument, NULL, 'F'}, 'F', "PC PROFILE FREQUENCY", "Specified PC profiling frequency", @@ -106,6 +112,135 @@ static const OPTION profile_options[] = { { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } }; +/* Set/reset the profile options indicated in MASK. */ + +SIM_RC +set_profile_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg) +{ + int profile_nr; + int cpu_nr; + int profile_val = 1; + + if (arg != NULL) + { + if (strcmp (arg, "yes") == 0 + || strcmp (arg, "on") == 0 + || strcmp (arg, "1") == 0) + profile_val = 1; + else if (strcmp (arg, "no") == 0 + || strcmp (arg, "off") == 0 + || strcmp (arg, "0") == 0) + profile_val = 0; + else + { + sim_io_eprintf (sd, "Argument `%s' for `--profile%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); + return SIM_RC_FAIL; + } + } + + /* update applicable profile bits */ + for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr) + { + if ((mask & (1 << profile_nr)) == 0) + continue; + +#if 0 /* see sim-trace.c, set flags in STATE here if/when there are any */ + /* Set non-cpu specific values. */ + switch (profile_nr) + { + case ??? : + break; + } +#endif + + /* Set cpu values. */ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr] = profile_val; + } + } + + /* Re-compute the cpu profile summary. */ + if (profile_val) + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1; + } + else + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 0; + for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr) + { + if (CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr]) + { + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1; + break; + } + } + } + } + + return SIM_RC_OK; +} + +/* Set one profile option based on its IDX value. + Not static as cgen-scache.c uses it. */ + +SIM_RC +sim_profile_set_option (SIM_DESC sd, const char *name, int idx, const char *arg) +{ + return set_profile_option_mask (sd, name, 1 << idx, arg); +} + +static SIM_RC +parse_frequency (SIM_DESC sd, const char *arg, unsigned long *freq) +{ + const char *ch; + /* First, parse a decimal number. */ + *freq = 0; + ch = arg; + if (isdigit (*arg)) + { + for (/**/; *ch != '\0'; ++ch) + { + if (! isdigit (*ch)) + break; + *freq = *freq * 10 + (*ch - '0'); + } + + /* Accept KHz, MHz or Hz as a suffix. */ + if (tolower (*ch) == 'm') + { + *freq *= 1000000; + ++ch; + } + else if (tolower (*ch) == 'k') + { + *freq *= 1000; + ++ch; + } + + if (tolower (*ch) == 'h') + { + ++ch; + if (tolower (*ch) == 'z') + ++ch; + } + } + + if (*ch != '\0') + { + sim_io_eprintf (sd, "Invalid argument for --profile-cpu-frequency: %s\n", + arg); + *freq = 0; + return SIM_RC_FAIL; + } + + return SIM_RC_OK; +} + static SIM_RC profile_option_handler (SIM_DESC sd, sim_cpu *cpu, @@ -121,51 +256,52 @@ profile_option_handler (SIM_DESC sd, { case 'p' : if (! WITH_PROFILE) - sim_io_eprintf (sd, "Profiling not compiled in, -p option ignored\n"); + sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n"); else - { - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - for (prof_nr = 0; prof_nr < MAX_PROFILE_VALUES; ++prof_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[prof_nr] = 1; - } + return set_profile_option_mask (sd, "profile", PROFILE_USEFUL_MASK, + arg); break; case OPTION_PROFILE_INSN : -#if WITH_PROFILE_INSN_P - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_INSN_IDX] = 1; -#else - sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n"); -#endif + if (WITH_PROFILE_INSN_P) + return sim_profile_set_option (sd, "-insn", PROFILE_INSN_IDX, arg); + else + sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n"); break; case OPTION_PROFILE_MEMORY : -#if WITH_PROFILE_MEMORY_P - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_MEMORY_IDX] = 1; -#else - sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n"); -#endif + if (WITH_PROFILE_MEMORY_P) + return sim_profile_set_option (sd, "-memory", PROFILE_MEMORY_IDX, arg); + else + sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n"); break; case OPTION_PROFILE_CORE : -#if WITH_PROFILE_CORE_P - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_CORE_IDX] = 1; -#else - sim_io_eprintf (sd, "CORE profiling not compiled in, `--profile-core' ignored\n"); -#endif + if (WITH_PROFILE_CORE_P) + return sim_profile_set_option (sd, "-core", PROFILE_CORE_IDX, arg); + else + sim_io_eprintf (sd, "CORE profiling not compiled in, `--profile-core' ignored\n"); break; case OPTION_PROFILE_MODEL : -#if WITH_PROFILE_MODEL_P - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_MODEL_IDX] = 1; -#else - sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n"); -#endif + if (WITH_PROFILE_MODEL_P) + return sim_profile_set_option (sd, "-model", PROFILE_MODEL_IDX, arg); + else + sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n"); break; + case OPTION_PROFILE_CPU_FREQUENCY : + { + unsigned long val; + SIM_RC rc = parse_frequency (sd, arg, &val); + if (rc == SIM_RC_OK) + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + PROFILE_CPU_FREQ (CPU_PROFILE_DATA (STATE_CPU (sd,cpu_nr))) = val; + } + return rc; + } + case OPTION_PROFILE_FILE : /* FIXME: Might want this to apply to pc profiling only, or have two profile file options. */ @@ -187,10 +323,7 @@ profile_option_handler (SIM_DESC sd, case OPTION_PROFILE_PC: if (WITH_PROFILE_PC_P) - { - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; - } + return sim_profile_set_option (sd, "-pc", PROFILE_PC_IDX, arg); else sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc' ignored\n"); break; @@ -277,6 +410,7 @@ profile_option_handler (SIM_DESC sd, } else sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-range' ignored\n"); + break; #ifdef SIM_HAVE_ADDR_RANGE case OPTION_PROFILE_RANGE : @@ -315,20 +449,6 @@ profile_option_handler (SIM_DESC sd, #endif /* SIM_HAVE_ADDR_RANGE */ } - /* Re-compute the cpu profile summary. */ - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) - { - CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 0; - for (prof_nr = 0; prof_nr < MAX_PROFILE_VALUES; ++prof_nr) - { - if (CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[prof_nr]) - { - CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1; - break; - } - } - } - return SIM_RC_OK; } @@ -869,31 +989,59 @@ profile_print_speed (sim_cpu *cpu) PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); unsigned long milliseconds = sim_events_elapsed_time (sd); unsigned long total = PROFILE_TOTAL_INSN_COUNT (data); + double clock; + double secs; char comma_buf[20]; sim_io_printf (sd, "Simulator Execution Speed\n\n"); if (total != 0) - sim_io_printf (sd, " Total instructions: %s\n", COMMAS (total)); + sim_io_printf (sd, " Total instructions: %s\n", COMMAS (total)); if (milliseconds < 1000) - sim_io_printf (sd, " Total execution time: < 1 second\n\n"); + sim_io_printf (sd, " Total execution time: < 1 second\n\n"); else { /* The printing of the time rounded to 2 decimal places makes the speed calculation seem incorrect [even though it is correct]. So round MILLISECONDS first. This can marginally affect the result, but it's better that the user not perceive there's a math error. */ - double secs = (double) milliseconds / 1000; + secs = (double) milliseconds / 1000; secs = ((double) (unsigned long) (secs * 100 + .5)) / 100; - sim_io_printf (sd, " Total execution time: %.2f seconds\n", secs); + sim_io_printf (sd, " Total execution time : %.2f seconds\n", secs); /* Don't confuse things with data that isn't useful. If we ran for less than 2 seconds, only use the data if we executed more than 100,000 insns. */ if (secs >= 2 || total >= 100000) - sim_io_printf (sd, " Simulator speed: %s insns/second\n\n", + sim_io_printf (sd, " Simulator speed: %s insns/second\n", COMMAS ((unsigned long) ((double) total / secs))); } + + /* Print simulated execution time if the cpu frequency has been specified. */ + clock = PROFILE_CPU_FREQ (data); + if (clock != 0) + { + if (clock >= 1000000) + sim_io_printf (sd, " Simulated cpu frequency: %.2f MHz\n", + clock / 1000000); + else + sim_io_printf (sd, " Simulated cpu frequency: %.2f Hz\n", clock); + +#if WITH_PROFILE_MODEL_P + if (PROFILE_FLAGS (data) [PROFILE_MODEL_IDX]) + { + /* The printing of the time rounded to 2 decimal places makes the + speed calculation seem incorrect [even though it is correct]. + So round SECS first. This can marginally affect the result, + but it's better that the user not perceive there's a math + error. */ + secs = PROFILE_MODEL_TOTAL_CYCLES (data) / clock; + secs = ((double) (unsigned long) (secs * 100 + .5)) / 100; + sim_io_printf (sd, " Simulated execution time: %.2f seconds\n", + secs); + } +#endif /* WITH_PROFILE_MODEL_P */ + } } /* Print selected address ranges. */ @@ -906,10 +1054,10 @@ profile_print_addr_ranges (sim_cpu *cpu) if (asr) { - sim_io_printf (sd, "Selected address ranges:\n"); + sim_io_printf (sd, "Selected address ranges\n\n"); while (asr != NULL) { - sim_io_printf (sd, "0x%lx - 0x%lx\n", + sim_io_printf (sd, " 0x%lx - 0x%lx\n", (long) asr->start, (long) asr->end); asr = asr->next; }