1 // See LICENSE for license details.
2 
3 #include "arith.h"
4 #include "processor.h"
5 #include "extension.h"
6 #include "common.h"
7 #include "config.h"
8 #include "simif.h"
9 #include "mmu.h"
10 #include "disasm.h"
11 #include "platform.h"
12 #include <cinttypes>
13 #include <cmath>
14 #include <cstdlib>
15 #include <iostream>
16 #include <iomanip>
17 #include <assert.h>
18 #include <limits.h>
19 #include <stdexcept>
20 #include <string>
21 #include <algorithm>
22 
23 #undef STATE
24 #define STATE state
25 
processor_t(const char * isa,const char * priv,const char * varch,simif_t * sim,uint32_t id,bool halt_on_reset,FILE * log_file,std::ostream & sout_)26 processor_t::processor_t(const char* isa, const char* priv, const char* varch,
27                          simif_t* sim, uint32_t id, bool halt_on_reset,
28                          FILE* log_file, std::ostream& sout_)
29   : debug(false), halt_request(HR_NONE), sim(sim), id(id), xlen(0),
30   histogram_enabled(false), log_commits_enabled(false),
31   log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset),
32   extension_table(256, false), impl_table(256, false), last_pc(1), executions(1)
33 {
34   VU.p = this;
35 
36   parse_isa_string(isa);
37   parse_priv_string(priv);
38   parse_varch_string(varch);
39 
40   register_base_instructions();
41   mmu = new mmu_t(sim, this);
42 
43   disassembler = new disassembler_t(max_xlen);
44   for (auto e : custom_extensions)
45     for (auto disasm_insn : e.second->get_disasms())
46       disassembler->add_insn(disasm_insn);
47 
48   set_pmp_granularity(1 << PMP_SHIFT);
49   set_pmp_num(state.max_pmp);
50 
51   if (max_xlen == 32)
52     set_mmu_capability(IMPL_MMU_SV32);
53   else if (max_xlen == 64)
54     set_mmu_capability(IMPL_MMU_SV48);
55 
56   reset();
57 }
58 
~processor_t()59 processor_t::~processor_t()
60 {
61 #ifdef RISCV_ENABLE_HISTOGRAM
62   if (histogram_enabled)
63   {
64     fprintf(stderr, "PC Histogram size:%zu\n", pc_histogram.size());
65     for (auto it : pc_histogram)
66       fprintf(stderr, "%0" PRIx64 " %" PRIu64 "\n", it.first, it.second);
67   }
68 #endif
69 
70   delete mmu;
71   delete disassembler;
72 }
73 
bad_option_string(const char * option,const char * value,const char * msg)74 static void bad_option_string(const char *option, const char *value,
75                               const char *msg)
76 {
77   fprintf(stderr, "error: bad %s option '%s'. %s\n", option, value, msg);
78   abort();
79 }
80 
bad_isa_string(const char * isa,const char * msg)81 static void bad_isa_string(const char* isa, const char* msg)
82 {
83   bad_option_string("--isa", isa, msg);
84 }
85 
bad_priv_string(const char * priv)86 static void bad_priv_string(const char* priv)
87 {
88   fprintf(stderr, "error: bad --priv option %s\n", priv);
89   abort();
90 }
91 
bad_varch_string(const char * varch,const char * msg)92 static void bad_varch_string(const char* varch, const char *msg)
93 {
94   bad_option_string("--varch", varch, msg);
95 }
96 
get_string_token(std::string str,const char delimiter,size_t & pos)97 static std::string get_string_token(std::string str, const char delimiter, size_t& pos)
98 {
99   size_t _pos = pos;
100   while (pos < str.length() && str[pos] != delimiter) ++pos;
101   return str.substr(_pos, pos - _pos);
102 }
103 
get_int_token(std::string str,const char delimiter,size_t & pos)104 static int get_int_token(std::string str, const char delimiter, size_t& pos)
105 {
106   size_t _pos = pos;
107   while (pos < str.length() && str[pos] != delimiter) {
108     if (!isdigit(str[pos]))
109       bad_varch_string(str.c_str(), "Unsupported value"); // An integer is expected
110     ++pos;
111   }
112   return (pos == _pos) ? 0 : stoi(str.substr(_pos, pos - _pos));
113 }
114 
check_pow2(int val)115 static bool check_pow2(int val)
116 {
117   return ((val & (val - 1))) == 0;
118 }
119 
parse_varch_string(const char * s)120 void processor_t::parse_varch_string(const char* s)
121 {
122   std::string str, tmp;
123   for (const char *r = s; *r; r++)
124     str += std::tolower(*r);
125 
126   size_t pos = 0;
127   size_t len = str.length();
128   int vlen = 0;
129   int elen = 0;
130   int vstart_alu = 0;
131 
132   while (pos < len) {
133     std::string attr = get_string_token(str, ':', pos);
134 
135     ++pos;
136 
137     if (attr == "vlen")
138       vlen = get_int_token(str, ',', pos);
139     else if (attr == "elen")
140       elen = get_int_token(str, ',', pos);
141     else if (attr == "vstartalu")
142       vstart_alu = get_int_token(str, ',', pos);
143     else
144       bad_varch_string(s, "Unsupported token");
145 
146     ++pos;
147   }
148 
149   // The integer should be the power of 2
150   if (!check_pow2(vlen) || !check_pow2(elen)){
151     bad_varch_string(s, "The integer value should be the power of 2");
152   }
153 
154   /* Vector spec requirements. */
155   if (vlen < elen)
156     bad_varch_string(s, "vlen must be >= elen");
157 
158   /* spike requirements. */
159   if (vlen > 4096)
160     bad_varch_string(s, "vlen must be <= 4096");
161 
162   VU.VLEN = vlen;
163   VU.ELEN = elen;
164   VU.vlenb = vlen / 8;
165   VU.vstart_alu = vstart_alu;
166 }
167 
strtolower(const char * str)168 static std::string strtolower(const char* str)
169 {
170   std::string res;
171   for (const char *r = str; *r; r++)
172     res += std::tolower(*r);
173   return res;
174 }
175 
parse_priv_string(const char * str)176 void processor_t::parse_priv_string(const char* str)
177 {
178   std::string lowercase = strtolower(str);
179   bool user = false, supervisor = false;
180 
181   if (lowercase == "m")
182     ;
183   else if (lowercase == "mu")
184     user = true;
185   else if (lowercase == "msu")
186     user = supervisor = true;
187   else
188     bad_priv_string(str);
189 
190   if (user) {
191     max_isa |= reg_t(user) << ('u' - 'a');
192     extension_table['U'] = true;
193   }
194 
195   if (supervisor) {
196     max_isa |= reg_t(supervisor) << ('s' - 'a');
197     extension_table['S'] = true;
198   }
199 }
200 
parse_isa_string(const char * str)201 void processor_t::parse_isa_string(const char* str)
202 {
203   isa_string = strtolower(str);
204   const char* all_subsets = "imafdqchp"
205 #ifdef __SIZEOF_INT128__
206     "v"
207 #endif
208     "";
209 
210   max_isa = reg_t(2) << 62;
211   if (isa_string.compare(0, 4, "rv32") == 0)
212     max_xlen = 32, max_isa = reg_t(1) << 30;
213   else if (isa_string.compare(0, 4, "rv64") == 0)
214     max_xlen = 64;
215   else
216     bad_isa_string(str, "Spike supports either RV32I or RV64I");
217   if (isa_string[4] == 'g')
218     isa_string = isa_string.substr(0, 4) + "imafd" + isa_string.substr(5);
219   if (isa_string[4] != 'i')
220     bad_isa_string(str, "'I' extension is required");
221 
222   auto p = isa_string.begin();
223   for (p += 4; islower(*p) && !strchr("zsx", *p); ++p) {
224     while (*all_subsets && (*p != *all_subsets))
225       ++all_subsets;
226     if (!*all_subsets)
227       bad_isa_string(str, "Wrong order");
228     switch (*p) {
229       case 'p': extension_table[EXT_ZBPBO] = true;
230                 extension_table[EXT_ZPN] = true;
231                 extension_table[EXT_ZPSFOPERAND] = true;
232                 extension_table[EXT_ZMMUL] = true; break;
233       case 'q': max_isa |= 1L << ('d' - 'a');
234       case 'd': max_isa |= 1L << ('f' - 'a');
235     }
236     max_isa |= 1L << (*p - 'a');
237     extension_table[toupper(*p)] = true;
238     while (isdigit(*(p + 1))) {
239       ++p; // skip major version, point, and minor version if presented
240       if (*(p + 1) == 'p') ++p;
241     }
242     p += *(p + 1) == '_'; // underscores may be used to improve readability
243   }
244 
245   while (islower(*p) || (*p == '_')) {
246     p += *p == '_'; // first underscore is optional
247     auto end = p;
248     do ++end; while (*end && *end != '_');
249     auto ext_str = std::string(p, end);
250     if (ext_str == "zfh") {
251       if (!((max_isa >> ('f' - 'a')) & 1))
252         bad_isa_string(str, "'Zfh' extension requires 'F'");
253       extension_table[EXT_ZFH] = true;
254     } else if (ext_str == "zicsr") {
255       // Spike necessarily has Zicsr, because
256       // Zicsr is implied by the privileged architecture
257     } else if (ext_str == "zmmul") {
258       extension_table[EXT_ZMMUL] = true;
259     } else if (ext_str == "zba") {
260       extension_table[EXT_ZBA] = true;
261     } else if (ext_str == "zbb") {
262       extension_table[EXT_ZBB] = true;
263     } else if (ext_str == "zbc") {
264       extension_table[EXT_ZBC] = true;
265     } else if (ext_str == "zbs") {
266       extension_table[EXT_ZBS] = true;
267     } else if (ext_str == "zbkb") {
268       extension_table[EXT_ZBKB] = true;
269     } else if (ext_str == "zbkc") {
270       extension_table[EXT_ZBKC] = true;
271     } else if (ext_str == "zbkx") {
272       extension_table[EXT_ZBKX] = true;
273     } else if (ext_str == "zk") {
274       extension_table[EXT_ZBKB] = true;
275       extension_table[EXT_ZBKC] = true;
276       extension_table[EXT_ZBKX] = true;
277       extension_table[EXT_ZKND] = true;
278       extension_table[EXT_ZKNE] = true;
279       extension_table[EXT_ZKNH] = true;
280       extension_table[EXT_ZKR] = true;
281     } else if (ext_str == "zkn") {
282       extension_table[EXT_ZBKB] = true;
283       extension_table[EXT_ZBKC] = true;
284       extension_table[EXT_ZBKX] = true;
285       extension_table[EXT_ZKND] = true;
286       extension_table[EXT_ZKNE] = true;
287       extension_table[EXT_ZKNH] = true;
288     } else if (ext_str == "zknd") {
289       extension_table[EXT_ZKND] = true;
290     } else if (ext_str == "zkne") {
291       extension_table[EXT_ZKNE] = true;
292     } else if (ext_str == "zknh") {
293       extension_table[EXT_ZKNH] = true;
294     } else if (ext_str == "zks") {
295       extension_table[EXT_ZBKB] = true;
296       extension_table[EXT_ZBKC] = true;
297       extension_table[EXT_ZBKX] = true;
298       extension_table[EXT_ZKSED] = true;
299       extension_table[EXT_ZKSH] = true;
300     } else if (ext_str == "zksed") {
301       extension_table[EXT_ZKSED] = true;
302     } else if (ext_str == "zksh") {
303       extension_table[EXT_ZKSH] = true;
304     } else if (ext_str == "zkr") {
305       extension_table[EXT_ZKR] = true;
306     } else if (ext_str == "zkt") {
307     } else if (ext_str == "svnapot") {
308       extension_table[EXT_SVNAPOT] = true;
309     } else if (ext_str == "svpbmt") {
310       extension_table[EXT_SVPBMT] = true;
311     } else if (ext_str == "svinval") {
312       extension_table[EXT_SVINVAL] = true;
313     } else if (ext_str[0] == 'x') {
314       max_isa |= 1L << ('x' - 'a');
315       extension_table[toupper('x')] = true;
316       if (ext_str == "xbitmanip") {
317         extension_table[EXT_XBITMANIP] = true;
318       } else if (ext_str.size() == 1) {
319         bad_isa_string(str, "single 'X' is not a proper name");
320       } else if (ext_str != "xdummy") {
321         register_extension(find_extension(ext_str.substr(1).c_str())());
322       }
323     } else {
324       bad_isa_string(str, ("unsupported extension: " + ext_str).c_str());
325     }
326     p = end;
327   }
328   if (*p) {
329     bad_isa_string(str, ("can't parse: " + std::string(p, isa_string.end())).c_str());
330   }
331 }
332 
xlen_to_uxl(int xlen)333 static int xlen_to_uxl(int xlen)
334 {
335   if (xlen == 32)
336     return 1;
337   if (xlen == 64)
338     return 2;
339   abort();
340 }
341 
reset(processor_t * const proc,reg_t max_isa)342 void state_t::reset(processor_t* const proc, reg_t max_isa)
343 {
344   pc = DEFAULT_RSTVEC;
345   XPR.reset();
346   FPR.reset();
347 
348   // This assumes xlen is always max_xlen, which is true today (see
349   // mstatus_csr_t::unlogged_write()):
350   auto xlen = proc->get_max_xlen();
351 
352   prv = PRV_M;
353   v = false;
354   csrmap[CSR_MISA] = misa = std::make_shared<misa_csr_t>(proc, CSR_MISA, max_isa);
355   csrmap[CSR_MSTATUS] = mstatus = std::make_shared<mstatus_csr_t>(proc, CSR_MSTATUS);
356   if (xlen == 32) csrmap[CSR_MSTATUSH] = std::make_shared<mstatush_csr_t>(proc, CSR_MSTATUSH, mstatus);
357   csrmap[CSR_MEPC] = mepc = std::make_shared<epc_csr_t>(proc, CSR_MEPC);
358   csrmap[CSR_MTVAL] = mtval = std::make_shared<basic_csr_t>(proc, CSR_MTVAL, 0);
359   csrmap[CSR_MSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MSCRATCH, 0);
360   csrmap[CSR_MTVEC] = mtvec = std::make_shared<tvec_csr_t>(proc, CSR_MTVEC);
361   csrmap[CSR_MCAUSE] = mcause = std::make_shared<cause_csr_t>(proc, CSR_MCAUSE);
362   csrmap[CSR_MINSTRET] = minstret = std::make_shared<minstret_csr_t>(proc, CSR_MINSTRET);
363   csrmap[CSR_MCYCLE] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLE, minstret);
364   csrmap[CSR_INSTRET] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRET, minstret);
365   csrmap[CSR_CYCLE] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLE, minstret);
366   if (xlen == 32) {
367     minstreth_csr_t_p minstreth;
368     csrmap[CSR_MINSTRETH] = minstreth = std::make_shared<minstreth_csr_t>(proc, CSR_MINSTRETH, minstret);
369     csrmap[CSR_MCYCLEH] = std::make_shared<proxy_csr_t>(proc, CSR_MCYCLEH, minstreth);
370     csrmap[CSR_INSTRETH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_INSTRETH, minstreth);
371     csrmap[CSR_CYCLEH] = std::make_shared<counter_proxy_csr_t>(proc, CSR_CYCLEH, minstreth);
372   }
373   for (reg_t i=3; i<=31; ++i) {
374     const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3;
375     const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3;
376     const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i - 3;
377     const reg_t which_counter = CSR_HPMCOUNTER3 + i - 3;
378     const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3;
379     auto mevent = std::make_shared<const_csr_t>(proc, which_mevent, 0);
380     auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0);
381     auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter);
382     csrmap[which_mevent] = mevent;
383     csrmap[which_mcounter] = mcounter;
384     csrmap[which_counter] = counter;
385     if (xlen == 32) {
386       auto mcounterh = std::make_shared<const_csr_t>(proc, which_mcounterh, 0);
387       auto counterh = std::make_shared<counter_proxy_csr_t>(proc, which_counterh, mcounterh);
388       csrmap[which_mcounterh] = mcounterh;
389       csrmap[which_counterh] = counterh;
390     }
391   }
392   csrmap[CSR_MCOUNTINHIBIT] = std::make_shared<const_csr_t>(proc, CSR_MCOUNTINHIBIT, 0);
393   csrmap[CSR_MIE] = mie = std::make_shared<mie_csr_t>(proc, CSR_MIE);
394   csrmap[CSR_MIP] = mip = std::make_shared<mip_csr_t>(proc, CSR_MIP);
395   auto sip_sie_accr = std::make_shared<generic_int_accessor_t>(this,
396                                                                ~MIP_HS_MASK,  // read_mask
397                                                                MIP_SSIP,      // ip_write_mask
398                                                                ~MIP_HS_MASK,  // ie_write_mask
399                                                                true,          // mask_mideleg
400                                                                false,         // mask_hideleg
401                                                                0);            // shiftamt
402 
403   auto hip_hie_accr = std::make_shared<generic_int_accessor_t>(this,
404                                                                MIP_HS_MASK,   // read_mask
405                                                                MIP_VSSIP,     // ip_write_mask
406                                                                MIP_HS_MASK,   // ie_write_mask
407                                                                false,         // mask_mideleg
408                                                                false,         // mask_hideleg
409                                                                0);
410 
411   auto hvip_accr = std::make_shared<generic_int_accessor_t>(this,
412                                                             MIP_VS_MASK,   // read_mask
413                                                             MIP_VS_MASK,   // ip_write_mask
414                                                             MIP_VS_MASK,   // ie_write_mask
415                                                             false,         // mask_mideleg
416                                                             false,         // mask_hideleg
417                                                             0);            // shiftamt
418 
419   auto vsip_vsie_accr = std::make_shared<generic_int_accessor_t>(this,
420                                                                  MIP_VS_MASK,   // read_mask
421                                                                  MIP_VSSIP,     // ip_write_mask
422                                                                  MIP_VS_MASK,   // ie_write_mask
423                                                                  false,         // mask_mideleg
424                                                                  true,          // mask_hideleg
425                                                                  1);            // shiftamt
426 
427   auto nonvirtual_sip = std::make_shared<mip_proxy_csr_t>(proc, CSR_SIP, sip_sie_accr);
428   auto vsip = std::make_shared<mip_proxy_csr_t>(proc, CSR_VSIP, vsip_vsie_accr);
429   csrmap[CSR_VSIP] = vsip;
430   csrmap[CSR_SIP] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sip, vsip);
431   csrmap[CSR_HIP] = std::make_shared<mip_proxy_csr_t>(proc, CSR_HIP, hip_hie_accr);
432   csrmap[CSR_HVIP] = std::make_shared<mip_proxy_csr_t>(proc, CSR_HVIP, hvip_accr);
433 
434   auto nonvirtual_sie = std::make_shared<mie_proxy_csr_t>(proc, CSR_SIE, sip_sie_accr);
435   auto vsie = std::make_shared<mie_proxy_csr_t>(proc, CSR_VSIE, vsip_vsie_accr);
436   csrmap[CSR_VSIE] = vsie;
437   csrmap[CSR_SIE] = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sie, vsie);
438   csrmap[CSR_HIE] = std::make_shared<mie_proxy_csr_t>(proc, CSR_HIE, hip_hie_accr);
439 
440   csrmap[CSR_MEDELEG] = medeleg = std::make_shared<medeleg_csr_t>(proc, CSR_MEDELEG);
441   csrmap[CSR_MIDELEG] = mideleg = std::make_shared<mideleg_csr_t>(proc, CSR_MIDELEG);
442   const reg_t counteren_mask = 0xffffffffULL;
443   mcounteren = std::make_shared<masked_csr_t>(proc, CSR_MCOUNTEREN, counteren_mask, 0);
444   if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren;
445   csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared<masked_csr_t>(proc, CSR_SCOUNTEREN, counteren_mask, 0);
446   auto nonvirtual_sepc = std::make_shared<epc_csr_t>(proc, CSR_SEPC);
447   csrmap[CSR_VSEPC] = vsepc = std::make_shared<epc_csr_t>(proc, CSR_VSEPC);
448   csrmap[CSR_SEPC] = sepc = std::make_shared<virtualized_csr_t>(proc, nonvirtual_sepc, vsepc);
449   auto nonvirtual_stval = std::make_shared<basic_csr_t>(proc, CSR_STVAL, 0);
450   csrmap[CSR_VSTVAL] = vstval = std::make_shared<basic_csr_t>(proc, CSR_VSTVAL, 0);
451   csrmap[CSR_STVAL] = stval = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stval, vstval);
452   auto sscratch = std::make_shared<basic_csr_t>(proc, CSR_SSCRATCH, 0);
453   auto vsscratch = std::make_shared<basic_csr_t>(proc, CSR_VSSCRATCH, 0);
454   // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt):
455   csrmap[CSR_SSCRATCH] = std::make_shared<virtualized_csr_t>(proc, sscratch, vsscratch);
456   csrmap[CSR_VSSCRATCH] = vsscratch;
457   auto nonvirtual_stvec = std::make_shared<tvec_csr_t>(proc, CSR_STVEC);
458   csrmap[CSR_VSTVEC] = vstvec = std::make_shared<tvec_csr_t>(proc, CSR_VSTVEC);
459   csrmap[CSR_STVEC] = stvec = std::make_shared<virtualized_csr_t>(proc, nonvirtual_stvec, vstvec);
460   auto nonvirtual_satp = std::make_shared<satp_csr_t>(proc, CSR_SATP);
461   csrmap[CSR_VSATP] = vsatp = std::make_shared<base_atp_csr_t>(proc, CSR_VSATP);
462   csrmap[CSR_SATP] = satp = std::make_shared<virtualized_satp_csr_t>(proc, nonvirtual_satp, vsatp);
463   auto nonvirtual_scause = std::make_shared<cause_csr_t>(proc, CSR_SCAUSE);
464   csrmap[CSR_VSCAUSE] = vscause = std::make_shared<cause_csr_t>(proc, CSR_VSCAUSE);
465   csrmap[CSR_SCAUSE] = scause = std::make_shared<virtualized_csr_t>(proc, nonvirtual_scause, vscause);
466   csrmap[CSR_MTVAL2] = mtval2 = std::make_shared<hypervisor_csr_t>(proc, CSR_MTVAL2);
467   csrmap[CSR_MTINST] = mtinst = std::make_shared<hypervisor_csr_t>(proc, CSR_MTINST);
468   const reg_t hstatus_init = set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()));
469   const reg_t hstatus_mask = HSTATUS_VTSR | HSTATUS_VTW
470     | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0)
471     | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA;
472   csrmap[CSR_HSTATUS] = hstatus = std::make_shared<masked_csr_t>(proc, CSR_HSTATUS, hstatus_mask, hstatus_init);
473   csrmap[CSR_HGEIE] = std::make_shared<const_csr_t>(proc, CSR_HGEIE, 0);
474   csrmap[CSR_HGEIP] = std::make_shared<const_csr_t>(proc, CSR_HGEIP, 0);
475   csrmap[CSR_HIDELEG] = hideleg = std::make_shared<masked_csr_t>(proc, CSR_HIDELEG, MIP_VS_MASK, 0);
476   const reg_t hedeleg_mask =
477     (1 << CAUSE_MISALIGNED_FETCH) |
478     (1 << CAUSE_FETCH_ACCESS) |
479     (1 << CAUSE_ILLEGAL_INSTRUCTION) |
480     (1 << CAUSE_BREAKPOINT) |
481     (1 << CAUSE_MISALIGNED_LOAD) |
482     (1 << CAUSE_LOAD_ACCESS) |
483     (1 << CAUSE_MISALIGNED_STORE) |
484     (1 << CAUSE_STORE_ACCESS) |
485     (1 << CAUSE_USER_ECALL) |
486     (1 << CAUSE_FETCH_PAGE_FAULT) |
487     (1 << CAUSE_LOAD_PAGE_FAULT) |
488     (1 << CAUSE_STORE_PAGE_FAULT);
489   csrmap[CSR_HEDELEG] = hedeleg = std::make_shared<masked_csr_t>(proc, CSR_HEDELEG, hedeleg_mask, 0);
490   csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared<masked_csr_t>(proc, CSR_HCOUNTEREN, counteren_mask, 0);
491   csrmap[CSR_HTVAL] = htval = std::make_shared<basic_csr_t>(proc, CSR_HTVAL, 0);
492   csrmap[CSR_HTINST] = htinst = std::make_shared<basic_csr_t>(proc, CSR_HTINST, 0);
493   csrmap[CSR_HGATP] = hgatp = std::make_shared<hgatp_csr_t>(proc, CSR_HGATP);
494   auto nonvirtual_sstatus = std::make_shared<sstatus_proxy_csr_t>(proc, CSR_SSTATUS, mstatus);
495   csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared<vsstatus_csr_t>(proc, CSR_VSSTATUS);
496   csrmap[CSR_SSTATUS] = sstatus = std::make_shared<sstatus_csr_t>(proc, nonvirtual_sstatus, vsstatus);
497 
498   csrmap[CSR_DPC] = dpc = std::make_shared<dpc_csr_t>(proc, CSR_DPC);
499   csrmap[CSR_DSCRATCH0] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH0);
500   csrmap[CSR_DSCRATCH1] = std::make_shared<debug_mode_csr_t>(proc, CSR_DSCRATCH1);
501   csrmap[CSR_DCSR] = dcsr = std::make_shared<dcsr_csr_t>(proc, CSR_DCSR);
502 
503   csrmap[CSR_TSELECT] = tselect = std::make_shared<tselect_csr_t>(proc, CSR_TSELECT);
504   memset(this->mcontrol, 0, sizeof(this->mcontrol));
505   for (auto &item : mcontrol)
506     item.type = 2;
507 
508   csrmap[CSR_TDATA1] = std::make_shared<tdata1_csr_t>(proc, CSR_TDATA1);
509   csrmap[CSR_TDATA2] = tdata2 = std::make_shared<tdata2_csr_t>(proc, CSR_TDATA2, num_triggers);
510   csrmap[CSR_TDATA3] = std::make_shared<const_csr_t>(proc, CSR_TDATA3, 0);
511   debug_mode = false;
512   single_step = STEP_NONE;
513 
514   for (int i=0; i < max_pmp; ++i) {
515     csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared<pmpaddr_csr_t>(proc, CSR_PMPADDR0 + i);
516   }
517   for (int i=0; i < max_pmp; i += xlen/8) {
518     reg_t addr = CSR_PMPCFG0 + i/4;
519     csrmap[addr] = std::make_shared<pmpcfg_csr_t>(proc, addr);
520   }
521 
522   csrmap[CSR_FFLAGS] = fflags = std::make_shared<float_csr_t>(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0);
523   csrmap[CSR_FRM] = frm = std::make_shared<float_csr_t>(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0);
524   assert(FSR_AEXC_SHIFT == 0);  // composite_csr_t assumes fflags begins at bit 0
525   csrmap[CSR_FCSR] = std::make_shared<composite_csr_t>(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT);
526 
527   csrmap[CSR_SENTROPY] = std::make_shared<sentropy_csr_t>(proc, CSR_SENTROPY);
528 
529   csrmap[CSR_MARCHID] = std::make_shared<const_csr_t>(proc, CSR_MARCHID, 5);
530   csrmap[CSR_MIMPID] = std::make_shared<const_csr_t>(proc, CSR_MIMPID, 0);
531   csrmap[CSR_MVENDORID] = std::make_shared<const_csr_t>(proc, CSR_MVENDORID, 0);
532   csrmap[CSR_MHARTID] = std::make_shared<const_csr_t>(proc, CSR_MHARTID, proc->get_id());
533 
534   serialized = false;
535 
536 #ifdef RISCV_ENABLE_COMMITLOG
537   log_reg_write.clear();
538   log_mem_read.clear();
539   log_mem_write.clear();
540   last_inst_priv = 0;
541   last_inst_xlen = 0;
542   last_inst_flen = 0;
543 #endif
544 }
545 
reset()546 void processor_t::vectorUnit_t::reset(){
547   free(reg_file);
548   VLEN = get_vlen();
549   ELEN = get_elen();
550   reg_file = malloc(NVPR * vlenb);
551   memset(reg_file, 0, NVPR * vlenb);
552 
553   auto& csrmap = p->get_state()->csrmap;
554   csrmap[CSR_VXSAT] = vxsat = std::make_shared<vxsat_csr_t>(p, CSR_VXSAT);
555   csrmap[CSR_VSTART] = vstart = std::make_shared<vector_csr_t>(p, CSR_VSTART, /*mask*/ VLEN - 1);
556   csrmap[CSR_VXRM] = vxrm = std::make_shared<vector_csr_t>(p, CSR_VXRM, /*mask*/ 0x3ul);
557   csrmap[CSR_VL] = vl = std::make_shared<vector_csr_t>(p, CSR_VL, /*mask*/ 0);
558   csrmap[CSR_VTYPE] = vtype = std::make_shared<vector_csr_t>(p, CSR_VTYPE, /*mask*/ 0);
559   csrmap[CSR_VLENB] = std::make_shared<vector_csr_t>(p, CSR_VLENB, /*mask*/ 0, /*init*/ vlenb);
560   assert(VCSR_VXSAT_SHIFT == 0);  // composite_csr_t assumes vxsat begins at bit 0
561   csrmap[CSR_VCSR] = std::make_shared<composite_csr_t>(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT);
562 
563   vtype->write_raw(0);
564   set_vl(0, 0, 0, -1); // default to illegal configuration
565 }
566 
set_vl(int rd,int rs1,reg_t reqVL,reg_t newType)567 reg_t processor_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t newType){
568   int new_vlmul = 0;
569   if (vtype->read() != newType){
570     vtype->write_raw(newType);
571     vsew = 1 << (extract64(newType, 3, 3) + 3);
572     new_vlmul = int8_t(extract64(newType, 0, 3) << 5) >> 5;
573     vflmul = new_vlmul >= 0 ? 1 << new_vlmul : 1.0 / (1 << -new_vlmul);
574     vlmax = (VLEN/vsew) * vflmul;
575     vta = extract64(newType, 6, 1);
576     vma = extract64(newType, 7, 1);
577 
578     vill = !(vflmul >= 0.125 && vflmul <= 8)
579            || vsew > std::min(vflmul, 1.0f) * ELEN
580            || (newType >> 8) != 0;
581 
582     if (vill) {
583       vlmax = 0;
584       vtype->write_raw(UINT64_MAX << (p->get_xlen() - 1));
585     }
586   }
587 
588   // set vl
589   if (vlmax == 0) {
590     vl->write_raw(0);
591   } else if (rd == 0 && rs1 == 0) {
592     vl->write_raw(vl->read() > vlmax ? vlmax : vl->read());
593   } else if (rd != 0 && rs1 == 0) {
594     vl->write_raw(vlmax);
595   } else if (rs1 != 0) {
596     vl->write_raw(reqVL > vlmax ? vlmax : reqVL);
597   }
598 
599   vstart->write_raw(0);
600   setvl_count++;
601   return vl->read();
602 }
603 
set_debug(bool value)604 void processor_t::set_debug(bool value)
605 {
606   debug = value;
607 
608   for (auto e : custom_extensions)
609     e.second->set_debug(value);
610 }
611 
set_histogram(bool value)612 void processor_t::set_histogram(bool value)
613 {
614   histogram_enabled = value;
615 #ifndef RISCV_ENABLE_HISTOGRAM
616   if (value) {
617     fprintf(stderr, "PC Histogram support has not been properly enabled;");
618     fprintf(stderr, " please re-build the riscv-isa-sim project using \"configure --enable-histogram\".\n");
619     abort();
620   }
621 #endif
622 }
623 
624 #ifdef RISCV_ENABLE_COMMITLOG
enable_log_commits()625 void processor_t::enable_log_commits()
626 {
627   log_commits_enabled = true;
628 }
629 #endif
630 
reset()631 void processor_t::reset()
632 {
633   xlen = max_xlen;
634   state.reset(this, max_isa);
635   state.dcsr->halt = halt_on_reset;
636   halt_on_reset = false;
637   VU.reset();
638 
639   if (n_pmp > 0) {
640     // For backwards compatibility with software that is unaware of PMP,
641     // initialize PMP to permit unprivileged access to all of memory.
642     set_csr(CSR_PMPADDR0, ~reg_t(0));
643     set_csr(CSR_PMPCFG0, PMP_R | PMP_W | PMP_X | PMP_NAPOT);
644   }
645 
646    for (auto e : custom_extensions) // reset any extensions
647     e.second->reset();
648 
649   if (sim)
650     sim->proc_reset(id);
651 }
652 
get_extension()653 extension_t* processor_t::get_extension()
654 {
655   switch (custom_extensions.size()) {
656     case 0: return NULL;
657     case 1: return custom_extensions.begin()->second;
658     default:
659       fprintf(stderr, "processor_t::get_extension() is ambiguous when multiple extensions\n");
660       fprintf(stderr, "are present!\n");
661       abort();
662   }
663 }
664 
get_extension(const char * name)665 extension_t* processor_t::get_extension(const char* name)
666 {
667   auto it = custom_extensions.find(name);
668   if (it == custom_extensions.end())
669     abort();
670   return it->second;
671 }
672 
set_pmp_num(reg_t n)673 void processor_t::set_pmp_num(reg_t n)
674 {
675   // check the number of pmp is in a reasonable range
676   if (n > state.max_pmp) {
677     fprintf(stderr, "error: bad number of pmp regions: '%ld' from the dtb\n", (unsigned long)n);
678     abort();
679   }
680   n_pmp = n;
681 }
682 
set_pmp_granularity(reg_t gran)683 void processor_t::set_pmp_granularity(reg_t gran) {
684   // check the pmp granularity is set from dtb(!=0) and is power of 2
685   if (gran < (1 << PMP_SHIFT) || (gran & (gran - 1)) != 0) {
686     fprintf(stderr, "error: bad pmp granularity '%ld' from the dtb\n", (unsigned long)gran);
687     abort();
688   }
689 
690   lg_pmp_granularity = ctz(gran);
691 }
692 
set_mmu_capability(int cap)693 void processor_t::set_mmu_capability(int cap)
694 {
695   switch (cap) {
696     case IMPL_MMU_SV32:
697       set_impl(cap, true);
698       set_impl(IMPL_MMU, true);
699       break;
700     case IMPL_MMU_SV39:
701       set_impl(cap, true);
702       set_impl(IMPL_MMU, true);
703       break;
704     case IMPL_MMU_SV48:
705       set_impl(cap, true);
706       set_impl(IMPL_MMU_SV39, true);
707       set_impl(IMPL_MMU, true);
708       break;
709     default:
710       set_impl(IMPL_MMU_SV32, false);
711       set_impl(IMPL_MMU_SV39, false);
712       set_impl(IMPL_MMU_SV48, false);
713       set_impl(IMPL_MMU, false);
714       break;
715   }
716 }
717 
take_interrupt(reg_t pending_interrupts)718 void processor_t::take_interrupt(reg_t pending_interrupts)
719 {
720   // Do nothing if no pending interrupts
721   if (!pending_interrupts) {
722     return;
723   }
724 
725   // M-ints have higher priority over HS-ints and VS-ints
726   const reg_t mie = get_field(state.mstatus->read(), MSTATUS_MIE);
727   const reg_t m_enabled = state.prv < PRV_M || (state.prv == PRV_M && mie);
728   reg_t enabled_interrupts = pending_interrupts & ~state.mideleg->read() & -m_enabled;
729   if (enabled_interrupts == 0) {
730     // HS-ints have higher priority over VS-ints
731     const reg_t deleg_to_hs = state.mideleg->read() & ~state.hideleg->read();
732     const reg_t sie = get_field(state.sstatus->read(), MSTATUS_SIE);
733     const reg_t hs_enabled = state.v || state.prv < PRV_S || (state.prv == PRV_S && sie);
734     enabled_interrupts = pending_interrupts & deleg_to_hs & -hs_enabled;
735     if (state.v && enabled_interrupts == 0) {
736       // VS-ints have least priority and can only be taken with virt enabled
737       const reg_t deleg_to_vs = state.mideleg->read() & state.hideleg->read();
738       const reg_t vs_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
739       enabled_interrupts = pending_interrupts & deleg_to_vs & -vs_enabled;
740     }
741   }
742 
743   if (!state.debug_mode && enabled_interrupts) {
744     // nonstandard interrupts have highest priority
745     if (enabled_interrupts >> (IRQ_M_EXT + 1))
746       enabled_interrupts = enabled_interrupts >> (IRQ_M_EXT + 1) << (IRQ_M_EXT + 1);
747     // standard interrupt priority is MEI, MSI, MTI, SEI, SSI, STI
748     else if (enabled_interrupts & MIP_MEIP)
749       enabled_interrupts = MIP_MEIP;
750     else if (enabled_interrupts & MIP_MSIP)
751       enabled_interrupts = MIP_MSIP;
752     else if (enabled_interrupts & MIP_MTIP)
753       enabled_interrupts = MIP_MTIP;
754     else if (enabled_interrupts & MIP_SEIP)
755       enabled_interrupts = MIP_SEIP;
756     else if (enabled_interrupts & MIP_SSIP)
757       enabled_interrupts = MIP_SSIP;
758     else if (enabled_interrupts & MIP_STIP)
759       enabled_interrupts = MIP_STIP;
760     else if (enabled_interrupts & MIP_VSEIP)
761       enabled_interrupts = MIP_VSEIP;
762     else if (enabled_interrupts & MIP_VSSIP)
763       enabled_interrupts = MIP_VSSIP;
764     else if (enabled_interrupts & MIP_VSTIP)
765       enabled_interrupts = MIP_VSTIP;
766     else
767       abort();
768 
769     throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts));
770   }
771 }
772 
legalize_privilege(reg_t prv)773 reg_t processor_t::legalize_privilege(reg_t prv)
774 {
775   assert(prv <= PRV_M);
776 
777   if (!extension_enabled('U'))
778     return PRV_M;
779 
780   if (prv == PRV_HS || (prv == PRV_S && !extension_enabled('S')))
781     return PRV_U;
782 
783   return prv;
784 }
785 
set_privilege(reg_t prv)786 void processor_t::set_privilege(reg_t prv)
787 {
788   mmu->flush_tlb();
789   state.prv = legalize_privilege(prv);
790 }
791 
set_virt(bool virt)792 void processor_t::set_virt(bool virt)
793 {
794   reg_t tmp, mask;
795 
796   if (state.prv == PRV_M)
797     return;
798 
799   if (state.v != virt) {
800     /*
801      * Ideally, we should flush TLB here but we don't need it because
802      * set_virt() is always used in conjucter with set_privilege() and
803      * set_privilege() will flush TLB unconditionally.
804      *
805      * The virtualized sstatus register also relies on this TLB flush,
806      * since changing V might change sstatus.MXR and sstatus.SUM.
807      */
808     state.v = virt;
809   }
810 }
811 
enter_debug_mode(uint8_t cause)812 void processor_t::enter_debug_mode(uint8_t cause)
813 {
814   state.debug_mode = true;
815   state.dcsr->write_cause_and_prv(cause, state.prv);
816   set_privilege(PRV_M);
817   state.dpc->write(state.pc);
818   state.pc = DEBUG_ROM_ENTRY;
819 }
820 
debug_output_log(std::stringstream * s)821 void processor_t::debug_output_log(std::stringstream *s)
822 {
823   if (log_file==stderr) {
824     std::ostream out(sout_.rdbuf());
825     out << s->str(); // handles command line options -d -s -l
826   } else {
827     fputs(s->str().c_str(), log_file); // handles command line option --log
828   }
829 }
830 
take_trap(trap_t & t,reg_t epc)831 void processor_t::take_trap(trap_t& t, reg_t epc)
832 {
833   if (debug) {
834     std::stringstream s; // first put everything in a string, later send it to output
835     s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
836       << ": exception " << t.name() << ", epc 0x"
837       << std::hex << std::setfill('0') << std::setw(max_xlen/4) << zext(epc, max_xlen) << std::endl;
838     if (t.has_tval())
839        s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
840          << ":           tval 0x" << std::hex << std::setfill('0') << std::setw(max_xlen/4)
841          << zext(t.get_tval(), max_xlen) << std::endl;
842     debug_output_log(&s);
843   }
844 
845   if (state.debug_mode) {
846     if (t.cause() == CAUSE_BREAKPOINT) {
847       state.pc = DEBUG_ROM_ENTRY;
848     } else {
849       state.pc = DEBUG_ROM_TVEC;
850     }
851     return;
852   }
853 
854   if (t.cause() == CAUSE_BREAKPOINT && (
855               (state.prv == PRV_M && state.dcsr->ebreakm) ||
856               (state.prv == PRV_S && state.dcsr->ebreaks) ||
857               (state.prv == PRV_U && state.dcsr->ebreaku))) {
858     enter_debug_mode(DCSR_CAUSE_SWBP);
859     return;
860   }
861 
862   // By default, trap to M-mode, unless delegated to HS-mode or VS-mode
863   reg_t vsdeleg, hsdeleg;
864   reg_t bit = t.cause();
865   bool curr_virt = state.v;
866   bool interrupt = (bit & ((reg_t)1 << (max_xlen-1))) != 0;
867   if (interrupt) {
868     vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.mideleg->read() & state.hideleg->read()) : 0;
869     hsdeleg = (state.prv <= PRV_S) ? state.mideleg->read() : 0;
870     bit &= ~((reg_t)1 << (max_xlen-1));
871   } else {
872     vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.medeleg->read() & state.hedeleg->read()) : 0;
873     hsdeleg = (state.prv <= PRV_S) ? state.medeleg->read() : 0;
874   }
875   if (state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) {
876     // Handle the trap in VS-mode
877     reg_t vector = (state.vstvec->read() & 1) && interrupt ? 4*bit : 0;
878     state.pc = (state.vstvec->read() & ~(reg_t)1) + vector;
879     state.vscause->write((interrupt) ? (t.cause() - 1) : t.cause());
880     state.vsepc->write(epc);
881     state.vstval->write(t.get_tval());
882 
883     reg_t s = state.sstatus->read();
884     s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
885     s = set_field(s, MSTATUS_SPP, state.prv);
886     s = set_field(s, MSTATUS_SIE, 0);
887     state.sstatus->write(s);
888     set_privilege(PRV_S);
889   } else if (state.prv <= PRV_S && bit < max_xlen && ((hsdeleg >> bit) & 1)) {
890     // Handle the trap in HS-mode
891     set_virt(false);
892     reg_t vector = (state.stvec->read() & 1) && interrupt ? 4*bit : 0;
893     state.pc = (state.stvec->read() & ~(reg_t)1) + vector;
894     state.scause->write(t.cause());
895     state.sepc->write(epc);
896     state.stval->write(t.get_tval());
897     state.htval->write(t.get_tval2());
898     state.htinst->write(t.get_tinst());
899 
900     reg_t s = state.sstatus->read();
901     s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
902     s = set_field(s, MSTATUS_SPP, state.prv);
903     s = set_field(s, MSTATUS_SIE, 0);
904     state.sstatus->write(s);
905     if (extension_enabled('H')) {
906       s = state.hstatus->read();
907       if (curr_virt)
908         s = set_field(s, HSTATUS_SPVP, state.prv);
909       s = set_field(s, HSTATUS_SPV, curr_virt);
910       s = set_field(s, HSTATUS_GVA, t.has_gva());
911       state.hstatus->write(s);
912     }
913     set_privilege(PRV_S);
914   } else {
915     // Handle the trap in M-mode
916     set_virt(false);
917     reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4*bit : 0;
918     state.pc = (state.mtvec->read() & ~(reg_t)1) + vector;
919     state.mepc->write(epc);
920     state.mcause->write(t.cause());
921     state.mtval->write(t.get_tval());
922     state.mtval2->write(t.get_tval2());
923     state.mtinst->write(t.get_tinst());
924 
925     reg_t s = state.mstatus->read();
926     s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
927     s = set_field(s, MSTATUS_MPP, state.prv);
928     s = set_field(s, MSTATUS_MIE, 0);
929     s = set_field(s, MSTATUS_MPV, curr_virt);
930     s = set_field(s, MSTATUS_GVA, t.has_gva());
931     state.mstatus->write(s);
932     set_privilege(PRV_M);
933   }
934 }
935 
disasm(insn_t insn)936 void processor_t::disasm(insn_t insn)
937 {
938   uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
939   if (last_pc != state.pc || last_bits != bits) {
940     std::stringstream s;  // first put everything in a string, later send it to output
941 
942 #ifdef RISCV_ENABLE_COMMITLOG
943     const char* sym = get_symbol(state.pc);
944     if (sym != nullptr)
945     {
946       s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
947         << ": >>>>  " << sym << std::endl;
948     }
949 #endif
950 
951     if (executions != 1) {
952       s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
953         << ": Executed " << executions << " times" << std::endl;
954     }
955 
956     s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id
957       << std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen/4)
958       << zext(state.pc, max_xlen) << " (0x" << std::setw(8) << bits << ") "
959       << disassembler->disassemble(insn) << std::endl;
960 
961     debug_output_log(&s);
962 
963     last_pc = state.pc;
964     last_bits = bits;
965     executions = 1;
966   } else {
967     executions++;
968   }
969 }
970 
paddr_bits()971 int processor_t::paddr_bits()
972 {
973   assert(xlen == max_xlen);
974   return max_xlen == 64 ? 50 : 34;
975 }
976 
set_csr(int which,reg_t val)977 void processor_t::set_csr(int which, reg_t val)
978 {
979   val = zext_xlen(val);
980   auto search = state.csrmap.find(which);
981   if (search != state.csrmap.end()) {
982     search->second->write(val);
983     return;
984   }
985 }
986 
987 // Note that get_csr is sometimes called when read side-effects should not
988 // be actioned.  In other words, Spike cannot currently support CSRs with
989 // side effects on reads.
get_csr(int which,insn_t insn,bool write,bool peek)990 reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
991 {
992   auto search = state.csrmap.find(which);
993   if (search != state.csrmap.end()) {
994     if (!peek)
995       search->second->verify_permissions(insn, write);
996     return search->second->read();
997   }
998   // If we get here, the CSR doesn't exist.  Unimplemented CSRs always throw
999   // illegal-instruction exceptions, not virtual-instruction exceptions.
1000   throw trap_illegal_instruction(insn.bits());
1001 }
1002 
illegal_instruction(processor_t * p,insn_t insn,reg_t pc)1003 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
1004 {
1005   throw trap_illegal_instruction(insn.bits());
1006 }
1007 
decode_insn(insn_t insn)1008 insn_func_t processor_t::decode_insn(insn_t insn)
1009 {
1010   // look up opcode in hash table
1011   size_t idx = insn.bits() % OPCODE_CACHE_SIZE;
1012   insn_desc_t desc = opcode_cache[idx];
1013 
1014   if (unlikely(insn.bits() != desc.match || !(xlen == 64 ? desc.rv64 : desc.rv32))) {
1015     // fall back to linear search
1016     int cnt = 0;
1017     insn_desc_t* p = &instructions[0];
1018     while ((insn.bits() & p->mask) != p->match || !(xlen == 64 ? p->rv64 : p->rv32))
1019       p++, cnt++;
1020     desc = *p;
1021 
1022     if (p->mask != 0 && p > &instructions[0]) {
1023       if (p->match != (p-1)->match && p->match != (p+1)->match) {
1024         // move to front of opcode list to reduce miss penalty
1025         while (--p >= &instructions[0])
1026           *(p+1) = *p;
1027         instructions[0] = desc;
1028       }
1029     }
1030 
1031     opcode_cache[idx] = desc;
1032     opcode_cache[idx].match = insn.bits();
1033   }
1034 
1035   return xlen == 64 ? desc.rv64 : desc.rv32;
1036 }
1037 
register_insn(insn_desc_t desc)1038 void processor_t::register_insn(insn_desc_t desc)
1039 {
1040   instructions.push_back(desc);
1041 }
1042 
build_opcode_map()1043 void processor_t::build_opcode_map()
1044 {
1045   struct cmp {
1046     bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) {
1047       if (lhs.match == rhs.match)
1048         return lhs.mask > rhs.mask;
1049       return lhs.match > rhs.match;
1050     }
1051   };
1052   std::sort(instructions.begin(), instructions.end(), cmp());
1053 
1054   for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++)
1055     opcode_cache[i] = {0, 0, &illegal_instruction, &illegal_instruction};
1056 }
1057 
register_extension(extension_t * x)1058 void processor_t::register_extension(extension_t* x)
1059 {
1060   for (auto insn : x->get_instructions())
1061     register_insn(insn);
1062   build_opcode_map();
1063 
1064   if (disassembler)
1065     for (auto disasm_insn : x->get_disasms())
1066       disassembler->add_insn(disasm_insn);
1067 
1068   if (!custom_extensions.insert(std::make_pair(x->name(), x)).second) {
1069     fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name());
1070     abort();
1071   }
1072 
1073   x->set_processor(this);
1074 }
1075 
register_base_instructions()1076 void processor_t::register_base_instructions()
1077 {
1078   #define DECLARE_INSN(name, match, mask) \
1079     insn_bits_t name##_match = (match), name##_mask = (mask);
1080   #include "encoding.h"
1081   #undef DECLARE_INSN
1082 
1083   #define DEFINE_INSN(name) \
1084     extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
1085     extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
1086     register_insn((insn_desc_t){ \
1087       name##_match, \
1088       name##_mask, \
1089       rv32_##name, \
1090       rv64_##name});
1091   #include "insn_list.h"
1092   #undef DEFINE_INSN
1093 
1094   register_insn({0, 0, &illegal_instruction, &illegal_instruction});
1095   build_opcode_map();
1096 }
1097 
load(reg_t addr,size_t len,uint8_t * bytes)1098 bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes)
1099 {
1100   switch (addr)
1101   {
1102     case 0:
1103       if (len <= 4) {
1104         memset(bytes, 0, len);
1105         bytes[0] = get_field(state.mip->read(), MIP_MSIP);
1106         return true;
1107       }
1108       break;
1109   }
1110 
1111   return false;
1112 }
1113 
store(reg_t addr,size_t len,const uint8_t * bytes)1114 bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes)
1115 {
1116   switch (addr)
1117   {
1118     case 0:
1119       if (len <= 4) {
1120         state.mip->write_with_mask(MIP_MSIP, bytes[0] << IRQ_M_SOFT);
1121         return true;
1122       }
1123       break;
1124   }
1125 
1126   return false;
1127 }
1128 
trigger_updated()1129 void processor_t::trigger_updated()
1130 {
1131   mmu->flush_tlb();
1132   mmu->check_triggers_fetch = false;
1133   mmu->check_triggers_load = false;
1134   mmu->check_triggers_store = false;
1135 
1136   for (unsigned i = 0; i < state.num_triggers; i++) {
1137     if (state.mcontrol[i].execute) {
1138       mmu->check_triggers_fetch = true;
1139     }
1140     if (state.mcontrol[i].load) {
1141       mmu->check_triggers_load = true;
1142     }
1143     if (state.mcontrol[i].store) {
1144       mmu->check_triggers_store = true;
1145     }
1146   }
1147 }
1148