aboutsummaryrefslogtreecommitdiff
path: root/riscv/devices.h
diff options
context:
space:
mode:
authorAnup Patel <anup@brainfault.org>2021-12-14 11:25:55 +0530
committerAnup Patel <anup@brainfault.org>2022-04-20 10:20:10 +0530
commit5a433081f4ce1a49ee83d1a81cf4922e7542a20c (patch)
treec99dfe8db908caf9319c905e5bba388b3206d43a /riscv/devices.h
parentd5b1a65c0e3a0b6b46eb66d5d0284bf3a6cc1e0c (diff)
downloadspike-5a433081f4ce1a49ee83d1a81cf4922e7542a20c.zip
spike-5a433081f4ce1a49ee83d1a81cf4922e7542a20c.tar.gz
spike-5a433081f4ce1a49ee83d1a81cf4922e7542a20c.tar.bz2
Add PLIC emulation
We need an interrupt controller in Spike which will allow us to emulate more real-world devices such as UART, VirtIO net, VirtIO block, etc. The RISC-V PLIC (or SiFive PLIC) is the commonly used interrupt controller in existing RISC-V platforms so this patch adds PLIC emulation for Spike. Signed-off-by: Anup Patel <anup@brainfault.org>
Diffstat (limited to 'riscv/devices.h')
-rw-r--r--riscv/devices.h45
1 files changed, 45 insertions, 0 deletions
diff --git a/riscv/devices.h b/riscv/devices.h
index 934904a..c9e4f66 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -72,6 +72,51 @@ class clint_t : public abstract_device_t {
std::vector<mtimecmp_t> mtimecmp;
};
+#define PLIC_MAX_DEVICES 1024
+
+struct plic_context {
+ uint32_t num;
+ processor_t *proc;
+ bool mmode;
+
+ uint8_t priority_threshold;
+ uint32_t enable[PLIC_MAX_DEVICES/32];
+ uint32_t pending[PLIC_MAX_DEVICES/32];
+ uint8_t pending_priority[PLIC_MAX_DEVICES];
+ uint32_t claimed[PLIC_MAX_DEVICES/32];
+};
+typedef struct plic_context 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);
+ 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);
+ size_t size() { return PLIC_SIZE; }
+ private:
+ std::vector<processor_t*>& procs;
+ std::vector<plic_context_t> contexts;
+ uint32_t num_ids;
+ uint32_t num_ids_word;
+ uint32_t max_prio;
+ uint8_t priority[PLIC_MAX_DEVICES];
+ uint32_t level[PLIC_MAX_DEVICES/32];
+ uint32_t context_best_pending(plic_context_t *c);
+ void context_update(plic_context_t *context);
+ uint32_t context_claim(plic_context_t *c);
+ bool priority_read(reg_t offset, uint32_t *val);
+ bool priority_write(reg_t offset, uint32_t val);
+ bool context_enable_read(plic_context_t *context,
+ reg_t offset, uint32_t *val);
+ bool context_enable_write(plic_context_t *context,
+ reg_t offset, uint32_t val);
+ bool context_read(plic_context_t *context,
+ reg_t offset, uint32_t *val);
+ bool context_write(plic_context_t *context,
+ reg_t offset, uint32_t val);
+};
+
class mmio_plugin_device_t : public abstract_device_t {
public:
mmio_plugin_device_t(const std::string& name, const std::string& args);