mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-24 22:27:10 -04:00
Clean-up TLB interface before moving ITLB
This commit is contained in:
parent
f0c4d6f3e4
commit
c3f343e47c
7 changed files with 120 additions and 114 deletions
|
@ -265,6 +265,16 @@ package ariane_pkg;
|
|||
logic v;
|
||||
} pte_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic valid; // valid flag
|
||||
logic is_2M; //
|
||||
logic is_1G; //
|
||||
logic [26:0] vpn;
|
||||
logic [ASID_WIDTH-1:0] asid;
|
||||
pte_t content;
|
||||
} tlb_update_t;
|
||||
|
||||
// Bits required for representation of physical address space as 4K pages
|
||||
// (e.g. 27*4K == 39bit address space).
|
||||
localparam PPN4K_WIDTH = 38;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// Date: 08.02.2018
|
||||
// Description: Ariane Instruction Fetch Frontend
|
||||
|
||||
// import ariane_pkg::*;
|
||||
import ariane_pkg::*;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
|
@ -53,9 +53,33 @@ module frontend #(
|
|||
parameter int unsigned BHT_ENTRIES = 32,
|
||||
parameter int unsigned RAS_DEPTH = 2
|
||||
)(
|
||||
input clk_i, // Clock
|
||||
input rst_ni // Asynchronous reset active low
|
||||
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush request for PCGEN
|
||||
input logic flush_bp_i, // flush branch prediction
|
||||
// global input
|
||||
input logic [63:0] boot_addr_i,
|
||||
input logic fetch_enable_i, // start fetching instructions
|
||||
// Set a new PC
|
||||
// mispredict
|
||||
input branchpredict_t resolved_branch_i, // from controller signaling a branch_predict -> update BTB
|
||||
// from commit, when flushing the whole pipeline
|
||||
input logic [63:0] pc_commit_i, // PC of instruction in commit stage
|
||||
// CSR input
|
||||
input logic [63:0] epc_i, // exception PC which we need to return to
|
||||
input logic eret_i, // return from exception
|
||||
input logic [63:0] trap_vector_base_i, // base of trap vector
|
||||
input logic ex_valid_i, // exception is valid - from commit
|
||||
// Debug
|
||||
input logic [63:0] debug_pc_i, // PC from debug stage
|
||||
input logic debug_set_pc_i, // Set PC request from debug
|
||||
// Instruction Fetch
|
||||
AXI_BUS.Master instr_if,
|
||||
//
|
||||
// instruction output port -> to processor back-end
|
||||
output fetch_entry_t fetch_entry_o, // fetch entry containing all relevant data for the ID stage
|
||||
output logic fetch_entry_valid_o, // instruction in IF is valid
|
||||
input logic fetch_ack_i // ID acknowledged this instruction
|
||||
);
|
||||
|
||||
logic push_i;
|
||||
|
@ -64,7 +88,6 @@ module frontend #(
|
|||
ras_t data_o;
|
||||
bht_update_t bht_update_i;
|
||||
bht_prediction_t bht_prediction_o;
|
||||
logic flush_i;
|
||||
logic [63:0] vpc_i;
|
||||
btb_update_t btb_update_i;
|
||||
btb_prediction_t btb_prediction_o;
|
||||
|
@ -108,9 +131,9 @@ endmodule
|
|||
// ------------------------------
|
||||
// Instruction Cache
|
||||
// ------------------------------
|
||||
module icache #()();
|
||||
// module icache #()();
|
||||
|
||||
endmodule
|
||||
// endmodule
|
||||
|
||||
// ------------------------------
|
||||
// Branch Prediction
|
||||
|
@ -265,7 +288,7 @@ module bht #(
|
|||
if (~bht_update_i.taken)
|
||||
bht_d[update_pc].saturation_counter = saturation_counter - 1;
|
||||
// then check if it saturated in the negative regime e.g.: branch not taken
|
||||
end else if (saturation_counter == 2'b11) begin
|
||||
end else if (saturation_counter == 2'b00) begin
|
||||
// we can safely increase it
|
||||
if (bht_update_i.taken)
|
||||
bht_d[update_pc].saturation_counter = saturation_counter + 1;
|
||||
|
|
46
src/mmu.sv
Normal file → Executable file
46
src/mmu.sv
Normal file → Executable file
|
@ -94,11 +94,8 @@ module mmu #(
|
|||
logic ptw_error; // PTW threw an exception
|
||||
logic [63:0] faulting_address;
|
||||
|
||||
logic update_is_2M;
|
||||
logic update_is_1G;
|
||||
logic [38:0] update_vaddr;
|
||||
logic [0:0] update_asid;
|
||||
pte_t update_content;
|
||||
tlb_update_t update_ptw_itlb, update_ptw_dtlb;
|
||||
|
||||
logic itlb_update;
|
||||
logic itlb_lu_access;
|
||||
|
@ -122,44 +119,38 @@ module mmu #(
|
|||
tlb #(
|
||||
.TLB_ENTRIES ( INSTR_TLB_ENTRIES ),
|
||||
.ASID_WIDTH ( ASID_WIDTH )
|
||||
) itlb_i (
|
||||
) i_itlb (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( flush_tlb_i ),
|
||||
.update_is_2M_i ( update_is_2M ),
|
||||
.update_is_1G_i ( update_is_1G ),
|
||||
.update_vpn_i ( update_vaddr[38:12] ),
|
||||
.update_asid_i ( update_asid ),
|
||||
.update_content_i ( update_content ),
|
||||
.update_tlb_i ( itlb_update ),
|
||||
|
||||
.update_i ( update_ptw_itlb ),
|
||||
|
||||
.lu_access_i ( itlb_lu_access ),
|
||||
.lu_asid_i ( asid_i ),
|
||||
.lu_vaddr_i ( fetch_vaddr_i ),
|
||||
.lu_content_o ( itlb_content ),
|
||||
|
||||
.lu_is_2M_o ( itlb_is_2M ),
|
||||
.lu_is_1G_o ( itlb_is_1G ),
|
||||
.lu_hit_o ( itlb_lu_hit )
|
||||
);
|
||||
|
||||
tlb #(
|
||||
.TLB_ENTRIES(DATA_TLB_ENTRIES),
|
||||
.ASID_WIDTH(ASID_WIDTH))
|
||||
dtlb_i (
|
||||
.TLB_ENTRIES ( DATA_TLB_ENTRIES ),
|
||||
.ASID_WIDTH ( ASID_WIDTH )
|
||||
) i_dtlb (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( flush_tlb_i ),
|
||||
.update_is_2M_i ( update_is_2M ),
|
||||
.update_is_1G_i ( update_is_1G ),
|
||||
.update_vpn_i ( update_vaddr[38:12] ),
|
||||
.update_asid_i ( update_asid ),
|
||||
.update_content_i ( update_content ),
|
||||
.update_tlb_i ( dtlb_update ),
|
||||
|
||||
.update_i ( update_ptw_dtlb ),
|
||||
|
||||
.lu_access_i ( dtlb_lu_access ),
|
||||
.lu_asid_i ( asid_i ),
|
||||
.lu_vaddr_i ( lsu_vaddr_i ),
|
||||
.lu_content_o ( dtlb_content ),
|
||||
|
||||
.lu_is_2M_o ( dtlb_is_2M ),
|
||||
.lu_is_1G_o ( dtlb_is_1G ),
|
||||
.lu_hit_o ( dtlb_lu_hit )
|
||||
|
@ -168,8 +159,7 @@ module mmu #(
|
|||
|
||||
ptw #(
|
||||
.ASID_WIDTH ( ASID_WIDTH )
|
||||
) ptw_i
|
||||
(
|
||||
) i_ptw (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.ptw_active_o ( ptw_active ),
|
||||
|
@ -178,20 +168,16 @@ module mmu #(
|
|||
.faulting_address_o ( faulting_address ),
|
||||
.enable_translation_i ( enable_translation_i ),
|
||||
|
||||
.itlb_update_o ( itlb_update ),
|
||||
.dtlb_update_o ( dtlb_update ),
|
||||
.update_content_o ( update_content ),
|
||||
.update_is_2M_o ( update_is_2M ),
|
||||
.update_is_1G_o ( update_is_1G ),
|
||||
.update_vaddr_o ( update_vaddr ),
|
||||
.update_asid_o ( update_asid ),
|
||||
.itlb_update_o ( update_ptw_itlb ),
|
||||
.dtlb_update_o ( update_ptw_dtlb ),
|
||||
|
||||
.itlb_access_i ( itlb_lu_access ),
|
||||
.itlb_miss_i ( ~itlb_lu_hit ),
|
||||
.itlb_hit_i ( itlb_lu_hit ),
|
||||
.itlb_vaddr_i ( fetch_vaddr_i ),
|
||||
|
||||
.dtlb_access_i ( dtlb_lu_access ),
|
||||
.dtlb_miss_i ( ~dtlb_lu_hit ),
|
||||
.dtlb_hit_i ( dtlb_lu_hit ),
|
||||
.dtlb_vaddr_i ( lsu_vaddr_i ),
|
||||
.*
|
||||
);
|
||||
|
|
14
src/pcgen_stage.sv
Normal file → Executable file
14
src/pcgen_stage.sv
Normal file → Executable file
|
@ -48,19 +48,7 @@ module pcgen_stage (
|
|||
// branch-predict input register -> this path is critical
|
||||
branchpredict_t resolved_branch_q;
|
||||
|
||||
btb #(
|
||||
.NR_ENTRIES ( BTB_ENTRIES ),
|
||||
.BITS_SATURATION_COUNTER ( BITS_SATURATION_COUNTER )
|
||||
)
|
||||
btb_i
|
||||
(
|
||||
// Use the PC from last cycle to perform branch lookup for the current cycle
|
||||
.flush_i ( flush_bp_i ),
|
||||
.vpc_i ( npc_q ),
|
||||
.branch_predict_i ( resolved_branch_q ), // update port
|
||||
.branch_predict_o ( branch_predict_btb ), // read port
|
||||
.*
|
||||
);
|
||||
assign branch_predict_btb = '0;
|
||||
// -------------------
|
||||
// Next PC
|
||||
// -------------------
|
||||
|
|
89
src/ptw.sv
Normal file → Executable file
89
src/ptw.sv
Normal file → Executable file
|
@ -18,8 +18,7 @@ import ariane_pkg::*;
|
|||
|
||||
module ptw #(
|
||||
parameter int ASID_WIDTH = 1
|
||||
)
|
||||
(
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush everything, we need to do this because
|
||||
|
@ -47,23 +46,20 @@ module ptw #(
|
|||
input logic data_rvalid_i,
|
||||
input logic [63:0] data_rdata_i,
|
||||
// to TLBs, update logic
|
||||
output logic itlb_update_o,
|
||||
output logic dtlb_update_o,
|
||||
output pte_t update_content_o,
|
||||
output tlb_update_t itlb_update_o,
|
||||
output tlb_update_t dtlb_update_o,
|
||||
|
||||
output logic update_is_2M_o,
|
||||
output logic update_is_1G_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
|
||||
// did we miss?
|
||||
input logic itlb_access_i,
|
||||
input logic itlb_miss_i,
|
||||
input logic itlb_hit_i,
|
||||
input logic [63:0] itlb_vaddr_i,
|
||||
|
||||
input logic dtlb_access_i,
|
||||
input logic dtlb_miss_i,
|
||||
input logic dtlb_hit_i,
|
||||
input logic [63:0] dtlb_vaddr_i,
|
||||
// from CSR file
|
||||
input logic [43:0] satp_ppn_i, // ppn from satp
|
||||
|
@ -107,6 +103,7 @@ module ptw #(
|
|||
|
||||
// Assignments
|
||||
assign update_vaddr_o = vaddr_q;
|
||||
|
||||
assign ptw_active_o = (CS != IDLE);
|
||||
assign walking_instr_o = is_instr_ptw_q;
|
||||
// directly output the correct physical address
|
||||
|
@ -116,13 +113,23 @@ module ptw #(
|
|||
assign kill_req_o = '0;
|
||||
// we are never going to write with the HPTW
|
||||
assign data_wdata_o = 64'b0;
|
||||
// -----------
|
||||
// TLB Update
|
||||
// -----------
|
||||
assign itlb_update_o.vpn = vaddr_q[38:12];
|
||||
assign dtlb_update_o.vpn = vaddr_q[38:12];
|
||||
// update the correct page table level
|
||||
assign update_is_2M_o = (ptw_lvl_q == LVL2);
|
||||
assign update_is_1G_o = (ptw_lvl_q == LVL1);
|
||||
assign itlb_update_o.is_2M = (ptw_lvl_q == LVL2);
|
||||
assign itlb_update_o.is_1G = (ptw_lvl_q == LVL1);
|
||||
assign dtlb_update_o.is_2M = (ptw_lvl_q == LVL2);
|
||||
assign dtlb_update_o.is_1G = (ptw_lvl_q == LVL1);
|
||||
// output the correct ASID
|
||||
assign update_asid_o = tlb_update_asid_q;
|
||||
assign itlb_update_o.asid = tlb_update_asid_q;
|
||||
assign dtlb_update_o.asid = tlb_update_asid_q;
|
||||
// set the global mapping bit
|
||||
assign update_content_o = pte | (global_mapping_q << 5);
|
||||
assign itlb_update_o.content = pte | (global_mapping_q << 5);
|
||||
assign dtlb_update_o.content = pte | (global_mapping_q << 5);
|
||||
|
||||
assign tag_valid_o = tag_valid_q;
|
||||
|
||||
//-------------------
|
||||
|
@ -151,26 +158,26 @@ module ptw #(
|
|||
always_comb begin : ptw
|
||||
// default assignments
|
||||
// PTW memory interface
|
||||
tag_valid_n = 1'b0;
|
||||
data_req_o = 1'b0;
|
||||
data_be_o = 8'hFF;
|
||||
data_size_o = 2'b11;
|
||||
data_we_o = 1'b0;
|
||||
ptw_error_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o = 1'b0;
|
||||
is_instr_ptw_n = is_instr_ptw_q;
|
||||
ptw_lvl_n = ptw_lvl_q;
|
||||
ptw_pptr_n = ptw_pptr_q;
|
||||
NS = CS;
|
||||
global_mapping_n = global_mapping_q;
|
||||
tag_valid_n = 1'b0;
|
||||
data_req_o = 1'b0;
|
||||
data_be_o = 8'hFF;
|
||||
data_size_o = 2'b11;
|
||||
data_we_o = 1'b0;
|
||||
ptw_error_o = 1'b0;
|
||||
itlb_update_o.valid = 1'b0;
|
||||
dtlb_update_o.valid = 1'b0;
|
||||
is_instr_ptw_n = is_instr_ptw_q;
|
||||
ptw_lvl_n = ptw_lvl_q;
|
||||
ptw_pptr_n = ptw_pptr_q;
|
||||
NS = CS;
|
||||
global_mapping_n = global_mapping_q;
|
||||
// input registers
|
||||
tlb_update_asid_n = tlb_update_asid_q;
|
||||
vaddr_n = vaddr_q;
|
||||
faulting_address_o = '0;
|
||||
tlb_update_asid_n = tlb_update_asid_q;
|
||||
vaddr_n = vaddr_q;
|
||||
faulting_address_o = '0;
|
||||
|
||||
itlb_miss_o = 1'b0;
|
||||
dtlb_miss_o = 1'b0;
|
||||
itlb_miss_o = 1'b0;
|
||||
dtlb_miss_o = 1'b0;
|
||||
|
||||
case (CS)
|
||||
|
||||
|
@ -180,7 +187,7 @@ module ptw #(
|
|||
global_mapping_n = 1'b0;
|
||||
is_instr_ptw_n = 1'b0;
|
||||
// if we got an ITLB miss
|
||||
if (enable_translation_i & itlb_access_i & itlb_miss_i & ~dtlb_access_i) begin
|
||||
if (enable_translation_i & itlb_access_i & ~itlb_hit_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;
|
||||
|
@ -188,7 +195,7 @@ module ptw #(
|
|||
NS = WAIT_GRANT;
|
||||
itlb_miss_o = 1'b1;
|
||||
// we got an DTLB miss
|
||||
end else if (en_ld_st_translation_i & dtlb_access_i & dtlb_miss_i) begin
|
||||
end else if (en_ld_st_translation_i & dtlb_access_i & ~dtlb_hit_i) begin
|
||||
ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[38:30], 3'b0};
|
||||
tlb_update_asid_n = asid_i;
|
||||
vaddr_n = dtlb_vaddr_i;
|
||||
|
@ -241,7 +248,7 @@ module ptw #(
|
|||
if (!pte.x || !pte.a)
|
||||
NS = PROPAGATE_ERROR;
|
||||
else
|
||||
itlb_update_o = 1'b1;
|
||||
itlb_update_o.valid = 1'b1;
|
||||
|
||||
end else begin
|
||||
// ------------
|
||||
|
@ -253,7 +260,7 @@ module ptw #(
|
|||
// we can directly raise an error. This doesn't put a useless
|
||||
// entry into the TLB.
|
||||
if (pte.a && (pte.r || (pte.x && mxr_i))) begin
|
||||
dtlb_update_o = 1'b1;
|
||||
dtlb_update_o.valid = 1'b1;
|
||||
end else begin
|
||||
NS = PROPAGATE_ERROR;
|
||||
end
|
||||
|
@ -261,7 +268,7 @@ module ptw #(
|
|||
// If the request was a store and the page is not write-able, raise an error
|
||||
// the same applies if the dirty flag is not set
|
||||
if (lsu_is_store_i && (!pte.w || !pte.d)) begin
|
||||
dtlb_update_o = 1'b0;
|
||||
dtlb_update_o.valid = 1'b0;
|
||||
NS = PROPAGATE_ERROR;
|
||||
end
|
||||
end
|
||||
|
@ -270,12 +277,12 @@ module ptw #(
|
|||
// exception.
|
||||
if (ptw_lvl_q == LVL1 && pte.ppn[17:0] != '0) begin
|
||||
NS = PROPAGATE_ERROR;
|
||||
dtlb_update_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o.valid = 1'b0;
|
||||
itlb_update_o.valid = 1'b0;
|
||||
end else if (ptw_lvl_q == LVL2 && pte.ppn[8:0] != '0) begin
|
||||
NS = PROPAGATE_ERROR;
|
||||
dtlb_update_o = 1'b0;
|
||||
itlb_update_o = 1'b0;
|
||||
dtlb_update_o.valid = 1'b0;
|
||||
itlb_update_o.valid = 1'b0;
|
||||
end
|
||||
// this is a pointer to the next TLB level
|
||||
end else begin
|
||||
|
|
34
src/tlb.sv
Normal file → Executable file
34
src/tlb.sv
Normal file → Executable file
|
@ -19,20 +19,12 @@ import ariane_pkg::*;
|
|||
module tlb #(
|
||||
parameter int unsigned TLB_ENTRIES = 4,
|
||||
parameter int unsigned ASID_WIDTH = 1
|
||||
)
|
||||
(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // Flush signal
|
||||
|
||||
// Update signals
|
||||
input logic update_is_2M_i,
|
||||
input logic update_is_1G_i,
|
||||
input logic [26:0] update_vpn_i,
|
||||
input logic [ASID_WIDTH-1:0] update_asid_i,
|
||||
input pte_t update_content_i,
|
||||
input logic update_tlb_i,
|
||||
|
||||
// Update TLB
|
||||
input tlb_update_t update_i,
|
||||
// Lookup signals
|
||||
input logic lu_access_i,
|
||||
input logic [ASID_WIDTH-1:0] lu_asid_i,
|
||||
|
@ -113,19 +105,19 @@ module tlb #(
|
|||
tags_n[i].valid = 1'b0;
|
||||
|
||||
// normal replacement
|
||||
end else if (update_tlb_i & replace_en[i]) begin
|
||||
end else if (update_i.valid & replace_en[i]) begin
|
||||
// update tag array
|
||||
tags_n[i] = '{
|
||||
asid: update_asid_i,
|
||||
vpn2: update_vpn_i [26:18],
|
||||
vpn1: update_vpn_i [17:9],
|
||||
vpn0: update_vpn_i [8:0],
|
||||
is_1G: update_is_1G_i,
|
||||
is_2M: update_is_2M_i,
|
||||
asid: update_i.asid,
|
||||
vpn2: update_i.vpn [26:18],
|
||||
vpn1: update_i.vpn [17:9],
|
||||
vpn0: update_i.vpn [8:0],
|
||||
is_1G: update_i.is_1G,
|
||||
is_2M: update_i.is_2M,
|
||||
valid: 1'b1
|
||||
};
|
||||
// and content as well
|
||||
content_n[i] = update_content_i;
|
||||
content_n[i] = update_i.content;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
2
tb
2
tb
|
@ -1 +1 @@
|
|||
Subproject commit 23e9244549a2b5bfc793ea69f753c5022401d881
|
||||
Subproject commit c871f64a7bbafc6881cf948715556a43405948f1
|
Loading…
Add table
Add a link
Reference in a new issue