Simplfy instruction address translation

This commit is contained in:
Florian Zaruba 2018-02-16 11:07:30 +01:00
parent 96a8e3165e
commit f2d45c007b
5 changed files with 50 additions and 141 deletions

View file

@ -176,11 +176,10 @@ module ariane #(
// IF <-> EX
// --------------
logic fetch_req_if_ex;
logic fetch_gnt_ex_if;
logic fetch_valid_ex_if;
logic [63:0] fetch_rdata_ex_if;
exception_t fetch_ex_ex_if;
logic [63:0] fetch_vaddr_if_ex;
logic fetch_valid_ex_if;
logic [63:0] fetch_paddr_ex_if;
exception_t fetch_ex_ex_if;
// --------------
// CSR <-> *
// --------------
@ -249,13 +248,6 @@ module ariane #(
// ----------------
// ICache <-> *
// ----------------
logic [63:0] instr_if_address;
logic instr_if_data_req; // fetch request
logic [3:0] instr_if_data_be;
logic instr_if_data_gnt; // fetch request
logic instr_if_data_rvalid; // fetch data
logic [63:0] instr_if_data_rdata;
logic flush_icache_ctrl_icache;
logic bypass_icache_csr_icache;
@ -270,9 +262,13 @@ module ariane #(
.flush_i ( flush_ctrl_if ), // not entirely correct
.flush_bp_i ( 1'b0 ),
.flush_icache_i ( flush_icache_ctrl_icache ),
.flush_itlb_i ( flush_tlb_ctrl_ex ),
.boot_addr_i ( boot_addr_i ),
.fetch_enable_i ( fetch_enable ),
.fetch_req_o ( fetch_req_if_ex ),
.fetch_vaddr_o ( fetch_vaddr_if_ex ),
.fetch_valid_i ( fetch_valid_ex_if ),
.fetch_paddr_i ( fetch_paddr_ex_if ),
.fetch_exception_i ( fetch_ex_ex_if ),
.resolved_branch_i ( resolved_branch ),
.pc_commit_i ( pc_commit ),
.set_pc_commit_i ( set_pc_ctrl_pcgen ),
@ -437,12 +433,12 @@ module ariane #(
.enable_translation_i ( enable_translation_csr_ex ), // from CSR
.en_ld_st_translation_i ( en_ld_st_translation_csr_ex ),
.flush_tlb_i ( flush_tlb_ctrl_ex ),
.fetch_req_i ( fetch_req_if_ex ),
.fetch_gnt_o ( fetch_gnt_ex_if ),
.fetch_valid_o ( fetch_valid_ex_if ),
.fetch_vaddr_i ( fetch_vaddr_if_ex ),
.fetch_rdata_o ( fetch_rdata_ex_if ),
.fetch_ex_o ( fetch_ex_ex_if ), // fetch exception to IF
.fetch_paddr_o ( fetch_paddr_ex_if ),
.fetch_exception_o ( fetch_ex_ex_if ), // fetch exception to IF
.priv_lvl_i ( priv_lvl ), // from CSR
.ld_st_priv_lvl_i ( ld_st_priv_lvl_csr_ex ), // from CSR
.sum_i ( sum_csr_ex ), // from CSR
@ -456,13 +452,6 @@ module ariane #(
.mult_result_o ( mult_result_ex_id ),
.mult_valid_o ( mult_valid_ex_id ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_req_o ( instr_if_data_req ),
.instr_if_data_be_o ( instr_if_data_be ),
.instr_if_data_gnt_i ( instr_if_data_gnt ),
.instr_if_data_rvalid_i ( instr_if_data_rvalid ),
.instr_if_data_rdata_i ( instr_if_data_rdata ),
.data_if ( data_if ),
.dcache_en_i ( dcache_en_csr_nbdcache ),
.flush_dcache_i ( flush_dcache_ctrl_ex | flush_dcache_i ),
@ -502,8 +491,7 @@ module ariane #(
// ---------
csr_regfile #(
.ASID_WIDTH ( ASID_WIDTH )
)
csr_regfile_i (
) csr_regfile_i (
.flush_o ( flush_csr_ctrl ),
.halt_csr_o ( halt_csr_ctrl ),
.debug_csr_req_i ( csr_req_debug_csr ),

View file

@ -82,11 +82,10 @@ module ex_stage #(
input logic en_ld_st_translation_i,
input logic flush_tlb_i,
input logic fetch_req_i,
output logic fetch_gnt_o,
output logic fetch_valid_o,
input logic [63:0] fetch_vaddr_i,
output logic [63:0] fetch_rdata_o,
output exception_t fetch_ex_o,
output logic fetch_valid_o,
output logic [63:0] fetch_paddr_o,
output exception_t fetch_exception_o,
input priv_lvl_t priv_lvl_i,
input priv_lvl_t ld_st_priv_lvl_i,
input logic sum_i,
@ -99,13 +98,6 @@ module ex_stage #(
output logic dtlb_miss_o,
output logic dcache_miss_o,
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [3:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
// DCache interface
input logic dcache_en_i,
input logic flush_dcache_i,

View file

@ -26,11 +26,16 @@ module frontend #(
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // flush request for PCGEN
input logic flush_bp_i, // flush branch prediction
input logic flush_icache_i, // instruction fence in
input logic flush_itlb_i, // flush itlb
input logic flush_icache_i, // instruction fence in
// global input
input logic [63:0] boot_addr_i,
input logic fetch_enable_i, // start fetching instructions
// Address translation interface
output logic fetch_req_o, // address translation request
output logic [63:0] fetch_vaddr_o, // virtual address out
input logic fetch_valid_i, // address translation valid
input logic [63:0] fetch_paddr_i, // physical address in
input exception_t fetch_exception_i, // exception occurred during fetch
// Set a new PC
// mispredict
input branchpredict_t resolved_branch_i, // from controller signaling a branch_predict -> update BTB

View file

@ -15,11 +15,11 @@
import ariane_pkg::*;
module lsu #(
parameter int ASID_WIDTH = 1,
parameter int unsigned ASID_WIDTH = 1,
parameter logic [63:0] CACHE_START_ADDR = 64'h4000_0000,
parameter int unsigned AXI_ID_WIDTH = 10,
parameter int unsigned AXI_USER_WIDTH = 1
)(
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
@ -41,12 +41,12 @@ module lsu #(
input logic enable_translation_i, // enable virtual memory translation
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
input logic fetch_req_i, // Instruction fetch interface
output logic fetch_gnt_o, // Instruction fetch interface
output logic fetch_valid_o, // Instruction fetch interface
input logic [63:0] fetch_vaddr_i, // Instruction fetch interface
output logic [63:0] fetch_rdata_o, // Instruction fetch interface
output exception_t fetch_ex_o, // Instruction fetch interface
output logic fetch_valid_o, // Instruction fetch interface
output logic [63:0] fetch_paddr_o, // Instruction fetch interface
output exception_t fetch_exception_o, // Instruction fetch interface
input priv_lvl_t priv_lvl_i, // From CSR register file
input priv_lvl_t ld_st_priv_lvl_i, // From CSR register file
@ -59,13 +59,6 @@ module lsu #(
output logic itlb_miss_o,
output logic dtlb_miss_o,
output logic dcache_miss_o,
// Instruction memory/cache
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [3:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
input logic dcache_en_i,
input logic flush_dcache_i,

View file

@ -17,11 +17,10 @@
import ariane_pkg::*;
module mmu #(
parameter int INSTR_TLB_ENTRIES = 4,
parameter int DATA_TLB_ENTRIES = 4,
parameter int ASID_WIDTH = 1
)
(
parameter int unsigned INSTR_TLB_ENTRIES = 4,
parameter int unsigned DATA_TLB_ENTRIES = 4,
parameter int unsigned ASID_WIDTH = 1
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
@ -30,11 +29,11 @@ module mmu #(
// IF interface
input logic fetch_req_i,
output logic fetch_gnt_o,
output logic fetch_valid_o,
input logic [63:0] fetch_vaddr_i,
output logic [63:0] fetch_rdata_o, // pass-through because of interfaces
output exception_t fetch_ex_o, // write-back fetch exceptions (e.g.: bus faults, page faults, etc.)
output logic fetch_valid_o, // translation is valid
output logic [63:0] fetch_paddr_o,
output exception_t fetch_exception_o, // write-back fetch exceptions (e.g.: bus faults, page faults, etc.)
// 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
@ -61,15 +60,7 @@ module mmu #(
// Performance counters
output logic itlb_miss_o,
output logic dtlb_miss_o,
// Memory interfaces
// Instruction memory/cache
output logic [63:0] instr_if_address_o,
output logic instr_if_data_req_o,
output logic [3:0] instr_if_data_be_o,
input logic instr_if_data_gnt_i,
input logic instr_if_data_rvalid_i,
input logic [63:0] instr_if_data_rdata_i,
// Data memory/cache
// PTW memory interface
output logic [11:0] address_index_o,
output logic [43:0] address_tag_o,
output logic [63:0] data_wdata_o,
@ -83,9 +74,6 @@ module mmu #(
input logic data_rvalid_i,
input logic [63:0] data_rdata_i
);
// instruction error
// instruction error valid signal and exception, delayed one cycle
logic ierr_valid_q, ierr_valid_n;
logic iaccess_err; // insufficient privilege to access this instruction page
logic daccess_err; // insufficient privilege to access this data page
@ -114,7 +102,6 @@ module mmu #(
// Assignments
assign itlb_lu_access = fetch_req_i;
assign dtlb_lu_access = lsu_req_i;
assign fetch_rdata_o = instr_if_data_rdata_i;
tlb #(
.TLB_ENTRIES ( INSTR_TLB_ENTRIES ),
@ -185,46 +172,39 @@ module mmu #(
//-----------------------
// Instruction Interface
//-----------------------
exception_t fetch_exception;
logic exception_fifo_empty;
// This is a full memory interface, e.g.: it handles all signals to the I$
// Exceptions are always signaled together with the fetch_valid_o signal
// The instruction interface is a simple request response interface
always_comb begin : instr_interface
// MMU disabled: just pass through
instr_if_data_req_o = fetch_req_i;
instr_if_address_o = fetch_vaddr_i; // play through in case we disabled address translation
fetch_gnt_o = instr_if_data_gnt_i;
fetch_valid_o = fetch_req_i;
fetch_paddr_o = fetch_vaddr_i; // play through in case we disabled address translation
// two potential exception sources:
// 1. HPTW threw an exception -> signal with a page fault exception
// 2. We got an access error because of insufficient permissions -> throw an access exception
fetch_exception = '0;
ierr_valid_n = 1'b0; // we keep a separate valid signal in case of an error
fetch_exception_o = '0;
// Check whether we are allowed to access this memory region from a fetch perspective
iaccess_err = fetch_req_i && (((priv_lvl_i == PRIV_LVL_U) && ~itlb_content.u)
|| ((priv_lvl_i == PRIV_LVL_S) && itlb_content.u));
// check that the upper-most bits (63-39) are the same, otherwise throw a page fault exception...
if (fetch_req_i && !((&fetch_vaddr_i[63:39]) == 1'b1 || (|fetch_vaddr_i[63:39]) == 1'b0)) begin
fetch_exception = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1};
ierr_valid_n = 1'b1;
fetch_gnt_o = 1'b1;
fetch_exception_o = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1};
end
// 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
instr_if_data_req_o = 1'b0;
fetch_valid_o = 1'b0;
// 4K page
instr_if_address_o = {itlb_content.ppn, fetch_vaddr_i[11:0]};
fetch_paddr_o = {itlb_content.ppn, fetch_vaddr_i[11:0]};
// Mega page
if (itlb_is_2M) begin
instr_if_address_o[20:12] = fetch_vaddr_i[20:12];
fetch_paddr_o[20:12] = fetch_vaddr_i[20:12];
end
// Giga page
if (itlb_is_1G) begin
instr_if_address_o[29:12] = fetch_vaddr_i[29:12];
fetch_paddr_o[29:12] = fetch_vaddr_i[29:12];
end
// ---------
@ -232,20 +212,11 @@ module mmu #(
// --------
// if we hit the ITLB output the request signal immediately
if (itlb_lu_hit) begin
instr_if_data_req_o = fetch_req_i;
fetch_valid_o = fetch_req_i;
// we got an access error
if (iaccess_err) begin
// immediately grant a fetch which threw an exception, and stop the request from happening
instr_if_data_req_o = 1'b0;
// in case we hit the TLB with an exception we need to order the memory request e.g.
// we need to wait until all outstanding request drained otherwise we get an out-of order result
// which will be wrong
if (exception_fifo_empty) begin
fetch_gnt_o = 1'b1;
ierr_valid_n = 1'b1;
end
// throw a page fault
fetch_exception = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1};
fetch_exception_o = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1};
end
end else
// ---------
@ -253,50 +224,10 @@ module mmu #(
// ---------
// watch out for exceptions happening during walking the page table
if (ptw_active && walking_instr) begin
// check that the fetch address is equal with the faulting address as it could be that the page table walker
// has walked an instruction the instruction fetch stage is no longer interested in as we didn't give a grant
// we should not propagate back the exception when the request is no longer high
if (faulting_address == fetch_vaddr_i && fetch_req_i) begin
// on an error pass through fetch with an error signaled
fetch_gnt_o = ptw_error;
ierr_valid_n = ptw_error; // signal valid/error on next cycle
end
fetch_exception = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
fetch_valid_o = 1'b1;
fetch_exception_o = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
end
end
// the fetch is valid if we either got an error in the previous cycle or the I$ gave us a valid signal.
fetch_valid_o = instr_if_data_rvalid_i || ierr_valid_q;
end
// ---------------------------
// Fetch exception register
// ---------------------------
// We can have two outstanding transactions
fifo #(
.dtype ( exception_t ),
.DEPTH ( 2 )
) i_exception_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.full_o ( ),
.empty_o ( exception_fifo_empty ),
.single_element_o ( ),
.data_i ( fetch_exception ),
.push_i ( fetch_gnt_o ),
.data_o ( fetch_ex_o ),
.pop_i ( fetch_valid_o ),
.*
);
// ----------
// 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
//-----------------------