* 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:
David Edelsohn 1997-05-01 18:05:37 +00:00
parent 2c8f0de695
commit c967f1874a
11 changed files with 987 additions and 446 deletions

View File

@ -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.

View File

@ -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

View File

@ -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");
}

View File

@ -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, ...)
{

View File

@ -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);
}

View File

@ -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. */

View File

@ -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
View 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
View 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;
}

View File

@ -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
View 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);
}