Implement exception/fault encoder module
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user