diff options
Diffstat (limited to '')
| -rw-r--r-- | rtl/core/arm810.sv | 6 | ||||
| -rw-r--r-- | rtl/core/control/control.sv | 6 | ||||
| -rw-r--r-- | rtl/core/control/cycles.sv | 7 | ||||
| -rw-r--r-- | rtl/core/control/data.sv | 10 | ||||
| -rw-r--r-- | rtl/core/control/exception.sv | 48 | ||||
| -rw-r--r-- | rtl/core/control/ldst/ldst.sv | 3 | ||||
| -rw-r--r-- | rtl/core/control/psr.sv | 5 | ||||
| -rw-r--r-- | rtl/core/control/writeback.sv | 4 | ||||
| -rw-r--r-- | rtl/core/cp15/cp15.sv | 5 | ||||
| -rw-r--r-- | rtl/core/cp15/far.sv | 5 | ||||
| -rw-r--r-- | rtl/core/mmu/mmu.sv | 12 | ||||
| -rw-r--r-- | rtl/core/mmu/pagewalk.sv | 17 |
12 files changed, 94 insertions, 34 deletions
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv index 1fd408f..bc4b5d9 100644 --- a/rtl/core/arm810.sv +++ b/rtl/core/arm810.sv @@ -76,6 +76,7 @@ module arm810 .mem_start(data_start), .mem_write(data_write), .mem_ready(data_ready), + .mem_fault(data_fault), .mem_data_rd(data_data_rd), .mem_data_wr(data_data_wr), .mem_data_be(data_data_be), @@ -165,7 +166,7 @@ module arm810 ptr data_addr; word data_data_rd, data_data_wr, insn_data_rd; - logic data_start, data_write, data_ready, insn_ready; + logic data_start, data_write, data_ready, insn_ready, data_fault; logic[3:0] data_data_be; core_mmu mmu @@ -173,8 +174,9 @@ module arm810 .* ); + ptr fault_addr; word coproc_read; - logic coproc, high_vectors, mmu_enable; + logic coproc, high_vectors, mmu_enable, fault_register; mmu_base mmu_ttbr; coproc_decode coproc_ctrl; diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv index 3c55507..8bf4976 100644 --- a/rtl/core/control/control.sv +++ b/rtl/core/control/control.sv @@ -20,6 +20,7 @@ module core_control q_shifter, input logic c_shifter, mem_ready, + mem_fault, input word mem_data_rd, input logic mul_ready, input word mul_q_hi, @@ -147,8 +148,9 @@ module core_control .* ); - word vector; - logic exception; + word exception_vector; + logic exception, exception_offset_pc; + psr_mode exception_mode; core_control_exception ctrl_exc ( diff --git a/rtl/core/control/cycles.sv b/rtl/core/control/cycles.sv index 88e0235..5779990 100644 --- a/rtl/core/control/cycles.sv +++ b/rtl/core/control/cycles.sv @@ -12,6 +12,7 @@ module core_control_cycles coproc, exception, mem_ready, + mem_fault, mul_add, mul_long, mul_ready, @@ -100,12 +101,16 @@ module core_control_cycles ESCALATE: next_state = EXCEPTION; - TRANSFER: + TRANSFER: begin if(!mem_ready || pop_valid) next_state = TRANSFER; else if(ldst_writeback) next_state = BASE_WRITEBACK; + if(mem_ready && mem_fault) + next_state = ESCALATE; + end + MUL: if(!mul_ready) next_state = MUL; diff --git a/rtl/core/control/data.sv b/rtl/core/control/data.sv index 5ba6b92..5d34b13 100644 --- a/rtl/core/control/data.sv +++ b/rtl/core/control/data.sv @@ -17,11 +17,12 @@ module core_control_data input ctrl_cycle cycle, next_cycle, - input ptr pc, + input ptr pc_visible, input logic ldst_next, input logic[1:0] ldst_shift, input word mem_offset, input psr_flags flags, + input logic exception_offset_pc, output alu_op alu, output word alu_a, @@ -52,7 +53,7 @@ module core_control_data if(cycle.transfer) alu_a = saved_base; else if(cycle.exception) - alu_a = {pc, 2'b00}; + alu_a = {pc_visible, 2'b00}; else alu_a = rd_value_a; @@ -107,8 +108,9 @@ module core_control_data shifter.ror <= 0; shifter.shr <= !mem_write; end else if(next_cycle.exception) begin - alu <= `ALU_ADD; - data_imm <= 12'd4; + alu <= `ALU_SUB; + // Either pc_visible - 0 (pc + 8) or pc_visible - 4 (pc + 4) + data_imm <= {9'd0, exception_offset_pc, 2'b00}; data_snd_is_imm <= 1; end diff --git a/rtl/core/control/exception.sv b/rtl/core/control/exception.sv index 3965114..2d12c0a 100644 --- a/rtl/core/control/exception.sv +++ b/rtl/core/control/exception.sv @@ -2,24 +2,42 @@ module core_control_exception ( - input logic clk, - rst_n, - - input logic undefined, - high_vectors, - - output word vector, - output logic exception + input logic clk, + rst_n, + + input ctrl_cycle next_cycle, + input logic high_vectors, + undefined, + mem_fault, + + output logic exception, + exception_offset_pc, + output psr_mode exception_mode, + output word exception_vector ); logic[2:0] vector_offset; - assign exception = undefined; //TODO - assign vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00}; - - always_comb - vector_offset = 3'b001; //TODO - - //TODO: Considerar que data abort usa + 8, no + 4 + //TODO: irq, fiq, prefetch abort, swi + + assign exception = undefined || mem_fault; + assign exception_vector = {{16{high_vectors}}, 11'b0, vector_offset, 2'b00}; + + always @(posedge clk or negedge rst_n) begin + if(!rst_n) begin + vector_offset <= 0; + exception_mode <= 0; + exception_offset_pc <= 0; + end else if(mem_fault) begin + vector_offset <= 3'b100; + exception_mode <= `MODE_ABT; + end else if(undefined) begin + vector_offset <= 3'b001; + exception_mode <= `MODE_UND; + end + + if(next_cycle.escalate) + exception_offset_pc <= !mem_fault; + end endmodule diff --git a/rtl/core/control/ldst/ldst.sv b/rtl/core/control/ldst/ldst.sv index dd5155a..027fb0a 100644 --- a/rtl/core/control/ldst/ldst.sv +++ b/rtl/core/control/ldst/ldst.sv @@ -77,7 +77,8 @@ module core_control_ldst mem_start <= 0; mem_offset <= 0; end else begin - mem_start <= 0; + if(mem_start) + mem_start <= 0; if(next_cycle.issue) begin // TODO: dec.ldst.unprivileged diff --git a/rtl/core/control/psr.sv b/rtl/core/control/psr.sv index 5767124..07bf4e5 100644 --- a/rtl/core/control/psr.sv +++ b/rtl/core/control/psr.sv @@ -10,6 +10,7 @@ module core_control_psr spsr_rd, alu_b, input psr_mode mode, + exception_mode, input ctrl_cycle cycle, next_cycle, @@ -44,8 +45,8 @@ module core_control_psr psr_write = 1; if(cycle.escalate) - //TODO: otros modos, y además F (FIQ) no cambia siempre - psr_wr = {24'b0, 3'b110, `MODE_UND}; + //TODO: F (FIQ) no cambia siempre + psr_wr = {24'b0, 3'b110, exception_mode}; else if(cycle.exception) psr_wr = exception_spsr; else diff --git a/rtl/core/control/writeback.sv b/rtl/core/control/writeback.sv index 3bacb75..a7738fb 100644 --- a/rtl/core/control/writeback.sv +++ b/rtl/core/control/writeback.sv @@ -17,7 +17,7 @@ module core_control_writeback input ctrl_cycle cycle, next_cycle, input word saved_base, - vector, + exception_vector, psr_wb, coproc_wb, input reg_num ra, @@ -81,7 +81,7 @@ module core_control_writeback end else if(next_cycle.base_writeback) wr_value = ldst_read; else if(next_cycle.exception) - wr_value = vector; + wr_value = exception_vector; else if(next_cycle.mul_hi_wb) wr_value = mul_q_hi; diff --git a/rtl/core/cp15/cp15.sv b/rtl/core/cp15/cp15.sv index 8ddc474..bf84292 100644 --- a/rtl/core/cp15/cp15.sv +++ b/rtl/core/cp15/cp15.sv @@ -10,6 +10,9 @@ module core_cp15 input coproc_decode dec, input word write, + input logic fault_register, + input ptr fault_addr, + output word read, output logic high_vectors, mmu_enable, @@ -61,7 +64,7 @@ module core_cp15 .* ); - core_cp15_far fsr + core_cp15_fsr fsr ( .read(read_fsr), .transfer(transfer && crn == `CP15_CRN_FSR), diff --git a/rtl/core/cp15/far.sv b/rtl/core/cp15/far.sv index b90dc0f..3d86151 100644 --- a/rtl/core/cp15/far.sv +++ b/rtl/core/cp15/far.sv @@ -11,6 +11,9 @@ module core_cp15_far input cp_opcode op2, input word write, + input logic fault_register, + input ptr fault_addr, + output word read ); @@ -21,6 +24,8 @@ module core_cp15_far always @(posedge clk or negedge rst_n) if(!rst_n) far <= 0; + else if(fault_register) + far <= {fault_addr, 2'b00}; else if(transfer && !load) far <= write; diff --git a/rtl/core/mmu/mmu.sv b/rtl/core/mmu/mmu.sv index 504e447..91986db 100644 --- a/rtl/core/mmu/mmu.sv +++ b/rtl/core/mmu/mmu.sv @@ -26,8 +26,12 @@ module core_mmu bus_write, insn_ready, data_ready, + data_fault, output word insn_data_rd, - data_data_rd + data_data_rd, + + output logic fault_register, + output ptr fault_addr ); ptr iphys_addr, dphys_addr; @@ -35,15 +39,19 @@ module core_mmu logic iphys_start, dphys_start, iphys_ready, dphys_ready, dphys_write; logic[3:0] dphys_data_be; + assign fault_register = data_fault; + core_mmu_pagewalk iwalk ( .core_addr(insn_addr), .core_start(insn_start), .core_write(0), .core_ready(insn_ready), + .core_fault(), .core_data_wr(0), .core_data_be(0), .core_data_rd(insn_data_rd), + .core_fault_addr(), .bus_addr(iphys_addr), .bus_start(iphys_start), @@ -62,9 +70,11 @@ module core_mmu .core_start(data_start), .core_write(data_write), .core_ready(data_ready), + .core_fault(data_fault), .core_data_wr(data_data_wr), .core_data_be(data_data_be), .core_data_rd(data_data_rd), + .core_fault_addr(fault_addr), .bus_addr(dphys_addr), .bus_start(dphys_start), diff --git a/rtl/core/mmu/pagewalk.sv b/rtl/core/mmu/pagewalk.sv index b16ce26..be4aa8b 100644 --- a/rtl/core/mmu/pagewalk.sv +++ b/rtl/core/mmu/pagewalk.sv @@ -25,7 +25,9 @@ module core_mmu_pagewalk bus_write, output logic core_ready, - output word core_data_rd + core_fault, + output word core_data_rd, + output ptr core_fault_addr ); enum int unsigned @@ -71,7 +73,9 @@ module core_mmu_pagewalk bus_data_wr <= 0; core_ready <= 0; + core_fault <= 0; core_data_rd <= 0; + core_fault_addr <= 0; end else begin if(bus_start) bus_start <= 0; @@ -79,6 +83,9 @@ module core_mmu_pagewalk if(core_ready) core_ready <= 0; + if(core_fault) + core_fault <= 0; + unique case(state) IDLE: if(core_start) begin @@ -157,8 +164,12 @@ module core_mmu_pagewalk core_data_rd <= bus_data_rd; end - //TODO - FAULT: ; + FAULT: begin + state <= IDLE; + core_fault <= 1; + core_ready <= 1; + core_fault_addr <= target; + end endcase end |
