--- /dev/null
+#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;
+ }
+}
std::vector<char> data;
};
-class rtc_t : public abstract_device_t {
+class clint_t : public abstract_device_t {
public:
- rtc_t(std::vector<processor_t*>&);
+ clint_t(std::vector<processor_t*>&);
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<processor_t*>& procs;
- std::vector<uint64_t> regs;
- uint64_t time() { return regs[0]; }
+ mtime_t mtime;
+ std::vector<mtimecmp_t> mtimecmp;
};
#endif
#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
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);
regnames.cc \
devices.cc \
rom.cc \
- rtc.cc \
+ clint.cc \
gdbserver.cc \
debug_module.cc \
$(riscv_gen_srcs) \
+++ /dev/null
-#include "devices.h"
-#include "processor.h"
-
-rtc_t::rtc_t(std::vector<processor_t*>& 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;
- }
-}
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();
}
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();
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
" #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";
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());
std::vector<processor_t*> procs;
std::string dts;
std::unique_ptr<rom_device_t> boot_rom;
- std::unique_ptr<rtc_t> rtc;
+ std::unique_ptr<clint_t> clint;
bus_t bus;
debug_module_t debug_module;