📄 sim-profile.c
字号:
if (PROFILE_READ_COUNT (data) [i] != 0) { sim_io_printf (sd, " %*s read: %*s: ", max_name_len, MODE_NAME (i), max_val < 10000 ? 5 : 10, COMMAS (PROFILE_READ_COUNT (data) [i])); sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, PROFILE_READ_COUNT (data) [i], max_val); sim_io_printf (sd, "\n"); } if (PROFILE_WRITE_COUNT (data) [i] != 0) { sim_io_printf (sd, " %*s write: %*s: ", max_name_len, MODE_NAME (i), max_val < 10000 ? 5 : 10, COMMAS (PROFILE_WRITE_COUNT (data) [i])); sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, PROFILE_WRITE_COUNT (data) [i], max_val); sim_io_printf (sd, "\n"); } } } sim_io_printf (sd, "\n");}#endif#if WITH_PROFILE_CORE_Pstatic voidprofile_print_core (sim_cpu *cpu, int verbose){ unsigned int total; unsigned int max_val; /* FIXME: Need to add smp support. */ SIM_DESC sd = CPU_STATE (cpu); PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); char comma_buf[20]; sim_io_printf (sd, "CORE Statistics\n\n"); /* First pass over data computes various things. */ { unsigned map; total = 0; max_val = 0; for (map = 0; map < nr_maps; map++) { total += PROFILE_CORE_COUNT (data) [map]; if (PROFILE_CORE_COUNT (data) [map] > max_val) max_val = PROFILE_CORE_COUNT (data) [map]; } } /* One could use PROFILE_LABEL_WIDTH here. I chose not to. */ sim_io_printf (sd, " Total: %s accesses\n", COMMAS (total)); if (verbose && max_val != 0) { unsigned map; /* Now we can print the histogram. */ sim_io_printf (sd, "\n"); for (map = 0; map < nr_maps; map++) { if (PROFILE_CORE_COUNT (data) [map] != 0) { sim_io_printf (sd, "%10s:", map_to_str (map)); sim_io_printf (sd, "%*s: ", max_val < 10000 ? 5 : 10, COMMAS (PROFILE_CORE_COUNT (data) [map])); sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, PROFILE_CORE_COUNT (data) [map], max_val); sim_io_printf (sd, "\n"); } } } sim_io_printf (sd, "\n");}#endif#if WITH_PROFILE_MODEL_Pstatic voidprofile_print_model (sim_cpu *cpu, int verbose){ SIM_DESC sd = CPU_STATE (cpu); PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); unsigned long cti_stall_cycles = PROFILE_MODEL_CTI_STALL_CYCLES (data); unsigned long load_stall_cycles = PROFILE_MODEL_LOAD_STALL_CYCLES (data); unsigned long total_cycles = PROFILE_MODEL_TOTAL_CYCLES (data); char comma_buf[20]; sim_io_printf (sd, "Model %s Timing Information", MODEL_NAME (CPU_MODEL (cpu)));#ifdef SIM_HAVE_ADDR_RANGE if (PROFILE_RANGE (data)->ranges) sim_io_printf (sd, " (for selected address range(s))");#endif sim_io_printf (sd, "\n\n"); sim_io_printf (sd, " %-*s %s\n", PROFILE_LABEL_WIDTH, "Taken branches:", COMMAS (PROFILE_MODEL_TAKEN_COUNT (data))); sim_io_printf (sd, " %-*s %s\n", PROFILE_LABEL_WIDTH, "Untaken branches:", COMMAS (PROFILE_MODEL_UNTAKEN_COUNT (data))); sim_io_printf (sd, " %-*s %s\n", PROFILE_LABEL_WIDTH, "Cycles stalled due to branches:", COMMAS (cti_stall_cycles)); sim_io_printf (sd, " %-*s %s\n", PROFILE_LABEL_WIDTH, "Cycles stalled due to loads:", COMMAS (load_stall_cycles)); sim_io_printf (sd, " %-*s %s\n", PROFILE_LABEL_WIDTH, "Total cycles (*approximate*):", COMMAS (total_cycles)); sim_io_printf (sd, "\n");}#endifvoidsim_profile_print_bar (SIM_DESC sd, unsigned int width, unsigned int val, unsigned int max_val){ unsigned int i, count; count = ((double) val / (double) max_val) * (double) width; for (i = 0; i < count; ++i) sim_io_printf (sd, "*");}/* Print the simulator's execution speed for CPU. */static voidprofile_print_speed (sim_cpu *cpu){ SIM_DESC sd = CPU_STATE (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)); if (milliseconds < 1000) 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. */ secs = (double) milliseconds / 1000; secs = ((double) (unsigned long) (secs * 100 + .5)) / 100; 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", 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. */static voidprofile_print_addr_ranges (sim_cpu *cpu){ ADDR_SUBRANGE *asr = PROFILE_RANGE (CPU_PROFILE_DATA (cpu))->ranges; SIM_DESC sd = CPU_STATE (cpu); if (asr) { sim_io_printf (sd, "Selected address ranges\n\n"); while (asr != NULL) { sim_io_printf (sd, " 0x%lx - 0x%lx\n", (long) asr->start, (long) asr->end); asr = asr->next; } sim_io_printf (sd, "\n"); }}/* Top level function to print all summary profile information. It is [currently] intended that all such data is printed by this function. I'd rather keep it all in one place for now. To that end, MISC_CPU and MISC are callbacks used to print any miscellaneous data. One might want to add a user option that allows printing by type or by cpu (i.e. print all insn data for each cpu first, or print data cpu by cpu). This may be a case of featuritis so it's currently left out. Note that results are indented two spaces to distinguish them from section titles. */static voidprofile_info (SIM_DESC sd, int verbose){ int i,c; int print_title_p = 0; /* Only print the title if some data has been collected. */ /* ??? Why don't we just exit if no data collected? */ /* FIXME: If the number of processors can be selected on the command line, then MAX_NR_PROCESSORS will need to take an argument of `sd'. */ for (c = 0; c < MAX_NR_PROCESSORS; ++c) { sim_cpu *cpu = STATE_CPU (sd, c); PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); for (i = 0; i < MAX_PROFILE_VALUES; ++i) if (PROFILE_FLAGS (data) [i]) print_title_p = 1; /* One could break out early if print_title_p is set. */ } if (print_title_p) sim_io_printf (sd, "Summary profiling results:\n\n"); /* Loop, cpu by cpu, printing results. */ for (c = 0; c < MAX_NR_PROCESSORS; ++c) { sim_cpu *cpu = STATE_CPU (sd, c); PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); if (MAX_NR_PROCESSORS > 1 && (0#if WITH_PROFILE_INSN_P || PROFILE_FLAGS (data) [PROFILE_INSN_IDX]#endif#if WITH_PROFILE_MEMORY_P || PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX]#endif#if WITH_PROFILE_CORE_P || PROFILE_FLAGS (data) [PROFILE_CORE_IDX]#endif#if WITH_PROFILE_MODEL_P || PROFILE_FLAGS (data) [PROFILE_MODEL_IDX]#endif#if WITH_PROFILE_SCACHE_P && WITH_SCACHE || PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX]#endif#if WITH_PROFILE_PC_P || PROFILE_FLAGS (data) [PROFILE_PC_IDX]#endif )) { sim_io_printf (sd, "CPU %d\n\n", c); }#ifdef SIM_HAVE_ADDR_RANGE if (print_title_p && (PROFILE_INSN_P (cpu) || PROFILE_MODEL_P (cpu))) profile_print_addr_ranges (cpu);#endif#if WITH_PROFILE_INSN_P if (PROFILE_FLAGS (data) [PROFILE_INSN_IDX]) profile_print_insn (cpu, verbose);#endif#if WITH_PROFILE_MEMORY_P if (PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX]) profile_print_memory (cpu, verbose);#endif#if WITH_PROFILE_CORE_P if (PROFILE_FLAGS (data) [PROFILE_CORE_IDX]) profile_print_core (cpu, verbose);#endif#if WITH_PROFILE_MODEL_P if (PROFILE_FLAGS (data) [PROFILE_MODEL_IDX]) profile_print_model (cpu, verbose);#endif#if WITH_PROFILE_SCACHE_P && WITH_SCACHE if (PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX]) scache_print_profile (cpu, verbose);#endif#if WITH_PROFILE_PC_P if (PROFILE_FLAGS (data) [PROFILE_PC_IDX]) profile_print_pc (cpu, verbose);#endif /* Print cpu-specific data before the execution speed. */ if (PROFILE_INFO_CPU_CALLBACK (data) != NULL) PROFILE_INFO_CPU_CALLBACK (data) (cpu, verbose); /* Always try to print execution time and speed. */ if (verbose || PROFILE_FLAGS (data) [PROFILE_INSN_IDX]) profile_print_speed (cpu); } /* Finally print non-cpu specific miscellaneous data. */ if (STATE_PROFILE_INFO_CALLBACK (sd)) STATE_PROFILE_INFO_CALLBACK (sd) (sd, verbose);}/* Install profiling support in the simulator. */SIM_RCprofile_install (SIM_DESC sd){ int i; SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); sim_add_option_table (sd, NULL, profile_options); for (i = 0; i < MAX_NR_PROCESSORS; ++i) memset (CPU_PROFILE_DATA (STATE_CPU (sd, i)), 0, sizeof (* CPU_PROFILE_DATA (STATE_CPU (sd, i))));#if WITH_PROFILE_INSN_P sim_module_add_init_fn (sd, profile_insn_init);#endif#if WITH_PROFILE_PC_P sim_module_add_uninstall_fn (sd, profile_pc_uninstall); sim_module_add_init_fn (sd, profile_pc_init);#endif sim_module_add_init_fn (sd, profile_init); sim_module_add_uninstall_fn (sd, profile_uninstall); sim_module_add_info_fn (sd, profile_info); return SIM_RC_OK;}static SIM_RCprofile_init (SIM_DESC sd){#ifdef SIM_HAVE_ADDR_RANGE /* Check if a range has been specified without specifying what to collect. */ { int i; for (i = 0; i < MAX_NR_PROCESSORS; ++i) { sim_cpu *cpu = STATE_CPU (sd, i); if (ADDR_RANGE_RANGES (PROFILE_RANGE (CPU_PROFILE_DATA (cpu))) && ! (PROFILE_INSN_P (cpu) || PROFILE_MODEL_P (cpu))) { sim_io_eprintf_cpu (cpu, "Profiling address range specified without --profile-insn or --profile-model.\n"); sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); sim_addr_range_delete (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), 0, ~ (address_word) 0); } } }#endif return SIM_RC_OK;}static voidprofile_uninstall (SIM_DESC sd){ int i,j; for (i = 0; i < MAX_NR_PROCESSORS; ++i) { sim_cpu *cpu = STATE_CPU (sd, i); PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); if (PROFILE_FILE (data) != NULL) { /* If output from different cpus is going to the same file, avoid closing the file twice. */ for (j = 0; j < i; ++j) if (PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, j))) == PROFILE_FILE (data)) break; if (i == j) fclose (PROFILE_FILE (data)); } if (PROFILE_INSN_COUNT (data) != NULL) zfree (PROFILE_INSN_COUNT (data)); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -