TLB updates

This commit is contained in:
Eric Matthews 2020-08-27 17:00:11 -07:00
parent f501c938f4
commit b1d5439f7d
6 changed files with 104 additions and 49 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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<WAYS; i=i+1) begin
if(tag_hit[i] & tlb_on) tlb.physical_address[31:12] = ram_entry[i].phys_addr;
tlb.physical_address[31:12] = 0;
for (int i = 0; i < WAYS; i++) begin
if (tag_hit[i]) tlb.physical_address[31:12] |= ram_entry[i].phys_addr;
end
end
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//Assertions
multiple_tag_hit_in_tlb:
assert property (@(posedge clk) disable iff (rst) (tlb.done) |-> $onehot(tag_hit))
else $error("Multiple tag hits in TLB!");
endmodule
endmodule