aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-02-04 18:02:19 -0800
committerAndrew Waterman <andrew@sifive.com>2023-02-04 18:12:56 -0800
commit749b03f3b86b601dee814d4299deee3e97e0e3b7 (patch)
tree090d3f7a918598efc59f6fad86c8591e6e0efd4a
parentb04229ee59cbe5286478b7cfa930b9995d2bdd93 (diff)
downloadspike-749b03f3b86b601dee814d4299deee3e97e0e3b7.zip
spike-749b03f3b86b601dee814d4299deee3e97e0e3b7.tar.gz
spike-749b03f3b86b601dee814d4299deee3e97e0e3b7.tar.bz2
Correctly instantiate PLIC contexts for mixed-hart targets
This commit started as an attempt to make the PLIC tolerant of discontiguous hart IDs, but it turns out it was already most of the way there: PLIC contexts can still be dense even if the hart IDs are not. Nevertheless, I wanted to avoid passing the procs vector directly to the plic_t constructor. In removing it, I realized I could also get rid of the smode parameter by querying whether each hart has S-mode. This is also more correct; previously, we were instantiating the PLIC as though all harts had S-mode, regardless of whether they actually did.
-rw-r--r--riscv/devices.h3
-rw-r--r--riscv/plic.cc26
-rw-r--r--riscv/sim.cc2
3 files changed, 20 insertions, 11 deletions
diff --git a/riscv/devices.h b/riscv/devices.h
index 53db96a..6facaa3 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -12,6 +12,7 @@
#include <utility>
class processor_t;
+class sim_t;
class bus_t : public abstract_device_t {
public:
@@ -91,7 +92,7 @@ struct plic_context_t {
class plic_t : public abstract_device_t, public abstract_interrupt_controller_t {
public:
- plic_t(std::vector<processor_t*>&, bool smode, uint32_t ndev);
+ plic_t(sim_t*, uint32_t ndev);
bool load(reg_t addr, size_t len, uint8_t* bytes);
bool store(reg_t addr, size_t len, const uint8_t* bytes);
void set_interrupt_level(uint32_t id, int lvl);
diff --git a/riscv/plic.cc b/riscv/plic.cc
index e070c9e..64041b7 100644
--- a/riscv/plic.cc
+++ b/riscv/plic.cc
@@ -1,6 +1,7 @@
#include <sys/time.h>
#include "devices.h"
#include "processor.h"
+#include "sim.h"
#define PLIC_MAX_CONTEXTS 15872
@@ -66,11 +67,8 @@
#define REG_SIZE 0x1000000
-plic_t::plic_t(std::vector<processor_t*>& procs, bool smode, uint32_t ndev)
- : contexts(procs.size() * (smode ? 2 : 1))
+plic_t::plic_t(sim_t* sim, uint32_t ndev)
{
- size_t contexts_per_hart = smode ? 2 : 1;
-
num_ids = ndev + 1;
num_ids_word = num_ids / 32;
if ((num_ids_word * 32) < num_ids)
@@ -79,11 +77,21 @@ plic_t::plic_t(std::vector<processor_t*>& procs, bool smode, uint32_t ndev)
memset(priority, 0, sizeof(priority));
memset(level, 0, sizeof(level));
- for (size_t i = 0; i < contexts.size(); i++) {
- plic_context_t* c = &contexts[i];
- memset(c, 0, sizeof(*c));
- c->proc = procs[i / contexts_per_hart];
- c->mmode = (i % contexts_per_hart == 0);
+ // PLIC contexts are contiguous in memory even if harts are discontiguous.
+ for (const auto& [hart_id, hart] : sim->get_harts()) {
+ contexts.push_back(plic_context_t());
+ plic_context_t* m_context = &contexts.back();
+ memset(m_context, 0, sizeof(*m_context));
+ m_context->proc = hart;
+ m_context->mmode = true;
+
+ if (hart->extension_enabled_const('S')) {
+ contexts.push_back(plic_context_t());
+ plic_context_t* s_context = &contexts.back();
+ memset(s_context, 0, sizeof(*s_context));
+ s_context->proc = hart;
+ s_context->mmode = false;
+ }
}
}
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 274a7c2..4e5e9a7 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -127,7 +127,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
reg_t plic_base;
uint32_t plic_ndev;
if (fdt_parse_plic(fdt, &plic_base, &plic_ndev, "riscv,plic0") == 0) {
- plic.reset(new plic_t(procs, true, plic_ndev));
+ plic.reset(new plic_t(this, plic_ndev));
bus.add_device(plic_base, plic.get());
intctrl = plic.get();
}