Clean-up TLB interface before moving ITLB

This commit is contained in:
Florian Zaruba 2018-02-08 13:13:09 +01:00
parent f0c4d6f3e4
commit c3f343e47c
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
7 changed files with 120 additions and 114 deletions

View file

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

View file

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

@ -1 +1 @@
Subproject commit 23e9244549a2b5bfc793ea69f753c5022401d881
Subproject commit c871f64a7bbafc6881cf948715556a43405948f1