aboutsummaryrefslogtreecommitdiff
path: root/riscv/clint.cc
diff options
context:
space:
mode:
authorWesley W. Terpstra <wesley@sifive.com>2017-03-22 13:57:56 -0700
committerWesley W. Terpstra <wesley@sifive.com>2017-03-22 14:21:54 -0700
commit46f1423c6566aee512fbc7a8ef6ff4aae2b7d1fb (patch)
tree1ff563929c13be279340ad439af8692d3c9913aa /riscv/clint.cc
parent693fc45eb8ccc3c9f84b898de3119a172e0776f5 (diff)
downloadspike-46f1423c6566aee512fbc7a8ef6ff4aae2b7d1fb.zip
spike-46f1423c6566aee512fbc7a8ef6ff4aae2b7d1fb.tar.gz
spike-46f1423c6566aee512fbc7a8ef6ff4aae2b7d1fb.tar.bz2
riscv: replace rtc device with a real clint implementation
Diffstat (limited to 'riscv/clint.cc')
-rw-r--r--riscv/clint.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/riscv/clint.cc b/riscv/clint.cc
new file mode 100644
index 0000000..08508b4
--- /dev/null
+++ b/riscv/clint.cc
@@ -0,0 +1,72 @@
+#include "devices.h"
+#include "processor.h"
+
+clint_t::clint_t(std::vector<processor_t*>& procs)
+ : procs(procs), mtimecmp(procs.size())
+{
+}
+
+/* 0000 msip hart 0
+ * 0004 msip hart 1
+ * 4000 mtimecmp hart 0 lo
+ * 4004 mtimecmp hart 0 hi
+ * 4008 mtimecmp hart 1 lo
+ * 400c mtimecmp hart 1 hi
+ * bff8 mtime lo
+ * bffc mtime hi
+ */
+
+#define MSIP_BASE 0x0
+#define MTIMECMP_BASE 0x4000
+#define MTIME_BASE 0xbff8
+
+bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+ if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
+ std::vector<msip_t> msip(procs.size());
+ for (size_t i = 0; i < procs.size(); ++i)
+ msip[i] = !!(procs[i]->state.mip & MIP_MSIP);
+ memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len);
+ } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
+ memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len);
+ } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
+ memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len);
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+ if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
+ std::vector<msip_t> msip(procs.size());
+ std::vector<msip_t> mask(procs.size(), 0);
+ memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len);
+ memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len);
+ for (size_t i = 0; i < procs.size(); ++i) {
+ if (!(mask[i] & 0xFF)) continue;
+ procs[i]->state.mip &= ~MIP_MSIP;
+ if (!!(msip[i] & 1))
+ procs[i]->state.mip |= MIP_MSIP;
+ }
+ } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
+ memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len);
+ } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
+ memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len);
+ } else {
+ return false;
+ }
+ increment(0);
+ return true;
+}
+
+void clint_t::increment(reg_t inc)
+{
+ mtime += inc;
+ for (size_t i = 0; i < procs.size(); i++) {
+ procs[i]->state.mip &= ~MIP_MTIP;
+ if (mtime >= mtimecmp[i])
+ procs[i]->state.mip |= MIP_MTIP;
+ }
+}