aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-02-04 17:23:49 -0800
committerAndrew Waterman <andrew@sifive.com>2023-02-04 17:23:49 -0800
commit2f5112f9dd94e0870f37711f3d99df4bfa6461d0 (patch)
treea0072400dd50b3a7e27fcbe41baf778b512b6ed7
parentdb65d052a89b85ee3be89fe5ea761e1752aaaad2 (diff)
downloadspike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.zip
spike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.tar.gz
spike-2f5112f9dd94e0870f37711f3d99df4bfa6461d0.tar.bz2
Add sim_t::get_harts accessor
-rw-r--r--riscv/cfg.h1
-rw-r--r--riscv/debug_module.cc44
-rw-r--r--riscv/debug_module.h1
-rw-r--r--riscv/sim.cc1
-rw-r--r--riscv/sim.h5
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;