Implement exception/fault encoder module

This commit is contained in:
2025-09-03 18:22:33 +03:00
parent ee55a07e0a
commit 97ae2dd172
3 changed files with 95 additions and 47 deletions
+2 -1
View File
@@ -15,6 +15,7 @@ obj_dir/apb0_memory.hex: obj_dir/firmware.bin tool/makebin.py
./tool/makebin.py obj_dir/firmware.bin $@
obj_dir/firmware.bin: firmware/target/riscv32i-unknown-none-elf/release/firmware
mkdir -p obj_dir
llvm-objcopy -O binary $< $@
firmware/target/riscv32i-unknown-none-elf/release/firmware: $(FIRMWARE_SRC)
@@ -22,7 +23,7 @@ firmware/target/riscv32i-unknown-none-elf/release/firmware: $(FIRMWARE_SRC)
obj_dir/rvx0: $(SRC_MODULE) $(DEF_MODULE) $(MAIN_TOP) obj_dir/apb0_memory.hex
mkdir -p obj_dir
verilator --assert --binary -Isrc -o rvx0 $(MAIN_TOP) $(SRC_MODULE)
verilator -Wno-fatal --assert --binary -Isrc -o rvx0 $(MAIN_TOP) $(SRC_MODULE)
#
# obj_dir/firmware.elf: $(FIRMWARE_OBJ) src/firmware.ld
#
+22 -46
View File
@@ -1,4 +1,3 @@
/* verilator lint_off PINMISSING */
/* verilator lint_off MULTIDRIVEN */
`include "rvx0_defs.svh"
@@ -205,14 +204,28 @@ module rvx0_core #(
.mtvec_o (csr_mtvec)
);
assign fault = fault_instruction_align ||
fault_instruction_fetch ||
fault_instruction ||
fault_memory_align ||
fault_memory_access ||
raise_ecall ||
raise_ebreak ||
intr_ext_i;
rvx0_fault_encoder fault_encoder (
.fault_instruction_decode_i (fault_instruction),
.fault_instruction_align_i (fault_instruction_align),
.fault_instruction_fetch_i (fault_instruction_fetch),
.fault_memory_align_i (fault_memory_align),
.fault_memory_access_i (fault_memory_access),
.raise_ecall_i (raise_ecall),
.raise_ebreak_i (raise_ebreak),
.intr_ext_i (intr_ext_i),
.pc_value_i (pc_value),
.memory_address_i (alu_output),
.instruction_i (instruction),
.need_memory_write_i (need_memory_write),
.fault_o (fault),
.mcause_write_value_o (mcause_write_value),
.mtval_write_value_o (mtval_write_value),
.mepc_write_value_o (mepc_write_value)
);
assign fault_instruction = fault_instruction_decode || (fault_unsupported_size && (need_memory_read || need_memory_write));
assign fault_memory_align = fault_address_align && (need_memory_write || need_memory_read);
@@ -251,43 +264,6 @@ module rvx0_core #(
end
end
// Exception parameter encoding
always_comb begin
mcause_write_value = 0;
mtval_write_value = 0;
mepc_write_value = pc_value;
if (fault_instruction_align) begin
mcause_write_value = MCAUSE_INSTRUCTION_ADDRESS_MISALIGN;
end else if (fault_instruction_fetch) begin
mcause_write_value = MCAUSE_INSTRUCTION_ACCESS_FAULT;
mtval_write_value = pc_value;
end else if (fault_instruction) begin
mcause_write_value = MCAUSE_ILLEGAL_INSTRUCTION;
mtval_write_value = instruction;
end else if (raise_ebreak) begin
mcause_write_value = MCAUSE_BREAKPOINT;
end else if (~need_memory_write && fault_memory_align) begin
mcause_write_value = MCAUSE_LOAD_ADDRESS_MISALIGNED;
mtval_write_value = alu_output;
end else if (~need_memory_write && fault_memory_access) begin
mcause_write_value = MCAUSE_LOAD_ACCESS_FAULT;
end else if (fault_memory_align) begin
mcause_write_value = MCAUSE_STORE_ADDRESS_MISALIGNED;
mtval_write_value = alu_output;
end else if (fault_memory_access) begin
mcause_write_value = MCAUSE_STORE_ACCESS_FAULT;
// Because this happens at write pipeline stage and PC has already
// been incremented
mepc_write_value = pc_value - 4;
mtval_write_value = alu_output;
end else if (raise_ecall) begin
mcause_write_value = MCAUSE_ECALL_MMODE;
end else if (intr_ext_i) begin
mcause_write_value = MCAUSE_INTR_EXT_MMODE | MCAUSE_INTERRUPT;
end
end
always @(posedge clk_i) begin
case (control_state)
CSTATE_EXEC: begin
+71
View File
@@ -0,0 +1,71 @@
module rvx0_fault_encoder (
// Instruction
input wire fault_instruction_align_i,
input wire fault_instruction_fetch_i,
input wire fault_instruction_decode_i,
// Memory
input wire fault_memory_align_i,
input wire fault_memory_access_i,
// External
input wire intr_ext_i,
// Internal
input wire raise_ecall_i,
input wire raise_ebreak_i,
input wire [31:0] pc_value_i,
input wire [31:0] instruction_i,
input wire [31:0] memory_address_i,
input wire need_memory_write_i,
output logic [31:0] mcause_write_value_o,
output logic [31:0] mtval_write_value_o,
output logic [31:0] mepc_write_value_o,
output logic fault_o
);
assign fault_o = fault_instruction_align_i ||
fault_instruction_fetch_i ||
fault_instruction_decode_i ||
fault_memory_align_i ||
fault_memory_access_i ||
raise_ecall_i ||
raise_ebreak_i ||
intr_ext_i;
// Exception parameter encoding
always_comb begin
mcause_write_value_o = 0;
mtval_write_value_o = 0;
mepc_write_value_o = pc_value_i;
if (fault_instruction_align_i) begin
mcause_write_value_o = MCAUSE_INSTRUCTION_ADDRESS_MISALIGN;
end else if (fault_instruction_fetch_i) begin
mcause_write_value_o = MCAUSE_INSTRUCTION_ACCESS_FAULT;
mtval_write_value_o = pc_value_i;
end else if (fault_instruction_decode_i) begin
mcause_write_value_o = MCAUSE_ILLEGAL_INSTRUCTION;
mtval_write_value_o = instruction_i;
end else if (raise_ebreak_i) begin
mcause_write_value_o = MCAUSE_BREAKPOINT;
end else if (~need_memory_write_i && fault_memory_align_i) begin
mcause_write_value_o = MCAUSE_LOAD_ADDRESS_MISALIGNED;
mtval_write_value_o = memory_address_i;
end else if (~need_memory_write_i && fault_memory_access_i) begin
mcause_write_value_o = MCAUSE_LOAD_ACCESS_FAULT;
end else if (fault_memory_align_i) begin
mcause_write_value_o = MCAUSE_STORE_ADDRESS_MISALIGNED;
mtval_write_value_o = memory_address_i;
end else if (fault_memory_access_i) begin
mcause_write_value_o = MCAUSE_STORE_ACCESS_FAULT;
// Because this happens at write pipeline stage and PC has already
// been incremented
mepc_write_value_o = pc_value_i - 4;
mtval_write_value_o = memory_address_i;
end else if (raise_ecall_i) begin
mcause_write_value_o = MCAUSE_ECALL_MMODE;
end else if (intr_ext_i) begin
mcause_write_value_o = MCAUSE_INTR_EXT_MMODE | MCAUSE_INTERRUPT;
end
end
endmodule