|
Message
From: =?unknown-8bit?Q?Gy=F6rgy?= 'nog' Jeney<nog@s...>
Date: Tue Mar 29 18:14:00 CEST 2005
Subject: [openrisc] [or1ksim #73] Make cli work with the recompiler
Hi,This patch makes the cli of the sim work (partially) with the recompiler. This makes heavy use of the scheduler to acomplish this.
What doesn't work (only in the recompiler): 1) The pr command won't work if the register that is being patched is in a temporary. 2) The pc command only updates the pc visually but doesn't actually alter the execution sequence. 3) The break command doesn't have any effect. 4) The stall command doesn't work. Actually, simulateing a stalled cpu is not implemented. 5) The trace (and run) command(s) only print the `just executed instruction' if running with analysis.
Nothing (appears to have) broke in the complex/simple execution models.
ChangeLog: * Rewrite the interactive mode handling to also work in the recompiler.
nog. -------------- next part -------------- diff -urp --unidirectional-new-file /home/nog/or1ksim-split/cpu/or1k/sprs.c ./cpu/or1k/sprs.c --- /home/nog/or1ksim-split/cpu/or1k/sprs.c 2005-03-24 18:53:42.000000000 +0100 +++ ./cpu/or1k/sprs.c 2005-03-25 18:10:51.000000000 +0100 @@ -153,13 +153,13 @@ mtspr(uint16_t regno, const sprword valu case 0xFFFF: fclose(fo); PRINTF("Audio closed.\n"); - runtime.sim.cont_run = 0; + sim_done(); break; case SPR_PMR: /* PMR[SDF] and PMR[DCGE] are ignored completely. */ if (value & SPR_PMR_SUME) { PRINTF ("SUSPEND: PMR[SUME] bit was set.\n"); - runtime.sim.cont_run = 0; + sim_done(); } break; default: diff -urp --unidirectional-new-file /home/nog/or1ksim-split/cpu/or32/execute.c ./cpu/or32/execute.c --- /home/nog/or1ksim-split/cpu/or32/execute.c 2005-03-24 18:53:42.000000000 +0100 +++ ./cpu/or32/execute.c 2005-03-26 11:26:32.000000000 +0100 @@ -99,7 +99,7 @@ uorreg_t evalsim_reg(unsigned int regno) return cpu_state.reg[regno]; } else { PRINTF("\nABORT: read out of registers\n"); - runtime.sim.cont_run = 0; + sim_done(); return 0; } } @@ -116,7 +116,7 @@ void setsim_reg(unsigned int regno, uorr cpu_state.reg[regno] = value; } else { PRINTF("\nABORT: write out of registers\n"); - runtime.sim.cont_run = 0; + sim_done(); } } @@ -144,7 +144,7 @@ inline static void set_reg(int regno, uo #endif /* RAW_RANGE */ } else { PRINTF("\nABORT: write out of registers\n"); - runtime.sim.cont_run = 0; + sim_done(); } } @@ -667,7 +668,6 @@ inline int cpu_clock () next_delay_insn = 0; if(fetch()) { PRINTF ("Breakpoint hit.\n"); - runtime.sim.cont_run = 0; /* memory breakpoint encountered */ return 1; } @@ -722,7 +722,7 @@ static uorreg_t eval_reg(unsigned int re return cpu_state.reg[regno]; } else { PRINTF("\nABORT: read out of registers\n"); - runtime.sim.cont_run = 0; + sim_done() return 0; } } diff -urp --unidirectional-new-file /home/nog/or1ksim-split/cpu/or32/insnset.c ./cpu/or32/insnset.c --- /home/nog/or1ksim-split/cpu/or32/insnset.c 2005-03-23 18:29:19.000000000 +0100 +++ ./cpu/or32/insnset.c 2005-03-25 18:09:32.000000000 +0100 @@ -309,7 +313,7 @@ INSTRUCTION (l_nop) { if (config.debug.gdb_enabled) set_stall_state (1); else - runtime.sim.cont_run = 0; + sim_done(); break; case NOP_CNT_RESET: PRINTF("****************** counters reset ******************\n"); @@ -414,7 +418,7 @@ INSTRUCTION (l_mtspr) { mtspr(regno, value);
else {
PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n");
- runtime.sim.cont_run = 0;
+ sim_done();
}
}
INSTRUCTION (l_mfspr) {
@@ -430,7 +434,7 @@ INSTRUCTION (l_mfspr) {
else {
SET_PARAM0(0);
PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n");
- runtime.sim.cont_run = 0;
+ sim_done();
}
}
INSTRUCTION (l_sys) {
diff -urp --unidirectional-new-file /home/nog/or1ksim-split/sim-cmd.c ./sim-cmd.c
--- /home/nog/or1ksim-split/sim-cmd.c 2005-03-24 18:08:57.000000000 +0100
+++ ./sim-cmd.c 2005-03-26 11:26:32.000000000 +0100
@@ -52,6 +52,7 @@ Foundation, Inc., 675 Mass Ave, Cambridg
#include "stats.h"
#include "cuc.h"
#include "gdbcomm.h"
+#include "sched.h"
/* FIXME: These *really* need to be cleaned up */
#include "sprs.h"
@@ -61,6 +62,9 @@ Foundation, Inc., 675 Mass Ave, Cambridg
#include "dcache_model.h"
#include "branch_predict.h"
+/* The number of instructions to execute before droping into interactive mode */
+static long long to_insn_num;
+
struct sim_stat {
void (*stat_func)(void *dat);
void *dat;
@@ -105,6 +109,30 @@ static void debugmem( oraddr_t from, ora
}
}
+/* Schedules the next job so that it will run after the next instruction */
+static void sched_next_insn(void (*func)(void *))
+{
+ int32_t cycles = 1;
+ struct sched_entry *cur = scheduler.job_queue;
+
+ /* The cycles count of the jobs may go into negatives. If this happens, func
+ * will get called before the next instruction has executed. */
+ while(cur && (cur->time < 0)) {
+ cycles -= cur->time;
+ cur = cur->next;
+ }
+
+ SCHED_ADD(func, NULL, cycles);
+}
+
+/* Scheduler job that drops us back into interactive mode after the next
+ * instruction has executed */
+void reenter_int(void *dat)
+{
+ if (!runtime.sim.hush) dumpreg();
+ handle_sim_command();
+}
+
static int sim_cmd_quit(int argc, char **argv) /* quit */
{
PRINTF ("\n");
@@ -146,7 +174,8 @@ static int sim_cmd_help(int argc, char *
static int sim_cmd_trace(int argc, char **argv) /* trace */
{
- runtime.sim.cont_run = 1;
+ runtime.sim.hush = 0;
+ sched_next_insn(reenter_int);
return 1;
}
@@ -359,19 +388,59 @@ static int sim_cmd_hist(int argc, char *
return 0;
}
+/* Called when it is suspisous that runtime.sim.instructions has reached
+ * to_insn_num */
+void check_insn_exec(void *dat)
+{
+ if(runtime.cpu.instructions < to_insn_num) {
+ /* Instruction count has not yet been reached, reschedule */
+ SCHED_ADD(check_insn_exec, NULL, to_insn_num - runtime.cpu.instructions);
+ return;
+ }
+ handle_sim_command();
+}
+
+void print_insn_exec(void *dat)
+{
+ dumpreg();
+ if(runtime.cpu.instructions < to_insn_num) {
+ /* Instruction count has not yet been reached, reschedule */
+ sched_next_insn(print_insn_exec);
+ return;
+ }
+ handle_sim_command();
+}
+
static int sim_cmd_run(int argc, char **argv) /* run */
{
+ runtime.sim.hush = 0;
if(argc >= 3) {
if(!strcmp(argv[2], "hush"))
runtime.sim.hush = 1;
- else
- runtime.sim.hush = 0;
}
- if(argc >= 2)
- runtime.sim.cont_run = strtol(argv[1], NULL, 0);
- else
- runtime.sim.cont_run = 0;
+ if(argc >= 2) {
+ if((to_insn_num = strtol(argv[1], NULL, 0)) != -1) {
+ if(runtime.sim.hush) {
+ /* Schedule a job to run in to_insn_num cycles time since an instruction
+ * may execute in only 1 cycle. check_insn_exec will check if the right
+ * number of instructions have been executed. If not it will
+ * reschedule. */
+ SCHED_ADD(check_insn_exec, NULL, to_insn_num);
+ } else {
+ /* The user wants to see the execution dumps. Schedule a task to show
+ * it to him after each cycle */
+ sched_next_insn(print_insn_exec);
+ }
+ to_insn_num += runtime.cpu.instructions;
+ } else {
+ if(!runtime.sim.hush)
+ sched_next_insn(print_insn_exec);
+ }
+ } else
+ /* Run 0 instructions */
+ return 0;
+
return 1;
}
@@ -379,7 +448,6 @@ static int sim_cmd_stall(int argc, char
{
set_stall_state (1);
runtime.sim.iprompt = 0;
- runtime.sim.cont_run = -1;
runtime.sim.hush = 1;
return 1;
}
@@ -522,6 +590,11 @@ void handle_sim_command(void)
static char prev_str[500] = { 0 };
#endif
+ /* Make sure that check_insn_exec is not left hanging in the scheduler (and
+ * breaking the sim when the user doesn't want it to break). */
+ SCHED_FIND_REMOVE(check_insn_exec, NULL);
+ SCHED_FIND_REMOVE(print_insn_exec, NULL);
+
#ifdef HAVE_LIBREADLINE
initialize_readline (); /* Bind our completer. */
#endif
@@ -595,8 +668,10 @@ void handle_sim_command(void)
for(cur_cmd = sim_commands; cur_cmd->name; cur_cmd++) {
if(!strcmp(cur_cmd->name, argv[0])) {
- if(cur_cmd->cmd_handle(argc, argv))
+ if(cur_cmd->cmd_handle(argc, argv)) {
+ runtime.sim.iprompt = 0;
return;
+ }
break;
}
}
diff -urp --unidirectional-new-file /home/nog/or1ksim-split/sim-config.h ./sim-config.h
--- /home/nog/or1ksim-split/sim-config.h 2005-03-25 14:39:47.000000000 +0100
+++ ./sim-config.h 2005-03-25 18:08:26.000000000 +0100
@@ -192,8 +192,6 @@ struct runtime {
char *filename; /* Original Command Simulator file (CZ) */
char script_fn[STR_SIZE]; /* Script file read */
int iprompt; /* Interactive prompt */
- int cont_run; /* Continuos run versus single
- step tracing switch. */
long long cycles; /* Cycles counts fetch stages */
int mem_cycles; /* Each cycle has counter of mem_cycles;
@@ -265,6 +260,12 @@ void print_config();
void sim_done(void);
+/* Periodically checks runtime.sim.iprompt to see if ctrl_c has been pressed */
+void check_int(void *dat);
+
+/* Number of cycles between checks to runtime.sim.iprompt */
+#define CHECK_INT_TIME 100000
+
/* Resets all subunits */
void sim_reset(void);
diff -urp --unidirectional-new-file /home/nog/or1ksim-split/toplevel.c ./toplevel.c
--- /home/nog/or1ksim-split/toplevel.c 2005-03-25 14:06:13.000000000 +0100
+++ ./toplevel.c 2005-03-26 11:11:30.000000000 +0100
@@ -101,13 +101,21 @@ inline void debug(int level, const char
void ctrl_c(signum)
int signum;
{
- runtime.sim.cont_run = runtime.cpu.stalled ? 0 : 1;
runtime.sim.iprompt = 1;
- set_stall_state (0);
signal(SIGINT, ctrl_c);
}
-void version()
+/* Periodically checks runtime.sim.iprompt to see if ctrl_c has been pressed */
+void check_int(void *dat)
+{
+ if(runtime.sim.iprompt) {
+ set_stall_state (0);
+ handle_sim_command();
+ }
+ SCHED_ADD(check_int, NULL, CHECK_INT_TIME);
+}
+
+void version(void)
{
PRINTF ("\n");
PRINTF ("OpenRISC 1000 (OR32) Architectural Simulator, %s\n", rcsrev);
@@ -170,6 +178,9 @@ void sim_reset (void)
pic_reset();
du_reset ();
+ /* Make sure that runtime.sim.iprompt is the first thing to get checked */
+ SCHED_ADD(check_int, NULL, 0);
+
lock_memory_table ();
/* FIXME: Lame-ass way to get runtime.sim.mem_cycles not going into overly
@@ -367,6 +378,13 @@ void do_scheduler (void)
} while (scheduler.job_queue->time <= 0);
}
+void recalc_do_stats(void)
+{
+ extern int do_stats;
+ do_stats = config.cpu.dependstats || config.cpu.superscalar ||
+ config.cpu.dependstats || config.sim.history || config.sim.exe_log;
+}
+
/* Main function */
int main(argc, argv)
int argc;
@@ -403,64 +422,50 @@ int main(argc, argv)
if (!runtime.sim.script_file_specified && config.sim.verbose)
fprintf (stderr, "WARNING: No config file read, assuming default configuration.\n");
print_config();
- sim_init ();
signal(SIGINT, ctrl_c);
runtime.sim.hush = 1;
- runtime.sim.cont_run = -1;
+ recalc_do_stats();
- while(1) {
- if (runtime.sim.iprompt)
- handle_sim_command();
-
- { /* Needed by execution */
- extern int do_stats;
- do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
- || config.sim.history || config.sim.exe_log;
- }
+ sim_init ();
- /* MM: 'run -1' means endless execution. */
- while(runtime.sim.cont_run) {
- long long time_start = runtime.sim.cycles;
- if (config.debug.enabled) {
- du_clock(); // reset watchpoints
- if (runtime.cpu.stalled) {
- if(config.debug.gdb_enabled) {
- BlockJTAG();
- HandleServerSocket(false);
- } else {
- fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.");
- runtime.sim.cont_run = 0;
- }
- continue;
+ while(1) {
+ long long time_start = runtime.sim.cycles;
+ if (config.debug.enabled) {
+ du_clock(); // reset watchpoints
+ while (runtime.cpu.stalled) {
+ if(config.debug.gdb_enabled) {
+ BlockJTAG();
+ HandleServerSocket(false);
+ } else {
+ fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.\n");
+ /* Dump the user into interactive mode. From there he can decide what
+ * to do. */
+ handle_sim_command();
+ sim_done();
}
+ if(runtime.sim.iprompt)
+ handle_sim_command();
}
-
- /* Each cycle has counter of mem_cycles; this value is joined with cycles
- at the end of the cycle; no sim originated memory accesses should be
- performed inbetween. */
- runtime.sim.mem_cycles = 0;
- if (!config.pm.enabled || !testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) {
- if (runtime.sim.cont_run > 0) runtime.sim.cont_run--;
- if (cpu_clock ()) break;
- }
-
- if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
- if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
- if(config.debug.enabled)
- if (testsprbits(SPR_DMR1, SPR_DMR1_ST)) set_stall_state (1);
-
- runtime.sim.cycles += runtime.sim.mem_cycles;
- scheduler.job_queue->time -= runtime.sim.cycles - time_start;
- if (scheduler.job_queue->time <= 0) do_scheduler ();
- if (!runtime.sim.hush) dumpreg();
}
- runtime.sim.hush = 0;
- fflush(stdout);
- runtime.sim.fout = stdout;
- if (!runtime.sim.iprompt) /* non-interactive quit */
- sim_done();
+ /* Each cycle has counter of mem_cycles; this value is joined with cycles
+ at the end of the cycle; no sim originated memory accesses should be
+ performed inbetween. */
+ runtime.sim.mem_cycles = 0;
+ if (!config.pm.enabled || !testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME))
+ if (cpu_clock ())
+ /* A breakpoint has been hit, drop to interactive mode */
+ handle_sim_command();
+
+ if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
+ if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
+ if(config.debug.enabled)
+ if (testsprbits(SPR_DMR1, SPR_DMR1_ST)) set_stall_state (1);
+
+ runtime.sim.cycles += runtime.sim.mem_cycles;
+ scheduler.job_queue->time -= runtime.sim.cycles - time_start;
+ if (scheduler.job_queue->time <= 0) do_scheduler ();
}
sim_done();
}
|
 |