Set tval to 0 on traps with no specified tval
[riscv-isa-sim.git] / riscv / clint.cc
1 #include "devices.h"
2 #include "processor.h"
3
4 clint_t::clint_t(std::vector<processor_t*>& procs)
5 : procs(procs), mtimecmp(procs.size())
6 {
7 }
8
9 /* 0000 msip hart 0
10 * 0004 msip hart 1
11 * 4000 mtimecmp hart 0 lo
12 * 4004 mtimecmp hart 0 hi
13 * 4008 mtimecmp hart 1 lo
14 * 400c mtimecmp hart 1 hi
15 * bff8 mtime lo
16 * bffc mtime hi
17 */
18
19 #define MSIP_BASE 0x0
20 #define MTIMECMP_BASE 0x4000
21 #define MTIME_BASE 0xbff8
22
23 bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
24 {
25 if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
26 std::vector<msip_t> msip(procs.size());
27 for (size_t i = 0; i < procs.size(); ++i)
28 msip[i] = !!(procs[i]->state.mip & MIP_MSIP);
29 memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len);
30 } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
31 memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len);
32 } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
33 memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len);
34 } else {
35 return false;
36 }
37 return true;
38 }
39
40 bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
41 {
42 if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
43 std::vector<msip_t> msip(procs.size());
44 std::vector<msip_t> mask(procs.size(), 0);
45 memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len);
46 memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len);
47 for (size_t i = 0; i < procs.size(); ++i) {
48 if (!(mask[i] & 0xFF)) continue;
49 procs[i]->state.mip &= ~MIP_MSIP;
50 if (!!(msip[i] & 1))
51 procs[i]->state.mip |= MIP_MSIP;
52 }
53 } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
54 memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len);
55 } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
56 memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len);
57 } else {
58 return false;
59 }
60 increment(0);
61 return true;
62 }
63
64 void clint_t::increment(reg_t inc)
65 {
66 mtime += inc;
67 for (size_t i = 0; i < procs.size(); i++) {
68 procs[i]->state.mip &= ~MIP_MTIP;
69 if (mtime >= mtimecmp[i])
70 procs[i]->state.mip |= MIP_MTIP;
71 }
72 }