1 // See LICENSE for license details.
2 #ifndef _RISCV_PROCESSOR_H
3 #define _RISCV_PROCESSOR_H
12 #include "debug_rom_defines.h"
14 #include "sv_decode.h"
19 typedef reg_t (*insn_func_t
)(processor_t
*, insn_t
, reg_t
);
33 struct commit_log_reg_t
53 ACTION_DEBUG_EXCEPTION
= MCONTROL_ACTION_DEBUG_EXCEPTION
,
54 ACTION_DEBUG_MODE
= MCONTROL_ACTION_DEBUG_MODE
,
55 ACTION_TRACE_START
= MCONTROL_ACTION_TRACE_START
,
56 ACTION_TRACE_STOP
= MCONTROL_ACTION_TRACE_STOP
,
57 ACTION_TRACE_EMIT
= MCONTROL_ACTION_TRACE_EMIT
62 MATCH_EQUAL
= MCONTROL_MATCH_EQUAL
,
63 MATCH_NAPOT
= MCONTROL_MATCH_NAPOT
,
64 MATCH_GE
= MCONTROL_MATCH_GE
,
65 MATCH_LT
= MCONTROL_MATCH_LT
,
66 MATCH_MASK_LOW
= MCONTROL_MATCH_MASK_LOW
,
67 MATCH_MASK_HIGH
= MCONTROL_MATCH_MASK_HIGH
77 mcontrol_action_t action
;
79 mcontrol_match_t match
;
89 // architectural state of a RISC-V hart
92 void reset(reg_t max_isa
);
94 static const int num_triggers
= 4;
97 regfile_t
<reg_t
, NXPR
, true> XPR
;
98 regfile_t
<freg_t
, NFPR
, false> FPR
;
100 // control and status registers
101 reg_t prv
; // TODO: Can this be an enum instead?
126 mcontrol_t mcontrol
[num_triggers
];
127 reg_t tdata2
[num_triggers
];
132 uint64_t destoffs
; // destination loop element offset
133 uint64_t srcoffs
; // source loop element offset (used in twin-predication)
134 sv_reg_csr_entry sv_csrs
[SV_CSR_SZ
];
135 sv_reg_entry sv_int_tb
[NXPR
];
136 sv_reg_entry sv_fp_tb
[NFPR
];
137 sv_pred_csr_entry sv_pred_csrs
[SV_CSR_SZ
];
138 sv_pred_entry sv_pred_int_tb
[NXPR
];
139 sv_pred_entry sv_pred_fp_tb
[NFPR
];
144 bool serialized
; // whether timer CSRs are in a well-defined state
146 // When true, execute a single instruction and then enter debug mode. This
147 // can only be set by executing dret.
154 #ifdef RISCV_ENABLE_COMMITLOG
155 commit_log_reg_t log_reg_write
;
156 reg_t last_inst_priv
;
166 } trigger_operation_t
;
168 // Count number of contiguous 1 bits starting from the LSB.
169 static int cto(reg_t val
)
172 while ((val
& 1) == 1)
177 // this class represents one processor in a RISC-V machine.
178 class processor_t
: public abstract_device_t
181 processor_t(const char* isa
, simif_t
* sim
, uint32_t id
, bool halt_on_reset
=false);
184 void set_debug(bool value
);
185 void set_histogram(bool value
);
187 void step(size_t n
); // run for n cycles
188 void set_csr(int which
, reg_t val
);
189 reg_t
get_csr(int which
);
190 mmu_t
* get_mmu() { return mmu
; }
191 state_t
* get_state() { return &state
; }
192 unsigned get_xlen() { return xlen
; }
193 unsigned get_max_xlen() { return max_xlen
; }
194 std::string
get_isa_string() { return isa_string
; }
195 unsigned get_flen() {
196 return supports_extension('Q') ? 128 :
197 supports_extension('D') ? 64 :
198 supports_extension('F') ? 32 : 0;
200 extension_t
* get_extension() { return ext
; }
201 bool supports_extension(unsigned char ext
) {
202 if (ext
>= 'a' && ext
<= 'z') ext
+= 'A' - 'a';
203 return ext
>= 'A' && ext
<= 'Z' && ((state
.misa
>> (ext
- 'A')) & 1);
205 reg_t
pc_alignment_mask() {
206 return ~(reg_t
)(supports_extension('C') ? 0 : 2);
208 void check_pc_alignment(reg_t pc
) {
209 if (unlikely(pc
& ~pc_alignment_mask()))
210 throw trap_instruction_address_misaligned(pc
);
212 reg_t
legalize_privilege(reg_t
);
213 void set_privilege(reg_t
);
214 void update_histogram(reg_t pc
);
215 const disassembler_t
* get_disassembler() { return disassembler
; }
217 void register_insn(insn_desc_t
);
218 void register_extension(extension_t
*);
220 // MMIO slave interface
221 bool load(reg_t addr
, size_t len
, uint8_t* bytes
);
222 bool store(reg_t addr
, size_t len
, const uint8_t* bytes
);
224 // When true, display disassembly of each instruction that's executed.
226 // When true, take the slow simulation path.
228 bool halted() { return state
.dcsr
.cause
? true : false; }
231 // Return the index of a trigger that matched, or -1.
232 inline int trigger_match(trigger_operation_t operation
, reg_t address
, reg_t data
)
234 if (state
.dcsr
.cause
)
237 bool chain_ok
= true;
239 for (unsigned int i
= 0; i
< state
.num_triggers
; i
++) {
241 chain_ok
|= !state
.mcontrol
[i
].chain
;
245 if ((operation
== OPERATION_EXECUTE
&& !state
.mcontrol
[i
].execute
) ||
246 (operation
== OPERATION_STORE
&& !state
.mcontrol
[i
].store
) ||
247 (operation
== OPERATION_LOAD
&& !state
.mcontrol
[i
].load
) ||
248 (state
.prv
== PRV_M
&& !state
.mcontrol
[i
].m
) ||
249 (state
.prv
== PRV_S
&& !state
.mcontrol
[i
].s
) ||
250 (state
.prv
== PRV_U
&& !state
.mcontrol
[i
].u
)) {
255 if (state
.mcontrol
[i
].select
) {
261 // We need this because in 32-bit mode sometimes the PC bits get sign
267 switch (state
.mcontrol
[i
].match
) {
269 if (value
!= state
.tdata2
[i
])
274 reg_t mask
= ~((1 << cto(state
.tdata2
[i
])) - 1);
275 if ((value
& mask
) != (state
.tdata2
[i
] & mask
))
280 if (value
< state
.tdata2
[i
])
284 if (value
>= state
.tdata2
[i
])
289 reg_t mask
= state
.tdata2
[i
] >> (xlen
/2);
290 if ((value
& mask
) != (state
.tdata2
[i
] & mask
))
294 case MATCH_MASK_HIGH
:
296 reg_t mask
= state
.tdata2
[i
] >> (xlen
/2);
297 if (((value
>> (xlen
/2)) & mask
) != (state
.tdata2
[i
] & mask
))
303 if (!state
.mcontrol
[i
].chain
) {
311 void trigger_updated();
315 mmu_t
* mmu
; // main memory is always accessed via the mmu
317 disassembler_t
* disassembler
;
323 std::string isa_string
;
324 bool histogram_enabled
;
327 std::vector
<insn_desc_t
> instructions
;
328 std::map
<reg_t
,uint64_t> pc_histogram
;
330 static const size_t OPCODE_CACHE_SIZE
= 8191;
331 insn_desc_t opcode_cache
[OPCODE_CACHE_SIZE
];
333 void take_pending_interrupt() { take_interrupt(state
.mip
& state
.mie
); }
334 void take_interrupt(reg_t mask
); // take first enabled interrupt in mask
335 void take_trap(trap_t
& t
, reg_t epc
); // take an exception
336 void disasm(insn_t insn
); // disassemble and print an instruction
339 void enter_debug_mode(uint8_t cause
);
342 friend class clint_t
;
343 friend class extension_t
;
345 void parse_isa_string(const char* isa
);
346 void build_opcode_map();
347 void register_base_instructions();
348 insn_func_t
decode_insn(insn_t insn
);
350 // Track repeated executions for processor_t::disasm()
351 uint64_t last_pc
, last_bits
, executions
;
354 reg_t
illegal_instruction(processor_t
* p
, insn_t insn
, reg_t pc
);
356 #define REGISTER_INSN(proc, name, match, mask) \
357 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
358 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
359 proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});