mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-29 06:50:32 +00:00
* Makefile.in (sim-options_h): Define.
(sim-{module,options,trace,profile,utils}.o): Clean up dependencies. (sim-model.o): Add new rule. (cgen-{scache,trace,utils}.o): Add new rules. * aclocal.m4 (SIM_AC_OPTION_{SCACHE,DEFAULT_MODEL}): Add. * cgen-scache.c (scache_print_profile): Change `sd' arg to `cpu'. Indent output by 2 spaces. * cgen-scache.h (scache_print_profile): Update. * cgen-trace.c (trace_insn_fini): Indent output by 2 spaces. Use trace_printf, not fprintf. (trace_extract): Use trace_printf, not cgen_trace_printf. * genmloop.sh (!FAST case): Increment `insn_count'. * sim-base.h (sim_state_base): Only include scache_size if WITH_SCACHE. (sim_cpu_base): Rename member `sd' to `state' to be consistent with access macro's name. * sim-core.c (sim_core_init): Use EXTERN_SIM_CORE to define it. Change return type to SIM_RC. (sim_core_{install,uninstall}): New functions. * sim-core.h (sim_core_{install,uninstall}): Declare. (sim_core_init): Use EXTERN_SIM_CORE to define it. Change return type to SIM_RC. * sim-model.h (models,machs,model_install): Declare. * sim-module.c (modules): Add scache_install, model_install. (sim_post_argv_init): Set cpu->state backlinks. * sim-options.c (standard_options): Delete --simcache-size,--max-insns. (standard_option_handler): Likewise. * sim-profile.c (PROFILE_{HISTOGRAM,LABEL}_WIDTH): Move to sim-profile.h. (*): Assume ANSI C. (profile_options): Delete --profile-simcache. (profile_option_handler): Likewise. (profile_print_insn): Change `sd' arg to `cpu'. Indent output 2 spaces. (profile_print_{memory,model}): Likewise. (profile_print_simcache): Delete. (profile_print_speed): New function. (profile_print): Rewrite. * sim-profile.h (PROFILE_scache): Renamed from PROFILE_simcache. (WITH_PROFILE_SCACHE_P): Renamed from WITH_PROFILE_SIMCACHE_P. (PROFILE_DATA): Delete members simcache_{hits,misses}. (PROFILE_COUNT_SIMCACHE_{HIT,MISS}): Delete. (PROFILE_{CALLBACK,CPU_CALLBACK}): New types. (profile_print): Update prototype.
This commit is contained in:
parent
2c8f0de695
commit
c967f1874a
@ -1,3 +1,49 @@
|
||||
Thu May 1 10:40:47 1997 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* Makefile.in (sim-options_h): Define.
|
||||
(sim-{module,options,trace,profile,utils}.o): Clean up dependencies.
|
||||
(sim-model.o): Add new rule.
|
||||
(cgen-{scache,trace,utils}.o): Add new rules.
|
||||
* aclocal.m4 (SIM_AC_OPTION_{SCACHE,DEFAULT_MODEL}): Add.
|
||||
* cgen-scache.c (scache_print_profile): Change `sd' arg to `cpu'.
|
||||
Indent output by 2 spaces.
|
||||
* cgen-scache.h (scache_print_profile): Update.
|
||||
* cgen-trace.c (trace_insn_fini): Indent output by 2 spaces.
|
||||
Use trace_printf, not fprintf.
|
||||
(trace_extract): Use trace_printf, not cgen_trace_printf.
|
||||
* genmloop.sh (!FAST case): Increment `insn_count'.
|
||||
* sim-base.h (sim_state_base): Only include scache_size if WITH_SCACHE.
|
||||
(sim_cpu_base): Rename member `sd' to `state' to be consistent with
|
||||
access macro's name.
|
||||
* sim-core.c (sim_core_init): Use EXTERN_SIM_CORE to define it.
|
||||
Change return type to SIM_RC.
|
||||
(sim_core_{install,uninstall}): New functions.
|
||||
* sim-core.h (sim_core_{install,uninstall}): Declare.
|
||||
(sim_core_init): Use EXTERN_SIM_CORE to define it.
|
||||
Change return type to SIM_RC.
|
||||
* sim-model.h (models,machs,model_install): Declare.
|
||||
* sim-module.c (modules): Add scache_install, model_install.
|
||||
(sim_post_argv_init): Set cpu->state backlinks.
|
||||
* sim-options.c (standard_options): Delete --simcache-size,--max-insns.
|
||||
(standard_option_handler): Likewise.
|
||||
* sim-profile.c (PROFILE_{HISTOGRAM,LABEL}_WIDTH): Move to
|
||||
sim-profile.h.
|
||||
(*): Assume ANSI C.
|
||||
(profile_options): Delete --profile-simcache.
|
||||
(profile_option_handler): Likewise.
|
||||
(profile_print_insn): Change `sd' arg to `cpu'. Indent output 2
|
||||
spaces.
|
||||
(profile_print_{memory,model}): Likewise.
|
||||
(profile_print_simcache): Delete.
|
||||
(profile_print_speed): New function.
|
||||
(profile_print): Rewrite.
|
||||
* sim-profile.h (PROFILE_scache): Renamed from PROFILE_simcache.
|
||||
(WITH_PROFILE_SCACHE_P): Renamed from WITH_PROFILE_SIMCACHE_P.
|
||||
(PROFILE_DATA): Delete members simcache_{hits,misses}.
|
||||
(PROFILE_COUNT_SIMCACHE_{HIT,MISS}): Delete.
|
||||
(PROFILE_{CALLBACK,CPU_CALLBACK}): New types.
|
||||
(profile_print): Update prototype.
|
||||
|
||||
Wed Apr 30 11:34:14 1997 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* cgen-mem.h, cgen-scache.[ch], cgen-sem.h, cgen-sim.h: New files.
|
||||
|
@ -71,7 +71,6 @@ SIM_DEBUG = @sim_debug@
|
||||
SIM_TRACE = @sim_trace@
|
||||
SIM_PROFILE = @sim_profile@
|
||||
|
||||
|
||||
HDEFINES = @HDEFINES@
|
||||
TDEFINES =
|
||||
|
||||
@ -177,8 +176,8 @@ sim_main_headers = \
|
||||
$(srcdir)/../common/sim-config.h \
|
||||
$(srcdir)/../common/sim-base.h \
|
||||
$(srcdir)/../common/sim-basics.h \
|
||||
$(srcdir)/../common/sim-module.h \
|
||||
$(srcdir)/../common/sim-model.h \
|
||||
$(srcdir)/../common/sim-module.h \
|
||||
$(srcdir)/../common/sim-trace.h \
|
||||
$(srcdir)/../common/sim-profile.h \
|
||||
tconfig.h
|
||||
@ -193,10 +192,10 @@ sim-core_h = $(srcdir)/../common/sim-core.h
|
||||
sim-n-core_h = $(srcdir)/../common/sim-n-core.h
|
||||
sim-events_h = $(srcdir)/../common/sim-events.h
|
||||
sim-io_h = $(srcdir)/../common/sim-io.h
|
||||
sim-n-io_h = $(srcdir)/../common/sim-n-io.h
|
||||
sim-options_h = $(srcdir)/../common/sim-options.h
|
||||
|
||||
# FIXME: If this complicated way of building .o files from ../common is
|
||||
# necessary, the reason should be documented here!
|
||||
# necessary, the reason should be documented here.
|
||||
|
||||
BUILT_SRC_FROM_COMMON= \
|
||||
sim-endian.c \
|
||||
@ -262,23 +261,27 @@ sim-io.c: $(srcdir)/../common/sim-io.c
|
||||
$(srcdir)/../../move-if-change tmp-$@ $@
|
||||
|
||||
sim-module.o: $(srcdir)/../common/sim-module.c $(sim_main_headers) \
|
||||
$(srcdir)/../common/sim-io.h
|
||||
$(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-module.c $(ALL_CFLAGS)
|
||||
|
||||
sim-options.o: $(srcdir)/../common/sim-options.c $(sim_main_headers) \
|
||||
$(srcdir)/../common/sim-options.h
|
||||
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS)
|
||||
|
||||
sim-trace.o: $(srcdir)/../common/sim-trace.c $(sim_main_headers) \
|
||||
$(srcdir)/../common/sim-io.h
|
||||
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS)
|
||||
|
||||
sim-profile.o: $(srcdir)/../common/sim-profile.c $(sim_main_headers) \
|
||||
$(srcdir)/../common/sim-io.h
|
||||
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-profile.c $(ALL_CFLAGS)
|
||||
|
||||
sim-model.o: $(srcdir)/../common/sim-model.c $(sim_main_headers) \
|
||||
$(sim-io_h) $(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-model.c $(ALL_CFLAGS)
|
||||
|
||||
sim-utils.o: $(srcdir)/../common/sim-utils.c $(sim_main_headers) \
|
||||
$(SIM_EXTRA_DEPS)
|
||||
$(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srcdir)/../common/sim-utils.c $(ALL_CFLAGS)
|
||||
|
||||
sim-load.o: $(srcdir)/../common/sim-load.c
|
||||
@ -288,6 +291,23 @@ nrun.o: $(srcdir)/../common/nrun.c config.h tconfig.h \
|
||||
$(srcroot)/include/callback.h $(sim_main_headers)
|
||||
$(CC) -c $(srcdir)/../common/nrun.c $(ALL_CFLAGS)
|
||||
|
||||
# CGEN support.
|
||||
|
||||
cgen-scache.o: $(srcdir)/../common/cgen-scache.c $(sim_main_headers) \
|
||||
$(SIM_EXTRA_DEPS) $(srcdir)/../common/cgen-scache.h
|
||||
$(CC) -c $(srcdir)/../common/cgen-scache.c $(ALL_CFLAGS)
|
||||
|
||||
cgen-trace.o: $(srcdir)/../common/cgen-trace.c $(sim_main_headers) \
|
||||
$(SIM_EXTRA_DEPS) $(srcdir)/../common/cgen-trace.h
|
||||
$(CC) -c $(srcdir)/../common/cgen-trace.c $(ALL_CFLAGS)
|
||||
|
||||
cgen-utils.o: $(srcdir)/../common/cgen-utils.c $(sim_main_headers) \
|
||||
$(SIM_EXTRA_DEPS) $(srcdir)/../common/cgen-mem.h \
|
||||
$(srcdir)/../common/cgen-sem.h
|
||||
$(CC) -c $(srcdir)/../common/cgen-utils.c $(ALL_CFLAGS)
|
||||
|
||||
# Support targets.
|
||||
|
||||
install: install-common $(SIM_EXTRA_INSTALL)
|
||||
|
||||
install-common: installdirs
|
||||
|
@ -174,21 +174,23 @@ scache_flush (SIM_DESC sd)
|
||||
}
|
||||
}
|
||||
|
||||
/* Print cache access statics for CPU. */
|
||||
|
||||
void
|
||||
scache_print_profile (SIM_DESC sd, int verbose)
|
||||
scache_print_profile (SIM_CPU *cpu, int verbose)
|
||||
{
|
||||
/* FIXME: Need to add smp support. */
|
||||
SIM_CPU *cpu = STATE_CPU (sd, 0);
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
unsigned long hits = CPU_SCACHE_HITS (cpu);
|
||||
unsigned long misses = CPU_SCACHE_MISSES (cpu);
|
||||
|
||||
sim_io_printf (sd, "Simulator Cache Statistics\n\n");
|
||||
|
||||
sim_io_printf (sd, "Cache size: %d\n", CPU_SCACHE_SIZE (cpu));
|
||||
sim_io_printf (sd, "Hits: %d\n", hits);
|
||||
sim_io_printf (sd, "Misses: %d\n", misses);
|
||||
/* One could use PROFILE_LABEL_WIDTH here. I chose not to. */
|
||||
sim_io_printf (sd, " Cache size: %d\n", CPU_SCACHE_SIZE (cpu));
|
||||
sim_io_printf (sd, " Hits: %d\n", hits);
|
||||
sim_io_printf (sd, " Misses: %d\n", misses);
|
||||
if (hits + misses != 0)
|
||||
sim_io_printf (sd, "Hit rate: %.2f%%\n",
|
||||
sim_io_printf (sd, " Hit rate: %.2f%%\n",
|
||||
((double) hits / ((double) hits + (double) misses)) * 100);
|
||||
sim_io_printf (sd, "\n");
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#endif
|
||||
|
||||
/* Text is queued in TRACE_BUF because we want to output the insn's cycle
|
||||
count first but that isn't know until after the insn has executed. */
|
||||
count first but that isn't known until after the insn has executed. */
|
||||
static char trace_buf[1024];
|
||||
/* If NULL, output to stdout directly. */
|
||||
static char *bufptr;
|
||||
@ -69,14 +69,13 @@ trace_insn_fini (SIM_CPU *cpu)
|
||||
if (CPU_PROFILE_FLAGS (cpu) [PROFILE_MODEL_IDX])
|
||||
{
|
||||
unsigned long total = PROFILE_TOTAL_CYCLE_COUNT (CPU_PROFILE_DATA (cpu));
|
||||
fprintf (stderr, "%-*ld %-*ld ",
|
||||
SIZE_CYCLE_COUNT, total - last_cycle_count,
|
||||
SIZE_TOTAL_CYCLE_COUNT, total);
|
||||
trace_printf (cpu, "%-*ld %-*ld ",
|
||||
SIZE_CYCLE_COUNT, total - last_cycle_count,
|
||||
SIZE_TOTAL_CYCLE_COUNT, total);
|
||||
last_cycle_count = total;
|
||||
}
|
||||
|
||||
fputs (trace_buf, stderr);
|
||||
fputc ('\n', stderr);
|
||||
trace_printf (cpu, "%s\n", trace_buf);
|
||||
}
|
||||
|
||||
/* For communication between trace_insn and trace_result. */
|
||||
@ -169,7 +168,7 @@ trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
|
||||
|
||||
va_start (args, name);
|
||||
|
||||
cgen_trace_printf (cpu, "0x%.*x: %s ", SIZE_PC, pc, name);
|
||||
trace_printf (cpu, "Extract: 0x%.*x: %s ", SIZE_PC, pc, name);
|
||||
|
||||
do {
|
||||
int type,ival;
|
||||
@ -179,14 +178,14 @@ trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
|
||||
if (fmt)
|
||||
{
|
||||
if (printed_one_p)
|
||||
cgen_trace_printf (cpu, ", ");
|
||||
trace_printf (cpu, ", ");
|
||||
printed_one_p = 1;
|
||||
type = va_arg (args, int);
|
||||
switch (type)
|
||||
{
|
||||
case 'x' :
|
||||
ival = va_arg (args, int);
|
||||
cgen_trace_printf (cpu, fmt, ival);
|
||||
trace_printf (cpu, fmt, ival);
|
||||
break;
|
||||
default :
|
||||
abort ();
|
||||
@ -195,7 +194,7 @@ trace_extract (SIM_CPU *cpu, PCADDR pc, char *name, ...)
|
||||
} while (fmt);
|
||||
|
||||
va_end (args);
|
||||
cgen_trace_printf (cpu, "\n");
|
||||
trace_printf (cpu, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -226,6 +225,9 @@ trace_result (SIM_CPU *cpu, char *name, int type, ...)
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* Print trace output to BUFPTR if active, otherwise print normally.
|
||||
This is only for tracing semantic code. */
|
||||
|
||||
void
|
||||
cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...)
|
||||
{
|
||||
|
@ -156,6 +156,7 @@ cat <<EOF
|
||||
|
||||
SIM_POST_EXEC_HOOK (current_cpu);
|
||||
|
||||
++insn_count;
|
||||
if (step)
|
||||
engine_halt (current_cpu, EXEC_STATE_STOPPED, SIM_SIGTRAP);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ extern struct sim_state *current_state;
|
||||
for a single processor or
|
||||
|
||||
struct sim_state {
|
||||
sim_cpu cpu[MAX_CPUS]; -- could be also be array of pointers
|
||||
sim_cpu cpu[MAX_NR_PROCESSORS]; -- could be also be array of pointers
|
||||
#define STATE_CPU(sd,n) (&(sd)->cpu[n])
|
||||
... simulator specific members ...
|
||||
sim_state_base base;
|
||||
@ -94,6 +94,18 @@ typedef struct {
|
||||
#define STATE_CONFIG(sd) ((sd)->base.config)
|
||||
#endif
|
||||
|
||||
/* List of installed module `init' handlers. */
|
||||
MODULE_INIT_LIST *init_list;
|
||||
#define STATE_INIT_LIST(sd) ((sd)->base.init_list)
|
||||
/* List of installed module `uninstall' handlers. */
|
||||
MODULE_UNINSTALL_LIST *uninstall_list;
|
||||
#define STATE_UNINSTALL_LIST(sd) ((sd)->base.uninstall_list)
|
||||
|
||||
/* ??? This might be more appropriate in sim_cpu. */
|
||||
/* Machine tables for this cpu. See sim-model.h. */
|
||||
const MODEL *model;
|
||||
#define STATE_MODEL(sd) ((sd)->base.model)
|
||||
|
||||
/* Supported options. */
|
||||
struct option_list *options;
|
||||
#define STATE_OPTIONS(sd) ((sd)->base.options)
|
||||
@ -123,11 +135,13 @@ typedef struct {
|
||||
SIM_ADDR start_addr;
|
||||
#define STATE_START_ADDR(sd) ((sd)->base.start_addr)
|
||||
|
||||
#if WITH_SCACHE
|
||||
/* Size of the simulator's cache, if any.
|
||||
This is not the target's cache. It is the cache the simulator uses
|
||||
to process instructions. */
|
||||
unsigned int simcache_size;
|
||||
#define STATE_SIMCACHE_SIZE(sd) ((sd)->base.simcache_size)
|
||||
unsigned int scache_size;
|
||||
#define STATE_SCACHE_SIZE(sd) ((sd)->base.scache_size)
|
||||
#endif
|
||||
|
||||
/* FIXME: Move to top level sim_state struct (as some struct)? */
|
||||
#ifdef SIM_HAVE_FLATMEM
|
||||
@ -149,34 +163,12 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
/* Backlink to main state struct. */
|
||||
SIM_DESC sd;
|
||||
#define CPU_STATE(cpu) ((cpu)->base.sd)
|
||||
SIM_DESC state;
|
||||
#define CPU_STATE(cpu) ((cpu)->base.state)
|
||||
|
||||
/* Maximum number of traceable entities. */
|
||||
#ifndef MAX_TRACE_VALUES
|
||||
#define MAX_TRACE_VALUES 12
|
||||
#endif
|
||||
|
||||
/* Boolean array of specified tracing flags. */
|
||||
/* ??? It's not clear that using an array vs a bit mask is faster.
|
||||
Consider the case where one wants to test whether any of several bits
|
||||
are set. */
|
||||
char trace_flags[MAX_TRACE_VALUES];
|
||||
#define CPU_TRACE_FLAGS(cpu) ((cpu)->base.trace_flags)
|
||||
/* Standard values. */
|
||||
#define TRACE_INSN_IDX 0
|
||||
#define TRACE_DECODE_IDX 1
|
||||
#define TRACE_EXTRACT_IDX 2
|
||||
#define TRACE_LINENUM_IDX 3
|
||||
#define TRACE_MEMORY_IDX 4
|
||||
#define TRACE_MODEL_IDX 5
|
||||
#define TRACE_ALU_IDX 6
|
||||
#define TRACE_NEXT_IDX 8 /* simulator specific trace bits begin here */
|
||||
|
||||
/* Tracing output goes to this or stdout if NULL.
|
||||
We can't store `stdout' here as stdout goes through a callback. */
|
||||
FILE *trace_file;
|
||||
#define CPU_TRACE_FILE(cpu) ((cpu)->base.trace_file)
|
||||
/* Trace data. See sim-trace.h. */
|
||||
TRACE_DATA trace_data;
|
||||
#define CPU_TRACE_DATA(cpu) (& (cpu)->base.trace_data)
|
||||
|
||||
/* Maximum number of debuggable entities.
|
||||
This debugging is not intended for normal use.
|
||||
@ -198,36 +190,9 @@ typedef struct {
|
||||
FILE *debug_file;
|
||||
#define CPU_DEBUG_FILE(cpu) ((cpu)->base.debug_file)
|
||||
|
||||
#ifdef SIM_HAVE_PROFILE
|
||||
/* Maximum number of profilable entities. */
|
||||
#ifndef MAX_PROFILE_VALUES
|
||||
#define MAX_PROFILE_VALUES 8
|
||||
#endif
|
||||
|
||||
/* Boolean array of specified profiling flags. */
|
||||
char profile_flags[MAX_PROFILE_VALUES];
|
||||
#define CPU_PROFILE_FLAGS(cpu) ((cpu)->base.profile_flags)
|
||||
/* Standard masks. */
|
||||
#define PROFILE_INSN_MASK 0
|
||||
#define PROFILE_MEMORY_MASK 1
|
||||
#define PROFILE_MODEL_MASK 2
|
||||
#define PROFILE_SIMCACHE_MASK 3
|
||||
#define PROFILE_NEXT_MASK 6 /* simulator specific profile bits begin here */
|
||||
|
||||
/* PC profiling attempts to determine function usage by sampling the PC
|
||||
every so many instructions. */
|
||||
#ifdef SIM_HAVE_PROFILE_PC
|
||||
unsigned int profile_pc_freq;
|
||||
#define STATE_PROFILE_PC_FREQ(sd) ((sd)->base.profile_pc_freq)
|
||||
unsigned int profile_pc_size;
|
||||
#define STATE_PROFILE_PC_SIZE(sd) ((sd)->base.profile_pc_size)
|
||||
#endif
|
||||
|
||||
/* Profile output goes to this or stdout if NULL.
|
||||
We can't store `stderr' here as stdout goes through a callback. */
|
||||
FILE *profile_file;
|
||||
#define CPU_PROFILE_FILE(cpu) ((cpu)->base.profile_file)
|
||||
#endif /* SIM_HAVE_PROFILE */
|
||||
/* Profile data. See sim-profile.h. */
|
||||
PROFILE_DATA profile_data;
|
||||
#define CPU_PROFILE_DATA(cpu) (& (cpu)->base.profile_data)
|
||||
} sim_cpu_base;
|
||||
|
||||
/* Functions for allocating/freeing a sim_state. */
|
||||
|
@ -22,38 +22,64 @@
|
||||
#ifndef _SIM_CORE_C_
|
||||
#define _SIM_CORE_C_
|
||||
|
||||
#include "engine.h"
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(void)
|
||||
core_init(engine *system)
|
||||
/* "core" module install handler.
|
||||
This is called via sim_module_install to install the "core" subsystem
|
||||
into the simulator. */
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(SIM_RC)
|
||||
sim_core_install (SIM_DESC sd)
|
||||
{
|
||||
core *memory = &system->memory;
|
||||
core_maps map;
|
||||
sim_module_add_uninstall_fn (sd, sim_core_uninstall);
|
||||
sim_module_add_init_fn (sd, sim_core_init);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Uninstall the "core" subsystem from the simulator. */
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(void)
|
||||
sim_core_uninstall (SIM_DESC sd)
|
||||
{
|
||||
/* FIXME: free buffers, etc. */
|
||||
}
|
||||
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(SIM_RC)
|
||||
sim_core_init (SIM_DESC sd)
|
||||
{
|
||||
sim_core *memory = &sd->core;
|
||||
sim_core_maps map;
|
||||
for (map = 0;
|
||||
map < nr_core_maps;
|
||||
map < nr_sim_core_maps;
|
||||
map++) {
|
||||
/* blow away old mappings */
|
||||
core_mapping *curr = memory->map[map].first;
|
||||
sim_core_mapping *curr = memory->map[map].first;
|
||||
while (curr != NULL) {
|
||||
core_mapping *tbd = curr;
|
||||
sim_core_mapping *tbd = curr;
|
||||
curr = curr->next;
|
||||
if (tbd->free_buffer) {
|
||||
ASSERT(tbd->buffer != NULL);
|
||||
SIM_ASSERT(tbd->buffer != NULL);
|
||||
zfree(tbd->buffer);
|
||||
}
|
||||
zfree(tbd);
|
||||
}
|
||||
memory->map[map].first = NULL;
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(core_mapping *)
|
||||
new_core_mapping(engine *system,
|
||||
(sim_core_mapping *)
|
||||
new_sim_core_mapping(SIM_DESC sd,
|
||||
attach_type attach,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
@ -62,7 +88,7 @@ new_core_mapping(engine *system,
|
||||
void *buffer,
|
||||
int free_buffer)
|
||||
{
|
||||
core_mapping *new_mapping = ZALLOC(core_mapping);
|
||||
sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping);
|
||||
/* common */
|
||||
new_mapping->level = attach;
|
||||
new_mapping->space = space;
|
||||
@ -77,7 +103,7 @@ new_core_mapping(engine *system,
|
||||
new_mapping->device = device;
|
||||
}
|
||||
else {
|
||||
engine_error(system, "new_core_mapping - internal error - unknown attach type %d\n",
|
||||
sim_io_error (sd, "new_sim_core_mapping - internal error - unknown attach type %d\n",
|
||||
attach);
|
||||
}
|
||||
return new_mapping;
|
||||
@ -86,8 +112,8 @@ new_core_mapping(engine *system,
|
||||
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(void)
|
||||
core_map_attach(engine *system,
|
||||
core_map *access_map,
|
||||
sim_core_map_attach(SIM_DESC sd,
|
||||
sim_core_map *access_map,
|
||||
attach_type attach,
|
||||
int space,
|
||||
unsigned_word addr,
|
||||
@ -98,18 +124,18 @@ core_map_attach(engine *system,
|
||||
{
|
||||
/* find the insertion point for this additional mapping and then
|
||||
insert */
|
||||
core_mapping *next_mapping;
|
||||
core_mapping **last_mapping;
|
||||
sim_core_mapping *next_mapping;
|
||||
sim_core_mapping **last_mapping;
|
||||
|
||||
ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer)
|
||||
SIM_ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer)
|
||||
|| (attach == attach_raw_memory && client == NULL && buffer != NULL));
|
||||
|
||||
/* actually do occasionally get a zero size map */
|
||||
if (nr_bytes == 0) {
|
||||
#if (WITH_DEVICES)
|
||||
device_error(client, "called on core_map_attach with size zero");
|
||||
device_error(client, "called on sim_core_map_attach with size zero");
|
||||
#else
|
||||
engine_error(system, "called on core_map_attach with size zero");
|
||||
sim_io_error (sd, "called on sim_core_map_attach with size zero");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -128,20 +154,20 @@ core_map_attach(engine *system,
|
||||
}
|
||||
|
||||
/* check insertion point correct */
|
||||
ASSERT(next_mapping == NULL || next_mapping->level >= attach);
|
||||
SIM_ASSERT(next_mapping == NULL || next_mapping->level >= attach);
|
||||
if (next_mapping != NULL && next_mapping->level == attach
|
||||
&& next_mapping->base < (addr + (nr_bytes - 1))) {
|
||||
#if (WITH_DEVICES)
|
||||
device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
|
||||
space, (long)addr, (long)nr_bytes);
|
||||
#else
|
||||
engine_error(system, "map overlap when attaching %d:0x%lx (%ld)",
|
||||
sim_io_error (sd, "map overlap when attaching %d:0x%lx (%ld)",
|
||||
space, (long)addr, (long)nr_bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* create/insert the new mapping */
|
||||
*last_mapping = new_core_mapping(system,
|
||||
*last_mapping = new_sim_core_mapping(sd,
|
||||
attach,
|
||||
space, addr, nr_bytes,
|
||||
client, buffer, free_buffer);
|
||||
@ -151,7 +177,7 @@ core_map_attach(engine *system,
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(void)
|
||||
core_attach(engine *system,
|
||||
sim_core_attach(SIM_DESC sd,
|
||||
attach_type attach,
|
||||
access_type access,
|
||||
int space,
|
||||
@ -160,8 +186,8 @@ core_attach(engine *system,
|
||||
device *client,
|
||||
void *optional_buffer)
|
||||
{
|
||||
core *memory = &system->memory;
|
||||
core_maps map;
|
||||
sim_core *memory = &sd->core;
|
||||
sim_core_maps map;
|
||||
void *buffer;
|
||||
int buffer_freed;
|
||||
if ((access & access_read_write_exec) == 0
|
||||
@ -169,7 +195,7 @@ core_attach(engine *system,
|
||||
#if (WITH_DEVICES)
|
||||
device_error(client, "invalid access for core attach");
|
||||
#else
|
||||
engine_error(system, "invalid access for core attach");
|
||||
sim_io_error (sd, "invalid access for core attach");
|
||||
#endif
|
||||
}
|
||||
/* verify the attach type */
|
||||
@ -189,44 +215,44 @@ core_attach(engine *system,
|
||||
}
|
||||
else {
|
||||
#if (WITH_DEVICES)
|
||||
device_error(client, "core_attach - conflicting buffer and attach arguments");
|
||||
device_error(client, "sim_core_attach - conflicting buffer and attach arguments");
|
||||
#else
|
||||
engine_error(system, "core_attach - conflicting buffer and attach arguments");
|
||||
sim_io_error (sd, "sim_core_attach - conflicting buffer and attach arguments");
|
||||
#endif
|
||||
buffer = NULL;
|
||||
buffer_freed = 1;
|
||||
}
|
||||
/* attach the region to all applicable access maps */
|
||||
for (map = 0;
|
||||
map < nr_core_maps;
|
||||
map < nr_sim_core_maps;
|
||||
map++) {
|
||||
switch (map) {
|
||||
case core_read_map:
|
||||
case sim_core_read_map:
|
||||
if (access & access_read)
|
||||
core_map_attach(system, &memory->map[map],
|
||||
sim_core_map_attach(sd, &memory->map[map],
|
||||
attach,
|
||||
space, addr, nr_bytes,
|
||||
client, buffer, !buffer_freed);
|
||||
buffer_freed ++;
|
||||
break;
|
||||
case core_write_map:
|
||||
case sim_core_write_map:
|
||||
if (access & access_write)
|
||||
core_map_attach(system, &memory->map[map],
|
||||
sim_core_map_attach(sd, &memory->map[map],
|
||||
attach,
|
||||
space, addr, nr_bytes,
|
||||
client, buffer, !buffer_freed);
|
||||
buffer_freed ++;
|
||||
break;
|
||||
case core_execute_map:
|
||||
case sim_core_execute_map:
|
||||
if (access & access_exec)
|
||||
core_map_attach(system, &memory->map[map],
|
||||
sim_core_map_attach(sd, &memory->map[map],
|
||||
attach,
|
||||
space, addr, nr_bytes,
|
||||
client, buffer, !buffer_freed);
|
||||
buffer_freed ++;
|
||||
break;
|
||||
case nr_core_maps:
|
||||
engine_error(system, "core_attach - internal error - bad switch");
|
||||
case nr_sim_core_maps:
|
||||
sim_io_error (sd, "sim_core_attach - internal error - bad switch");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -234,16 +260,16 @@ core_attach(engine *system,
|
||||
|
||||
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(core_mapping *)
|
||||
core_map_find_mapping(engine *system,
|
||||
core_maps map,
|
||||
(sim_core_mapping *)
|
||||
sim_core_find_mapping(SIM_DESC sd,
|
||||
sim_core_maps map,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
int abort) /*either 0 or 1 - helps inline */
|
||||
{
|
||||
core_mapping *mapping = system->memory.map[map].first;
|
||||
ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
|
||||
ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
|
||||
sim_core_mapping *mapping = sd->core.map[map].first;
|
||||
SIM_ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */
|
||||
SIM_ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
|
||||
while (mapping != NULL) {
|
||||
if (addr >= mapping->base
|
||||
&& (addr + (nr_bytes - 1)) <= mapping->bound)
|
||||
@ -251,7 +277,7 @@ core_map_find_mapping(engine *system,
|
||||
mapping = mapping->next;
|
||||
}
|
||||
if (abort)
|
||||
engine_error(system, "access to unmaped address 0x%x (%d bytes)\n",
|
||||
sim_io_error (sd, "access to unmaped address 0x%x (%d bytes)\n",
|
||||
addr, nr_bytes);
|
||||
return NULL;
|
||||
}
|
||||
@ -259,7 +285,7 @@ core_map_find_mapping(engine *system,
|
||||
|
||||
STATIC_INLINE_SIM_CORE\
|
||||
(void *)
|
||||
core_translate(core_mapping *mapping,
|
||||
sim_core_translate(sim_core_mapping *mapping,
|
||||
unsigned_word addr)
|
||||
{
|
||||
return (void *)(((char *)mapping->buffer) + addr - mapping->base);
|
||||
@ -268,8 +294,8 @@ core_translate(core_mapping *mapping,
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(unsigned)
|
||||
core_map_read_buffer(engine *system,
|
||||
core_maps map,
|
||||
sim_core_read_buffer(SIM_DESC sd,
|
||||
sim_core_maps map,
|
||||
void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len)
|
||||
@ -277,8 +303,8 @@ core_map_read_buffer(engine *system,
|
||||
unsigned count = 0;
|
||||
while (count < len) {
|
||||
unsigned_word raddr = addr + count;
|
||||
core_mapping *mapping =
|
||||
core_map_find_mapping(system, map,
|
||||
sim_core_mapping *mapping =
|
||||
sim_core_find_mapping(sd, map,
|
||||
raddr, 1,
|
||||
0); /*dont-abort*/
|
||||
if (mapping == NULL)
|
||||
@ -300,7 +326,7 @@ core_map_read_buffer(engine *system,
|
||||
#endif
|
||||
{
|
||||
((unsigned_1*)buffer)[count] =
|
||||
*(unsigned_1*)core_translate(mapping, raddr);
|
||||
*(unsigned_1*)sim_core_translate(mapping, raddr);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
@ -310,8 +336,8 @@ core_map_read_buffer(engine *system,
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(unsigned)
|
||||
core_map_write_buffer(engine *system,
|
||||
core_maps map,
|
||||
sim_core_write_buffer(SIM_DESC sd,
|
||||
sim_core_maps map,
|
||||
const void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len)
|
||||
@ -319,9 +345,9 @@ core_map_write_buffer(engine *system,
|
||||
unsigned count = 0;
|
||||
while (count < len) {
|
||||
unsigned_word raddr = addr + count;
|
||||
core_mapping *mapping = core_map_find_mapping(system, map,
|
||||
raddr, 1,
|
||||
0); /*dont-abort*/
|
||||
sim_core_mapping *mapping = sim_core_find_mapping(sd, map,
|
||||
raddr, 1,
|
||||
0); /*dont-abort*/
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
#if (WITH_DEVICES)
|
||||
@ -341,7 +367,7 @@ core_map_write_buffer(engine *system,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*(unsigned_1*)core_translate(mapping, raddr) =
|
||||
*(unsigned_1*)sim_core_translate(mapping, raddr) =
|
||||
((unsigned_1*)buffer)[count];
|
||||
count += 1;
|
||||
}
|
||||
|
169
sim/common/sim-core.h
Normal file
169
sim/common/sim-core.h
Normal file
@ -0,0 +1,169 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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 of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SIM_CORE_H_
|
||||
#define _SIM_CORE_H_
|
||||
|
||||
|
||||
/* basic types */
|
||||
|
||||
typedef struct _sim_core_mapping sim_core_mapping;
|
||||
struct _sim_core_mapping {
|
||||
/* common */
|
||||
int level;
|
||||
int space;
|
||||
unsigned_word base;
|
||||
unsigned_word bound;
|
||||
unsigned nr_bytes;
|
||||
/* memory map */
|
||||
int free_buffer;
|
||||
void *buffer;
|
||||
/* callback map */
|
||||
device *device;
|
||||
/* growth */
|
||||
sim_core_mapping *next;
|
||||
};
|
||||
|
||||
typedef struct _sim_core_map sim_core_map;
|
||||
struct _sim_core_map {
|
||||
sim_core_mapping *first;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
sim_core_read_map,
|
||||
sim_core_write_map,
|
||||
sim_core_execute_map,
|
||||
nr_sim_core_maps,
|
||||
} sim_core_maps;
|
||||
|
||||
typedef struct _sim_core sim_core;
|
||||
struct _sim_core {
|
||||
int trace;
|
||||
sim_core_map map[nr_sim_core_maps];
|
||||
};
|
||||
|
||||
|
||||
/* Install the "core" module. */
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(SIM_RC) sim_core_install (SIM_DESC sd);
|
||||
|
||||
|
||||
/* Uninstall the "core" subsystem. */
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(void)
|
||||
sim_core_uninstall (SIM_DESC sd);
|
||||
|
||||
|
||||
/* initialize */
|
||||
|
||||
EXTERN_SIM_CORE\
|
||||
(SIM_RC) sim_core_init
|
||||
(SIM_DESC sd);
|
||||
|
||||
|
||||
/* tracing */
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(void) sim_core_set_trace\
|
||||
(SIM_DESC sd,
|
||||
int level);
|
||||
|
||||
|
||||
|
||||
/* Create a memory space within the core. */
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(void) sim_core_attach
|
||||
(SIM_DESC sd,
|
||||
attach_type attach,
|
||||
access_type access,
|
||||
int address_space,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes, /* host limited */
|
||||
device *client,
|
||||
void *optional_buffer);
|
||||
|
||||
|
||||
|
||||
/* Variable sized read/write
|
||||
|
||||
Transfer (zero) a variable size block of data between the host and
|
||||
target (possibly byte swapping it). Should any problems occure,
|
||||
the number of bytes actually transfered is returned. */
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(unsigned) sim_core_read_buffer
|
||||
(SIM_DESC sd,
|
||||
sim_core_maps map,
|
||||
void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes);
|
||||
|
||||
INLINE_SIM_CORE\
|
||||
(unsigned) sim_core_write_buffer
|
||||
(SIM_DESC sd,
|
||||
sim_core_maps map,
|
||||
const void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes);
|
||||
|
||||
|
||||
/* Fixed sized read/write
|
||||
|
||||
Transfer a fixed amout of memory between the host and target. The
|
||||
memory always being translated and the operation always aborting
|
||||
should a problem occure */
|
||||
|
||||
#define DECLARE_SIM_CORE_WRITE_N(N) \
|
||||
INLINE_SIM_CORE\
|
||||
(void) sim_core_write_##N \
|
||||
(SIM_DESC sd, \
|
||||
sim_core_maps map, \
|
||||
unsigned_word addr, \
|
||||
unsigned_##N val);
|
||||
|
||||
DECLARE_SIM_CORE_WRITE_N(1)
|
||||
DECLARE_SIM_CORE_WRITE_N(2)
|
||||
DECLARE_SIM_CORE_WRITE_N(4)
|
||||
DECLARE_SIM_CORE_WRITE_N(8)
|
||||
DECLARE_SIM_CORE_WRITE_N(word)
|
||||
|
||||
#undef DECLARE_SIM_CORE_WRITE_N
|
||||
|
||||
|
||||
#define DECLARE_SIM_CORE_READ_N(N) \
|
||||
INLINE_SIM_CORE\
|
||||
(unsigned_##N) sim_core_read_##N \
|
||||
(SIM_DESC sd, \
|
||||
sim_core_maps map, \
|
||||
unsigned_word addr);
|
||||
|
||||
DECLARE_SIM_CORE_READ_N(1)
|
||||
DECLARE_SIM_CORE_READ_N(2)
|
||||
DECLARE_SIM_CORE_READ_N(4)
|
||||
DECLARE_SIM_CORE_READ_N(8)
|
||||
DECLARE_SIM_CORE_READ_N(word)
|
||||
|
||||
#undef DECLARE_SIM_CORE_READ_N
|
||||
|
||||
#endif
|
146
sim/common/sim-module.c
Normal file
146
sim/common/sim-module.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* Module support.
|
||||
Copyright (C) 1996, 1997 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 modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the 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 of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with 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"
|
||||
|
||||
/* List of all modules. */
|
||||
static MODULE_INSTALL_FN * const modules[] = {
|
||||
standard_install,
|
||||
trace_install,
|
||||
profile_install,
|
||||
sim_core_install,
|
||||
#if WITH_SCACHE
|
||||
scache_install,
|
||||
#endif
|
||||
#ifdef SIM_HAVE_MODEL /* FIXME: temporary */
|
||||
model_install,
|
||||
#endif
|
||||
/* Configured in [simulator specific] additional modules. */
|
||||
#ifdef MODULE_LIST
|
||||
MODULE_LIST
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
/* Functions called from sim_open. */
|
||||
|
||||
/* Initialize common parts before argument processing. */
|
||||
|
||||
SIM_RC
|
||||
sim_pre_argv_init (SIM_DESC sd, const char *myname)
|
||||
{
|
||||
STATE_MY_NAME (sd) = myname + strlen (myname);
|
||||
while (STATE_MY_NAME (sd) > myname && STATE_MY_NAME (sd)[-1] != '/')
|
||||
--STATE_MY_NAME (sd);
|
||||
|
||||
/* Install all configured in modules. */
|
||||
if (sim_module_install (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Initialize common parts after argument processing. */
|
||||
|
||||
SIM_RC
|
||||
sim_post_argv_init (SIM_DESC sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sim_module_init (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
/* Set the cpu->state backlinks for each cpu. */
|
||||
for (i = 0; i < MAX_NR_PROCESSORS; ++i)
|
||||
CPU_STATE (STATE_CPU (sd, i)) = sd;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Install all modules. */
|
||||
|
||||
SIM_RC
|
||||
sim_module_install (SIM_DESC sd)
|
||||
{
|
||||
MODULE_INSTALL_FN * const *modp;
|
||||
|
||||
for (modp = modules; *modp != NULL; ++modp)
|
||||
{
|
||||
if ((*modp) (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Called after all modules have been installed and after argv
|
||||
has been processed. */
|
||||
|
||||
SIM_RC
|
||||
sim_module_init (SIM_DESC sd)
|
||||
{
|
||||
MODULE_INIT_LIST *modp;
|
||||
|
||||
for (modp = STATE_INIT_LIST (sd); modp != NULL; modp = modp->next)
|
||||
{
|
||||
if ((*modp->fn) (sd) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Uninstall installed modules, called by sim_close. */
|
||||
|
||||
void
|
||||
sim_module_uninstall (SIM_DESC sd)
|
||||
{
|
||||
MODULE_UNINSTALL_LIST *modp;
|
||||
|
||||
/* Uninstall the modules. */
|
||||
for (modp = STATE_UNINSTALL_LIST (sd); modp != NULL; modp = modp->next)
|
||||
(*modp->fn) (sd);
|
||||
}
|
||||
|
||||
/* Add FN to the init handler list. */
|
||||
|
||||
void
|
||||
sim_module_add_init_fn (SIM_DESC sd, MODULE_INIT_FN fn)
|
||||
{
|
||||
MODULE_INIT_LIST *l =
|
||||
(MODULE_INIT_LIST *) xmalloc (sizeof (MODULE_INIT_LIST));
|
||||
|
||||
l->fn = fn;
|
||||
l->next = STATE_INIT_LIST (sd);
|
||||
STATE_INIT_LIST (sd) = l;
|
||||
}
|
||||
|
||||
/* Add FN to the uninstall handler list. */
|
||||
|
||||
void
|
||||
sim_module_add_uninstall_fn (SIM_DESC sd, MODULE_UNINSTALL_FN fn)
|
||||
{
|
||||
MODULE_UNINSTALL_LIST *l =
|
||||
(MODULE_UNINSTALL_LIST *) xmalloc (sizeof (MODULE_UNINSTALL_LIST));
|
||||
|
||||
l->fn = fn;
|
||||
l->next = STATE_UNINSTALL_LIST (sd);
|
||||
STATE_UNINSTALL_LIST (sd) = l;
|
||||
}
|
@ -31,11 +31,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "sim-options.h"
|
||||
#include "sim-io.h"
|
||||
|
||||
/* This is defined in sim-config.h. */
|
||||
#ifndef MAX_NR_PROCESSORS
|
||||
#define MAX_NR_PROCESSORS 1
|
||||
#endif
|
||||
|
||||
/* Add a set of options to the simulator.
|
||||
TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry.
|
||||
This is intended to be called by modules in their `install' handler. */
|
||||
@ -83,19 +78,6 @@ static DECLARE_OPTION_HANDLER (standard_option_handler);
|
||||
|
||||
#define OPTION_DEBUG_INSN (OPTION_START + 0)
|
||||
#define OPTION_DEBUG_FILE (OPTION_START + 1)
|
||||
#define OPTION_TRACE_INSN (OPTION_START + 2)
|
||||
#define OPTION_TRACE_DECODE (OPTION_START + 3)
|
||||
#define OPTION_TRACE_EXTRACT (OPTION_START + 4)
|
||||
#define OPTION_TRACE_LINENUM (OPTION_START + 5)
|
||||
#define OPTION_TRACE_MEMORY (OPTION_START + 6)
|
||||
#define OPTION_TRACE_MODEL (OPTION_START + 7)
|
||||
#define OPTION_TRACE_ALU (OPTION_START + 8)
|
||||
#define OPTION_TRACE_FILE (OPTION_START + 9)
|
||||
#define OPTION_PROFILE_INSN (OPTION_START + 10)
|
||||
#define OPTION_PROFILE_MEMORY (OPTION_START + 11)
|
||||
#define OPTION_PROFILE_MODEL (OPTION_START + 12)
|
||||
#define OPTION_PROFILE_SIMCACHE (OPTION_START + 13)
|
||||
#define OPTION_PROFILE_FILE (OPTION_START + 14)
|
||||
|
||||
static const OPTION standard_options[] =
|
||||
{
|
||||
@ -119,87 +101,18 @@ static const OPTION standard_options[] =
|
||||
'\0', "FILE NAME", "Specify debugging output file",
|
||||
standard_option_handler },
|
||||
|
||||
{ {"trace", no_argument, NULL, 't'},
|
||||
't', NULL, "Perform tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN},
|
||||
'\0', NULL, "Perform instruction tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE},
|
||||
'\0', NULL, "Perform instruction decoding tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT},
|
||||
'\0', NULL, "Perform instruction extraction tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM},
|
||||
'\0', NULL, "Perform line number tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY},
|
||||
'\0', NULL, "Perform memory tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL},
|
||||
'\0', NULL, "Perform model tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU},
|
||||
'\0', NULL, "Perform ALU tracing",
|
||||
standard_option_handler },
|
||||
{ {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
|
||||
'\0', "FILE NAME", "Specify tracing output file",
|
||||
standard_option_handler },
|
||||
|
||||
#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */
|
||||
{ {"h8300h", no_argument, NULL, 'h'},
|
||||
'h', NULL, "Indicate the CPU is h8/300h or h8/300s",
|
||||
standard_option_handler },
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_SIMCACHE
|
||||
{ {"simcache-size", required_argument, NULL, 'c'},
|
||||
'c', "SIM CACHE SIZE", "Specify size of simulator execution cache",
|
||||
standard_option_handler },
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_FLATMEM
|
||||
{ {"mem-size", required_argument, NULL, 'm'},
|
||||
'm', "MEMORY SIZE", "Specify memory size",
|
||||
standard_option_handler },
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_MAX_INSNS
|
||||
{ {"max-insns", required_argument, NULL, 'M'},
|
||||
'M', "MAX INSNS", "Specify maximum number of instructions to execute",
|
||||
standard_option_handler },
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_PROFILE
|
||||
{ {"profile", no_argument, NULL, 'p'},
|
||||
'p', NULL, "Perform profiling",
|
||||
standard_option_handler },
|
||||
{ {"profile-insn", no_argument, NULL, OPTION_PROFILE_INSN},
|
||||
'\0', NULL, "Perform instruction profiling",
|
||||
standard_option_handler },
|
||||
{ {"profile-memory", no_argument, NULL, OPTION_PROFILE_MEMORY},
|
||||
'\0', NULL, "Perform memory profiling",
|
||||
standard_option_handler },
|
||||
{ {"profile-model", no_argument, NULL, OPTION_PROFILE_MODEL},
|
||||
'\0', NULL, "Perform model profiling",
|
||||
standard_option_handler },
|
||||
{ {"profile-simcache", no_argument, NULL, OPTION_PROFILE_SIMCACHE},
|
||||
'\0', NULL, "Perform simulator execution cache profiling",
|
||||
standard_option_handler },
|
||||
{ {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE},
|
||||
'\0', "FILE NAME", "Specify profile output file",
|
||||
standard_option_handler },
|
||||
#ifdef SIM_HAVE_PROFILE_PC
|
||||
{ {"profile-pc-frequency", required_argument, NULL, 'F'},
|
||||
'F', "PC PROFILE FREQUENCY", "Turn on PC profiling at specified frequency",
|
||||
standard_option_handler },
|
||||
{ {"profile-pc-size", required_argument, NULL, 'S'},
|
||||
'S', "PC PROFILE SIZE", "Specify PC profiling size",
|
||||
standard_option_handler },
|
||||
#endif
|
||||
#endif /* SIM_HAVE_PROFILE */
|
||||
|
||||
{ {"help", no_argument, NULL, 'H'},
|
||||
'H', NULL, "Print help information",
|
||||
standard_option_handler },
|
||||
@ -288,122 +201,12 @@ standard_option_handler (sd, opt, arg)
|
||||
}
|
||||
break;
|
||||
|
||||
case 't' :
|
||||
if (! WITH_TRACE)
|
||||
sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
for (i = 0; i < MAX_TRACE_VALUES; ++i)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_INSN :
|
||||
if (! (WITH_TRACE & (1 << TRACE_INSN_IDX)))
|
||||
sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_DECODE :
|
||||
if (! (WITH_TRACE & (1 << TRACE_DECODE_IDX)))
|
||||
sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_EXTRACT :
|
||||
if (! (WITH_TRACE & (1 << TRACE_EXTRACT_IDX)))
|
||||
sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_LINENUM :
|
||||
if (! (WITH_TRACE & (1 << TRACE_LINENUM_IDX)))
|
||||
sim_io_eprintf (sd, "Line number tracing not compiled in, `--trace-linenum' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_MEMORY :
|
||||
if (! (WITH_TRACE & (1 << TRACE_MEMORY_IDX)))
|
||||
sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_MODEL :
|
||||
if (! (WITH_TRACE & (1 << TRACE_MODEL_IDX)))
|
||||
sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_ALU :
|
||||
if (! (WITH_TRACE & (1 << TRACE_ALU_IDX)))
|
||||
sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_TRACE_FILE :
|
||||
if (! WITH_TRACE)
|
||||
sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
|
||||
else
|
||||
{
|
||||
FILE *f = fopen (arg, "w");
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_TRACE_FILE (STATE_CPU (sd, n)) = f;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */
|
||||
case 'h' :
|
||||
set_h8300h (1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_SIMCACHE
|
||||
case 'c':
|
||||
n = strtol (arg, NULL, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
sim_io_eprintf (sd, "Invalid simulator cache size: %d", n);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
STATE_SIMCACHE_SIZE (sd) = n;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_FLATMEM
|
||||
case 'm':
|
||||
ul = strtol (arg, NULL, 0);
|
||||
@ -417,101 +220,6 @@ standard_option_handler (sd, opt, arg)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_MAX_INSNS
|
||||
case 'M' :
|
||||
ul = strtoul (arg, NULL, 0);
|
||||
if (! isdigit (arg[0]))
|
||||
{
|
||||
sim_io_eprintf (sd, "Invalid maximum instruction count: `%s'", arg);
|
||||
return SIM_RC_FAIL;
|
||||
}
|
||||
STATE_MAX_INSNS (sd) = ul;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIM_HAVE_PROFILE
|
||||
case 'p' :
|
||||
if (! WITH_PROFILE)
|
||||
sim_io_eprintf (sd, "Profile not compiled in, -p option ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
for (i = 0; i < MAX_PROFILE_VALUES; ++i)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[i] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_INSN :
|
||||
if (! (WITH_PROFILE & (1 << PROFILE_INSN_IDX)))
|
||||
sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_INSN_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_MEMORY :
|
||||
if (! (WITH_PROFILE & (1 << PROFILE_MEMORY_IDX)))
|
||||
sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MEMORY_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_MODEL :
|
||||
if (! (WITH_PROFILE & (1 << PROFILE_MODEL_IDX)))
|
||||
sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MODEL_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_SIMCACHE :
|
||||
if (! (WITH_PROFILE & (1 << PROFILE_SIMCACHE_IDX)))
|
||||
sim_io_eprintf (sd, "Simulator cache profiling not compiled in, `--profile-simcache' ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_SIMCACHE_IDX] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
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 (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FILE (STATE_CPU (sd, n)) = f;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef SIM_HAVE_PROFILE_PC
|
||||
case 'F' :
|
||||
STATE_PROFILE_PC_FREQUENCY (sd) = atoi (arg);
|
||||
/* FIXME: Validate arg. */
|
||||
break;
|
||||
case 'S' :
|
||||
STATE_PROFILE_PC_SIZE (sd) = atoi (arg);
|
||||
/* FIXME: Validate arg. */
|
||||
break;
|
||||
#endif
|
||||
#endif /* SIM_HAVE_PROFILE */
|
||||
|
||||
case 'H':
|
||||
sim_print_help (sd);
|
||||
if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
|
||||
@ -523,21 +231,13 @@ standard_option_handler (sd, opt, arg)
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Initialize common parts before argument processing.
|
||||
Called by sim_open. */
|
||||
/* Add the standard option list to the simulator. */
|
||||
|
||||
SIM_RC
|
||||
sim_pre_argv_init (sd, myname)
|
||||
SIM_DESC sd;
|
||||
const char *myname;
|
||||
standard_install (SIM_DESC sd)
|
||||
{
|
||||
STATE_MY_NAME (sd) = myname + strlen (myname);
|
||||
while (STATE_MY_NAME (sd) > myname && STATE_MY_NAME (sd)[-1] != '/')
|
||||
--STATE_MY_NAME (sd);
|
||||
|
||||
if (sim_add_option_table (sd, standard_options) != SIM_RC_OK)
|
||||
return SIM_RC_FAIL;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
|
464
sim/common/sim-profile.c
Normal file
464
sim/common/sim-profile.c
Normal file
@ -0,0 +1,464 @@
|
||||
/* Default profiling support.
|
||||
Copyright (C) 1996, 1997 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 modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the 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 of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with 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"
|
||||
|
||||
static MODULE_UNINSTALL_FN profile_uninstall;
|
||||
|
||||
static void print_bar (SIM_DESC, unsigned int, unsigned int, unsigned int);
|
||||
|
||||
static DECLARE_OPTION_HANDLER (profile_option_handler);
|
||||
|
||||
#define OPTION_PROFILE_INSN (OPTION_START + 0)
|
||||
#define OPTION_PROFILE_MEMORY (OPTION_START + 1)
|
||||
#define OPTION_PROFILE_MODEL (OPTION_START + 2)
|
||||
#define OPTION_PROFILE_FILE (OPTION_START + 3)
|
||||
#define OPTION_PROFILE_RANGE (OPTION_START + 4)
|
||||
|
||||
static const OPTION profile_options[] = {
|
||||
{ {"profile", no_argument, NULL, 'p'},
|
||||
'p', NULL, "Perform profiling",
|
||||
profile_option_handler },
|
||||
{ {"profile-insn", no_argument, NULL, OPTION_PROFILE_INSN},
|
||||
'\0', NULL, "Perform instruction profiling",
|
||||
profile_option_handler },
|
||||
{ {"profile-memory", no_argument, NULL, OPTION_PROFILE_MEMORY},
|
||||
'\0', NULL, "Perform memory profiling",
|
||||
profile_option_handler },
|
||||
{ {"profile-model", no_argument, NULL, OPTION_PROFILE_MODEL},
|
||||
'\0', NULL, "Perform model profiling",
|
||||
profile_option_handler },
|
||||
{ {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE},
|
||||
'\0', "FILE NAME", "Specify profile output file",
|
||||
profile_option_handler },
|
||||
{ {"profile-pc-frequency", required_argument, NULL, 'F'},
|
||||
'F', "PC PROFILE FREQUENCY", "Turn on PC profiling at specified frequency",
|
||||
profile_option_handler },
|
||||
{ {"profile-pc-size", required_argument, NULL, 'S'},
|
||||
'S', "PC PROFILE SIZE", "Specify PC profiling size",
|
||||
profile_option_handler },
|
||||
#if 0 /*FIXME:wip*/
|
||||
{ {"profile-range", required_argument, NULL, OPTION_PROFILE_RANGE},
|
||||
0, NULL, "Specify range of addresses to profile",
|
||||
profile_option_handler },
|
||||
#endif
|
||||
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static SIM_RC
|
||||
profile_option_handler (SIM_DESC sd, int opt, char *arg)
|
||||
{
|
||||
int i,n;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'p' :
|
||||
if (! WITH_PROFILE)
|
||||
sim_io_eprintf (sd, "Profiling not compiled in, -p option ignored\n");
|
||||
else
|
||||
{
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
for (i = 0; i < MAX_PROFILE_VALUES; ++i)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[i] = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_INSN :
|
||||
#if WITH_PROFILE_INSN_P
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_INSN_IDX] = 1;
|
||||
#else
|
||||
sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_MEMORY :
|
||||
#if WITH_PROFILE_MEMORY_P
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MEMORY_IDX] = 1;
|
||||
#else
|
||||
sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPTION_PROFILE_MODEL :
|
||||
#if WITH_PROFILE_MODEL_P
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_MODEL_IDX] = 1;
|
||||
#else
|
||||
sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
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 (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, n))) = f;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F' :
|
||||
#if WITH_PROFILE_PC_P
|
||||
/* FIXME: Validate arg. */
|
||||
i = atoi (arg);
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
PROFILE_PC_FREQ (CPU_PROFILE_DATA (STATE_CPU (sd, n))) = i;
|
||||
#else
|
||||
sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-frequency' ignored\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'S' :
|
||||
#if WITH_PROFILE_PC_P
|
||||
/* FIXME: Validate arg. */
|
||||
i = atoi (arg);
|
||||
for (n = 0; n < MAX_NR_PROCESSORS; ++n)
|
||||
PROFILE_PC_SIZE (CPU_PROFILE_DATA (STATE_CPU (sd, n))) = i;
|
||||
#else
|
||||
sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-size' ignored\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if 0 /* FIXME:wip */
|
||||
case OPTION_PROFILE_RANGE :
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
profile_install (SIM_DESC sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
sim_add_option_table (sd, 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))));
|
||||
sim_module_add_uninstall_fn (sd, profile_uninstall);
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
profile_uninstall (SIM_DESC sd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_NR_PROCESSORS; ++i)
|
||||
{
|
||||
PROFILE_DATA *data = CPU_PROFILE_DATA (STATE_CPU (sd, i));
|
||||
if (PROFILE_FILE (data) != NULL)
|
||||
fclose (PROFILE_FILE (data));
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_PROFILE_INSN_P
|
||||
|
||||
static void
|
||||
profile_print_insn (sim_cpu *cpu, int verbose)
|
||||
{
|
||||
unsigned int i, n, total, max_val, max_name_len;
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
|
||||
|
||||
sim_io_printf (sd, "Instruction Statistics\n\n");
|
||||
|
||||
/* First pass over data computes various things. */
|
||||
max_val = total = max_name_len = 0;
|
||||
for (i = 1; i < MAX_INSNS; ++i)
|
||||
{
|
||||
total += PROFILE_INSN_COUNT (data) [i];
|
||||
if (PROFILE_INSN_COUNT (data) [i] > max_val)
|
||||
max_val = PROFILE_INSN_COUNT (data) [i];
|
||||
n = strlen (INSN_NAME (i));
|
||||
if (n > max_name_len)
|
||||
max_name_len = n;
|
||||
}
|
||||
|
||||
sim_io_printf (sd, " Total: %d insns\n", total);
|
||||
|
||||
if (verbose && max_val != 0)
|
||||
{
|
||||
/* Now we can print the histogram. */
|
||||
sim_io_printf (sd, "\n");
|
||||
for (i = 1; i < MAX_INSNS; ++i)
|
||||
{
|
||||
if (PROFILE_INSN_COUNT (data) [i] != 0)
|
||||
{
|
||||
sim_io_printf (sd, " %*s: %*d: ",
|
||||
max_name_len, INSN_NAME (i),
|
||||
max_val < 10000 ? 4 : 8,
|
||||
PROFILE_INSN_COUNT (data) [i]);
|
||||
print_bar (sd, PROFILE_HISTOGRAM_WIDTH,
|
||||
PROFILE_INSN_COUNT (data) [i],
|
||||
max_val);
|
||||
sim_io_printf (sd, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sim_io_printf (sd, "\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if WITH_PROFILE_MEMORY_P
|
||||
|
||||
static void
|
||||
profile_print_memory (sim_cpu *cpu, int verbose)
|
||||
{
|
||||
unsigned int i, n;
|
||||
unsigned int total_read, total_write;
|
||||
unsigned int max_val, max_name_len;
|
||||
/* FIXME: Need to add smp support. */
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
|
||||
|
||||
sim_io_printf (sd, "Memory Access Statistics\n\n");
|
||||
|
||||
/* First pass over data computes various things. */
|
||||
max_val = total_read = total_write = max_name_len = 0;
|
||||
for (i = 0; i < MAX_MODES; ++i)
|
||||
{
|
||||
total_read += PROFILE_READ_COUNT (data) [i];
|
||||
total_write += PROFILE_WRITE_COUNT (data) [i];
|
||||
if (PROFILE_READ_COUNT (data) [i] > max_val)
|
||||
max_val = PROFILE_READ_COUNT (data) [i];
|
||||
if (PROFILE_WRITE_COUNT (data) [i] > max_val)
|
||||
max_val = PROFILE_WRITE_COUNT (data) [i];
|
||||
n = strlen (MODE_NAME (i));
|
||||
if (n > max_name_len)
|
||||
max_name_len = n;
|
||||
}
|
||||
|
||||
/* One could use PROFILE_LABEL_WIDTH here. I chose not to. */
|
||||
sim_io_printf (sd, " Total read: %d accesses\n", total_read);
|
||||
sim_io_printf (sd, " Total write: %d accesses\n", total_write);
|
||||
|
||||
if (verbose && max_val != 0)
|
||||
{
|
||||
/* FIXME: Need to separate instruction fetches from data fetches
|
||||
as the former swamps the latter. */
|
||||
/* Now we can print the histogram. */
|
||||
sim_io_printf (sd, "\n");
|
||||
for (i = 0; i < MAX_MODES; ++i)
|
||||
{
|
||||
if (PROFILE_READ_COUNT (data) [i] != 0)
|
||||
{
|
||||
sim_io_printf (sd, " %*s read: %*d: ",
|
||||
max_name_len, MODE_NAME (i),
|
||||
max_val < 10000 ? 4 : 8,
|
||||
PROFILE_READ_COUNT (data) [i]);
|
||||
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: %*d: ",
|
||||
max_name_len, MODE_NAME (i),
|
||||
max_val < 10000 ? 4 : 8,
|
||||
PROFILE_WRITE_COUNT (data) [i]);
|
||||
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_MODEL_P
|
||||
|
||||
static void
|
||||
profile_print_model (sim_cpu *cpu, int verbose)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
|
||||
unsigned long cti_stalls = PROFILE_MODEL_CTI_STALL_COUNT (data);
|
||||
unsigned long load_stalls = PROFILE_MODEL_LOAD_STALL_COUNT (data);
|
||||
unsigned long total = PROFILE_MODEL_CYCLE_COUNT (data)
|
||||
+ cti_stalls + load_stalls;
|
||||
|
||||
sim_io_printf (sd, "Model %s Timing Information\n\n",
|
||||
MODEL_NAME (STATE_MODEL (sd)));
|
||||
sim_io_printf (sd, " %-*s %ld\n",
|
||||
PROFILE_LABEL_WIDTH, "Taken branches:",
|
||||
PROFILE_MODEL_TAKEN_COUNT (data));
|
||||
sim_io_printf (sd, " %-*s %ld\n",
|
||||
PROFILE_LABEL_WIDTH, "Untaken branches:",
|
||||
PROFILE_MODEL_UNTAKEN_COUNT (data));
|
||||
sim_io_printf (sd, " %-*s %ld\n",
|
||||
PROFILE_LABEL_WIDTH, "Cycles stalled due to branches:",
|
||||
cti_stalls);
|
||||
sim_io_printf (sd, " %-*s %ld\n",
|
||||
PROFILE_LABEL_WIDTH, "Cycles stalled due to loads:",
|
||||
load_stalls);
|
||||
sim_io_printf (sd, " %-*s %ld\n",
|
||||
PROFILE_LABEL_WIDTH, "Total cycles (*approximate*):",
|
||||
total);
|
||||
sim_io_printf (sd, "\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
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 void
|
||||
profile_print_speed (sim_cpu *cpu)
|
||||
{
|
||||
SIM_DESC sd = CPU_STATE (cpu);
|
||||
PROFILE_DATA *data = CPU_PROFILE_DATA (cpu);
|
||||
unsigned long milliseconds = PROFILE_EXEC_TIME (data);
|
||||
unsigned long total = PROFILE_TOTAL_INSN_COUNT (data);
|
||||
|
||||
sim_io_printf (sd, "Simulator Execution Speed\n\n");
|
||||
|
||||
if (total != 0)
|
||||
sim_io_printf (sd, " Total instructions: %ld\n", total);
|
||||
if (milliseconds < 1000)
|
||||
sim_io_printf (sd, " Total Execution Time: < 1 second\n\n");
|
||||
else
|
||||
{
|
||||
sim_io_printf (sd, " Total Execution Time: %.2f seconds\n",
|
||||
(double) milliseconds / 1000);
|
||||
/* Don't confuse things with data that isn't useful.
|
||||
If we ran for less than two seconds, only use the data if we
|
||||
executed more than 100,000 insns. */
|
||||
if (milliseconds >= 2000 || total >= 100000)
|
||||
sim_io_printf (sd, " Simulator Speed: %.0f insns/second\n\n",
|
||||
(double) total / ((double) milliseconds / 1000));
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
void
|
||||
profile_print (SIM_DESC sd, int verbose,
|
||||
PROFILE_CALLBACK *misc, PROFILE_CPU_CALLBACK *misc_cpu)
|
||||
{
|
||||
int i,c;
|
||||
int print_title_p = 0;
|
||||
|
||||
/* Only print the title if some data has been 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)
|
||||
sim_io_printf (sd, "CPU %d\n\n", c);
|
||||
|
||||
#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_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
|
||||
|
||||
/* Print cpu-specific data before the execution speed. */
|
||||
if (misc_cpu != NULL)
|
||||
(*misc_cpu) (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 (misc != NULL)
|
||||
(*misc) (sd, verbose);
|
||||
}
|
Loading…
Reference in New Issue
Block a user