From 46f1423c6566aee512fbc7a8ef6ff4aae2b7d1fb Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 22 Mar 2017 13:57:56 -0700 Subject: [PATCH] riscv: replace rtc device with a real clint implementation --- riscv/clint.cc | 72 +++++++++++++++++++++++++++++++++++++++++++++++ riscv/devices.h | 13 +++++---- riscv/encoding.h | 2 ++ riscv/processor.h | 2 +- riscv/riscv.mk.in | 2 +- riscv/rtc.cc | 34 ---------------------- riscv/sim.cc | 24 ++++++++-------- riscv/sim.h | 2 +- 8 files changed, 96 insertions(+), 55 deletions(-) create mode 100644 riscv/clint.cc delete mode 100644 riscv/rtc.cc 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& 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(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(procs.size()); + std::vector 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; + } +} diff --git a/riscv/devices.h b/riscv/devices.h index cb3b6d9..f3ecb67 100644 --- a/riscv/devices.h +++ b/riscv/devices.h @@ -34,17 +34,20 @@ class rom_device_t : public abstract_device_t { std::vector data; }; -class rtc_t : public abstract_device_t { +class clint_t : public abstract_device_t { public: - rtc_t(std::vector&); + clint_t(std::vector&); 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 regs.size() * sizeof(regs[0]); } + size_t size() { return CLINT_SIZE; } void increment(reg_t inc); private: + typedef uint64_t mtime_t; + typedef uint64_t mtimecmp_t; + typedef uint32_t msip_t; std::vector& procs; - std::vector regs; - uint64_t time() { return regs[0]; } + mtime_t mtime; + std::vector mtimecmp; }; #endif diff --git a/riscv/encoding.h b/riscv/encoding.h index ef68c2f..3923bff 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -137,6 +137,8 @@ #define IRQ_HOST 13 #define DEFAULT_RSTVEC 0x00001000 +#define CLINT_BASE 0x02000000 +#define CLINT_SIZE 0x000c0000 #define EXT_IO_BASE 0x40000000 #define DRAM_BASE 0x80000000 diff --git a/riscv/processor.h b/riscv/processor.h index c294e57..7e9e932 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -306,7 +306,7 @@ private: friend class sim_t; friend class mmu_t; - friend class rtc_t; + friend class clint_t; friend class extension_t; void parse_isa_string(const char* isa); diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 17479dc..e954416 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -44,7 +44,7 @@ riscv_srcs = \ regnames.cc \ devices.cc \ rom.cc \ - rtc.cc \ + clint.cc \ gdbserver.cc \ debug_module.cc \ $(riscv_gen_srcs) \ diff --git a/riscv/rtc.cc b/riscv/rtc.cc deleted file mode 100644 index 22f318c..0000000 --- a/riscv/rtc.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include "devices.h" -#include "processor.h" - -rtc_t::rtc_t(std::vector& procs) - : procs(procs), regs(1 + procs.size()) -{ -} - -bool rtc_t::load(reg_t addr, size_t len, uint8_t* bytes) -{ - if (addr + len > size()) - return false; - memcpy(bytes, (uint8_t*)®s[0] + addr, len); - return true; -} - -bool rtc_t::store(reg_t addr, size_t len, const uint8_t* bytes) -{ - if (addr + len > size() || addr < 8) - return false; - memcpy((uint8_t*)®s[0] + addr, bytes, len); - increment(0); - return true; -} - -void rtc_t::increment(reg_t inc) -{ - regs[0] += inc; - for (size_t i = 0; i < procs.size(); i++) { - procs[i]->state.mip &= ~MIP_MTIP; - if (regs[0] >= regs[1+i]) - procs[i]->state.mip |= MIP_MTIP; - } -} diff --git a/riscv/sim.cc b/riscv/sim.cc index bdf55e2..e1a8540 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -52,7 +52,9 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted, procs[i] = new processor_t(isa, this, i, halted); } - rtc.reset(new rtc_t(procs)); + clint.reset(new clint_t(procs)); + bus.add_device(CLINT_BASE, clint.get()); + make_dtb(); } @@ -107,7 +109,7 @@ void sim_t::step(size_t n) procs[current_proc]->yield_load_reservation(); if (++current_proc == procs.size()) { current_proc = 0; - rtc->increment(INTERLEAVE / INSNS_PER_RTC_TICK); + clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK); } host->switch_to(); @@ -236,13 +238,6 @@ static std::string dts_compile(const std::string& dts) void sim_t::make_dtb() { - reg_t rtc_addr = EXT_IO_BASE; - bus.add_device(rtc_addr, rtc.get()); - - const int align = 0x1000; - reg_t cpu_addr = rtc_addr + ((rtc->size() - 1) / align + 1) * align; - reg_t cpu_size = align; - uint32_t reset_vec[] = { 0x297 + DRAM_BASE - DEFAULT_RSTVEC, // auipc t0, DRAM_BASE 0x597, // auipc a1, 0 @@ -293,14 +288,16 @@ void sim_t::make_dtb() " #size-cells = <2>;\n" " compatible = \"ucbbar,spike-bare-soc\";\n" " ranges;\n" - " clint@" << rtc_addr << " {\n" + " clint@" << CLINT_BASE << " {\n" " compatible = \"riscv,clint0\";\n" " interrupts-extended = <" << std::dec; for (size_t i = 0; i < procs.size(); i++) s << "&CPU" << i << " 3 &CPU" << i << " 7 "; + reg_t clintbs = CLINT_BASE; + reg_t clintsz = CLINT_SIZE; s << std::hex << ">;\n" - " reg = <0x" << (rtc_addr >> 32) << " 0x" << (rtc_addr & (uint32_t)-1) << - " 0x0 0x10000>;\n" + " reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) << + " 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n" " };\n" " };\n" "};\n"; @@ -309,7 +306,8 @@ void sim_t::make_dtb() std::string dtb = dts_compile(dts); rom.insert(rom.end(), dtb.begin(), dtb.end()); - rom.resize((rom.size() / align + 1) * align); + const int align = 0x1000; + rom.resize((rom.size() + align - 1) / align * align); boot_rom.reset(new rom_device_t(rom)); bus.add_device(DEFAULT_RSTVEC, boot_rom.get()); diff --git a/riscv/sim.h b/riscv/sim.h index 4111caf..57bdf8c 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -40,7 +40,7 @@ private: std::vector procs; std::string dts; std::unique_ptr boot_rom; - std::unique_ptr rtc; + std::unique_ptr clint; bus_t bus; debug_module_t debug_module; -- 2.30.2