diff --git a/Makefile b/Makefile index 9157739..d25ec43 100644 --- a/Makefile +++ b/Makefile @@ -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 # diff --git a/src/core/rvx0_core.sv b/src/core/rvx0_core.sv index 1162bdb..3d99022 100644 --- a/src/core/rvx0_core.sv +++ b/src/core/rvx0_core.sv @@ -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 diff --git a/src/core/rvx0_fault_encoder.sv b/src/core/rvx0_fault_encoder.sv new file mode 100644 index 0000000..1f49c19 --- /dev/null +++ b/src/core/rvx0_fault_encoder.sv @@ -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