1 // See LICENSE for license details.
2 #ifndef _RISCV_PROCESSOR_H
3 #define _RISCV_PROCESSOR_H
14 typedef reg_t (*insn_func_t
)(processor_t
*, insn_t
, reg_t
);
28 struct commit_log_reg_t
48 ACTION_NONE
= MCONTROL_ACTION_NONE
,
49 ACTION_DEBUG_EXCEPTION
= MCONTROL_ACTION_DEBUG_EXCEPTION
,
50 ACTION_DEBUG_MODE
= MCONTROL_ACTION_DEBUG_MODE
,
51 ACTION_TRACE_START
= MCONTROL_ACTION_TRACE_START
,
52 ACTION_TRACE_STOP
= MCONTROL_ACTION_TRACE_STOP
,
53 ACTION_TRACE_EMIT
= MCONTROL_ACTION_TRACE_EMIT
58 MATCH_EQUAL
= MCONTROL_MATCH_EQUAL
,
59 MATCH_NAPOT
= MCONTROL_MATCH_NAPOT
,
60 MATCH_GE
= MCONTROL_MATCH_GE
,
61 MATCH_LT
= MCONTROL_MATCH_LT
,
62 MATCH_MASK_LOW
= MCONTROL_MATCH_MASK_LOW
,
63 MATCH_MASK_HIGH
= MCONTROL_MATCH_MASK_HIGH
71 mcontrol_action_t action
;
73 mcontrol_match_t match
;
83 // architectural state of a RISC-V hart
88 static const int num_triggers
= 4;
91 regfile_t
<reg_t
, NXPR
, true> XPR
;
92 regfile_t
<freg_t
, NFPR
, false> FPR
;
94 // control and status registers
95 reg_t prv
; // TODO: Can this be an enum instead?
119 mcontrol_t mcontrol
[num_triggers
];
120 reg_t tdata1
[num_triggers
];
124 bool serialized
; // whether timer CSRs are in a well-defined state
126 // When true, execute a single instruction and then enter debug mode. This
127 // can only be set by executing dret.
134 reg_t load_reservation
;
136 #ifdef RISCV_ENABLE_COMMITLOG
137 commit_log_reg_t log_reg_write
;
138 reg_t last_inst_priv
;
146 } trigger_operation_t
;
148 // Count number of contiguous 1 bits starting from the LSB.
149 static int cto(reg_t val
)
152 while ((val
& 1) == 1)
157 // this class represents one processor in a RISC-V machine.
158 class processor_t
: public abstract_device_t
161 processor_t(const char* isa
, sim_t
* sim
, uint32_t id
, bool halt_on_reset
=false);
164 void set_debug(bool value
);
165 void set_histogram(bool value
);
167 void step(size_t n
); // run for n cycles
168 void set_csr(int which
, reg_t val
);
169 void raise_interrupt(reg_t which
);
170 reg_t
get_csr(int which
);
171 mmu_t
* get_mmu() { return mmu
; }
172 state_t
* get_state() { return &state
; }
173 extension_t
* get_extension() { return ext
; }
174 bool supports_extension(unsigned char ext
) {
175 if (ext
>= 'a' && ext
<= 'z') ext
+= 'A' - 'a';
176 return ext
>= 'A' && ext
<= 'Z' && ((isa
>> (ext
- 'A')) & 1);
178 void set_privilege(reg_t
);
179 void yield_load_reservation() { state
.load_reservation
= (reg_t
)-1; }
180 void update_histogram(reg_t pc
);
181 const disassembler_t
* get_disassembler() { return disassembler
; }
183 void register_insn(insn_desc_t
);
184 void register_extension(extension_t
*);
186 // MMIO slave interface
187 bool load(reg_t addr
, size_t len
, uint8_t* bytes
);
188 bool store(reg_t addr
, size_t len
, const uint8_t* bytes
);
190 // When true, display disassembly of each instruction that's executed.
192 void update_slow_path();
194 // Return the index of a trigger that matched, or -1.
195 inline int trigger_match(trigger_operation_t operation
, reg_t address
, reg_t data
)
197 if (state
.dcsr
.cause
)
200 bool chain_ok
= false;
202 for (unsigned int i
= 0; i
< state
.num_triggers
; i
++) {
203 if (state
.mcontrol
[i
].action
== ACTION_NONE
||
204 (operation
== OPERATION_EXECUTE
&& !state
.mcontrol
[i
].execute
) ||
205 (operation
== OPERATION_STORE
&& !state
.mcontrol
[i
].store
) ||
206 (operation
== OPERATION_LOAD
&& !state
.mcontrol
[i
].load
) ||
207 (state
.prv
== PRV_M
&& !state
.mcontrol
[i
].m
) ||
208 (state
.prv
== PRV_H
&& !state
.mcontrol
[i
].h
) ||
209 (state
.prv
== PRV_S
&& !state
.mcontrol
[i
].s
) ||
210 (state
.prv
== PRV_U
&& !state
.mcontrol
[i
].u
)) {
215 if (state
.mcontrol
[i
].select
) {
221 // We need this because in 32-bit mode sometimes the PC bits get sign
227 switch (state
.mcontrol
[i
].match
) {
229 if (value
!= state
.tdata1
[i
])
234 reg_t mask
= ~((1 << cto(state
.tdata1
[i
])) - 1);
235 if ((value
& mask
) != (state
.tdata1
[i
] & mask
))
240 if (value
< state
.tdata1
[i
])
244 if (value
>= state
.tdata1
[i
])
249 reg_t mask
= state
.tdata1
[i
] >> (xlen
/2);
250 if ((value
& mask
) != (state
.tdata1
[i
] & mask
))
254 case MATCH_MASK_HIGH
:
256 reg_t mask
= state
.tdata1
[i
] >> (xlen
/2);
257 if (((value
>> (xlen
/2)) & mask
) != (state
.tdata1
[i
] & mask
))
263 if (state
.mcontrol
[i
].chain
&& !chain_ok
) {
267 // We got here, so this trigger matches. But if the next trigger has
268 // chain set, then we can't perform the action.
269 if (i
+1 < state
.num_triggers
&& state
.mcontrol
[i
+1].chain
) {
282 void trigger_updated();
286 mmu_t
* mmu
; // main memory is always accessed via the mmu
288 disassembler_t
* disassembler
;
294 std::string isa_string
;
295 bool histogram_enabled
;
297 // When true, take the slow simulation path.
300 std::vector
<insn_desc_t
> instructions
;
301 std::map
<reg_t
,uint64_t> pc_histogram
;
303 static const size_t OPCODE_CACHE_SIZE
= 8191;
304 insn_desc_t opcode_cache
[OPCODE_CACHE_SIZE
];
307 void take_interrupt(); // take a trap if any interrupts are pending
308 void take_trap(trap_t
& t
, reg_t epc
); // take an exception
309 void disasm(insn_t insn
); // disassemble and print an instruction
312 void enter_debug_mode(uint8_t cause
);
317 friend class extension_t
;
319 void parse_isa_string(const char* isa
);
320 void build_opcode_map();
321 void register_base_instructions();
322 insn_func_t
decode_insn(insn_t insn
);
325 reg_t
illegal_instruction(processor_t
* p
, insn_t insn
, reg_t pc
);
327 #define REGISTER_INSN(proc, name, match, mask) \
328 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
329 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
330 proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});