diff --git a/core/csr_regs.sv b/core/csr_regs.sv index 40a9428..39aabb0 100755 --- a/core/csr_regs.sv +++ b/core/csr_regs.sv @@ -473,15 +473,12 @@ endgenerate //////////////////////////////////////////////////// //BEGIN OF SUPERVISOR REGS //////////////////////////////////////////////////// - -generate if (ENABLE_S_MODE) begin - - //****************************************************************** //TLB status --- used to mux physical/virtual address - assign tlb_on = satp.mode; + assign tlb_on = ENABLE_S_MODE & satp.mode; assign asid = satp.asid; //****************** +generate if (ENABLE_S_MODE) begin //////////////////////////////////////////////////// //MMU interface assign immu.mxr = mstatus.mxr; diff --git a/core/fetch.sv b/core/fetch.sv index f26d04a..a62e007 100755 --- a/core/fetch.sv +++ b/core/fetch.sv @@ -32,6 +32,7 @@ module fetch( input logic gc_fetch_hold, input logic gc_fetch_flush, input logic gc_fetch_pc_override, + input logic tlb_on, input logic exception, input logic [31:0] gc_fetch_pc, @@ -48,7 +49,7 @@ module fetch( output logic [31:0] if_pc, output logic [31:0] fetch_instruction, - tlb_interface.mem tlb, + tlb_interface.requester tlb, local_memory_interface.master instruction_bram, input logic icache_on, l1_arbiter_request_interface.master l1_request, @@ -71,6 +72,7 @@ module fetch( logic [31:0] unit_data_array [NUM_SUB_UNITS-1:0]; logic units_ready; + logic address_valid; typedef struct packed{ logic address_valid; @@ -87,6 +89,9 @@ module fetch( logic update_pc; logic new_mem_request; + logic exception_pending; + + logic [31:0] translated_address; //Cache related logic [31:0] stage2_phys_address; @@ -117,6 +122,16 @@ module fetch( next_pc = pc_plus_4; end + //If an exception occurs here in the fetch logic, + //hold the fetching of data from memory until the status of the + //exception has been resolved + always_ff @(posedge clk) begin + if (rst | gc_fetch_flush) + exception_pending <= 0; + else if (tlb.is_fault | (new_mem_request & ~address_valid)) + exception_pending <= 1; + end + assign bp.new_mem_request = update_pc; assign bp.next_pc = next_pc; assign bp.if_pc = pc; @@ -131,18 +146,19 @@ module fetch( assign tlb.virtual_address = pc; assign tlb.execute = 1; assign tlb.rnw = 0; - assign tlb.new_request = update_pc; + assign tlb.new_request = tlb.ready & tlb_on; + assign translated_address = tlb_on ? tlb.physical_address : pc; always_ff @(posedge clk) begin if (new_mem_request) - stage2_phys_address <= tlb.physical_address; + stage2_phys_address <= translated_address; end ////////////////////////////////////////////// //Issue Control Signals assign flush_or_rst = (rst | gc_fetch_flush); - assign new_mem_request = tlb.complete & pc_id_available & units_ready & ~gc_fetch_hold; + assign new_mem_request = (~tlb_on | tlb.done) & pc_id_available & units_ready & ~gc_fetch_hold & ~exception_pending; assign pc_id_assigned = new_mem_request; ////////////////////////////////////////////// @@ -156,7 +172,7 @@ module fetch( .one_hot (sub_unit_address_match), .int_out (fetch_attr_next.subunit_id) ); - assign fetch_attr_next.address_valid = |sub_unit_address_match; + assign fetch_attr_next.address_valid = address_valid; assign fetch_attr_fifo.data_in = fetch_attr_next; @@ -179,13 +195,14 @@ module fetch( assign unit_ready[i] = fetch_sub[i].ready; assign unit_data_valid[i] = fetch_sub[i].data_valid; assign fetch_sub[i].new_request = new_mem_request & sub_unit_address_match[i]; - assign fetch_sub[i].stage1_addr = tlb.physical_address; + assign fetch_sub[i].stage1_addr = translated_address; assign fetch_sub[i].stage2_addr = stage2_phys_address; assign fetch_sub[i].flush = gc_fetch_flush; assign unit_data_array[i] = fetch_sub[i].data_out; end endgenerate assign units_ready = &unit_ready; + assign address_valid = |sub_unit_address_match; generate if (USE_I_SCRATCH_MEM) begin ibram i_bram ( @@ -194,7 +211,7 @@ module fetch( .fetch_sub (fetch_sub[BRAM_ID]), .instruction_bram (instruction_bram) ); - assign sub_unit_address_match[BRAM_ID] = tlb.physical_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK]; + assign sub_unit_address_match[BRAM_ID] = translated_address[31:32-SCRATCH_BIT_CHECK] == SCRATCH_ADDR_L[31:32-SCRATCH_BIT_CHECK]; end endgenerate generate if (USE_ICACHE) begin @@ -206,7 +223,7 @@ module fetch( .l1_response (l1_response), .fetch_sub (fetch_sub[ICACHE_ID]) ); - assign sub_unit_address_match[ICACHE_ID] = tlb.physical_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK]; + assign sub_unit_address_match[ICACHE_ID] = translated_address[31:32-MEMORY_BIT_CHECK] == MEMORY_ADDR_L[31:32-MEMORY_BIT_CHECK]; end endgenerate diff --git a/core/interfaces.sv b/core/interfaces.sv index a544bc1..97430c9 100755 --- a/core/interfaces.sv +++ b/core/interfaces.sv @@ -159,17 +159,28 @@ interface mmu_interface; endinterface interface tlb_interface; - logic [31:0] virtual_address; + //Handshaking + logic ready; logic new_request; + logic done; + + //TLB Inputs + logic [31:0] virtual_address; logic rnw; logic execute; - logic complete; + //TLB Outputs + logic is_fault; logic [31:0] physical_address; - modport tlb (input virtual_address, new_request, rnw, execute, output complete, physical_address); - modport mem (output new_request, virtual_address, rnw, execute, input complete, physical_address); - + modport tlb ( + input new_request, virtual_address, rnw, execute, + output ready, done, is_fault, physical_address + ); + modport requester ( + output new_request, virtual_address, rnw, execute, + input ready, done, is_fault, physical_address + ); endinterface interface load_store_queue_interface; diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index 4248f99..c47c56c 100755 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -32,10 +32,11 @@ module load_store_unit ( input logic dcache_on, input logic clear_reservation, - tlb_interface.mem tlb, + tlb_interface.requester tlb, input logic gc_fetch_flush, input logic gc_issue_flush, + input logic tlb_on, l1_arbiter_request_interface.master l1_request, l1_arbiter_return_interface.master l1_response, @@ -84,7 +85,7 @@ module load_store_unit ( logic units_ready; logic unit_switch_stall; - logic ready_for_issue; + logic ready_for_issue_from_lsq; logic issue_request; logic load_complete; @@ -140,10 +141,10 @@ generate if (ENABLE_M_MODE) begin endcase end assign ls_exception_is_store = ls_inputs.store; - assign ls_exception.valid = unaligned_addr & issue.new_request; - assign ls_exception.code = ls_inputs.store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED; - assign ls_exception.tval = virtual_address; - assign ls_exception.id = issue.id; + assign ls_exception.valid = unaligned_addr & issue.new_request; + assign ls_exception.code = ls_inputs.store ? STORE_AMO_ADDR_MISSALIGNED : LOAD_ADDR_MISSALIGNED; + assign ls_exception.tval = virtual_address; + assign ls_exception.id = issue.id; end endgenerate @@ -152,7 +153,7 @@ endgenerate assign virtual_address = ls_inputs.rs1 + 32'(signed'(ls_inputs.offset)); assign tlb.virtual_address = virtual_address; - assign tlb.new_request = issue_request; + assign tlb.new_request = tlb_on & issue_request; assign tlb.execute = 0; assign tlb.rnw = ls_inputs.load & ~ls_inputs.store; @@ -177,7 +178,7 @@ endgenerate //////////////////////////////////////////////////// //Load Store Queue - assign lsq.addr = virtual_address; + assign lsq.addr = tlb_on ? tlb.physical_address : virtual_address; assign lsq.fn3 = ls_inputs.fn3; assign lsq.be = be; assign lsq.data_in = ls_inputs.rs2; @@ -188,7 +189,7 @@ endgenerate assign lsq.data_id = ls_inputs.store_forward_id; assign lsq.possible_issue = issue.possible_issue; - assign lsq.new_issue = issue.new_request & ~unaligned_addr; + assign lsq.new_issue = issue.new_request & ~unaligned_addr & (~tlb_on | tlb.done); logic [MAX_IDS-1:0] wb_hold_for_store_ids; load_store_queue lsq_block ( @@ -235,10 +236,10 @@ endgenerate assign units_ready = &unit_ready; assign load_complete = |unit_data_valid; - assign ready_for_issue = units_ready & (~unit_switch_stall); + assign ready_for_issue_from_lsq = units_ready & (~unit_switch_stall); - assign issue.ready = ls_inputs.forwarded_store ? lsq.ready & ready_for_forwarded_store : lsq.ready; - assign issue_request = lsq.transaction_ready & ready_for_issue; + assign issue.ready = (~tlb_on | tlb.ready) & (ls_inputs.forwarded_store ? lsq.ready & ready_for_forwarded_store : lsq.ready); + assign issue_request = lsq.transaction_ready & ready_for_issue_from_lsq; //////////////////////////////////////////////////// //Load attributes FIFO diff --git a/core/taiga.sv b/core/taiga.sv index d716d96..dd3a64f 100755 --- a/core/taiga.sv +++ b/core/taiga.sv @@ -262,7 +262,9 @@ module taiga ( .if_pc (if_pc), .fetch_instruction (fetch_instruction), .instruction_bram (instruction_bram), - .icache_on('1), .tlb(itlb), + .icache_on('1), + .tlb(itlb), + .tlb_on (tlb_on), .l1_request(l1_request[L1_ICACHE_ID]), .l1_response(l1_response[L1_ICACHE_ID]), .exception(1'b0) @@ -289,7 +291,7 @@ module taiga ( tlb_lut_ram #(ITLB_WAYS, ITLB_DEPTH) i_tlb ( .clk (clk), .rst (rst), - .tlb_on (tlb_on), + .abort_request (gc_fetch_flush), .gc_tlb_flush (gc_tlb_flush), .asid (asid), .tlb (itlb), @@ -307,7 +309,8 @@ module taiga ( end else begin - assign itlb.complete = 1; + assign itlb.ready = 1; + assign itlb.done = itlb.new_request; assign itlb.physical_address = itlb.virtual_address; end endgenerate @@ -420,7 +423,8 @@ module taiga ( .clear_reservation (1'b0), .tlb (dtlb), .gc_fetch_flush (gc_fetch_flush), - .gc_issue_flush (gc_issue_flush), + .gc_issue_flush (gc_issue_flush), + .tlb_on (tlb_on), .l1_request (l1_request[L1_DCACHE_ID]), .l1_response (l1_response[L1_DCACHE_ID]), .sc_complete (sc_complete), @@ -446,7 +450,7 @@ module taiga ( tlb_lut_ram #(DTLB_WAYS, DTLB_DEPTH) d_tlb ( .clk (clk), .rst (rst), - .tlb_on (tlb_on), + .abort_request (1'b0), .gc_tlb_flush (gc_tlb_flush), .asid (asid), .tlb (dtlb), @@ -463,7 +467,8 @@ module taiga ( ); end else begin - assign dtlb.complete = 1; + assign dtlb.ready = 1; + assign dtlb.done = dtlb.new_request; assign dtlb.physical_address = dtlb.virtual_address; end endgenerate diff --git a/core/tlb_lut_ram.sv b/core/tlb_lut_ram.sv index 995903b..0f4fe34 100755 --- a/core/tlb_lut_ram.sv +++ b/core/tlb_lut_ram.sv @@ -30,8 +30,8 @@ module tlb_lut_ram #( ( input logic clk, input logic rst, - input logic tlb_on, - input gc_tlb_flush, + input logic gc_tlb_flush, + input logic abort_request, input logic [ASIDLEN-1:0] asid, mmu_interface.tlb mmu, tlb_interface.tlb tlb @@ -62,6 +62,8 @@ module tlb_lut_ram #( logic [$clog2(DEPTH)-1:0] flush_addr; logic [WAYS-1:0] tlb_write; + logic request_in_progress; + logic mmu_request_complete; //////////////////////////////////////////////////// //Implementation //LUTRAM-based @@ -112,30 +114,52 @@ module tlb_lut_ram #( end end + assign tlb.ready = ~request_in_progress; + always_ff @ (posedge clk) begin if (rst) - mmu.request <= 0; - else if (mmu.write_entry | mmu.is_fault) - mmu.request <= 0; - else if (tlb_on & ~hit & tlb.new_request) - mmu.request <= 1; + request_in_progress <= 0; + else if (mmu.write_entry | mmu.is_fault | abort_request) + request_in_progress <= 0; + else if (tlb.new_request & ~hit) + request_in_progress <= 1; + end + + assign mmu.request = request_in_progress; + + always_ff @ (posedge clk) begin + if (rst) + mmu_request_complete <= 0; + else + mmu_request_complete <= mmu.write_entry; end assign mmu.virtual_address = tlb.virtual_address; assign mmu.execute = tlb.execute; assign mmu.rnw = tlb.rnw; - //On a TLB miss, the + //On a TLB miss, the entry is requested from the MMU + //Once the request completes, it will update the TLB, causing + //the current request to output a hit assign hit = |tag_hit; - assign tlb.complete = hit | ~tlb_on; + assign tlb.done = hit & (tlb.new_request | mmu_request_complete); + assign tlb.is_fault = mmu.is_fault; always_comb begin tlb.physical_address[11:0] = tlb.virtual_address[11:0]; - tlb.physical_address[31:12] = tlb.virtual_address[31:12]; - for (int i=0; i $onehot(tag_hit)) + else $error("Multiple tag hits in TLB!"); -endmodule +endmodule \ No newline at end of file