diff options
author | Andrew Waterman <andrew@sifive.com> | 2023-02-04 17:23:49 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2023-02-04 17:23:49 -0800 |
commit | 2f5112f9dd94e0870f37711f3d99df4bfa6461d0 (patch) | |
tree | a0072400dd50b3a7e27fcbe41baf778b512b6ed7 | |
parent | db65d052a89b85ee3be89fe5ea761e1752aaaad2 (diff) | |
download | spike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.zip spike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.tar.gz spike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.tar.bz2 |
Add sim_t::get_harts accessor
-rw-r--r-- | riscv/cfg.h | 1 | ||||
-rw-r--r-- | riscv/debug_module.cc | 44 | ||||
-rw-r--r-- | riscv/debug_module.h | 1 | ||||
-rw-r--r-- | riscv/sim.cc | 1 | ||||
-rw-r--r-- | riscv/sim.h | 5 |
5 files changed, 29 insertions, 23 deletions
diff --git a/riscv/cfg.h b/riscv/cfg.h index 58c792c..f6d231e 100644 --- a/riscv/cfg.h +++ b/riscv/cfg.h @@ -103,6 +103,7 @@ public: reg_t trigger_count; size_t nprocs() const { return hartids().size(); } + size_t max_hartid() const { return hartids().back(); } }; #endif diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc index e5b86e6..fb049a1 100644 --- a/riscv/debug_module.cc +++ b/riscv/debug_module.cc @@ -32,18 +32,17 @@ static unsigned field_width(unsigned n) ///////////////////////// debug_module_t debug_module_t::debug_module_t(sim_t *sim, const debug_module_config_t &config) : - nprocs(sim->nprocs()), config(config), program_buffer_bytes((config.support_impebreak ? 4 : 0) + 4*config.progbufsize), debug_progbuf_start(debug_data_start - program_buffer_bytes), debug_abstract_start(debug_progbuf_start - debug_abstract_size*4), custom_base(0), - hartsellen(field_width(sim->nprocs())), + hartsellen(field_width(sim->get_cfg().max_hartid() + 1)), sim(sim), // The spec lets a debugger select nonexistent harts. Create hart_state for // them because I'm too lazy to add the code to just ignore accesses. - hart_state(1 << field_width(sim->nprocs())), - hart_array_mask(sim->nprocs()), + hart_state(1 << field_width(sim->get_cfg().max_hartid() + 1)), + hart_array_mask(sim->get_cfg().max_hartid() + 1), rti_remaining(0) { D(fprintf(stderr, "debug_data_start=0x%x\n", debug_data_start)); @@ -51,9 +50,9 @@ debug_module_t::debug_module_t(sim_t *sim, const debug_module_config_t &config) D(fprintf(stderr, "debug_abstract_start=0x%x\n", debug_abstract_start)); const unsigned max_procs = 1024; - if (nprocs > max_procs) { - fprintf(stderr, "At most %u processors are supported (%u requested)\n", - max_procs, nprocs); + if (sim->get_cfg().max_hartid() >= max_procs) { + fprintf(stderr, "Hart IDs must not exceed %u (%zu harts with max hart ID %zu requested)\n", + max_procs - 1, sim->get_cfg().nprocs(), sim->get_cfg().max_hartid()); exit(1); } @@ -85,9 +84,8 @@ debug_module_t::~debug_module_t() void debug_module_t::reset() { - assert(sim->nprocs() > 0); - for (unsigned i = 0; i < sim->nprocs(); i++) { - processor_t *proc = sim->get_core(i); + for (unsigned i = 0; i < hart_array_mask.size(); i++) { + processor_t *proc = processor(i); if (proc) proc->halt_request = proc->HR_NONE; } @@ -208,11 +206,12 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes) if (!hart_state[id].halted) { hart_state[id].halted = true; if (hart_state[id].haltgroup) { - for (unsigned i = 0; i < nprocs; i++) { + for (unsigned i = 0; i < hart_array_mask.size(); i++) { if (!hart_state[i].halted && hart_state[i].haltgroup == hart_state[id].haltgroup) { - processor_t *proc = sim->get_core(i); - proc->halt_request = proc->HR_GROUP; + processor_t *proc = processor(i); + if (proc) + proc->halt_request = proc->HR_GROUP; // TODO: What if the debugger comes and writes dmcontrol before the // halt occurs? } @@ -412,7 +411,7 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value) dmstatus.allnonexistant = true; dmstatus.allresumeack = true; dmstatus.anyresumeack = false; - for (unsigned i = 0; i < nprocs; i++) { + for (unsigned i = 0; i < hart_array_mask.size(); i++) { if (hart_selected(i)) { dmstatus.allnonexistant = false; if (hart_state[i].resumeack) { @@ -433,7 +432,7 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value) // We don't allow selecting non-existant harts through // hart_array_mask, so the only way it's possible is by writing a // non-existant hartsel. - dmstatus.anynonexistant = (dmcontrol.hartsel >= nprocs); + dmstatus.anynonexistant = processor(dmcontrol.hartsel) == nullptr; dmstatus.allunavail = false; dmstatus.anyunavail = false; @@ -487,7 +486,7 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value) unsigned base = hawindowsel * 32; for (unsigned i = 0; i < 32; i++) { unsigned n = base + i; - if (n < nprocs && hart_array_mask[n]) { + if (n < hart_array_mask.size() && hart_array_mask[n]) { result |= 1 << i; } } @@ -809,7 +808,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) DM_DMCONTROL_HARTSELLO_LENGTH; dmcontrol.hartsel |= get_field(value, DM_DMCONTROL_HARTSELLO); dmcontrol.hartsel &= (1L<<hartsellen) - 1; - for (unsigned i = 0; i < nprocs; i++) { + for (unsigned i = 0; i < hart_array_mask.size(); i++) { if (hart_selected(i)) { if (get_field(value, DM_DMCONTROL_ACKHAVERESET)) { hart_state[i].havereset = false; @@ -833,9 +832,10 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) } if (dmcontrol.ndmreset) { - for (size_t i = 0; i < sim->nprocs(); i++) { - processor_t *proc = sim->get_core(i); - proc->reset(); + for (size_t i = 0; i < hart_array_mask.size(); i++) { + processor_t *proc = processor(i); + if (proc) + proc->reset(); } } } @@ -846,7 +846,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) return perform_abstract_command(); case DM_HAWINDOWSEL: - hawindowsel = value & ((1U<<field_width(nprocs))-1); + hawindowsel = value & ((1U<<field_width(hart_array_mask.size()))-1); return true; case DM_HAWINDOW: @@ -854,7 +854,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value) unsigned base = hawindowsel * 32; for (unsigned i = 0; i < 32; i++) { unsigned n = base + i; - if (n < nprocs) { + if (n < hart_array_mask.size()) { hart_array_mask[n] = (value >> i) & 1; } } diff --git a/riscv/debug_module.h b/riscv/debug_module.h index 51f3b84..b837bfc 100644 --- a/riscv/debug_module.h +++ b/riscv/debug_module.h @@ -132,7 +132,6 @@ class debug_module_t : public abstract_device_t private: static const unsigned datasize = 2; - unsigned nprocs; debug_module_config_t config; // Actual size of the program buffer, which is 1 word bigger than we let on // to implement the implicit ebreak at the end. diff --git a/riscv/sim.cc b/riscv/sim.cc index 051a483..274a7c2 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -100,6 +100,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, for (size_t i = 0; i < cfg->nprocs(); i++) { procs[i] = new processor_t(&isa, cfg, this, cfg->hartids()[i], halted, log_file.get(), sout_); + harts[cfg->hartids()[i]] = procs[i]; } make_dtb(); diff --git a/riscv/sim.h b/riscv/sim.h index 350d82f..cf81002 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -12,6 +12,7 @@ #include <fesvr/htif.h> #include <vector> +#include <map> #include <string> #include <memory> #include <sys/types.h> @@ -51,8 +52,11 @@ public: } const char* get_dts() { if (dts.empty()) reset(); return dts.c_str(); } processor_t* get_core(size_t i) { return procs.at(i); } + const cfg_t &get_cfg() { return *cfg; } unsigned nprocs() const { return procs.size(); } + const std::map<size_t, processor_t*>& get_harts() { return harts; } + // Callback for processors to let the simulation know they were reset. void proc_reset(unsigned id); @@ -63,6 +67,7 @@ private: std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices; mmu_t* debug_mmu; // debug port into main memory std::vector<processor_t*> procs; + std::map<size_t, processor_t*> harts; std::pair<reg_t, reg_t> initrd_range; std::string dts; std::string dtb; |