diff --git a/riscv/cfg.h b/riscv/cfg.h index e844738b..6369bd84 100644 --- a/riscv/cfg.h +++ b/riscv/cfg.h @@ -2,6 +2,7 @@ #ifndef _RISCV_CFG_H #define _RISCV_CFG_H +#include #include "decode.h" #include "mmu.h" #include @@ -53,23 +54,35 @@ class cfg_t { public: cfg_t(std::pair default_initrd_bounds, - const char *default_bootargs, size_t default_nprocs, + const char *default_bootargs, const char *default_isa, const char *default_priv, - const std::vector &default_mem_layout) + const char *default_varch, + const std::vector &default_mem_layout, + const std::vector default_hartids, + bool default_real_time_clint) : initrd_bounds(default_initrd_bounds), bootargs(default_bootargs), - nprocs(default_nprocs), isa(default_isa), priv(default_priv), - mem_layout(default_mem_layout) + varch(default_varch), + mem_layout(default_mem_layout), + hartids(default_hartids), + explicit_hartids(false), + real_time_clint(default_real_time_clint) {} cfg_arg_t> initrd_bounds; cfg_arg_t bootargs; - cfg_arg_t nprocs; cfg_arg_t isa; cfg_arg_t priv; + cfg_arg_t varch; cfg_arg_t> mem_layout; + std::optional start_pc; + cfg_arg_t> hartids; + bool explicit_hartids; + cfg_arg_t real_time_clint; + + size_t nprocs() const { return hartids().size(); } }; #endif diff --git a/riscv/sim.cc b/riscv/sim.cc index be608647..069e1b51 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -28,11 +28,10 @@ static void handle_signal(int sig) signal(sig, &handle_signal); } -sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_clint, - reg_t start_pc, std::vector> mems, +sim_t::sim_t(const cfg_t *cfg, bool halted, + std::vector> mems, std::vector> plugin_devices, const std::vector& args, - std::vector const hartids, const debug_module_config_t &dm_config, const char *log_path, bool dtb_enabled, const char *dtb_file, @@ -46,7 +45,6 @@ sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_cl mems(mems), plugin_devices(plugin_devices), procs(std::max(cfg->nprocs(), size_t(1))), - start_pc(start_pc), dtb_file(dtb_file ? dtb_file : ""), dtb_enabled(dtb_enabled), log_file(log_path), @@ -78,17 +76,8 @@ sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_cl debug_mmu = new mmu_t(this, NULL); - if (! (hartids.empty() || hartids.size() == nprocs())) { - std::cerr << "Number of specified hartids (" - << hartids.size() - << ") doesn't match number of processors (" - << nprocs() << ").\n"; - exit(1); - } - - for (size_t i = 0; i < nprocs(); i++) { - int hart_id = hartids.empty() ? i : hartids[i]; - procs[i] = new processor_t(&isa, varch, this, hart_id, halted, + for (size_t i = 0; i < cfg->nprocs(); i++) { + procs[i] = new processor_t(&isa, cfg->varch(), this, cfg->hartids()[i], halted, log_file.get(), sout_); } @@ -105,7 +94,7 @@ sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_cl // setting the dtb_file argument has one. reg_t clint_base; if (fdt_parse_clint(fdt, &clint_base, "riscv,clint0") == 0) { - clint.reset(new clint_t(procs, CPU_HZ / INSNS_PER_RTC_TICK, real_time_clint)); + clint.reset(new clint_t(procs, CPU_HZ / INSNS_PER_RTC_TICK, cfg->real_time_clint())); bus.add_device(clint_base, clint.get()); } @@ -129,7 +118,7 @@ sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_cl procs[cpu_idx]->set_pmp_num(pmp_num); } else { std::cerr << "core (" - << hartids.size() + << cpu_idx << ") doesn't have valid 'riscv,pmpregions'" << pmp_num << ").\n"; exit(1); @@ -159,7 +148,7 @@ sim_t::sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_cl //has been set in the beginning } else { std::cerr << "core (" - << hartids.size() + << cpu_idx << ") has an invalid 'mmu-type': " << mmu_type << ").\n"; exit(1); @@ -334,7 +323,7 @@ void sim_t::set_rom() { const int reset_vec_size = 8; - start_pc = start_pc == reg_t(-1) ? get_entry_point() : start_pc; + reg_t start_pc = cfg->start_pc.value_or(get_entry_point()); uint32_t reset_vec[reset_vec_size] = { 0x297, // auipc t0,0x0 diff --git a/riscv/sim.h b/riscv/sim.h index fc20a2c8..97cada13 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -32,10 +32,10 @@ class remote_bitbang_t; class sim_t : public htif_t, public simif_t { public: - sim_t(const cfg_t *cfg, const char* varch, bool halted, bool real_time_clint, - reg_t start_pc, std::vector> mems, + sim_t(const cfg_t *cfg, bool halted, + std::vector> mems, std::vector> plugin_devices, - const std::vector& args, const std::vector hartids, + const std::vector& args, const debug_module_config_t &dm_config, const char *log_path, bool dtb_enabled, const char *dtb_file, #ifdef HAVE_BOOST_ASIO @@ -76,7 +76,6 @@ private: mmu_t* debug_mmu; // debug port into main memory std::vector procs; std::pair initrd_range; - reg_t start_pc; std::string dts; std::string dtb; std::string dtb_file; diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 3080efbd..55290452 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -220,6 +220,21 @@ static unsigned long atoul_nonzero_safe(const char* s) return res; } +static std::vector parse_hartids(const char *s) +{ + std::string const str(s); + std::stringstream stream(str); + std::vector hartids; + + int n; + while (stream >> n) { + hartids.push_back(n); + if (stream.peek() == ',') stream.ignore(); + } + + return hartids; +} + int main(int argc, char** argv) { bool debug = false; @@ -229,10 +244,8 @@ int main(int argc, char** argv) bool socket = false; // command line option -s bool dump_dts = false; bool dtb_enabled = true; - bool real_time_clint = false; const char* kernel = NULL; reg_t kernel_offset, kernel_size; - reg_t start_pc = reg_t(-1); std::vector> plugin_devices; std::unique_ptr ic; std::unique_ptr dc; @@ -242,7 +255,6 @@ int main(int argc, char** argv) const char *log_path = nullptr; std::vector> extensions; const char* initrd = NULL; - const char* varch = DEFAULT_VARCH; const char* dtb_file = NULL; uint16_t rbb_port = 0; bool use_rbb = false; @@ -258,25 +270,16 @@ int main(int argc, char** argv) .support_haltgroups = true, .support_impebreak = true }; - std::vector hartids; + cfg_arg_t nprocs(1); + cfg_t cfg(/*default_initrd_bounds=*/std::make_pair((reg_t)0, (reg_t)0), /*default_bootargs=*/nullptr, - /*default_nprocs=*/1, /*default_isa=*/DEFAULT_ISA, /*default_priv=*/DEFAULT_PRIV, - /*default_mem_layout=*/parse_mem_layout("2048")); - - auto const hartids_parser = [&](const char *s) { - std::string const str(s); - std::stringstream stream(str); - - int n; - while (stream >> n) - { - hartids.push_back(n); - if (stream.peek() == ',') stream.ignore(); - } - }; + /*default_varch=*/DEFAULT_VARCH, + /*default_mem_layout=*/parse_mem_layout("2048"), + /*default_hartids=*/std::vector(), + /*default_real_time_clint=*/false); auto const device_parser = [&plugin_devices](const char *s) { const std::string str(s); @@ -330,20 +333,23 @@ int main(int argc, char** argv) #ifdef HAVE_BOOST_ASIO parser.option('s', 0, 0, [&](const char* s){socket = true;}); #endif - parser.option('p', 0, 1, [&](const char* s){cfg.nprocs = atoul_nonzero_safe(s);}); + parser.option('p', 0, 1, [&](const char* s){nprocs = atoul_nonzero_safe(s);}); parser.option('m', 0, 1, [&](const char* s){cfg.mem_layout = parse_mem_layout(s);}); // I wanted to use --halted, but for some reason that doesn't work. parser.option('H', 0, 0, [&](const char* s){halted = true;}); parser.option(0, "rbb-port", 1, [&](const char* s){use_rbb = true; rbb_port = atoul_safe(s);}); - parser.option(0, "pc", 1, [&](const char* s){start_pc = strtoull(s, 0, 0);}); - parser.option(0, "hartids", 1, hartids_parser); + parser.option(0, "pc", 1, [&](const char* s){cfg.start_pc = strtoull(s, 0, 0);}); + parser.option(0, "hartids", 1, [&](const char* s){ + cfg.hartids = parse_hartids(s); + cfg.explicit_hartids = true; + }); parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));}); parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));}); parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));}); parser.option(0, "log-cache-miss", 0, [&](const char* s){log_cache = true;}); parser.option(0, "isa", 1, [&](const char* s){cfg.isa = s;}); parser.option(0, "priv", 1, [&](const char* s){cfg.priv = s;}); - parser.option(0, "varch", 1, [&](const char* s){varch = s;}); + parser.option(0, "varch", 1, [&](const char* s){cfg.varch = s;}); parser.option(0, "device", 1, device_parser); parser.option(0, "extension", 1, [&](const char* s){extensions.push_back(find_extension(s));}); parser.option(0, "dump-dts", 0, [&](const char *s){dump_dts = true;}); @@ -352,7 +358,7 @@ int main(int argc, char** argv) parser.option(0, "kernel", 1, [&](const char* s){kernel = s;}); parser.option(0, "initrd", 1, [&](const char* s){initrd = s;}); parser.option(0, "bootargs", 1, [&](const char* s){cfg.bootargs = s;}); - parser.option(0, "real-time-clint", 0, [&](const char *s){real_time_clint = true;}); + parser.option(0, "real-time-clint", 0, [&](const char *s){cfg.real_time_clint = true;}); parser.option(0, "extlib", 1, [&](const char *s){ void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL); if (lib == NULL) { @@ -456,9 +462,28 @@ int main(int argc, char** argv) } #endif - sim_t s(&cfg, varch, halted, real_time_clint, - start_pc, mems, plugin_devices, htif_args, - std::move(hartids), dm_config, log_path, dtb_enabled, dtb_file, + if (cfg.explicit_hartids) { + if (nprocs.overridden() && (nprocs() != cfg.nprocs())) { + std::cerr << "Number of specified hartids (" + << cfg.nprocs() + << ") doesn't match specified number of processors (" + << nprocs() << ").\n"; + exit(1); + } + } else { + // Set default set of hartids based on nprocs, but don't set the + // explicit_hartids flag (which means that downstream code can know that + // we've only set the number of harts, not explicitly chosen their IDs). + std::vector default_hartids; + default_hartids.reserve(nprocs()); + for (size_t i = 0; i < nprocs(); ++i) { + default_hartids.push_back(i); + } + cfg.hartids = default_hartids; + } + + sim_t s(&cfg, halted, + mems, plugin_devices, htif_args, dm_config, log_path, dtb_enabled, dtb_file, #ifdef HAVE_BOOST_ASIO io_service_ptr, acceptor_ptr, #endif