diff options
author | Andrew Waterman <andrew@sifive.com> | 2023-02-04 18:02:19 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2023-02-04 18:12:56 -0800 |
commit | 749b03f3b86b601dee814d4299deee3e97e0e3b7 (patch) | |
tree | 090d3f7a918598efc59f6fad86c8591e6e0efd4a | |
parent | b04229ee59cbe5286478b7cfa930b9995d2bdd93 (diff) | |
download | spike-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.h | 3 | ||||
-rw-r--r-- | riscv/plic.cc | 26 | ||||
-rw-r--r-- | riscv/sim.cc | 2 |
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(); } |