1 /* Main simulator loop for CGEN-based simulators.
2 Copyright (C) 1998-2024 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
5 This file is part of GDB, the GNU debugger.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* ??? These are old notes, kept around for now.
21 Collecting profile data and tracing slow us down so we don't do them in
23 There are 6 possibilities on 2 axes:
24 - no-scaching, insn-scaching, basic-block-scaching
25 - run with full features or run fast
26 Supporting all six possibilities in one executable is a bit much but
27 supporting full/fast seems reasonable.
28 If the scache is configured in it is always used.
29 If pbb-scaching is configured in it is always used.
30 ??? Sometimes supporting more than one set of semantic functions will make
31 the simulator too large - this should be configurable. Blah blah blah.
32 ??? Supporting full/fast can be more modular, blah blah blah.
33 When the framework is more modular, this can be.
36 /* This must come before any other includes. */
40 #include "sim-assert.h"
41 #include "sim-signal.h"
43 #ifndef SIM_ENGINE_PREFIX_HOOK
44 #define SIM_ENGINE_PREFIX_HOOK(sd)
46 #ifndef SIM_ENGINE_POSTFIX_HOOK
47 #define SIM_ENGINE_POSTFIX_HOOK(sd)
50 static sim_event_handler has_stepped
;
51 static void prime_cpu (SIM_CPU
*, int);
52 static void engine_run_1 (SIM_DESC
, int, int);
53 static void engine_run_n (SIM_DESC
, int, int, int, int);
55 /* If no profiling or tracing has been enabled, run in fast mode. */
57 cgen_get_fast_p (SIM_DESC sd
)
61 for (c
= 0; c
< MAX_NR_PROCESSORS
; ++c
)
63 SIM_CPU
*cpu
= STATE_CPU (sd
, c
);
65 if (PROFILE_ANY_P (cpu
) || TRACE_ANY_P (cpu
))
72 /* sim_resume for cgen */
75 sim_resume (SIM_DESC sd
, int step
, int siggnal
)
77 sim_engine
*engine
= STATE_ENGINE (sd
);
80 static int fast_p
= -1;
82 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
85 fast_p
= cgen_get_fast_p (sd
);
87 /* we only want to be single stepping the simulator once */
88 if (engine
->stepper
!= NULL
)
90 sim_events_deschedule (sd
, engine
->stepper
);
91 engine
->stepper
= NULL
;
94 engine
->stepper
= sim_events_schedule (sd
, 1, has_stepped
, sd
);
96 sim_module_resume (sd
);
99 if (USING_SCACHE_P (sd
))
103 /* run/resume the simulator */
105 sim_engine_set_run_state (sd
, sim_running
, 0);
107 engine
->jmpbuf
= &buf
;
108 jmpval
= setjmp (buf
);
109 if (jmpval
== sim_engine_start_jmpval
110 || jmpval
== sim_engine_restart_jmpval
)
112 int last_cpu_nr
= sim_engine_last_cpu_nr (sd
);
113 int next_cpu_nr
= sim_engine_next_cpu_nr (sd
);
114 int nr_cpus
= sim_engine_nr_cpus (sd
);
115 /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
116 useful if all one wants to do is run a benchmark. Need some better
117 way to identify this case. */
118 int max_insns
= (step
122 /* Don't do this if running under gdb, need to
123 poll ui for events. */
124 && STATE_OPEN_KIND (sd
) == SIM_OPEN_STANDALONE
)
126 : 8); /*FIXME: magic number*/
128 sim_events_preprocess (sd
, last_cpu_nr
>= nr_cpus
, next_cpu_nr
>= nr_cpus
);
129 if (next_cpu_nr
>= nr_cpus
)
132 engine_run_1 (sd
, max_insns
, fast_p
);
134 engine_run_n (sd
, next_cpu_nr
, nr_cpus
, max_insns
, fast_p
);
139 /* Account for the last insn executed. */
140 SIM_CPU
*cpu
= STATE_CPU (sd
, sim_engine_last_cpu_nr (sd
));
141 ++ CPU_INSN_COUNT (cpu
);
142 CGEN_TRACE_INSN_FINI (cpu
, NULL
, 1);
146 engine
->jmpbuf
= NULL
;
150 int nr_cpus
= sim_engine_nr_cpus (sd
);
153 /* If the loop exits, either we single-stepped or @cpu@_engine_stop
156 sim_engine_set_run_state (sd
, sim_stopped
, SIM_SIGTRAP
);
158 sim_engine_set_run_state (sd
, pending_reason
, pending_sigrc
);
161 for (i
= 0; i
< nr_cpus
; ++i
)
163 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
165 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu
)) += CPU_INSN_COUNT (cpu
);
169 sim_module_suspend (sd
);
172 /* Halt the simulator after just one instruction. */
175 has_stepped (SIM_DESC sd
, void *data
)
177 ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
178 sim_engine_halt (sd
, NULL
, NULL
, NULL_CIA
, sim_stopped
, SIM_SIGTRAP
);
181 /* Prepare a cpu for running.
182 MAX_INSNS is the number of insns to execute per time slice.
183 If 0 it means the cpu can run as long as it wants (e.g. until the
185 ??? Perhaps this should be an argument to the engine_fn. */
188 prime_cpu (SIM_CPU
*cpu
, int max_insns
)
190 CPU_MAX_SLICE_INSNS (cpu
) = max_insns
;
191 CPU_INSN_COUNT (cpu
) = 0;
193 /* Initialize the insn descriptor table.
194 This has to be done after all initialization so we just defer it to
197 if (MACH_PREPARE_RUN (CPU_MACH (cpu
)))
198 (* MACH_PREPARE_RUN (CPU_MACH (cpu
))) (cpu
);
201 /* Main loop, for 1 cpu. */
204 engine_run_1 (SIM_DESC sd
, int max_insns
, int fast_p
)
206 sim_cpu
*cpu
= STATE_CPU (sd
, 0);
207 ENGINE_FN
*fn
= fast_p
? CPU_FAST_ENGINE_FN (cpu
) : CPU_FULL_ENGINE_FN (cpu
);
209 prime_cpu (cpu
, max_insns
);
213 SIM_ENGINE_PREFIX_HOOK (sd
);
217 SIM_ENGINE_POSTFIX_HOOK (sd
);
219 /* process any events */
220 if (sim_events_tick (sd
))
221 sim_events_process (sd
);
225 /* Main loop, for multiple cpus. */
228 engine_run_n (SIM_DESC sd
, int next_cpu_nr
, int nr_cpus
, int max_insns
, int fast_p
)
231 /* Ensure that engine_fns is fully initialized, this silences a compiler
232 warning when engine_fns is used below. */
233 ENGINE_FN
*engine_fns
[MAX_NR_PROCESSORS
] = {};
235 SIM_ASSERT (nr_cpus
<= MAX_NR_PROCESSORS
);
236 SIM_ASSERT (next_cpu_nr
>= 0 && next_cpu_nr
< nr_cpus
);
238 for (i
= 0; i
< nr_cpus
; ++i
)
240 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
242 engine_fns
[i
] = fast_p
? CPU_FAST_ENGINE_FN (cpu
) : CPU_FULL_ENGINE_FN (cpu
);
243 prime_cpu (cpu
, max_insns
);
248 SIM_ENGINE_PREFIX_HOOK (sd
);
250 /* FIXME: proper cycling of all of them, blah blah blah. */
251 while (next_cpu_nr
< nr_cpus
)
253 SIM_CPU
*cpu
= STATE_CPU (sd
, next_cpu_nr
);
255 (* engine_fns
[next_cpu_nr
]) (cpu
);
259 SIM_ENGINE_POSTFIX_HOOK (sd
);
261 /* process any events */
262 if (sim_events_tick (sd
))
263 sim_events_process (sd
);