mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-24 14:17:16 -04:00
Simplfy instruction address translation
This commit is contained in:
parent
96a8e3165e
commit
f2d45c007b
5 changed files with 50 additions and 141 deletions
|
@ -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 ),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
19
src/lsu.sv
19
src/lsu.sv
|
@ -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,
|
||||
|
|
113
src/mmu.sv
113
src/mmu.sv
|
@ -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
|
||||
|
||||
//-----------------------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue