mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 13:37:14 -04:00
TLB updates
This commit is contained in:
parent
f501c938f4
commit
b1d5439f7d
6 changed files with 104 additions and 49 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue