diff --git a/src/mmu.sv b/src/mmu.sv index 7959ca658..692dc9232 100644 --- a/src/mmu.sv +++ b/src/mmu.sv @@ -93,6 +93,7 @@ module mmu #( logic ptw_active; // PTW is currently walking a page table logic walking_instr; // PTW is walking because of an ITLB miss logic ptw_error; // PTW threw an exception + logic [63:0] faulting_address; logic update_is_2M; logic update_is_1G; @@ -175,6 +176,7 @@ module mmu #( .ptw_active_o ( ptw_active ), .walking_instr_o ( walking_instr ), .ptw_error_o ( ptw_error ), + .faulting_address_o ( faulting_address ), .enable_translation_i ( enable_translation_i ), .itlb_update_o ( itlb_update ), @@ -261,9 +263,14 @@ module mmu #( // --------- // watch out for exceptions happening during walking the page table if (ptw_active && walking_instr) begin - // on an error pass through fetch with an error signaled - fetch_gnt_o = ptw_error; - ierr_valid_n = ptw_error; // signal valid/error on next cycle + // check that the fetch address is equal with the faulting address as it could be that the page table walker + // has walked an instruction the instruction fetch stage is no longer interested in as we didn't give a grant + // we should not propagate back the exception when the request is no longer high + if (faulting_address == fetch_vaddr_i && fetch_req_i) begin + // on an error pass through fetch with an error signaled + fetch_gnt_o = ptw_error; + ierr_valid_n = ptw_error; // signal valid/error on next cycle + end fetch_exception = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; end end @@ -273,14 +280,14 @@ module mmu #( // --------------------------- // Fetch exception register // --------------------------- - // We can have two oustanding transactions + // We can have two outstanding transactions fifo #( .dtype ( exception ), .DEPTH ( 2 ) ) i_exception_fifo ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), - .flush_i ( ), + .flush_i ( 1'b0 ), .full_o ( ), .empty_o ( ), .single_element_o ( ), diff --git a/src/ptw.sv b/src/ptw.sv index c92da239e..8883b5e5b 100644 --- a/src/ptw.sv +++ b/src/ptw.sv @@ -32,6 +32,7 @@ module ptw #( output logic ptw_active_o, output logic walking_instr_o, // set when walking for TLB output logic ptw_error_o, // set when an error occurred + output logic [63:0] faulting_address_o, // the address which threw the page-fault exception input logic enable_translation_i, // CSRs indicate to enable SV39 input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores @@ -97,7 +98,7 @@ module ptw #( // register the ASID logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n; // register the VPN we need to walk, SV39 defines a 39 bit virtual address - logic [38:0] vaddr_q, vaddr_n; + logic [63:0] vaddr_q, vaddr_n; // 4 byte aligned physical pointer logic[55:0] ptw_pptr_q, ptw_pptr_n; @@ -147,22 +148,22 @@ module ptw #( always_comb begin : ptw // default assignments // PTW memory interface - tag_valid_n = 1'b0; - data_req_o = 1'b0; - data_be_o = 8'hFF; - data_we_o = 1'b0; - ptw_error_o = 1'b0; - itlb_update_o = 1'b0; - dtlb_update_o = 1'b0; - is_instr_ptw_n = is_instr_ptw_q; - ptw_lvl_n = ptw_lvl_q; - ptw_pptr_n = ptw_pptr_q; - NS = CS; - global_mapping_n = global_mapping_q; + tag_valid_n = 1'b0; + data_req_o = 1'b0; + data_be_o = 8'hFF; + data_we_o = 1'b0; + ptw_error_o = 1'b0; + itlb_update_o = 1'b0; + dtlb_update_o = 1'b0; + is_instr_ptw_n = is_instr_ptw_q; + ptw_lvl_n = ptw_lvl_q; + ptw_pptr_n = ptw_pptr_q; + NS = CS; + global_mapping_n = global_mapping_q; // input registers - tlb_update_asid_n = tlb_update_asid_q; - vaddr_n = vaddr_q; - + tlb_update_asid_n = tlb_update_asid_q; + vaddr_n = vaddr_q; + faulting_address_o = '0; case (CS) @@ -297,7 +298,8 @@ module ptw #( // Propagate error to MMU/LSU PROPAGATE_ERROR: begin NS = IDLE; - ptw_error_o = 1'b1; + ptw_error_o = 1'b1; + faulting_address_o = vaddr_q; end // wait for the rvalid before going back to IDLE WAIT_RVALID: begin @@ -305,6 +307,7 @@ module ptw #( NS = IDLE; end endcase + // ------- // Flush // -------