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 $@
|
./tool/makebin.py obj_dir/firmware.bin $@
|
||||||
|
|
||||||
obj_dir/firmware.bin: firmware/target/riscv32i-unknown-none-elf/release/firmware
|
obj_dir/firmware.bin: firmware/target/riscv32i-unknown-none-elf/release/firmware
|
||||||
|
mkdir -p obj_dir
|
||||||
llvm-objcopy -O binary $< $@
|
llvm-objcopy -O binary $< $@
|
||||||
|
|
||||||
firmware/target/riscv32i-unknown-none-elf/release/firmware: $(FIRMWARE_SRC)
|
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
|
obj_dir/rvx0: $(SRC_MODULE) $(DEF_MODULE) $(MAIN_TOP) obj_dir/apb0_memory.hex
|
||||||
mkdir -p obj_dir
|
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
|
# obj_dir/firmware.elf: $(FIRMWARE_OBJ) src/firmware.ld
|
||||||
#
|
#
|
||||||
|
|||||||
+22
-46
@@ -1,4 +1,3 @@
|
|||||||
/* verilator lint_off PINMISSING */
|
|
||||||
/* verilator lint_off MULTIDRIVEN */
|
/* verilator lint_off MULTIDRIVEN */
|
||||||
|
|
||||||
`include "rvx0_defs.svh"
|
`include "rvx0_defs.svh"
|
||||||
@@ -205,14 +204,28 @@ module rvx0_core #(
|
|||||||
.mtvec_o (csr_mtvec)
|
.mtvec_o (csr_mtvec)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign fault = fault_instruction_align ||
|
rvx0_fault_encoder fault_encoder (
|
||||||
fault_instruction_fetch ||
|
.fault_instruction_decode_i (fault_instruction),
|
||||||
fault_instruction ||
|
.fault_instruction_align_i (fault_instruction_align),
|
||||||
fault_memory_align ||
|
.fault_instruction_fetch_i (fault_instruction_fetch),
|
||||||
fault_memory_access ||
|
.fault_memory_align_i (fault_memory_align),
|
||||||
raise_ecall ||
|
.fault_memory_access_i (fault_memory_access),
|
||||||
raise_ebreak ||
|
|
||||||
intr_ext_i;
|
.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_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);
|
assign fault_memory_align = fault_address_align && (need_memory_write || need_memory_read);
|
||||||
@@ -251,43 +264,6 @@ module rvx0_core #(
|
|||||||
end
|
end
|
||||||
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
|
always @(posedge clk_i) begin
|
||||||
case (control_state)
|
case (control_state)
|
||||||
CSTATE_EXEC: begin
|
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