diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 50fac117..a638a4cd 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -30,6 +30,8 @@ using std::right; using std::setw; using std::endl; +#define MAX_CMD_STR 40 // maximum possible size of a command line + #define STR_(X) #X // these definitions allow to use a macro as a string #define STR(X) STR_(X) @@ -110,7 +112,8 @@ std::string sim_t::rin(streambuf *bout_ptr) { // write sout to socket (via bout) void sim_t::wout(streambuf *bout_ptr) { - if (acceptor_ptr) { // only if a socket has been created + if (!cmd_file && acceptor_ptr) { // only if we are not getting command inputs from a file + // and if a socket has been created try { boost::system::error_code ignored_error; boost::asio::write(*socket_ptr, *bout_ptr, transfer_all(), ignored_error); @@ -151,14 +154,27 @@ void sim_t::interactive() while (!done()) { - std::string s; #ifdef HAVE_BOOST_ASIO streambuf bout; // socket output - s = rin(&bout); // get command string from socket or terminal +#endif + std::string s; + char cmd_str[MAX_CMD_STR+1]; // only used for following fscanf + // first get commands from file, if cmd_file has been set + if (cmd_file && !feof(cmd_file) && fscanf(cmd_file,"%" STR(MAX_CMD_STR) "[^\n]\n", cmd_str)==1) { + // up to MAX_CMD_STR characters before \n, skipping \n + s = cmd_str; + // while we get input from file, output goes to stderr + sout.rdbuf(cerr.rdbuf()); + } else { + // when there are no commands left from file or if there was no file from the beginning + cmd_file = NULL; // mark file pointer as being not valid, so any method can test this easily +#ifdef HAVE_BOOST_ASIO + s = rin(&bout); // get command string from socket or terminal #else - cerr << ": " << std::flush; - s = readline(2); // 2 is stderr, but when doing reads it reverts to stdin + cerr << ": " << std::flush; + s = readline(2); // 2 is stderr, but when doing reads it reverts to stdin #endif + } std::stringstream ss(s); std::string cmd, tmp; diff --git a/riscv/sim.cc b/riscv/sim.cc index 23852d84..317d5b4c 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -36,11 +36,11 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch, std::vector const hartids, const debug_module_config_t &dm_config, const char *log_path, - bool dtb_enabled, const char *dtb_file + bool dtb_enabled, const char *dtb_file, #ifdef HAVE_BOOST_ASIO - , io_service *io_service_ptr, tcp::acceptor *acceptor_ptr // option -s + io_service *io_service_ptr, tcp::acceptor *acceptor_ptr, // option -s #endif - ) + FILE *cmd_file) // needed for command line option --cmd : htif_t(args), mems(mems), plugin_devices(plugin_devices), @@ -52,6 +52,7 @@ sim_t::sim_t(const char* isa, const char* priv, const char* varch, dtb_file(dtb_file ? dtb_file : ""), dtb_enabled(dtb_enabled), log_file(log_path), + cmd_file(cmd_file), #ifdef HAVE_BOOST_ASIO io_service_ptr(io_service_ptr), // socket interface acceptor_ptr(acceptor_ptr), diff --git a/riscv/sim.h b/riscv/sim.h index 274361c6..cf50de5f 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -52,11 +52,11 @@ public: std::vector> plugin_devices, const std::vector& args, const std::vector hartids, const debug_module_config_t &dm_config, const char *log_path, - bool dtb_enabled, const char *dtb_file + bool dtb_enabled, const char *dtb_file, #ifdef HAVE_BOOST_ASIO - , io_service *io_service_ptr_ctor, tcp::acceptor *acceptor_ptr_ctor // option -s + io_service *io_service_ptr_ctor, tcp::acceptor *acceptor_ptr_ctor, // option -s #endif - ); + FILE *cmd_file); // needed for command line option --cmd ~sim_t(); // run the simulation to completion @@ -101,6 +101,8 @@ private: bus_t bus; log_file_t log_file; + FILE *cmd_file; // pointer to debug command input file + #ifdef HAVE_BOOST_ASIO // the following are needed for command socket interface boost::asio::io_service *io_service_ptr; diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 46d5537b..ebe3337e 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -35,6 +35,7 @@ static void help(int exit_code = 1) fprintf(stderr, " -h, --help Print this help message\n"); fprintf(stderr, " -H Start halted, allowing a debugger to connect\n"); fprintf(stderr, " --log= File name for option -l\n"); + fprintf(stderr, " --debug-cmd= Read commands from file (use with -d)\n"); fprintf(stderr, " --isa= RISC-V ISA string [default %s]\n", DEFAULT_ISA); fprintf(stderr, " --priv= RISC-V privilege modes supported [default %s]\n", DEFAULT_PRIV); fprintf(stderr, " --varch= RISC-V Vector uArch string [default %s]\n", DEFAULT_VARCH); @@ -370,6 +371,13 @@ int main(int argc, char** argv) [&](const char* s){log_commits = true;}); parser.option(0, "log", 1, [&](const char* s){log_path = s;}); + FILE *cmd_file = NULL; + parser.option(0, "debug-cmd", 1, [&](const char* s){ + if ((cmd_file = fopen(s, "r"))==NULL) { + fprintf(stderr, "Unable to open command file '%s'\n", s); + exit(-1); + } + }); auto argv1 = parser.parse(argv); std::vector htif_args(argv1, (const char*const*)argv + argc); @@ -429,11 +437,11 @@ int main(int argc, char** argv) sim_t s(isa, priv, varch, nprocs, halted, real_time_clint, initrd_start, initrd_end, bootargs, start_pc, mems, plugin_devices, htif_args, - std::move(hartids), dm_config, log_path, dtb_enabled, dtb_file + std::move(hartids), dm_config, log_path, dtb_enabled, dtb_file, #ifdef HAVE_BOOST_ASIO - , io_service_ptr, acceptor_ptr + io_service_ptr, acceptor_ptr, #endif - ); + cmd_file); std::unique_ptr remote_bitbang((remote_bitbang_t *) NULL); std::unique_ptr jtag_dtm( new jtag_dtm_t(&s.debug_module, dmi_rti));