diff --git a/riscv/cfg.cc b/riscv/cfg.cc index 794e9555..e546fca3 100644 --- a/riscv/cfg.cc +++ b/riscv/cfg.cc @@ -48,3 +48,24 @@ cfg_t::cfg_t() trigger_count = 4; cache_blocksz = 64; } + +void start_pc_t::set_global(reg_t pc) +{ + global_pc = pc; +} + +void start_pc_t::set_override(size_t hart_id, reg_t pc) +{ + hart_pcs[hart_id] = pc; +} + +std::optional start_pc_t::get(size_t hart_id) const +{ + auto it = hart_pcs.find(hart_id); + + if (it != hart_pcs.end()) { + return it->second; + } else { + return global_pc; + } +} diff --git a/riscv/cfg.h b/riscv/cfg.h index 779634e9..ea3219ad 100644 --- a/riscv/cfg.h +++ b/riscv/cfg.h @@ -6,6 +6,7 @@ #include #include "decode.h" #include +#include class abstract_sim_if_t; typedef enum { @@ -59,6 +60,20 @@ private: reg_t size; }; +class start_pc_t +{ +public: + void set_global(reg_t pc); + + void set_override(size_t hart_id, reg_t pc); + + std::optional get(size_t hart_id) const; + +private: + std::optional global_pc; + std::map hart_pcs; +}; + class cfg_t { public: @@ -72,7 +87,7 @@ public: reg_t pmpregions; reg_t pmpgranularity; std::vector mem_layout; - std::optional start_pc; + start_pc_t start_pc; std::vector hartids; bool explicit_hartids; bool real_time_clint; diff --git a/riscv/sim.cc b/riscv/sim.cc index ca20cbf8..856e54b3 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -106,6 +106,14 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, log_file.get(), sout_)); harts[cfg->hartids[i]] = procs[i]; } + for (auto& x : this->mems) { + bus.add_device(x.first, x.second); + } + for (auto& pair : harts) { + if (auto pc = cfg->start_pc.get(pair.first)) { + pair.second->get_state()->pc = *pc; + } + } return; } // otherwise, generate the procs by parsing the DTS @@ -246,15 +254,15 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, dtb_discovery_plugin_device_factories.end()); //Remove default memories and use dtb discovered memories - mems.clear(); - dtb_discovery::discover_memory_from_dtb(fdt, mems); + this->mems.clear(); + dtb_discovery::discover_memory_from_dtb(fdt, this->mems); } //clint, plic, ns16550 are always discovered via dtb, independently from the --dtb_discovery flag device_factories.insert(device_factories.end(), plugin_device_factories.begin(), plugin_device_factories.end()); - for (auto& x : mems) + for (auto& x : this->mems) { bus.add_device(x.first, x.second); } @@ -281,6 +289,12 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, } } } + + for (auto& pair : harts) { + if (auto pc = cfg->start_pc.get(pair.first)) { + pair.second->get_state()->pc = *pc; + } + } } sim_t::~sim_t() @@ -380,7 +394,7 @@ void sim_t::set_rom() { const int reset_vec_size = 8; - reg_t start_pc = cfg->start_pc.value_or(get_entry_point()); + reg_t start_pc = cfg->start_pc.get(0).value_or(get_entry_point()); uint32_t reset_vec[reset_vec_size] = { 0x297, // auipc t0,0x0 @@ -499,4 +513,9 @@ endianness_t sim_t::get_target_endianness() const void sim_t::proc_reset(unsigned id) { debug_module.proc_reset(id); + if (harts.count(id)) { + if (auto pc = cfg->start_pc.get(id)) { + harts[id]->get_state()->pc = *pc; + } + } } diff --git a/spike_main/spike.cc b/spike_main/spike.cc index f62d1daf..56c041d1 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "../VERSION" static void help(int exit_code = 1) @@ -46,6 +47,7 @@ static void help(int exit_code = 1) fprintf(stderr, " --pmpgranularity= PMP Granularity in bytes [default 4]\n"); fprintf(stderr, " --priv= RISC-V privilege modes supported [default %s]\n", DEFAULT_PRIV); fprintf(stderr, " --pc=
Override ELF entry point\n"); + fprintf(stderr, " --pcs= Override start PC for specific harts\n"); fprintf(stderr, " --hartids= Explicitly specify hartids, default is 0,1,...\n"); fprintf(stderr, " --ic=:: Instantiate a cache model with S sets,\n"); fprintf(stderr, " --dc=:: W ways, and B-byte blocks (with S and\n"); @@ -383,7 +385,24 @@ int main(int argc, char** argv) parser.option('m', 0, 1, [&](const char* s){cfg.mem_layout = parse_mem_layout(s); memory_option=true; }); parser.option(0, "halted", 0, [&](const char UNUSED *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){cfg.start_pc = strtoull(s, 0, 0);}); + parser.option(0, "pc", 1, [&](const char* s){cfg.start_pc.set_global(strtoull(s, 0, 0));}); + + parser.option(0, "pcs", 1, [&](const char* s){ + std::string arg(s); + std::stringstream ss(arg); + std::string pair; + while (std::getline(ss, pair, ',')) { + size_t delim = pair.find(':'); + if (delim == std::string::npos) { + fprintf(stderr, "Error: --pcs format is hartid:addr,hartid:addr\n"); + exit(1); + } + size_t hartid = std::strtoull(pair.substr(0, delim).c_str(), 0, 0); + reg_t addr = std::strtoull(pair.substr(delim+1).c_str(), 0, 0); + cfg.start_pc.set_override(hartid, addr); + } + }); + parser.option(0, "hartids", 1, [&](const char* s){ cfg.hartids = parse_hartids(s); cfg.explicit_hartids = true;