Add MMU implementation incl PTW and TLBs

This commit is contained in:
Florian Zaruba 2017-04-25 13:00:09 +02:00
parent c15ef3d1b7
commit c4edf3de3d
9 changed files with 277 additions and 216 deletions

View file

@ -15,7 +15,7 @@ agents = tb/agents/fu_if/fu_if.sv tb/agents/fu_if/fu_if_agent_pkg.sv \
interfaces = include/debug_if.svh include/mem_if.svh tb/agents/fifo_if/fifo_if.sv
# this list contains the standalone components
src = alu.sv tb/sequences/alu_sequence_pkg.sv tb/env/alu_env_pkg.sv tb/test/alu_lib_pkg.sv tb/alu_tb.sv \
tb/scoreboard_tb.sv ptw.sv \
tb/scoreboard_tb.sv ptw.sv tlb.sv \
if_stage.sv compressed_decoder.sv fetch_fifo.sv commit_stage.sv prefetch_buffer.sv \
mmu.sv lsu.sv fifo.sv tb/fifo_tb.sv mem_arbiter.sv \
scoreboard.sv issue_read_operands.sv decoder.sv id_stage.sv util/cluster_clock_gating.sv regfile.sv ex_stage.sv ariane.sv \

View file

@ -93,7 +93,7 @@ module ariane
priv_lvl_t priv_lvl_i;
logic flag_pum_i;
logic flag_mxr_i;
logic [19:0] pd_ppn_i;
logic [37:0] pd_ppn_i;
logic [0:0] asid_i;
logic flush_tlb_i;
@ -184,7 +184,7 @@ module ariane
.lsu_valid_o ( lsu_valid_o ),
// memory management
.enable_translation_i ( enable_translation_i ), // from CSR
.enable_translation_i ( 1'b0 ), // from CSR
.fetch_req_i ( fetch_req_i ),
.fetch_gnt_o ( fetch_gnt_o ),
.fetch_valid_o ( fetch_valid_o ),

106
btb.sv
View file

@ -1,106 +0,0 @@
// Author: Florian Zaruba, ETH Zurich
// Date: 19.04.2017
// Description: Branch Target Buffer implementation
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
import ariane_pkg::*;
module btb #(
parameter int NR_ENTRIES = 64,
parameter int BITS_SATURATION_COUNTER = 2
)
(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // flush the btb
input logic [63:0] vpc_i, // virtual PC from IF stage
input misspredict misspredict_i, // a miss-predict happened -> update data structure
output logic is_branch_o, // instruction at vpc_i is a branch
output logic predict_taken_o, // the branch is taken
output logic [63:0] branch_target_address_o // instruction has the following target address
);
// number of bits which are not used for indexing
localparam OFFSET = 2;
// typedef for all branch target entries
// we may want to try to put a tag field that fills the rest of the PC in-order to mitigate aliasing effects
struct packed {
logic valid;
logic [63:0] target_address;
logic [BITS_SATURATION_COUNTER-1:0] saturation_counter;
} btb_n [NR_ENTRIES-1:0], btb_q [NR_ENTRIES-1:0];
logic [$clog2(NR_ENTRIES)-1:0] index, update_pc;
logic [BITS_SATURATION_COUNTER-1:0] saturation_counter;
// get actual index positions
// we ignore the 0th bit since all instructions are aligned on
// a half word boundary
assign update_pc = misspredict_i.pc[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET];
assign index = vpc_i[$clog2(NR_ENTRIES) + OFFSET - 1:OFFSET];
// we combinatorially predict the branch and the target address
assign is_branch_o = btb_q[$unsigned(index)].valid;
assign predict_taken_o = btb_q[$unsigned(index)].saturation_counter[BITS_SATURATION_COUNTER-1];
assign branch_target_address_o = btb_q[$unsigned(index)].target_address;
// update on a miss-predict
always_comb begin : update_misspredict
btb_n = btb_q;
saturation_counter = btb_q[$unsigned(update_pc)].saturation_counter;
if (misspredict_i.valid) begin
btb_n[$unsigned(update_pc)].valid = 1'b1;
// update saturation counter
// first check if counter is already saturated in the positive regime e.g.: branch taken
if (saturation_counter == {BITS_SATURATION_COUNTER{1'b1}} && ~misspredict_i.is_taken) begin
// we can safely decrease it
btb_n[$unsigned(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 == {BITS_SATURATION_COUNTER{1'b0}} && misspredict_i.is_taken) begin
// we can safely increase it
btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter + 1;
end else begin // otherwise we are not in any boundaries and can decrease or increase it
if (misspredict_i.is_taken)
btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter + 1;
else
btb_n[$unsigned(update_pc)].saturation_counter = saturation_counter - 1;
end
// the target address is simply updated
btb_n[$unsigned(update_pc)].target_address = misspredict_i.target_address;
end
end
// sequential process
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
// TODO: think about the reset value
btb_q <= '{default: 0};
end else begin
// evict all entries
if (flush_i) begin
for (int i = 0; i < NR_ENTRIES; i++) begin
btb_q[i].valid <= 1'b0;
btb_q[i].saturation_counter <= '{default: 0};
end
end else begin
btb_q <= btb_n;
end
end
end
endmodule

View file

@ -55,7 +55,7 @@ module ex_stage #(
input priv_lvl_t priv_lvl_i,
input logic flag_pum_i,
input logic flag_mxr_i,
input logic [19:0] pd_ppn_i,
input logic [37:0] pd_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
mem_if.Slave instr_if,

View file

@ -153,6 +153,7 @@ package ariane_pkg;
PRIV_LVL_S = 2'b01,
PRIV_LVL_U = 2'b00
} priv_lvl_t;
// memory management, pte
typedef struct packed {
logic[37:0] ppn;
@ -166,6 +167,7 @@ package ariane_pkg;
logic r;
logic v;
} pte_t;
// Bits required for representation of physical address space as 4K pages
// (e.g. 27*4K == 39bit address space).
localparam PPN4K_WIDTH = 38;

122
lsu.sv
View file

@ -21,58 +21,100 @@ import ariane_pkg::*;
module lsu #(
parameter int ASID_WIDTH = 1
)(
input logic clk_i,
input logic rst_ni,
input logic clk_i,
input logic rst_ni,
input fu_op operator_i,
input logic [63:0] operand_a_i,
input logic [63:0] operand_b_i,
input logic [63:0] imm_i,
output logic lsu_ready_o, // FU is ready e.g. not busy
input logic lsu_valid_i, // Input is valid
input logic lsu_trans_id_i, // transaction id, needed for WB
output logic [4:0] lsu_trans_id_o, // ID of scoreboard entry at which to write back
output logic lsu_valid_o, // transaction id for which the output is the requested one
input fu_op operator_i,
input logic [63:0] operand_a_i,
input logic [63:0] operand_b_i,
input logic [63:0] imm_i,
output logic lsu_ready_o, // FU is ready e.g. not busy
input logic lsu_valid_i, // Input is valid
input logic [TRANS_ID_BITS-1:0] lsu_trans_id_i, // transaction id, needed for WB
output logic [TRANS_ID_BITS-1:0] lsu_trans_id_o, // ID of scoreboard entry at which to write back
output logic lsu_valid_o, // transaction id for which the output is the requested one
input logic enable_translation_i,
input logic enable_translation_i,
input logic fetch_req_i,
output logic fetch_gnt_o,
output logic fetch_valid_o,
output logic fetch_err_o,
input logic [63:0] fetch_vaddr_i,
output logic [31:0] fetch_rdata_o,
input logic fetch_req_i,
output logic fetch_gnt_o,
output logic fetch_valid_o,
output logic fetch_err_o,
input logic [63:0] fetch_vaddr_i,
output logic [31:0] fetch_rdata_o,
input priv_lvl_t priv_lvl_i,
input logic flag_pum_i,
input logic flag_mxr_i,
input logic [19:0] pd_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
mem_if.Slave instr_if,
mem_if.Slave data_if,
input priv_lvl_t priv_lvl_i,
input logic flag_pum_i,
input logic flag_mxr_i,
input logic [37:0] pd_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
output exception lsu_exception_o // to WB, signal exception status LD/ST exception
mem_if.Slave instr_if,
mem_if.Slave data_if,
output exception lsu_exception_o // to WB, signal exception status LD/ST exception
);
assign lsu_trans_id_o = lsu_trans_id_i;
assign lsu_valid_o = 1'b0;
logic [63:0] vaddr;
// dummy implementation
// instruction interface
assign instr_if.data_req = fetch_req_i;
assign fetch_gnt_o = instr_if.data_gnt;
assign fetch_valid_o = instr_if.data_rvalid;
assign instr_if.address = fetch_vaddr_i;
assign fetch_rdata_o = instr_if.data_rdata;
assign fetch_err_o = 1'b0;
// -------------------
// MMU e.g.: TLBs/PTW
// -------------------
// ---------------
// Memory Arbiter
// ---------------
logic [2:0][63:0] address_i;
logic [2:0][63:0] data_wdata_i;
logic [2:0] data_req_i;
logic [2:0] data_we_i;
logic [2:0][7:0] data_be_i;
logic [2:0] data_gnt_o;
logic [2:0] data_rvalid_o;
logic [2:0][63:0] data_rdata_o;
mem_arbiter i_mem_arbiter (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// to D$
.address_o ( data_if.address ),
.data_wdata_o ( data_if.data_wdata ),
.data_req_o ( data_if.data_req ),
.data_we_o ( data_if.data_we ),
.data_be_o ( data_if.data_be ),
.data_gnt_i ( data_if.data_gnt ),
.data_rvalid_i( data_if.data_rvalid ),
.data_rdata_i ( data_if.data_rdata ),
// from PTW, Load logic and store queue
.address_i ( address_i ),
.data_wdata_i ( data_wdata_i ),
.data_req_i ( data_req_i ),
.data_we_i ( data_we_i ),
.data_be_i ( data_be_i ),
.data_gnt_o ( data_gnt_o ),
.data_rvalid_o( data_rvalid_o ),
.data_rdata_o ( data_rdata_o )
);
// -------------------
// MMU e.g.: TLBs/PTW
// -------------------
logic lsu_req_i;
logic [63:0] lsu_vaddr_i;
logic lsu_ready_wb_i;
mmu #(
.INSTR_TLB_ENTRIES ( 16 ),
.DATA_TLB_ENTRIES ( 16 ),
.ASID_WIDTH ( ASID_WIDTH )
) i_mmu (
.lsu_req_i ( lsu_req_i ),
.lsu_vaddr_i ( lsu_vaddr_i ),
.lsu_valid_o ( ),
.*
);
// ---------------
// Store Queue

184
mmu.sv
View file

@ -38,21 +38,18 @@ module mmu #(
input logic [63:0] fetch_vaddr_i,
output logic [31:0] fetch_rdata_o, // pass-through because of interfaces
// LSU interface
// this is a more minimalistic interface because the actual addressing logic is handled
// in the LSU as we distinguish load and stores, what we do here is simple address translation
input logic lsu_req_i,
output logic lsu_gnt_o,
output logic lsu_valid_o,
input logic lsu_we_i,
input logic [7:0] lsu_be_i,
output logic lsu_err_o,
input logic [63:0] lsu_vaddr_i,
input logic [63:0] lsu_wdata_i, // pass-through because of interfaces
output logic [63:0] lsu_rdata_o, // pass-through because of interfaces
// if we need to walk the page table we can't grant in the same cycle
output logic lsu_valid_o, // translation is valid
// General control signals
input priv_lvl_t priv_lvl_i,
input logic flag_pum_i,
input logic flag_mxr_i,
// input logic flag_mprv_i,
input logic [19:0] pd_ppn_i,
input logic [37:0] pd_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic flush_tlb_i,
input logic lsu_ready_wb_i,
@ -62,13 +59,168 @@ module mmu #(
// Data memory interface
mem_if.Slave data_if
);
// dummy implementation
// instruction interface
assign instr_if.data_req = fetch_req_i;
assign fetch_gnt_o = instr_if.data_gnt;
assign fetch_valid_o = instr_if.data_rvalid;
assign instr_if.address = fetch_vaddr_i;
// assignments necessary to use interfaces here
// only done for the few signals of the instruction interface
logic [63:0] fetch_paddr;
logic fetch_req;
assign instr_if.data_req = fetch_req;
assign instr_if.address = fetch_paddr;
assign fetch_rdata_o = instr_if.data_rdata;
assign fetch_err_o = 1'b0;
// instruction error
logic ierr_valid_q, ierr_valid_n;
logic iaccess_err;
logic ptw_active;
logic walking_instr;
logic ptw_error;
logic flush_i;
logic update_is_2M;
logic update_is_1G;
logic [26:0] update_vpn;
logic [0:0] update_asid;
pte_t update_content;
logic itlb_update;
logic itlb_lu_access;
logic [0:0] lu_asid_i;
logic [63:0] lu_vaddr_i;
pte_t itlb_content;
logic itlb_is_2M;
logic itlb_is_1G;
logic itlb_lu_hit;
tlb #(
.TLB_ENTRIES ( INSTR_TLB_ENTRIES ),
.ASID_WIDTH ( ASID_WIDTH )
) itlb_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_i ),
.update_is_2M_i ( update_is_2M ),
.update_is_1G_i ( update_is_1G ),
.update_vpn_i ( update_vpn ),
.update_asid_i ( update_asid ),
.update_content_i ( update_content ),
.update_tlb_i ( itlb_update_i ),
.lu_access_i ( itlb_lu_access ),
.lu_asid_i ( lu_asid_i ),
.lu_vaddr_i ( lu_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 )
);
ptw #(
.ASID_WIDTH ( ASID_WIDTH )
) ptw_i
(
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( ),
.ptw_active_o ( ptw_active ),
.walking_instr_o ( walking_instr ),
.ptw_error_o ( ptw_error ),
.enable_translation_i ( enable_translation_i ),
.address_o ( data_if.address ),
.data_wdata_o ( data_if.data_wdata ),
.data_req_o ( data_if.data_req ),
.data_we_o ( data_if.data_we ),
.data_be_o ( data_if.data_be ),
.data_gnt_i ( data_if.data_gnt ),
.data_rvalid_i ( data_if.data_rvalid ),
.data_rdata_i ( data_if.data_rdata ),
.itlb_update_o ( itlb_update ),
.dtlb_update_o ( ),
.update_content_o ( update_content ),
.update_is_2M_o ( update_is_2M ),
.update_is_1G_o ( update_is_1G ),
.update_vpn_o ( update_vpn ),
.update_asid_o ( update_asid ),
.itlb_access_i ( itlb_lu_access ),
.itlb_miss_i ( ~itlb_lu_hit ),
.itlb_vaddr_i ( fetch_vaddr_i ),
.dtlb_access_i ( ),
.dtlb_miss_i ( ),
.dtlb_vaddr_i ( ),
.*
);
assign iaccess_err = fetch_req_i & (
((priv_lvl_i == PRIV_LVL_U) & ~itlb_content.u)
| (flag_pum_i & (priv_lvl_i == PRIV_LVL_S) & itlb_content.u)
);
//-----------------------
// Instruction interface
//-----------------------
always_comb begin
// MMU disabled: just pass through
automatic logic fetch_valid = instr_if.data_rvalid;
fetch_req = fetch_req_i;
fetch_paddr = fetch_vaddr_i;
fetch_gnt_o = instr_if.data_gnt;
fetch_err_o = 1'b0;
ierr_valid_n = 1'b0;
// MMU enabled: address from TLB, request delayed until hit. Error when TLB
// hit and no access right or TLB hit and translated address not valid (e.g.
// AXI decode error), or when PTW performs walk due to itlb miss and raises
// an error.
if (enable_translation_i) begin
fetch_req = 1'b0;
fetch_paddr = {itlb_content.ppn, fetch_vaddr_i[11:0]};
if (itlb_is_2M) begin
fetch_paddr[20:12] = fetch_vaddr_i[20:12];
end
if (itlb_is_1G) begin
fetch_paddr[29:12] = fetch_vaddr_i[29:12];
end
fetch_gnt_o = instr_if.data_gnt;
// TODO the following two ifs should be mutually exclusive
if (itlb_lu_hit) begin
fetch_req = fetch_req_i;
if (iaccess_err) begin
// Play through an instruction fetch with error signaled with rvalid
fetch_req = 1'b0;
fetch_gnt_o = 1'b1; // immediate grant
//fetch_valid = 1'b0; NOTE: valid from previous fetch: pass through
// NOTE: back-to-back transfers: We only get a request if previous
// transfer is completed, or completes in this cycle)
ierr_valid_n = 1'b1; // valid signaled in next cycle
end
end
if (ptw_active & walking_instr) begin
// On error play through fetch with error signaled with valid
fetch_gnt_o = ptw_error;
ierr_valid_n = ptw_error; // signal valid/error on next cycle
end
end
fetch_err_o = ierr_valid_q;
fetch_valid_o = fetch_valid || ierr_valid_q;
end
// registers
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
ierr_valid_q <= 1'b0;
end else begin
ierr_valid_q <= ierr_valid_n;
end
end
//-----------------------
// Data interface
//-----------------------
endmodule

61
ptw.sv
View file

@ -21,8 +21,7 @@
import ariane_pkg::*;
module ptw #(
parameter int ASID_WIDTH = 1,
parameter int CONTENT_SIZE = 24 // data: ppn + u + g + w + x_only , instr: ppn + u + g
parameter int ASID_WIDTH = 1
)
(
input logic clk_i, // Clock
@ -30,6 +29,9 @@ module ptw #(
input logic flush_i, // flush everything, we need to do this because
// actually everything we do is speculative at this stage
// e.g.: there could be a CSR instruction that changes everything
output logic ptw_active_o,
output logic walking_instr_o, // set when walking for TLB
output logic ptw_error_o, // set when an error occured
input logic enable_translation_i,
// memory port
output logic [63:0] address_o,
@ -43,23 +45,21 @@ module ptw #(
// to TLBs, update logic
output logic itlb_update_o,
output logic dtlb_update_o,
output logic [CONTENT_SIZE-1:0] itlb_update_content_o,
output logic [CONTENT_SIZE-1:0] dtlb_update_content_o,
output pte_t update_content_o,
output logic update_is_2M_o,
output logic update_is_1G_o,
output logic [26:0] update_vpn_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 [ASID_WIDTH-1:0] itlb_asid_i,
input logic [63:0] itlb_vaddr_i,
input logic dtlb_access_i,
input logic dtlb_miss_i,
input logic [ASID_WIDTH-1:0] dtlb_asid_i,
input logic [63:0] dtlb_vaddr_i,
// from CSR file
input logic [37:0] pd_ppn_i, // ppn from sptbr
@ -77,15 +77,17 @@ module ptw #(
PTW_PROPAGATE_ERROR
} ptw_state_q, ptw_state_n;
// RV39 defines three levels of page tables
// SV39 defines three levels of page tables
enum logic [1:0] {
LVL1, LVL2, LVL3
} ptw_lvl_q, ptw_lvl_n;
logic ptw_active;
assign ptw_active = (ptw_state_q != PTW_READY);
// is this an instruction page table walk?
logic is_instr_ptw_q, is_instr_ptw_n;
assign ptw_active_o = (ptw_state_q != PTW_READY);
assign walking_instr_o = is_instr_ptw_q;
// register the ASID
logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n;
// register the VPN we need to walk
@ -101,40 +103,7 @@ module ptw #(
assign update_vpn_o = tlb_update_vpn_q;
assign update_asid_o = tlb_update_asid_q;
struct packed {
// logic r; don't care
// logic w; don't care
// logic x; If page isn't executable it isn't put in the instruction TLB
logic u;
logic g;
logic[PPN4K_WIDTH-1:0] ppn;
} itlb_content;
struct packed {
// logic r; If page isn't readable it isn't put in the data TLB (unless it
// is executable and the MXR flag is set)
logic x_only; // Because of the MXR flag we need an indication if the page
// is actually not readable, but executable
logic w;
logic u;
logic g;
logic[PPN4K_WIDTH-1:0] ppn;
} dtlb_content;
always_comb begin
itlb_update_content_o = '{
u : ptw_pte_i.u,
g : ptw_pte_i.g,
ppn : ptw_pte_i.ppn[37:0]
};
dtlb_update_content_o = '{
x_only : ptw_pte_i.x & ~ptw_pte_i.r,
w : ptw_pte_i.w,
u : ptw_pte_i.u,
g : ptw_pte_i.g,
ppn : ptw_pte_i.ppn[37:0]
};
end
assign update_content_o = ptw_pte_i;
//-------------------
// Page table walker
@ -162,6 +131,7 @@ module ptw #(
always_comb begin : ptw
// default assignments
data_req_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;
@ -178,14 +148,14 @@ module ptw #(
if (enable_translation_i & itlb_access_i & itlb_miss_i & ~dtlb_access_i) begin
ptw_pptr_n = {pd_ppn_i, itlb_vaddr_i[38:30]};
is_instr_ptw_n = 1'b0;
tlb_update_asid_n = itlb_asid_i;
tlb_update_asid_n = asid_i;
tlb_update_vpn_n = itlb_vaddr_i[38:12];
ptw_state_n = PTW_WAIT_GRANT;
// we got a DTLB miss
end else if (enable_translation_i & dtlb_access_i & dtlb_miss_i) begin
ptw_pptr_n = {pd_ppn_i, dtlb_vaddr_i[38:30]};
is_instr_ptw_n = 1'b0;
tlb_update_asid_n = dtlb_asid_i;
tlb_update_asid_n = asid_i;
tlb_update_vpn_n = dtlb_vaddr_i[38:12];
ptw_state_n = PTW_WAIT_GRANT;
end
@ -263,6 +233,7 @@ module ptw #(
// TODO: propagate error
PTW_PROPAGATE_ERROR: begin
ptw_state_n = PTW_READY;
ptw_error_o = 1'b1;
end
default:

10
tlb.sv
View file

@ -17,11 +17,11 @@
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
import ariane_pkg::*;
module tlb #(
parameter int TLB_ENTRIES = 4,
parameter int ASID_WIDTH = 1,
parameter int CONTENT_SIZE = 24 // data: ppn + u + g + w + x_only , instr: ppn + u + g
parameter int ASID_WIDTH = 1
)
(
input logic clk_i, // Clock
@ -33,14 +33,14 @@ module tlb #(
input logic update_is_1G_i,
input logic [26:0] update_vpn_i,
input logic [ASID_WIDTH-1:0] update_asid_i,
input logic [CONTENT_SIZE-1:0] update_content_i,
input pte_t update_content_i,
input logic update_tlb_i,
// Lookup signals
input logic lu_access_i,
input logic [ASID_WIDTH-1:0] lu_asid_i,
input logic [63:0] lu_vaddr_i,
output logic [CONTENT_SIZE-1:0] lu_content_o,
output pte_t lu_content_o,
output logic lu_is_2M_o,
output logic lu_is_1G_o,
output logic lu_hit_o
@ -57,7 +57,7 @@ module tlb #(
logic valid;
} [TLB_ENTRIES-1:0] tags_q, tags_n;
logic [TLB_ENTRIES-1:0][CONTENT_SIZE-1:0] content_q, content_n;
pte_t [TLB_ENTRIES-1:0] content_q, content_n;
logic [8:0] vpn0, vpn1, vpn2;
logic [TLB_ENTRIES-1:0] lu_hit; // to replacement logic
logic [TLB_ENTRIES-1:0] replace_en; // replace the following entry, set by replacement strategy