From a965833575a336a10200d3697483d802a425b019 Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Thu, 3 Oct 2024 17:36:07 +0100 Subject: [PATCH] Add instruction limit Adds an optional --instructions=N CLI argument which will stop the simulation after N instructions. This is useful for benchmarking and profiling and sometimes debugging. --- fesvr/htif.cc | 18 +++++++++++++----- fesvr/htif.h | 10 +++++++++- fesvr/syscall.cc | 4 ++-- riscv/sim.cc | 17 +++++++++++++++-- riscv/sim.h | 6 ++++-- spike_main/spike.cc | 8 +++++++- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/fesvr/htif.cc b/fesvr/htif.cc index 46f15d3169..b52b8d28eb 100644 --- a/fesvr/htif.cc +++ b/fesvr/htif.cc @@ -46,7 +46,7 @@ static void handle_signal(int sig) htif_t::htif_t() : mem(this), entry(DRAM_BASE), sig_addr(0), sig_len(0), - tohost_addr(0), fromhost_addr(0), exitcode(0), stopped(false), + tohost_addr(0), fromhost_addr(0), stopped(false), syscall_proxy(this) { signal(SIGINT, &handle_signal); @@ -116,7 +116,7 @@ std::map htif_t::load_payload(const std::string& payload, else throw std::runtime_error( "could not open " + payload + "; searched paths:\n" + - "\t. (current directory)\n" + + "\t. (current directory)\n" + "\t" + PREFIX TARGET_DIR + " (based on configured --prefix and --with-target)" ); } @@ -207,6 +207,14 @@ const char* htif_t::get_symbol(uint64_t addr) return it->second.c_str(); } +bool htif_t::should_exit() const { + return signal_exit || exitcode.has_value(); +} + +void htif_t::exit(int exit_code) { + exitcode = exit_code; +} + void htif_t::stop() { if (!sig_file.empty() && sig_len) // print final torture test signature @@ -253,11 +261,11 @@ int htif_t::run() std::bind(enq_func, &fromhost_queue, std::placeholders::_1); if (tohost_addr == 0) { - while (!signal_exit) + while (!should_exit()) idle(); } - while (!signal_exit && exitcode == 0) + while (!should_exit()) { uint64_t tohost; @@ -305,7 +313,7 @@ bool htif_t::done() int htif_t::exit_code() { - return exitcode >> 1; + return exitcode.value_or(0) >> 1; } void htif_t::parse_arguments(int argc, char ** argv) diff --git a/fesvr/htif.h b/fesvr/htif.h index 74511f58a5..a7ef98dc6c 100644 --- a/fesvr/htif.h +++ b/fesvr/htif.h @@ -24,6 +24,9 @@ class htif_t : public chunked_memif_t virtual void start(); virtual void stop(); + // Cause the simulation to exit with the given exit code. + void exit(int exit_code); + int run(); bool done(); int exit_code(); @@ -76,6 +79,10 @@ class htif_t : public chunked_memif_t // Given an address, return symbol from addr2symbol map const char* get_symbol(uint64_t addr); + // Return true if the simulation should exit due to a signal, + // or end-of-test from HTIF, or an instruction limit. + bool should_exit() const; + private: void parse_arguments(int argc, char ** argv); void register_devices(); @@ -93,7 +100,8 @@ class htif_t : public chunked_memif_t addr_t sig_len; // torture addr_t tohost_addr; addr_t fromhost_addr; - int exitcode; + // Set to a value by exit() when the simulation should exit. + std::optional exitcode; bool stopped; device_list_t device_list; diff --git a/fesvr/syscall.cc b/fesvr/syscall.cc index 162cbfc6a9..a4ecf6abaa 100644 --- a/fesvr/syscall.cc +++ b/fesvr/syscall.cc @@ -137,7 +137,7 @@ struct riscv_statx __spare2(), __spare3() #else __spare2() -#endif +#endif {} }; #endif @@ -221,7 +221,7 @@ void syscall_t::handle_syscall(command_t cmd) reg_t syscall_t::sys_exit(reg_t code, reg_t a1, reg_t a2, reg_t a3, reg_t a4, reg_t a5, reg_t a6) { - htif->exitcode = code << 1 | 1; + htif->exit(code << 1 | 1); return 0; } diff --git a/riscv/sim.cc b/riscv/sim.cc index d08e274d9d..7cfdbccc6f 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -44,7 +44,8 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, const char *log_path, bool dtb_enabled, const char *dtb_file, bool socket_enabled, - FILE *cmd_file) // needed for command line option --cmd + FILE *cmd_file, // needed for command line option --cmd + std::optional instruction_limit) : htif_t(args), isa(cfg->isa, cfg->priv), cfg(cfg), @@ -53,6 +54,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, dtb_enabled(dtb_enabled), log_file(log_path), cmd_file(cmd_file), + instruction_limit(instruction_limit), sout_(nullptr), current_step(0), current_proc(0), @@ -414,8 +416,19 @@ void sim_t::idle() if (debug || ctrlc_pressed) interactive(); - else + else { + if (instruction_limit.has_value()) { + if (*instruction_limit < INTERLEAVE) { + // Final step. + step(*instruction_limit); + exit(0); + *instruction_limit = 0; + return; + } + *instruction_limit -= INTERLEAVE; + } step(INTERLEAVE); + } if (remote_bitbang) remote_bitbang->tick(); diff --git a/riscv/sim.h b/riscv/sim.h index 726de7d794..348e136cf9 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -35,10 +35,10 @@ class sim_t : public htif_t, public simif_t const debug_module_config_t &dm_config, const char *log_path, bool dtb_enabled, const char *dtb_file, bool socket_enabled, - FILE *cmd_file); // needed for command line option --cmd + FILE *cmd_file, // needed for command line option --cmd + std::optional instruction_limit); ~sim_t(); - // run the simulation to completion int run(); void set_debug(bool value); void set_histogram(bool value); @@ -86,6 +86,8 @@ class sim_t : public htif_t, public simif_t FILE *cmd_file; // pointer to debug command input file + std::optional instruction_limit; + socketif_t *socketif; std::ostream sout_; // used for socket and terminal interface diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 6596bc1a58..6330181ec7 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -85,6 +85,7 @@ static void help(int exit_code = 1) fprintf(stderr, " --dm-no-halt-groups Debug module won't support halt groups\n"); fprintf(stderr, " --dm-no-impebreak Debug module won't support implicit ebreak in program buffer\n"); fprintf(stderr, " --blocksz= Cache block size (B) for CMO operations(powers of 2) [default 64]\n"); + fprintf(stderr, " --instructions= Stop after n instructions\n"); exit(exit_code); } @@ -349,6 +350,7 @@ int main(int argc, char** argv) bool use_rbb = false; unsigned dmi_rti = 0; reg_t blocksz = 64; + std::optional instructions; debug_module_config_t dm_config; cfg_arg_t nprocs(1); @@ -463,6 +465,9 @@ int main(int argc, char** argv) exit(-1); } }); + parser.option(0, "instructions", 1, [&](const char* s){ + instructions = strtoull(s, 0, 0); + }); auto argv1 = parser.parse(argv); std::vector htif_args(argv1, (const char*const*)argv + argc); @@ -524,7 +529,8 @@ int main(int argc, char** argv) sim_t s(&cfg, halted, mems, plugin_device_factories, htif_args, dm_config, log_path, dtb_enabled, dtb_file, socket, - cmd_file); + cmd_file, + instructions); std::unique_ptr remote_bitbang((remote_bitbang_t *) NULL); std::unique_ptr jtag_dtm( new jtag_dtm_t(&s.debug_module, dmi_rti));