xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/cgen-run.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
198b9484cSchristos /* Main simulator loop for CGEN-based simulators.
2*88241920Schristos    Copyright (C) 1998-2024 Free Software Foundation, Inc.
398b9484cSchristos    Contributed by Cygnus Solutions.
498b9484cSchristos 
598b9484cSchristos This file is part of GDB, the GNU debugger.
698b9484cSchristos 
798b9484cSchristos This program is free software; you can redistribute it and/or modify
898b9484cSchristos it under the terms of the GNU General Public License as published by
998b9484cSchristos the Free Software Foundation; either version 3 of the License, or
1098b9484cSchristos (at your option) any later version.
1198b9484cSchristos 
1298b9484cSchristos This program is distributed in the hope that it will be useful,
1398b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1498b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598b9484cSchristos GNU General Public License for more details.
1698b9484cSchristos 
1798b9484cSchristos You should have received a copy of the GNU General Public License
1898b9484cSchristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1998b9484cSchristos 
2098b9484cSchristos /* ??? These are old notes, kept around for now.
2198b9484cSchristos    Collecting profile data and tracing slow us down so we don't do them in
2298b9484cSchristos    "fast mode".
2398b9484cSchristos    There are 6 possibilities on 2 axes:
2498b9484cSchristos    - no-scaching, insn-scaching, basic-block-scaching
2598b9484cSchristos    - run with full features or run fast
2698b9484cSchristos    Supporting all six possibilities in one executable is a bit much but
2798b9484cSchristos    supporting full/fast seems reasonable.
2898b9484cSchristos    If the scache is configured in it is always used.
2998b9484cSchristos    If pbb-scaching is configured in it is always used.
3098b9484cSchristos    ??? Sometimes supporting more than one set of semantic functions will make
3198b9484cSchristos    the simulator too large - this should be configurable.  Blah blah blah.
3298b9484cSchristos    ??? Supporting full/fast can be more modular, blah blah blah.
3398b9484cSchristos    When the framework is more modular, this can be.
3498b9484cSchristos */
3598b9484cSchristos 
364b169a6bSchristos /* This must come before any other includes.  */
374b169a6bSchristos #include "defs.h"
384b169a6bSchristos 
3998b9484cSchristos #include "sim-main.h"
4098b9484cSchristos #include "sim-assert.h"
414b169a6bSchristos #include "sim-signal.h"
4298b9484cSchristos 
4398b9484cSchristos #ifndef SIM_ENGINE_PREFIX_HOOK
4498b9484cSchristos #define SIM_ENGINE_PREFIX_HOOK(sd)
4598b9484cSchristos #endif
4698b9484cSchristos #ifndef SIM_ENGINE_POSTFIX_HOOK
4798b9484cSchristos #define SIM_ENGINE_POSTFIX_HOOK(sd)
4898b9484cSchristos #endif
4998b9484cSchristos 
5098b9484cSchristos static sim_event_handler has_stepped;
5198b9484cSchristos static void prime_cpu (SIM_CPU *, int);
5298b9484cSchristos static void engine_run_1 (SIM_DESC, int, int);
5398b9484cSchristos static void engine_run_n (SIM_DESC, int, int, int, int);
5498b9484cSchristos 
554b169a6bSchristos /* If no profiling or tracing has been enabled, run in fast mode.  */
564b169a6bSchristos static int
574b169a6bSchristos cgen_get_fast_p (SIM_DESC sd)
584b169a6bSchristos {
59*88241920Schristos   int c;
604b169a6bSchristos 
614b169a6bSchristos   for (c = 0; c < MAX_NR_PROCESSORS; ++c)
624b169a6bSchristos     {
634b169a6bSchristos       SIM_CPU *cpu = STATE_CPU (sd, c);
644b169a6bSchristos 
654b169a6bSchristos       if (PROFILE_ANY_P (cpu) || TRACE_ANY_P (cpu))
664b169a6bSchristos 	return 0;
674b169a6bSchristos     }
684b169a6bSchristos 
694b169a6bSchristos   return 1;
704b169a6bSchristos }
714b169a6bSchristos 
7298b9484cSchristos /* sim_resume for cgen */
7398b9484cSchristos 
7498b9484cSchristos void
7598b9484cSchristos sim_resume (SIM_DESC sd, int step, int siggnal)
7698b9484cSchristos {
7798b9484cSchristos   sim_engine *engine = STATE_ENGINE (sd);
7898b9484cSchristos   jmp_buf buf;
7998b9484cSchristos   int jmpval;
804b169a6bSchristos   static int fast_p = -1;
8198b9484cSchristos 
8298b9484cSchristos   ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
8398b9484cSchristos 
844b169a6bSchristos   if (fast_p == -1)
854b169a6bSchristos     fast_p = cgen_get_fast_p (sd);
864b169a6bSchristos 
8798b9484cSchristos   /* we only want to be single stepping the simulator once */
8898b9484cSchristos   if (engine->stepper != NULL)
8998b9484cSchristos     {
9098b9484cSchristos       sim_events_deschedule (sd, engine->stepper);
9198b9484cSchristos       engine->stepper = NULL;
9298b9484cSchristos     }
9398b9484cSchristos   if (step)
9498b9484cSchristos     engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
9598b9484cSchristos 
9698b9484cSchristos   sim_module_resume (sd);
9798b9484cSchristos 
9898b9484cSchristos #if WITH_SCACHE
9998b9484cSchristos   if (USING_SCACHE_P (sd))
10098b9484cSchristos     scache_flush (sd);
10198b9484cSchristos #endif
10298b9484cSchristos 
10398b9484cSchristos   /* run/resume the simulator */
10498b9484cSchristos 
10598b9484cSchristos   sim_engine_set_run_state (sd, sim_running, 0);
10698b9484cSchristos 
10798b9484cSchristos   engine->jmpbuf = &buf;
10898b9484cSchristos   jmpval = setjmp (buf);
10998b9484cSchristos   if (jmpval == sim_engine_start_jmpval
11098b9484cSchristos       || jmpval == sim_engine_restart_jmpval)
11198b9484cSchristos     {
11298b9484cSchristos       int last_cpu_nr = sim_engine_last_cpu_nr (sd);
11398b9484cSchristos       int next_cpu_nr = sim_engine_next_cpu_nr (sd);
11498b9484cSchristos       int nr_cpus = sim_engine_nr_cpus (sd);
11598b9484cSchristos       /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is
11698b9484cSchristos 	 useful if all one wants to do is run a benchmark.  Need some better
11798b9484cSchristos 	 way to identify this case.  */
11898b9484cSchristos       int max_insns = (step
11998b9484cSchristos 		       ? 1
12098b9484cSchristos 		       : (nr_cpus == 1
12198b9484cSchristos 			  /*&& wip:no-events*/
12298b9484cSchristos 			  /* Don't do this if running under gdb, need to
12398b9484cSchristos 			     poll ui for events.  */
12498b9484cSchristos 			  && STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE)
12598b9484cSchristos 		       ? 0
12698b9484cSchristos 		       : 8); /*FIXME: magic number*/
12798b9484cSchristos 
12898b9484cSchristos       sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
12998b9484cSchristos       if (next_cpu_nr >= nr_cpus)
13098b9484cSchristos 	next_cpu_nr = 0;
13198b9484cSchristos       if (nr_cpus == 1)
13298b9484cSchristos 	engine_run_1 (sd, max_insns, fast_p);
13398b9484cSchristos       else
13498b9484cSchristos 	engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p);
13598b9484cSchristos     }
13698b9484cSchristos #if 1 /*wip*/
13798b9484cSchristos   else
13898b9484cSchristos     {
13998b9484cSchristos       /* Account for the last insn executed.  */
14098b9484cSchristos       SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd));
14198b9484cSchristos       ++ CPU_INSN_COUNT (cpu);
142212397c6Schristos       CGEN_TRACE_INSN_FINI (cpu, NULL, 1);
14398b9484cSchristos     }
14498b9484cSchristos #endif
14598b9484cSchristos 
14698b9484cSchristos   engine->jmpbuf = NULL;
14798b9484cSchristos 
14898b9484cSchristos   {
14998b9484cSchristos     int i;
15098b9484cSchristos     int nr_cpus = sim_engine_nr_cpus (sd);
15198b9484cSchristos 
15298b9484cSchristos #if 0 /*wip,ignore*/
15398b9484cSchristos     /* If the loop exits, either we single-stepped or @cpu@_engine_stop
15498b9484cSchristos        was called.  */
15598b9484cSchristos     if (step)
15698b9484cSchristos       sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP);
15798b9484cSchristos     else
15898b9484cSchristos       sim_engine_set_run_state (sd, pending_reason, pending_sigrc);
15998b9484cSchristos #endif
16098b9484cSchristos 
16198b9484cSchristos     for (i = 0; i < nr_cpus; ++i)
16298b9484cSchristos       {
16398b9484cSchristos 	SIM_CPU *cpu = STATE_CPU (sd, i);
16498b9484cSchristos 
16598b9484cSchristos 	PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu);
16698b9484cSchristos       }
16798b9484cSchristos   }
16898b9484cSchristos 
16998b9484cSchristos   sim_module_suspend (sd);
17098b9484cSchristos }
17198b9484cSchristos 
17298b9484cSchristos /* Halt the simulator after just one instruction.  */
17398b9484cSchristos 
17498b9484cSchristos static void
17598b9484cSchristos has_stepped (SIM_DESC sd, void *data)
17698b9484cSchristos {
17798b9484cSchristos   ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
17898b9484cSchristos   sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
17998b9484cSchristos }
18098b9484cSchristos 
18198b9484cSchristos /* Prepare a cpu for running.
18298b9484cSchristos    MAX_INSNS is the number of insns to execute per time slice.
18398b9484cSchristos    If 0 it means the cpu can run as long as it wants (e.g. until the
18498b9484cSchristos    program completes).
18598b9484cSchristos    ??? Perhaps this should be an argument to the engine_fn.  */
18698b9484cSchristos 
18798b9484cSchristos static void
18898b9484cSchristos prime_cpu (SIM_CPU *cpu, int max_insns)
18998b9484cSchristos {
19098b9484cSchristos   CPU_MAX_SLICE_INSNS (cpu) = max_insns;
19198b9484cSchristos   CPU_INSN_COUNT (cpu) = 0;
19298b9484cSchristos 
19398b9484cSchristos   /* Initialize the insn descriptor table.
19498b9484cSchristos      This has to be done after all initialization so we just defer it to
19598b9484cSchristos      here.  */
19698b9484cSchristos 
19798b9484cSchristos   if (MACH_PREPARE_RUN (CPU_MACH (cpu)))
19898b9484cSchristos     (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu);
19998b9484cSchristos }
20098b9484cSchristos 
20198b9484cSchristos /* Main loop, for 1 cpu.  */
20298b9484cSchristos 
20398b9484cSchristos static void
20498b9484cSchristos engine_run_1 (SIM_DESC sd, int max_insns, int fast_p)
20598b9484cSchristos {
20698b9484cSchristos   sim_cpu *cpu = STATE_CPU (sd, 0);
20798b9484cSchristos   ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
20898b9484cSchristos 
20998b9484cSchristos   prime_cpu (cpu, max_insns);
21098b9484cSchristos 
21198b9484cSchristos   while (1)
21298b9484cSchristos     {
21398b9484cSchristos       SIM_ENGINE_PREFIX_HOOK (sd);
21498b9484cSchristos 
21598b9484cSchristos       (*fn) (cpu);
21698b9484cSchristos 
21798b9484cSchristos       SIM_ENGINE_POSTFIX_HOOK (sd);
21898b9484cSchristos 
21998b9484cSchristos       /* process any events */
22098b9484cSchristos       if (sim_events_tick (sd))
22198b9484cSchristos 	sim_events_process (sd);
22298b9484cSchristos     }
22398b9484cSchristos }
22498b9484cSchristos 
22598b9484cSchristos /* Main loop, for multiple cpus.  */
22698b9484cSchristos 
22798b9484cSchristos static void
22898b9484cSchristos engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p)
22998b9484cSchristos {
23098b9484cSchristos   int i;
2314b169a6bSchristos   /* Ensure that engine_fns is fully initialized, this silences a compiler
2324b169a6bSchristos      warning when engine_fns is used below.  */
2334b169a6bSchristos   ENGINE_FN *engine_fns[MAX_NR_PROCESSORS] = {};
2344b169a6bSchristos 
2354b169a6bSchristos   SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);
2364b169a6bSchristos   SIM_ASSERT (next_cpu_nr >= 0 && next_cpu_nr < nr_cpus);
23798b9484cSchristos 
23898b9484cSchristos   for (i = 0; i < nr_cpus; ++i)
23998b9484cSchristos     {
24098b9484cSchristos       SIM_CPU *cpu = STATE_CPU (sd, i);
24198b9484cSchristos 
24298b9484cSchristos       engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu);
24398b9484cSchristos       prime_cpu (cpu, max_insns);
24498b9484cSchristos     }
24598b9484cSchristos 
24698b9484cSchristos   while (1)
24798b9484cSchristos     {
24898b9484cSchristos       SIM_ENGINE_PREFIX_HOOK (sd);
24998b9484cSchristos 
25098b9484cSchristos       /* FIXME: proper cycling of all of them, blah blah blah.  */
2514b169a6bSchristos       while (next_cpu_nr < nr_cpus)
25298b9484cSchristos 	{
25398b9484cSchristos 	  SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr);
25498b9484cSchristos 
25598b9484cSchristos 	  (* engine_fns[next_cpu_nr]) (cpu);
25698b9484cSchristos 	  ++next_cpu_nr;
25798b9484cSchristos 	}
25898b9484cSchristos 
25998b9484cSchristos       SIM_ENGINE_POSTFIX_HOOK (sd);
26098b9484cSchristos 
26198b9484cSchristos       /* process any events */
26298b9484cSchristos       if (sim_events_tick (sd))
26398b9484cSchristos 	sim_events_process (sd);
26498b9484cSchristos     }
26598b9484cSchristos }
266