aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-02-05 16:02:30 -0800
committerAndrew Waterman <andrew@sifive.com>2023-02-05 16:02:30 -0800
commit456c9e19d811ddc5da99974a40ee79a6f535a597 (patch)
tree3bd813365ea097bdee34d25871f4e1bf6e76ac48
parente85f86695092f1377a515c94de5c706bcff1f2bd (diff)
downloadspike-plic-clint-endian.zip
spike-plic-clint-endian.tar.gz
spike-plic-clint-endian.tar.bz2
Make clint tolerant of discontiguous hart IDsplic-clint-endian
-rw-r--r--riscv/clint.cc37
-rw-r--r--riscv/devices.h6
-rw-r--r--riscv/sim.cc2
3 files changed, 26 insertions, 19 deletions
diff --git a/riscv/clint.cc b/riscv/clint.cc
index 056aa00..338e7a3 100644
--- a/riscv/clint.cc
+++ b/riscv/clint.cc
@@ -1,9 +1,10 @@
#include <sys/time.h>
#include "devices.h"
#include "processor.h"
+#include "sim.h"
-clint_t::clint_t(std::vector<processor_t*>& procs, uint64_t freq_hz, bool real_time)
- : procs(procs), freq_hz(freq_hz), real_time(real_time), mtime(0), mtimecmp(procs.size())
+clint_t::clint_t(sim_t* sim, uint64_t freq_hz, bool real_time)
+ : sim(sim), freq_hz(freq_hz), real_time(real_time), mtime(0)
{
struct timeval base;
@@ -11,6 +12,8 @@ clint_t::clint_t(std::vector<processor_t*>& procs, uint64_t freq_hz, bool real_t
real_time_ref_secs = base.tv_sec;
real_time_ref_usecs = base.tv_usec;
+
+ increment(0); // initializes mtimecmp as a side effect
}
/* 0000 msip hart 0
@@ -53,19 +56,21 @@ bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
increment(0);
const auto msip_hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
+ const auto msip_hart_iter = sim->get_harts().find(msip_hart_id);
const auto mtimecmp_hart_id = (addr - MTIMECMP_BASE) / sizeof(mtimecmp_t);
+ const auto mtimecmp_iter = mtimecmp.find(mtimecmp_hart_id);
- if (addr >= MSIP_BASE && msip_hart_id < procs.size()) {
+ if (addr >= MSIP_BASE && msip_hart_iter != sim->get_harts().end()) {
if (len == 8) {
// Implement double-word loads as a pair of word loads
return load(addr, 4, bytes) && load(addr + 4, 4, bytes + 4);
}
- msip_t res = !!(procs[msip_hart_id]->state.mip->read() & MIP_MSIP);
+ msip_t res = !!(msip_hart_iter->second->state.mip->read() & MIP_MSIP);
partial_read(res, addr, len, bytes);
return true;
- } else if (addr >= MTIMECMP_BASE && mtimecmp_hart_id < procs.size()) {
- partial_read(mtimecmp[mtimecmp_hart_id], addr, len, bytes);
+ } else if (addr >= MTIMECMP_BASE && mtimecmp_iter != mtimecmp.end()) {
+ partial_read(mtimecmp_iter->second, addr, len, bytes);
} else if (addr >= MTIME_BASE && addr < MTIME_BASE + sizeof(mtime_t)) {
partial_read(mtime, addr, len, bytes);
} else if (addr + len <= CLINT_SIZE) {
@@ -82,18 +87,20 @@ bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
return false;
const auto msip_hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
+ const auto msip_hart_iter = sim->get_harts().find(msip_hart_id);
const auto mtimecmp_hart_id = (addr - MTIMECMP_BASE) / sizeof(mtimecmp_t);
+ const auto mtimecmp_iter = mtimecmp.find(mtimecmp_hart_id);
- if (addr >= MSIP_BASE && msip_hart_id < procs.size()) {
+ if (addr >= MSIP_BASE && msip_hart_iter != sim->get_harts().end()) {
if (len == 8) {
// Implement double-word stores as a pair of word stores
return store(addr, 4, bytes) && store(addr + 4, 4, bytes + 4);
}
if (addr % sizeof(msip_t) == 0)
- procs[msip_hart_id]->state.mip->backdoor_write_with_mask(MIP_MSIP, bytes[0] & 1 ? MIP_MSIP : 0);
- } else if (addr >= MTIMECMP_BASE && mtimecmp_hart_id < procs.size()) {
- partial_write(&mtimecmp[mtimecmp_hart_id], addr, len, bytes);
+ msip_hart_iter->second->state.mip->backdoor_write_with_mask(MIP_MSIP, bytes[0] & 1 ? MIP_MSIP : 0);
+ } else if (addr >= MTIMECMP_BASE && mtimecmp_iter != mtimecmp.end()) {
+ partial_write(&mtimecmp_iter->second, addr, len, bytes);
} else if (addr >= MTIME_BASE && addr < MTIME_BASE + sizeof(mtime_t)) {
partial_write(&mtime, addr, len, bytes);
} else if (addr + len <= CLINT_SIZE) {
@@ -117,10 +124,10 @@ void clint_t::increment(reg_t inc)
} else {
mtime += inc;
}
- for (size_t i = 0; i < procs.size(); i++) {
- procs[i]->state.time->sync(mtime);
- procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, 0);
- if (mtime >= mtimecmp[i])
- procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
+ for (const auto& [hart_id, hart] : sim->get_harts()) {
+ hart->state.time->sync(mtime);
+ hart->state.mip->backdoor_write_with_mask(MIP_MTIP, 0);
+ if (mtime >= mtimecmp[hart_id])
+ hart->state.mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
}
}
diff --git a/riscv/devices.h b/riscv/devices.h
index 6facaa3..eaa2f7a 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -57,7 +57,7 @@ class mem_t : public abstract_device_t {
class clint_t : public abstract_device_t {
public:
- clint_t(std::vector<processor_t*>&, uint64_t freq_hz, bool real_time);
+ clint_t(sim_t* sim, uint64_t freq_hz, bool real_time);
bool load(reg_t addr, size_t len, uint8_t* bytes);
bool store(reg_t addr, size_t len, const uint8_t* bytes);
size_t size() { return CLINT_SIZE; }
@@ -68,13 +68,13 @@ class clint_t : public abstract_device_t {
typedef uint64_t mtime_t;
typedef uint64_t mtimecmp_t;
typedef uint32_t msip_t;
- std::vector<processor_t*>& procs;
+ sim_t* sim;
uint64_t freq_hz;
bool real_time;
uint64_t real_time_ref_secs;
uint64_t real_time_ref_usecs;
mtime_t mtime;
- std::vector<mtimecmp_t> mtimecmp;
+ std::map<size_t, mtimecmp_t> mtimecmp;
};
#define PLIC_MAX_DEVICES 1024
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 4e5e9a7..114151a 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -116,7 +116,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
// setting the dtb_file argument has one.
reg_t clint_base;
if (fdt_parse_clint(fdt, &clint_base, "riscv,clint0") == 0) {
- clint.reset(new clint_t(procs, CPU_HZ / INSNS_PER_RTC_TICK, cfg->real_time_clint()));
+ clint.reset(new clint_t(this, CPU_HZ / INSNS_PER_RTC_TICK, cfg->real_time_clint()));
bus.add_device(clint_base, clint.get());
}