diff --git a/core/csr_regs.sv b/core/csr_regs.sv index 567389a..40a9428 100755 --- a/core/csr_regs.sv +++ b/core/csr_regs.sv @@ -482,6 +482,7 @@ generate if (ENABLE_S_MODE) begin assign asid = satp.asid; //****************** + //////////////////////////////////////////////////// //MMU interface assign immu.mxr = mstatus.mxr; assign dmmu.mxr = mstatus.mxr; @@ -489,13 +490,14 @@ generate if (ENABLE_S_MODE) begin assign dmmu.sum = mstatus.sum; assign immu.privilege = privilege_level; assign dmmu.privilege = mstatus.mprv ? mstatus.mpp : privilege_level; - assign immu.ppn = satp.ppn; - assign dmmu.ppn = satp.ppn; - //****************** + assign immu.satp_ppn = satp.ppn; + assign dmmu.satp_ppn = satp.ppn; + //////////////////////////////////////////////////// assign sip_mask = '{default:0, seip:1, stip:1, ssip:1}; - //stvec + //////////////////////////////////////////////////// + //STVEC logic [31:0] stvec_mask = '1; always_ff @(posedge clk) begin if (rst) @@ -504,7 +506,8 @@ generate if (ENABLE_S_MODE) begin stvec <= (updated_csr & stvec_mask); end - //satp + //////////////////////////////////////////////////// + //SATP logic[XLEN-1:0] satp_mask; assign satp_mask = '1; always_ff @(posedge clk) begin diff --git a/core/fetch.sv b/core/fetch.sv index b82ec9f..f26d04a 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -85,6 +85,7 @@ module fetch( logic flush_or_rst; fifo_interface #(.DATA_WIDTH($bits(fetch_attributes_t))) fetch_attr_fifo(); + logic update_pc; logic new_mem_request; //Cache related @@ -95,10 +96,11 @@ module fetch( //Implementation //////////////////////////////////////////////////// //Fetch PC + assign update_pc = new_mem_request | gc_fetch_flush; always_ff @(posedge clk) begin if (rst) pc <= RESET_VEC; - else if (new_mem_request | gc_fetch_flush) + else if (update_pc) pc <= {next_pc[31:2], 2'b0}; end @@ -115,7 +117,7 @@ module fetch( next_pc = pc_plus_4; end - assign bp.new_mem_request = new_mem_request | gc_fetch_flush; + assign bp.new_mem_request = update_pc; assign bp.next_pc = next_pc; assign bp.if_pc = pc; @@ -129,6 +131,7 @@ module fetch( assign tlb.virtual_address = pc; assign tlb.execute = 1; assign tlb.rnw = 0; + assign tlb.new_request = update_pc; always_ff @(posedge clk) begin if (new_mem_request) diff --git a/core/interfaces.sv b/core/interfaces.sv index 73c48cd..a544bc1 100755 --- a/core/interfaces.sv +++ b/core/interfaces.sv @@ -136,7 +136,7 @@ endinterface interface mmu_interface; //From TLB - logic new_request; + logic request; logic execute; logic rnw; logic [31:0] virtual_address; @@ -147,14 +147,14 @@ interface mmu_interface; logic is_fault; //From CSR - logic [21:0] ppn; + logic [21:0] satp_ppn; logic mxr; //Make eXecutable Readable logic sum; //permit Supervisor User Memory access logic [1:0] privilege; - modport mmu (input virtual_address, new_request, execute, rnw, ppn, mxr, sum, privilege, output write_entry, upper_physical_address, is_fault); - modport tlb (input write_entry, upper_physical_address, is_fault, output new_request, virtual_address, execute, rnw); - modport csr (output ppn, mxr, sum, privilege); + modport mmu (input virtual_address, request, execute, rnw, satp_ppn, mxr, sum, privilege, output write_entry, upper_physical_address, is_fault); + modport tlb (input write_entry, upper_physical_address, is_fault, output request, virtual_address, execute, rnw); + modport csr (output satp_ppn, mxr, sum, privilege); endinterface diff --git a/core/mmu.sv b/core/mmu.sv index daed011..256f51c 100755 --- a/core/mmu.sv +++ b/core/mmu.sv @@ -30,6 +30,7 @@ module mmu input logic clk, input logic rst, mmu_interface.mmu mmu, + input logic abort_request, l1_arbiter_request_interface.master l1_request, l1_arbiter_return_interface.master l1_response ); @@ -63,6 +64,10 @@ module mmu pte_t pte; logic access_valid; logic privilege_valid; + + localparam MAX_ABORTED_REQUESTS = 4; + logic abort_queue_full; + logic discard_data; //////////////////////////////////////////////////// //Implementation @@ -74,13 +79,13 @@ module mmu assign l1_request.is_amo = 0; assign l1_request.amo = 0; - assign l1_request.request = state[SEND_REQUEST_1] | state[SEND_REQUEST_2]; + assign l1_request.request = (state[SEND_REQUEST_1] | state[SEND_REQUEST_2]) & ~abort_request; //Page Table addresses always_ff @ (posedge clk) begin if (state[IDLE] | l1_response.data_valid) begin if (state[IDLE]) - l1_request.addr <= {mmu.ppn[19:0], mmu.virtual_address[31:22], 2'b00}; + l1_request.addr <= {mmu.satp_ppn[19:0], mmu.virtual_address[31:22], 2'b00}; else l1_request.addr <= {{pte.ppn1[9:0], pte.ppn0}, mmu.virtual_address[21:12], 2'b00}; end @@ -88,6 +93,25 @@ module mmu assign pte = l1_response.data; + //////////////////////////////////////////////////// + //Supports unlimited tracking of aborted requests + //Assumption: memory requests are returned in-order + localparam COUNT_W = $clog2(MAX_ABORTED_REQUESTS); + logic [COUNT_W:0] abort_tracking; + logic delayed_abort; + logic delayed_abort_complete; + + assign delayed_abort = abort_request & (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2]); + assign delayed_abort_complete = discard_data & l1_response.data_valid; + always_ff @ (posedge clk) begin + if (rst) + abort_tracking <= 0; + else + abort_tracking <= abort_tracking - COUNT_W'(delayed_abort) + COUNT_W'(delayed_abort_complete); + end + + assign discard_data = abort_tracking[COUNT_W]; + assign abort_queue_full = abort_tracking[COUNT_W] & ~|abort_tracking[COUNT_W-1:0]; //////////////////////////////////////////////////// //Access and permission checks //A and D bits are software managed @@ -107,15 +131,13 @@ module mmu next_state = state; case (1'b1) state[IDLE] : - if (mmu.new_request) begin + if (mmu.request & ~abort_queue_full) next_state = 2**SEND_REQUEST_1; - end state[SEND_REQUEST_1] : - if (l1_request.ack) begin + if (l1_request.ack) next_state = 2**WAIT_REQUEST_1; - end state[WAIT_REQUEST_1] : - if (l1_response.data_valid) begin + if (l1_response.data_valid & ~discard_data) begin if (~pte.v | (~pte.r & pte.w)) //page not valid OR invalid xwr pattern next_state = 2**COMPLETE_FAULT; else if (pte.v & (pte.r | pte.x)) begin//superpage (all remaining xwr patterns other than all zeros) @@ -123,16 +145,14 @@ module mmu next_state = 2**COMPLETE_SUCCESS; else next_state = 2**COMPLETE_FAULT; - end - else //(pte.v & ~pte.x & ~pte.w & ~pte.r) pointer to next level in page table + end else //(pte.v & ~pte.x & ~pte.w & ~pte.r) pointer to next level in page table next_state = 2**SEND_REQUEST_2; end state[SEND_REQUEST_2] : - if (l1_request.ack) begin + if (l1_request.ack) next_state = 2**WAIT_REQUEST_2; - end state[WAIT_REQUEST_2] : - if (l1_response.data_valid) begin + if (l1_response.data_valid & ~discard_data) begin if (access_valid & privilege_valid) next_state = 2**COMPLETE_SUCCESS; else @@ -141,6 +161,9 @@ module mmu state[COMPLETE_SUCCESS], state[COMPLETE_FAULT] : next_state = 2**IDLE; endcase + //If request is aborted, return to IDLE + if (abort_request) + next_state = 2**IDLE; end always_ff @ (posedge clk) begin @@ -167,8 +190,17 @@ module mmu //////////////////////////////////////////////////// //Assertions - mmu_spurious_l1_response: - assert property (@(posedge clk) disable iff (rst) (l1_response.data_valid) |-> (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2])) - else $error("mmu recieved response without a request"); + `ifdef ENABLE_SIMULATION_ASSERTIONS + mmu_spurious_l1_response: + assert property (@(posedge clk) disable iff (rst) (l1_response.data_valid) |-> (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2])) + else $error("mmu recieved response without a request"); + `endif + + //TLB request remains high until it recieves a response from the MMU unless + //the transaction is aborted. As such, if TLB request is low and we are not in the + //IDLE state, then our current processor state has been corrupted + mmu_tlb_state_mismatch: + assert property (@(posedge clk) disable iff (rst) (~mmu.request) |-> (state[IDLE])) + else $error("MMU and TLB state mismatch"); endmodule diff --git a/core/taiga.sv b/core/taiga.sv index 42a5c43..76e9bf2 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -300,6 +300,7 @@ module taiga ( .clk (clk), .rst (rst), .mmu (immu) , + .abort_request (gc_fetch_flush), .l1_request (l1_request[L1_IMMU_ID]), .l1_response (l1_response[L1_IMMU_ID]) ); @@ -456,6 +457,7 @@ module taiga ( .clk (clk), .rst (rst), .mmu (dmmu) , + .abort_request (1'b0), .l1_request (l1_request[L1_DMMU_ID]), .l1_response (l1_response[L1_DMMU_ID]) ); diff --git a/core/taiga_types.sv b/core/taiga_types.sv index 8599661..d358d22 100755 --- a/core/taiga_types.sv +++ b/core/taiga_types.sv @@ -28,8 +28,9 @@ package taiga_types; localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS); localparam LOG2_COMMIT_PORTS = $clog2(COMMIT_PORTS); + localparam LOG2_MAX_IDS = $clog2(MAX_IDS); - typedef logic[$clog2(MAX_IDS)-1:0] id_t; + typedef logic[LOG2_MAX_IDS-1:0] id_t; typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t; typedef logic[1:0] branch_predictor_metadata_t; diff --git a/core/tlb_lut_ram.sv b/core/tlb_lut_ram.sv index c929eb4..995903b 100755 --- a/core/tlb_lut_ram.sv +++ b/core/tlb_lut_ram.sv @@ -114,11 +114,11 @@ module tlb_lut_ram #( always_ff @ (posedge clk) begin if (rst) - mmu.new_request <= 0; - else if (mmu.write_entry) - mmu.new_request <= 0; + mmu.request <= 0; + else if (mmu.write_entry | mmu.is_fault) + mmu.request <= 0; else if (tlb_on & ~hit & tlb.new_request) - mmu.new_request <= 1; + mmu.request <= 1; end assign mmu.virtual_address = tlb.virtual_address;