[sim] fixed building sim without cache simulators
[riscv-isa-sim.git] / riscv / mmu.h
1 #include "decode.h"
2 #include "trap.h"
3 #include "icsim.h"
4
5 class processor_t;
6
7 class mmu_t
8 {
9 public:
10 mmu_t(char* _mem, size_t _memsz)
11 : mem(_mem), memsz(_memsz), badvaddr(0),
12 icsim(NULL), dcsim(NULL), itlbsim(NULL), dtlbsim(NULL)
13 {
14 }
15
16 void set_icsim(icsim_t* _icsim) { icsim = _icsim; }
17 void set_dcsim(icsim_t* _dcsim) { dcsim = _dcsim; }
18 void set_itlbsim(icsim_t* _itlbsim) { itlbsim = _itlbsim; }
19 void set_dtlbsim(icsim_t* _dtlbsim) { dtlbsim = _dtlbsim; }
20
21 #ifdef RISCV_ENABLE_ICSIM
22 # define dcsim_tick(dcsim, dtlbsim, addr, size, st) \
23 do { if(dcsim) (dcsim)->tick(addr, size, st); \
24 if(dtlbsim) (dtlbsim)->tick(addr, sizeof(reg_t), false); } while(0)
25 #else
26 # define dcsim_tick(dcsim, dtlbsim, addr, size, st)
27 #endif
28
29 #define load_func(type) \
30 type##_t load_##type(reg_t addr) { \
31 check_align_and_bounds(addr, sizeof(type##_t), false, false); \
32 dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), false); \
33 return *(type##_t*)(mem+addr); \
34 }
35
36 #define store_func(type) \
37 void store_##type(reg_t addr, type##_t val) { \
38 check_align_and_bounds(addr, sizeof(type##_t), true, false); \
39 dcsim_tick(dcsim, dtlbsim, addr, sizeof(type##_t), true); \
40 *(type##_t*)(mem+addr) = val; \
41 }
42
43 insn_t load_insn(reg_t addr, bool rvc)
44 {
45 #ifdef RISCV_ENABLE_RVC
46 check_align_and_bounds(addr, rvc ? 2 : 4, false, true);
47 uint16_t lo = *(uint16_t*)(mem+addr);
48 uint16_t hi = *(uint16_t*)(mem+addr+2);
49
50 insn_t insn;
51 insn.bits = lo | ((uint32_t)hi << 16);
52
53 #ifdef RISCV_ENABLE_ICSIM
54 if(icsim)
55 icsim->tick(addr, insn_length(insn), false);
56 if(itlbsim)
57 itlbsim->tick(addr, sizeof(reg_t), false);
58 #endif
59
60 return insn;
61 #else
62 check_align_and_bounds(addr, 4, false, true);
63 return *(insn_t*)(mem+addr);
64 #endif
65 }
66
67 load_func(uint8)
68 load_func(uint16)
69 load_func(uint32)
70 load_func(uint64)
71
72 load_func(int8)
73 load_func(int16)
74 load_func(int32)
75 load_func(int64)
76
77 store_func(uint8)
78 store_func(uint16)
79 store_func(uint32)
80 store_func(uint64)
81
82 reg_t get_badvaddr() { return badvaddr; }
83
84 private:
85 char* mem;
86 size_t memsz;
87 reg_t badvaddr;
88
89 icsim_t* icsim;
90 icsim_t* dcsim;
91 icsim_t* itlbsim;
92 icsim_t* dtlbsim;
93
94 void check_align(reg_t addr, int size, bool store, bool fetch)
95 {
96 if(addr & (size-1))
97 {
98 badvaddr = addr;
99 if(fetch)
100 throw trap_instruction_address_misaligned;
101 if(store)
102 throw trap_store_address_misaligned;
103 throw trap_load_address_misaligned;
104 }
105 }
106
107 void check_bounds(reg_t addr, int size, bool store, bool fetch)
108 {
109 if(addr >= memsz || addr + size > memsz)
110 {
111 badvaddr = addr;
112 if(fetch)
113 throw trap_instruction_access_fault;
114 throw store ? trap_store_access_fault : trap_load_access_fault;
115 }
116 }
117
118 void check_align_and_bounds(reg_t addr, int size, bool store, bool fetch)
119 {
120 check_align(addr, size, store, fetch);
121 check_bounds(addr, size, store, fetch);
122 }
123
124 friend class processor_t;
125 };