print out commit log (if enabled) for all privilege levels
[riscv-isa-sim.git] / riscv / execute.cc
1 // See LICENSE for license details.
2
3 #include "processor.h"
4 #include "mmu.h"
5 #include <cassert>
6
7 static void commit_log(state_t* state, reg_t pc, insn_t insn)
8 {
9 #ifdef RISCV_ENABLE_COMMITLOG
10 uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1;
11 if (state->log_reg_write.addr) {
12 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n",
13 pc,
14 insn.bits() & mask,
15 state->log_reg_write.addr & 1 ? 'f' : 'x',
16 state->log_reg_write.addr >> 1,
17 state->log_reg_write.data);
18 } else {
19 fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ")\n", pc, insn.bits() & mask);
20 }
21 state->log_reg_write.addr = 0;
22 #endif
23 }
24
25 inline void processor_t::update_histogram(size_t pc)
26 {
27 #ifdef RISCV_ENABLE_HISTOGRAM
28 size_t idx = pc >> 2;
29 pc_histogram[idx]++;
30 #endif
31 }
32
33 static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
34 {
35 reg_t npc = fetch.func(p, fetch.insn, pc);
36 if (npc != PC_SERIALIZE) {
37 commit_log(p->get_state(), pc, fetch.insn);
38 p->update_histogram(pc);
39 }
40 return npc;
41 }
42
43 // fetch/decode/execute loop
44 void processor_t::step(size_t n)
45 {
46 while (run && n > 0) {
47 size_t instret = 0;
48 reg_t pc = state.pc;
49 mmu_t* _mmu = mmu;
50
51 #define advance_pc() \
52 if (unlikely(pc == PC_SERIALIZE)) { \
53 pc = state.pc; \
54 state.serialized = true; \
55 break; \
56 } else { \
57 state.pc = pc; \
58 instret++; \
59 }
60
61 try
62 {
63 check_timer();
64 take_interrupt();
65
66 if (unlikely(debug))
67 {
68 while (instret < n)
69 {
70 insn_fetch_t fetch = mmu->load_insn(pc);
71 if (!state.serialized)
72 disasm(fetch.insn);
73 pc = execute_insn(this, pc, fetch);
74 advance_pc();
75 }
76 }
77 else while (instret < n)
78 {
79 size_t idx = _mmu->icache_index(pc);
80 auto ic_entry = _mmu->access_icache(pc);
81
82 #define ICACHE_ACCESS(i) { \
83 insn_fetch_t fetch = ic_entry->data; \
84 ic_entry++; \
85 pc = execute_insn(this, pc, fetch); \
86 if (i == mmu_t::ICACHE_ENTRIES-1) break; \
87 if (unlikely(ic_entry->tag != pc)) goto miss; \
88 if (unlikely(instret+1 == n)) break; \
89 instret++; \
90 state.pc = pc; \
91 }
92
93 switch (idx) {
94 #include "icache.h"
95 }
96
97 advance_pc();
98 continue;
99
100 miss:
101 advance_pc();
102 // refill I$ if it looks like there wasn't a taken branch
103 if (pc > (ic_entry-1)->tag && pc <= (ic_entry-1)->tag + MAX_INSN_LENGTH)
104 _mmu->refill_icache(pc, ic_entry);
105 }
106 }
107 catch(trap_t& t)
108 {
109 take_trap(t, pc);
110 }
111
112 state.minstret += instret;
113 n -= instret;
114 }
115 }