diff --git a/src/commit_stage.sv b/src/commit_stage.sv index 50f422cb3..919f1eb3f 100644 --- a/src/commit_stage.sv +++ b/src/commit_stage.sv @@ -149,7 +149,7 @@ module commit_stage ( STORE_PAGE_FAULT: cause = "Store Page Fault"; default: cause = "Interrupt"; endcase - $display("Exception @%t, PC: %0h, TVal: %0h, Cause: %s", $time, commit_instr_i.pc, exception_o.tval, cause); + $display("Exception @%t, PC: %h, TVal: %h, Cause: %s", $time, commit_instr_i.pc, exception_o.tval, cause); end end `endif diff --git a/src/if_stage.sv b/src/if_stage.sv index ba5c824f2..13d356124 100644 --- a/src/if_stage.sv +++ b/src/if_stage.sv @@ -57,7 +57,7 @@ module if_stage ( //--------------------------------- // we are busy if we are either waiting for a grant // or if the FIFO is full - assign if_busy_o = ((CS == WAIT_GNT) && !instr_req_o) || !fifo_ready; + assign if_busy_o = (CS == WAIT_GNT) || !fifo_ready; assign fetch_address = {fetch_address_i[63:2], 2'b0}; //--------------------------------- @@ -86,6 +86,7 @@ module if_stage ( instr_addr_o = fetch_address; fifo_valid = 1'b0; NS = CS; + addr_valid = 1'b0; unique case(CS) // default state, not waiting for requested data @@ -99,7 +100,7 @@ module if_stage ( addr_valid = 1'b1; - if(instr_gnt_i) //~> granted request + if (instr_gnt_i) //~> granted request // we have one outstanding rvalid: wait for it if (flush_i) NS = WAIT_ABORTED; @@ -183,6 +184,7 @@ module if_stage ( // we can do a new request here, we won't get a grant until the rvalid came back for the // request we sent to end in here instr_addr_o = fetch_address; + addr_valid = 1'b1; // we are aborting this instruction so don't tell the FIFO it is valid fifo_valid = 1'b0; // check if the fetch is valid before making a new request diff --git a/src/mmu.sv b/src/mmu.sv index 763570358..0ba885c7b 100644 --- a/src/mmu.sv +++ b/src/mmu.sv @@ -91,7 +91,7 @@ module mmu #( logic update_is_2M; logic update_is_1G; - logic [26:0] update_vpn; + logic [38:0] update_vaddr; logic [0:0] update_asid; pte_t update_content; @@ -124,7 +124,7 @@ module mmu #( .flush_i ( flush_tlb_i ), .update_is_2M_i ( update_is_2M ), .update_is_1G_i ( update_is_1G ), - .update_vpn_i ( update_vpn ), + .update_vpn_i ( update_vaddr[38:12] ), .update_asid_i ( update_asid ), .update_content_i ( update_content ), .update_tlb_i ( itlb_update ), @@ -147,7 +147,7 @@ module mmu #( .flush_i ( flush_tlb_i ), .update_is_2M_i ( update_is_2M ), .update_is_1G_i ( update_is_1G ), - .update_vpn_i ( update_vpn ), + .update_vpn_i ( update_vaddr[38:12] ), .update_asid_i ( update_asid ), .update_content_i ( update_content ), .update_tlb_i ( dtlb_update ), @@ -179,7 +179,7 @@ module mmu #( .update_content_o ( update_content ), .update_is_2M_o ( update_is_2M ), .update_is_1G_o ( update_is_1G ), - .update_vpn_o ( update_vpn ), + .update_vaddr_o ( update_vaddr ), .update_asid_o ( update_asid ), .itlb_access_i ( itlb_lu_access ), @@ -243,7 +243,7 @@ module mmu #( fetch_gnt_o = 1'b1; ierr_valid_n = 1'b1; // throw a page fault - fetch_ex_n = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1}; + fetch_ex_n = {INSTR_ACCESS_FAULT, fetch_vaddr_i, 1'b1}; end end else // --------- @@ -254,7 +254,7 @@ module mmu #( // 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 - fetch_ex_n = {INSTR_ACCESS_FAULT, fetch_vaddr_i, 1'b1}; + fetch_ex_n = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; end end // the fetch is valid if we either got an error in the previous cycle or the I$ gave us a valid signal. @@ -313,9 +313,9 @@ module mmu #( lsu_valid_o = 1'b1; // the page table walker can only throw page faults if (lsu_is_store_i) begin - lsu_exception_o = {STORE_PAGE_FAULT, lsu_vaddr_i, 1'b1}; + lsu_exception_o = {STORE_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; end else begin - lsu_exception_o = {LOAD_PAGE_FAULT, lsu_vaddr_i, 1'b1}; + lsu_exception_o = {LOAD_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; end end end diff --git a/src/pcgen.sv b/src/pcgen.sv index 4dfc3afba..9f6b21f80 100644 --- a/src/pcgen.sv +++ b/src/pcgen.sv @@ -79,7 +79,7 @@ module pcgen ( // ------------------------------- // default is a consecutive PC if (if_ready_i && fetch_enable_i) - npc_n = {npc_q[62:2], 2'b0} + 64'h4; + npc_n = {npc_q[63:2], 2'b0} + 64'h4; else // or keep the PC stable if IF is not ready npc_n = npc_q; // we only need to stall the consecutive and predicted case since in any other case we will flush at least diff --git a/src/ptw.sv b/src/ptw.sv index 057d9e26b..c593ccf1f 100644 --- a/src/ptw.sv +++ b/src/ptw.sv @@ -53,7 +53,7 @@ module ptw #( output logic update_is_2M_o, output logic update_is_1G_o, - output logic [26:0] update_vpn_o, + output logic [38:0] update_vaddr_o, output logic [ASID_WIDTH-1:0] update_asid_o, input logic [ASID_WIDTH-1:0] asid_i, // from TLBs @@ -90,22 +90,19 @@ module ptw #( logic is_instr_ptw_q, is_instr_ptw_n; logic global_mapping_q, global_mapping_n; // latched tag signal - logic tag_valid_n, tag_valid_q; + logic tag_valid_n, tag_valid_q; + // 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; + // 4 byte aligned physical pointer + logic[55:0] ptw_pptr_q, ptw_pptr_n; + // Assignments + assign update_vaddr_o = vaddr_q; assign ptw_active_o = (ptw_state_q != PTW_READY); assign walking_instr_o = is_instr_ptw_q; - - // register the ASID - logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n; - // register the VPN we need to walk - logic [26:0] tlb_update_vpn_q, tlb_update_vpn_n; - // 4 byte aligned physical pointer - logic[55:0] ptw_pptr_q, ptw_pptr_n; // directly output the correct physical address - // ------ - // TODO - // ------- - // assign address_o = {ptw_pptr_q, 4'b0}; TODO assign address_index_o = ptw_pptr_q[11:0]; assign address_tag_o = ptw_pptr_q[55:12]; // we are never going to kill this request @@ -115,8 +112,7 @@ module ptw #( // update the correct page table level assign update_is_2M_o = (ptw_lvl_q == LVL2); assign update_is_1G_o = (ptw_lvl_q == LVL1); - // output the correct VPN and ASID - assign update_vpn_o = tlb_update_vpn_q; + // output the correct ASID assign update_asid_o = tlb_update_asid_q; // set the global mapping bit assign update_content_o = pte || (global_mapping_q << 5); @@ -162,25 +158,28 @@ module ptw #( global_mapping_n = global_mapping_q; // input registers tlb_update_asid_n = tlb_update_asid_q; - tlb_update_vpn_n = tlb_update_vpn_q; + vaddr_n = vaddr_q; + case (ptw_state_q) PTW_READY: begin + // by default we start with the top-most page table + ptw_lvl_n = LVL1; global_mapping_n = 1'b0; // if we got an ITLB miss if (enable_translation_i & itlb_access_i & itlb_miss_i & ~dtlb_access_i) begin ptw_pptr_n = {satp_ppn_i, itlb_vaddr_i[38:30], 3'b0}; is_instr_ptw_n = 1'b1; tlb_update_asid_n = asid_i; - tlb_update_vpn_n = itlb_vaddr_i[38:12]; + vaddr_n = itlb_vaddr_i; ptw_state_n = PTW_WAIT_GRANT; // we got an DTLB miss end else if (enable_translation_i & dtlb_access_i & dtlb_miss_i) begin ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[38:30], 3'b0}; is_instr_ptw_n = 1'b0; tlb_update_asid_n = asid_i; - tlb_update_vpn_n = dtlb_vaddr_i[38:12]; + vaddr_n = dtlb_vaddr_i; ptw_state_n = PTW_WAIT_GRANT; end end @@ -188,6 +187,14 @@ module ptw #( PTW_WAIT_GRANT: begin // send a request out data_req_o = 1'b1; + + // depending on the current level send the right address + if (ptw_lvl_q == LVL2) + ptw_pptr_n = {pte.ppn, vaddr_q[29:21], 3'b0}; + + if (ptw_lvl_q == LVL3) + ptw_pptr_n = {pte.ppn, vaddr_q[20:12], 3'b0}; + // wait for the grant if (data_gnt_i) begin // send the tag valid signal one cycle later @@ -202,11 +209,6 @@ module ptw #( // check if the global mapping bit is set if (pte.g) global_mapping_n = 1'b1; - // depending on the current level send the right address - if (ptw_lvl_q == LVL2) - ptw_pptr_n = {pte.ppn, tlb_update_vpn_q[17:9], 3'b0}; - if (ptw_lvl_q == LVL3) - ptw_pptr_n = {pte.ppn, tlb_update_vpn_q[8:0], 3'b0}; // ------------- // Invalid PTE @@ -294,7 +296,7 @@ module ptw #( ptw_lvl_q <= LVL1; tag_valid_q <= 1'b0; tlb_update_asid_q <= '{default: 0}; - tlb_update_vpn_q <= '{default: 0}; + vaddr_q <= '0; ptw_pptr_q <= '{default: 0}; global_mapping_q <= 1'b0; end else begin @@ -304,7 +306,7 @@ module ptw #( ptw_lvl_q <= ptw_lvl_n; tag_valid_q <= tag_valid_n; tlb_update_asid_q <= tlb_update_asid_n; - tlb_update_vpn_q <= tlb_update_vpn_n; + vaddr_q <= vaddr_n; global_mapping_q <= global_mapping_n; end end