📄 sim-profile.c
字号:
/* Default profiling support. Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support.This file is part of GDB, the GNU debugger.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "sim-main.h"#include "sim-io.h"#include "sim-options.h"#include "sim-assert.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#include <ctype.h>#define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n))static MODULE_INIT_FN profile_init;static MODULE_UNINSTALL_FN profile_uninstall;static DECLARE_OPTION_HANDLER (profile_option_handler);enum { OPTION_PROFILE_INSN = OPTION_START, OPTION_PROFILE_MEMORY, OPTION_PROFILE_MODEL, OPTION_PROFILE_FILE, OPTION_PROFILE_CORE, OPTION_PROFILE_CPU_FREQUENCY, OPTION_PROFILE_PC, OPTION_PROFILE_PC_RANGE, OPTION_PROFILE_PC_GRANULARITY, OPTION_PROFILE_RANGE, OPTION_PROFILE_FUNCTION};static const OPTION profile_options[] = { { {"profile", optional_argument, NULL, 'p'}, 'p', "on|off", "Perform profiling", profile_option_handler }, { {"profile-insn", optional_argument, NULL, OPTION_PROFILE_INSN}, '\0', "on|off", "Perform instruction profiling", profile_option_handler }, { {"profile-memory", optional_argument, NULL, OPTION_PROFILE_MEMORY}, '\0', "on|off", "Perform memory profiling", profile_option_handler }, { {"profile-core", optional_argument, NULL, OPTION_PROFILE_CORE}, '\0', "on|off", "Perform CORE profiling", profile_option_handler }, { {"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", 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", profile_option_handler }, { {"profile-pc-size", required_argument, NULL, 'S'}, 'S', "PC PROFILE SIZE", "Specify PC profiling size", profile_option_handler }, { {"profile-pc-granularity", required_argument, NULL, OPTION_PROFILE_PC_GRANULARITY}, '\0', "PC PROFILE GRANULARITY", "Specify PC profiling sample coverage", profile_option_handler }, { {"profile-pc-range", required_argument, NULL, OPTION_PROFILE_PC_RANGE}, '\0', "BASE,BOUND", "Specify PC profiling address range", profile_option_handler },#ifdef SIM_HAVE_ADDR_RANGE { {"profile-range", required_argument, NULL, OPTION_PROFILE_RANGE}, '\0', "START,END", "Specify range of addresses for instruction and model profiling", profile_option_handler },#if 0 /*wip*/ { {"profile-function", required_argument, NULL, OPTION_PROFILE_FUNCTION}, '\0', "FUNCTION", "Specify function to profile", profile_option_handler },#endif#endif { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }};/* Set/reset the profile options indicated in MASK. */SIM_RCset_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_RCsim_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_RCparse_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_RCprofile_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, char *arg, int is_command){ int cpu_nr; /* FIXME: Need to handle `cpu' arg. */ switch (opt) { case 'p' : if (! WITH_PROFILE) sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n"); else return set_profile_option_mask (sd, "profile", PROFILE_USEFUL_MASK, arg); break; case OPTION_PROFILE_INSN : 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) 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) 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) 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. */ if (! WITH_PROFILE) sim_io_eprintf (sd, "Profiling not compiled in, `--profile-file' ignored\n"); else { FILE *f = fopen (arg, "w"); if (f == NULL) { sim_io_eprintf (sd, "Unable to open profile output file `%s'\n", arg); return SIM_RC_FAIL; } for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = f; } break; case OPTION_PROFILE_PC: if (WITH_PROFILE_PC_P) 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; case 'F' : if (WITH_PROFILE_PC_P) { /* FIXME: Validate arg. */ int val = atoi (arg); for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) PROFILE_PC_FREQ (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val; for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; } else sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-frequency' ignored\n"); break; case 'S' : if (WITH_PROFILE_PC_P) { /* FIXME: Validate arg. */ int val = atoi (arg); for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) PROFILE_PC_NR_BUCKETS (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val; for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; } else sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-size' ignored\n"); break; case OPTION_PROFILE_PC_GRANULARITY: if (WITH_PROFILE_PC_P) { int shift; int val = atoi (arg); /* check that the granularity is a power of two */ shift = 0; while (val > (1 << shift)) { shift += 1; } if (val != (1 << shift)) { sim_io_eprintf (sd, "PC profiling granularity not a power of two\n"); return SIM_RC_FAIL; } if (shift == 0) { sim_io_eprintf (sd, "PC profiling granularity too small"); return SIM_RC_FAIL; } for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) PROFILE_PC_SHIFT (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = shift; for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; } else sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-granularity' ignored\n"); break; case OPTION_PROFILE_PC_RANGE: if (WITH_PROFILE_PC_P) { /* FIXME: Validate args */ char *chp = arg; unsigned long base; unsigned long bound; base = strtoul (chp, &chp, 0); if (*chp != ',') { sim_io_eprintf (sd, "--profile-pc-range missing BOUND argument\n"); return SIM_RC_FAIL; } bound = strtoul (chp + 1, NULL, 0); for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) { PROFILE_PC_START (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = base; PROFILE_PC_END (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = bound; } for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; } 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 : if (WITH_PROFILE) { char *chp = arg; unsigned long start,end; start = strtoul (chp, &chp, 0); if (*chp != ',') { sim_io_eprintf (sd, "--profile-range missing END argument\n"); return SIM_RC_FAIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -