bb09eb50d353617e9e0bac6d4d064f2b87b63799
[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 #define execute_insn(noisy) \
176 do { insn_t insn = mmu.load_insn(pc, sr & SR_EC); \
177 if(noisy) disasm(insn,pc); \
178 pc = dispatch_table[insn.bits % DISPATCH_TABLE_SIZE](this, insn, pc); \
179 XPR[0] = 0; } while(0)
180
181 if(noisy) for( ; i < n; i++)
182 execute_insn(true);
183 else
184 {
185 for( ; n > 3 && i < n-3; i+=4)
186 {
187 execute_insn(false);
188 execute_insn(false);
189 execute_insn(false);
190 execute_insn(false);
191 }
192 for( ; i < n; i++)
193 execute_insn(false);
194 }
195
196 break;
197 }
198 catch(trap_t t)
199 {
200 i++;
201 take_trap(t,noisy);
202 }
203 catch(vt_command_t cmd)
204 {
205 i++;
206 if (cmd == vt_command_stop)
207 break;
208 }
209 catch(halt_t t)
210 {
211 reset();
212 return;
213 }
214
215 cycle += i;
216
217 typeof(count) old_count = count;
218 typeof(count) max_count = -1;
219 count += i;
220 if(old_count < compare && (count >= compare || old_count > max_count-i))
221 cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
222 }
223
224 void processor_t::take_trap(trap_t t, bool noisy)
225 {
226 demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
227 demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
228 id, trap_name(t), (unsigned long long)pc);
229 if(noisy)
230 printf("core %3d: trap %s, pc 0x%016llx\n",
231 id, trap_name(t), (unsigned long long)pc);
232
233 set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
234 cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
235 epc = pc;
236 pc = evec;
237 badvaddr = mmu.get_badvaddr();
238 }
239
240 void processor_t::deliver_ipi()
241 {
242 cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
243 run = true;
244 }
245
246 void processor_t::disasm(insn_t insn, reg_t pc)
247 {
248 printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
249
250 #ifdef RISCV_HAVE_LIBOPCODES
251 disassemble_info info;
252 INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
253 info.flavour = bfd_target_unknown_flavour;
254 info.arch = bfd_arch_mips;
255 info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
256 info.endian = BFD_ENDIAN_LITTLE;
257 info.buffer = (bfd_byte*)&insn;
258 info.buffer_length = sizeof(insn);
259 info.buffer_vma = pc;
260
261 int ret = print_insn_little_mips(pc, &info);
262 demand(ret == insn_length(insn.bits), "disasm bug!");
263 #else
264 printf("unknown");
265 #endif
266 printf("\n");
267 }