Correctly prioritize exceptions in controller

This commit is contained in:
Pirmin Vogel 2019-07-05 14:57:11 +01:00
parent 95c0dc0556
commit 3e1c8df311

View file

@ -411,57 +411,29 @@ module ibex_controller (
ctrl_fsm_ns = DECODE;
end
// flush the pipeline, insert NOP
FLUSH: begin
// flush the pipeline
halt_if_o = 1'b1;
halt_id = 1'b1;
ctrl_fsm_ns = DECODE;
halt_if_o = 1'b1;
halt_id = 1'b1;
// exceptions: set exception PC, save PC and exception cause
if (exc_req || store_err_q || load_err_q) begin
pc_set_o = 1'b1;
pc_mux_o = PC_EXC;
exc_pc_mux_o = debug_mode_q ? EXC_PC_DBG_EXC : EXC_PC_EXC;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
if (!wfi_insn_i) begin
ctrl_fsm_ns = DECODE;
end else begin
ctrl_fsm_ns = WAIT_SLEEP;
end
// set exception registers, priorities according to Table 3.7 of RISC-V Privileged Spec
if (illegal_insn_i) begin
exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
unique case(1'b1)
ecall_insn_i: begin
//ecall
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_EXC;
exc_cause_o = EXC_CAUSE_ECALL_MMODE;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
end
illegal_insn_i: begin
//exceptions
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
if (debug_mode_q) begin
exc_pc_mux_o = EXC_PC_DBG_EXC;
end else begin
exc_pc_mux_o = EXC_PC_EXC;
end
exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
end
mret_insn_i: begin
//mret
pc_mux_o = PC_ERET;
pc_set_o = 1'b1;
csr_restore_mret_id_o = 1'b1;
end
dret_insn_i: begin
//dret
pc_mux_o = PC_DRET;
pc_set_o = 1'b1;
debug_mode_n = 1'b0;
csr_restore_dret_id_o = 1'b1;
end
ebrk_insn_i: begin
//ebreak
end else if (ecall_insn_i) begin
exc_cause_o = EXC_CAUSE_ECALL_MMODE;
end else if (ebrk_insn_i) begin
if (debug_mode_q) begin
/*
* ebreak in debug mode re-enters debug mode
@ -470,14 +442,20 @@ module ibex_controller (
* Mode, it halts the hart again but without updating dpc or
* dcsr." [RISC-V Debug Specification v0.13.1, p. 41]
*/
ctrl_fsm_ns = DBG_TAKEN_ID;
pc_set_o = 1'b0;
csr_save_id_o = 1'b0;
csr_save_cause_o = 1'b0;
ctrl_fsm_ns = DBG_TAKEN_ID;
end else if (debug_ebreakm_i) begin
/*
* dcsr.ebreakm == 1:
* "ebreak instructions in M-mode enter Debug Mode."
* (Debug Spec, p. 44)
*/
ctrl_fsm_ns = DBG_TAKEN_ID;
pc_set_o = 1'b0;
csr_save_id_o = 1'b0;
csr_save_cause_o = 1'b0;
ctrl_fsm_ns = DBG_TAKEN_ID;
end else begin
/*
* "The EBREAK instruction is used by debuggers to cause control
@ -488,35 +466,33 @@ module ibex_controller (
* ECALL or EBREAK instruction itself, not the address of the
* following instruction." (Privileged Spec, p. 40)
*/
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_EXC;
exc_cause_o = EXC_CAUSE_BREAKPOINT;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
exc_cause_o = EXC_CAUSE_BREAKPOINT;
end
end
load_err_q: begin
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_EXC;
exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
csr_mtval_o = lsu_addr_last_i;
end
store_err_q: begin
pc_mux_o = PC_EXC;
pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_EXC;
end else if (store_err_q) begin
exc_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT;
csr_save_id_o = 1'b1;
csr_save_cause_o = 1'b1;
csr_mtval_o = lsu_addr_last_i;
end else if (load_err_q) begin
exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
csr_mtval_o = lsu_addr_last_i;
end
default:;
endcase
end else begin
// special instructions
if (mret_insn_i) begin
pc_mux_o = PC_ERET;
pc_set_o = 1'b1;
csr_restore_mret_id_o = 1'b1;
end else if (dret_insn_i) begin
pc_mux_o = PC_DRET;
pc_set_o = 1'b1;
csr_restore_dret_id_o = 1'b1;
debug_mode_n = 1'b0;
end else if (wfi_insn_i) begin
ctrl_fsm_ns = WAIT_SLEEP;
end
end // exc_req
// single stepping
// set exception registers, but do not jump into handler (debug-spec p.44).