e86536e4b4d05192bc5b678968c8103b272f856c
[riscv-isa-sim.git] / riscv / processor.cc
1 #include "processor.h"
2 #include <bfd.h>
3 #include <dis-asm.h>
4 #include <cmath>
5 #include <cstdlib>
6 #include <iostream>
7 #include "common.h"
8 #include "config.h"
9 #include "sim.h"
10 #include "icsim.h"
11
12 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu)
13 : sim(_sim), mmu(*_mmu)
14 {
15 // a few assumptions about endianness, including freg_t union
16 static_assert(BYTE_ORDER == LITTLE_ENDIAN);
17 static_assert(sizeof(freg_t) == 8);
18 static_assert(sizeof(reg_t) == 8);
19
20 static_assert(sizeof(insn_t) == 4);
21 static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
22
23 icsim = NULL;
24 dcsim = NULL;
25 itlbsim = NULL;
26 dtlbsim = NULL;
27
28 reset();
29 }
30
31 processor_t::~processor_t()
32 {
33 if(icsim)
34 icsim->print_stats();
35 delete icsim;
36
37 if(itlbsim)
38 itlbsim->print_stats();
39 delete itlbsim;
40
41 if(dcsim)
42 dcsim->print_stats();
43 delete dcsim;
44
45 if(dtlbsim)
46 dtlbsim->print_stats();
47 delete dtlbsim;
48 }
49
50 void processor_t::init(uint32_t _id, icsim_t* default_icache,
51 icsim_t* default_dcache)
52 {
53 id = _id;
54
55 for (int i=0; i<MAX_UTS; i++)
56 {
57 uts[i] = new processor_t(sim, &mmu);
58 uts[i]->id = id;
59 uts[i]->set_sr(uts[i]->sr | SR_EF);
60 uts[i]->set_sr(uts[i]->sr | SR_EV);
61 uts[i]->utidx = i;
62 }
63
64 #ifdef RISCV_ENABLE_ICSIM
65 icsim = new icsim_t(*default_icache);
66 mmu.set_icsim(icsim);
67 itlbsim = new icsim_t(1, 8, 4096, "ITLB");
68 mmu.set_itlbsim(itlbsim);
69 #endif
70 #ifdef RISCV_ENABLE_ICSIM
71 dcsim = new icsim_t(*default_dcache);
72 mmu.set_dcsim(dcsim);
73 dtlbsim = new icsim_t(1, 8, 4096, "DTLB");
74 mmu.set_dtlbsim(dtlbsim);
75 #endif
76 }
77
78 void processor_t::reset()
79 {
80 run = false;
81
82 memset(XPR,0,sizeof(XPR));
83 memset(FPR,0,sizeof(FPR));
84
85 pc = 0;
86 evec = 0;
87 epc = 0;
88 badvaddr = 0;
89 cause = 0;
90 pcr_k0 = 0;
91 pcr_k1 = 0;
92 tohost = 0;
93 fromhost = 0;
94 count = 0;
95 compare = 0;
96 cycle = 0;
97 set_sr(SR_S | SR_SX); // SX ignored if 64b mode not supported
98 set_fsr(0);
99
100 // vector stuff
101 vecbanks = 0xff;
102 vecbanks_count = 8;
103 utidx = -1;
104 vlmax = 32;
105 vl = 0;
106 nxfpr_bank = 256;
107 nxpr_use = 32;
108 nfpr_use = 32;
109 for (int i=0; i<MAX_UTS; i++)
110 uts[i] = NULL;
111 }
112
113 void processor_t::set_sr(uint32_t val)
114 {
115 sr = val & ~SR_ZERO;
116 #ifndef RISCV_ENABLE_64BIT
117 sr &= ~(SR_SX | SR_UX);
118 #endif
119 #ifndef RISCV_ENABLE_FPU
120 sr &= ~SR_EF;
121 #endif
122 #ifndef RISCV_ENABLE_RVC
123 sr &= ~SR_EC;
124 #endif
125 #ifndef RISCV_ENABLE_VEC
126 sr &= ~SR_EV;
127 #endif
128
129 mmu.set_vm_enabled(sr & SR_VM);
130 mmu.set_supervisor(sr & SR_S);
131 mmu.flush_tlb();
132
133 xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
134 }
135
136 void processor_t::set_fsr(uint32_t val)
137 {
138 fsr = val & ~FSR_ZERO;
139 }
140
141 void processor_t::vcfg()
142 {
143 if (nxpr_use + nfpr_use < 2)
144 vlmax = nxfpr_bank * vecbanks_count;
145 else
146 vlmax = (nxfpr_bank / (nxpr_use + nfpr_use - 1)) * vecbanks_count;
147
148 vlmax = std::min(vlmax, MAX_UTS);
149 }
150
151 void processor_t::setvl(int vlapp)
152 {
153 vl = std::min(vlmax, vlapp);
154 }
155
156 void processor_t::take_interrupt()
157 {
158 uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
159 interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
160
161 if(interrupts && (sr & SR_ET))
162 throw trap_interrupt;
163 }
164
165 void processor_t::step(size_t n, bool noisy)
166 {
167 if(!run)
168 return;
169
170 size_t i = 0;
171 while(1) try
172 {
173 take_interrupt();
174
175 mmu_t& _mmu = mmu;
176 insn_t insn;
177 insn_func_t func;
178 reg_t npc = pc;
179 #define execute_insn(noisy) \
180 do { \
181 insn = _mmu.load_insn(npc, sr & SR_EC, &func); \
182 if(noisy) disasm(insn,pc); \
183 npc = func(this, insn, npc); \
184 pc = npc; \
185 } while(0)
186
187 if(noisy) for( ; i < n; i++)
188 execute_insn(true);
189 else
190 {
191 for( ; n > 3 && i < n-3; i+=4)
192 {
193 execute_insn(false);
194 execute_insn(false);
195 execute_insn(false);
196 execute_insn(false);
197 }
198 for( ; i < n; i++)
199 execute_insn(false);
200 }
201
202 break;
203 }
204 catch(trap_t t)
205 {
206 i++;
207 take_trap(t,noisy);
208 }
209 catch(vt_command_t cmd)
210 {
211 i++;
212 if (cmd == vt_command_stop)
213 break;
214 }
215 catch(halt_t t)
216 {
217 reset();
218 return;
219 }
220
221 cycle += i;
222
223 typeof(count) old_count = count;
224 typeof(count) max_count = -1;
225 count += i;
226 if(old_count < compare && (count >= compare || old_count > max_count-i))
227 cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
228 }
229
230 void processor_t::take_trap(trap_t t, bool noisy)
231 {
232 demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
233 demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
234 id, trap_name(t), (unsigned long long)pc);
235 if(noisy)
236 printf("core %3d: trap %s, pc 0x%016llx\n",
237 id, trap_name(t), (unsigned long long)pc);
238
239 set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
240 cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
241 epc = pc;
242 pc = evec;
243 badvaddr = mmu.get_badvaddr();
244 }
245
246 void processor_t::deliver_ipi()
247 {
248 cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
249 run = true;
250 }
251
252 void processor_t::disasm(insn_t insn, reg_t pc)
253 {
254 printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
255
256 #ifdef RISCV_HAVE_LIBOPCODES
257 disassemble_info info;
258 INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
259 info.flavour = bfd_target_unknown_flavour;
260 info.arch = bfd_arch_mips;
261 info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
262 info.endian = BFD_ENDIAN_LITTLE;
263 info.buffer = (bfd_byte*)&insn;
264 info.buffer_length = sizeof(insn);
265 info.buffer_vma = pc;
266
267 int ret = print_insn_little_mips(pc, &info);
268 demand(ret == insn_length(insn.bits), "disasm bug!");
269 #else
270 printf("unknown");
271 #endif
272 printf("\n");
273 }