mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-19 11:54:46 -04:00
OBI protocol between Frontend to icache (#2205)
move cacheable region check from icache to frontend and manage it in OBI protocol move address translation request from icache to Frontend
This commit is contained in:
parent
be3b8fc0d4
commit
b59a0d1766
16 changed files with 1080 additions and 477 deletions
1
Makefile
1
Makefile
|
@ -305,6 +305,7 @@ riscv-benchmarks := $(shell xargs printf '\n%s' < $(riscv-benchmarks-li
|
|||
incdir := $(CVA6_REPO_DIR)/vendor/pulp-platform/common_cells/include/ $(CVA6_REPO_DIR)/vendor/pulp-platform/axi/include/ \
|
||||
$(CVA6_REPO_DIR)/corev_apu/register_interface/include/ $(CVA6_REPO_DIR)/corev_apu/tb/common/ \
|
||||
$(CVA6_REPO_DIR)/vendor/pulp-platform/axi/include/ \
|
||||
$(CVA6_REPO_DIR)/vendor/pulp-platform/obi/include/ \
|
||||
$(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_agents/uvma_rvfi/ \
|
||||
$(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_components/uvmc_rvfi_reference_model/ \
|
||||
$(CVA6_REPO_DIR)/verif/core-v-verif/lib/uvm_components/uvmc_rvfi_scoreboard/ \
|
||||
|
|
|
@ -33,6 +33,7 @@ ${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/SyncThreePortRam.sv
|
|||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/SyncDpRam_ind_r_w.sv
|
||||
|
||||
+incdir+${CVA6_REPO_DIR}/core/include/
|
||||
+incdir+${CVA6_REPO_DIR}/vendor/pulp-platform/obi/include/
|
||||
+incdir+${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/include/
|
||||
+incdir+${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/
|
||||
+incdir+${CVA6_REPO_DIR}/vendor/pulp-platform/axi/include/
|
||||
|
@ -59,6 +60,8 @@ ${CVA6_REPO_DIR}/core/cvfpu/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
|||
${CVA6_REPO_DIR}/core/cvfpu/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
${CVA6_REPO_DIR}/core/cvfpu/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_pkg.sv
|
||||
${CVA6_REPO_DIR}/core/include/config_pkg.sv
|
||||
${CVA6_REPO_DIR}/core/include/${TARGET_CFG}_config_pkg.sv
|
||||
${CVA6_REPO_DIR}/core/include/riscv_pkg.sv
|
||||
|
@ -83,7 +86,7 @@ ${CVA6_REPO_DIR}/core/cvxif_example/compressed_instr_decoder.sv
|
|||
${CVA6_REPO_DIR}/core/cvxif_example/copro_alu.sv
|
||||
|
||||
// Common Cells
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
|
||||
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/fifo_v3.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/lfsr.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/lfsr_8bit.sv
|
||||
|
@ -102,6 +105,16 @@ ${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/exp_backoff.sv
|
|||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/counter.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/delta_counter.sv
|
||||
|
||||
//OBI
|
||||
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_atop_resolver.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_demux.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_err_sbr.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_intf.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_mux.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_sram_shim.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/obi/src/obi_xbar.sv
|
||||
|
||||
// Top-level source files (not necessarily instantiated at the top of the cva6).
|
||||
${CVA6_REPO_DIR}/core/cva6.sv
|
||||
${CVA6_REPO_DIR}/core/cva6_rvfi_probes.sv
|
||||
|
|
|
@ -17,10 +17,10 @@ module cva6_hpdcache_subsystem
|
|||
// {{{
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_req_t = logic,
|
||||
parameter type fetch_rsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
parameter type dcache_req_i_t = logic,
|
||||
|
@ -65,14 +65,16 @@ module cva6_hpdcache_subsystem
|
|||
input logic icache_flush_i,
|
||||
// instructino cache miss - PERF_COUNTERS
|
||||
output logic icache_miss_o,
|
||||
// Input address translation request - EX_STAGE
|
||||
input icache_areq_t icache_areq_i,
|
||||
// Output address translation request - EX_STAGE
|
||||
output icache_arsp_t icache_areq_o,
|
||||
// Input data translation request - FRONTEND
|
||||
input icache_dreq_t icache_dreq_i,
|
||||
// Output data translation request - FRONTEND
|
||||
output icache_drsp_t icache_dreq_o,
|
||||
// Access request - FRONTEND
|
||||
input fetch_req_t fetch_req_i,
|
||||
// Output Access request - FRONTEND
|
||||
output fetch_rsp_t fetch_rsp_o,
|
||||
|
||||
// OBI Fetch Request channel - FRONTEND
|
||||
input obi_fetch_req_t obi_fetch_req_i,
|
||||
// OBI Fetch Response channel - FRONTEND
|
||||
output obi_fetch_rsp_t obi_fetch_rsp_o,
|
||||
|
||||
// }}}
|
||||
|
||||
// D$
|
||||
|
@ -149,28 +151,28 @@ module cva6_hpdcache_subsystem
|
|||
|
||||
cva6_icache #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_req_t(fetch_req_t),
|
||||
.fetch_rsp_t(fetch_rsp_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.RdTxId(ICACHE_RDTXID)
|
||||
) i_cva6_icache (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.areq_i (icache_areq_i),
|
||||
.areq_o (icache_areq_o),
|
||||
.dreq_i (icache_dreq_i),
|
||||
.dreq_o (icache_dreq_o),
|
||||
.mem_rtrn_vld_i(icache_miss_resp_valid),
|
||||
.mem_rtrn_i (icache_miss_resp),
|
||||
.mem_data_req_o(icache_miss_valid),
|
||||
.mem_data_ack_i(icache_miss_ready),
|
||||
.mem_data_o (icache_miss)
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.fetch_req_i (fetch_req_i),
|
||||
.fetch_rsp_o (fetch_rsp_o),
|
||||
.obi_fetch_req_i(obi_fetch_req_i),
|
||||
.obi_fetch_rsp_o(obi_fetch_rsp_o),
|
||||
.mem_rtrn_vld_i (icache_miss_resp_valid),
|
||||
.mem_rtrn_i (icache_miss_resp),
|
||||
.mem_data_req_o (icache_miss_valid),
|
||||
.mem_data_ack_i (icache_miss_ready),
|
||||
.mem_data_o (icache_miss)
|
||||
);
|
||||
// }}}
|
||||
|
||||
|
@ -428,13 +430,10 @@ module cva6_hpdcache_subsystem
|
|||
|
||||
a_invalid_instruction_fetch :
|
||||
assert property (
|
||||
@(posedge clk_i) disable iff (!rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
|
||||
@(posedge clk_i) disable iff (~rst_ni) (obi_fetch_rsp_o.rvalid && obi_fetch_req_i.rready && !fetch_rsp_o.invalid_data) |-> (|obi_fetch_rsp_o.r.rdata) !== 1'hX)
|
||||
else
|
||||
$warning(
|
||||
1,
|
||||
"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
|
||||
icache_dreq_o.vaddr,
|
||||
icache_dreq_o.data
|
||||
1, "[l1 icache] FETCH reading invalid instructions: data=%08X", obi_fetch_rsp_o.r.rdata
|
||||
);
|
||||
|
||||
a_invalid_write_data :
|
||||
|
|
|
@ -23,17 +23,19 @@
|
|||
//
|
||||
// 3) NC accesses to I/O space are expected to return 32bit from memory.
|
||||
//
|
||||
|
||||
// Additional contributions by:
|
||||
// 06.06.2024 - Yannick Casamatta, Thales
|
||||
// OBI Protocol
|
||||
|
||||
module cva6_icache
|
||||
import ariane_pkg::*;
|
||||
import wt_cache_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_req_t = logic,
|
||||
parameter type fetch_rsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
/// ID to be used for read transactions
|
||||
|
@ -43,17 +45,20 @@ module cva6_icache
|
|||
input logic rst_ni,
|
||||
|
||||
/// flush the icache, flush and kill have to be asserted together
|
||||
input logic flush_i,
|
||||
input logic flush_i,
|
||||
/// enable icache
|
||||
input logic en_i,
|
||||
input logic en_i,
|
||||
/// to performance counter
|
||||
output logic miss_o,
|
||||
// address translation requests
|
||||
input icache_areq_t areq_i,
|
||||
output icache_arsp_t areq_o,
|
||||
output logic miss_o,
|
||||
// data requests
|
||||
input icache_dreq_t dreq_i,
|
||||
output icache_drsp_t dreq_o,
|
||||
input fetch_req_t fetch_req_i,
|
||||
output fetch_rsp_t fetch_rsp_o,
|
||||
|
||||
// OBI Fetch Request channel - FRONTEND
|
||||
input obi_fetch_req_t obi_fetch_req_i,
|
||||
// OBI Fetch Response channel - FRONTEND
|
||||
output obi_fetch_rsp_t obi_fetch_rsp_o,
|
||||
|
||||
// refill port
|
||||
input logic mem_rtrn_vld_i,
|
||||
input icache_rtrn_t mem_rtrn_i,
|
||||
|
@ -78,8 +83,9 @@ module cva6_icache
|
|||
// signals
|
||||
logic cache_en_d, cache_en_q; // cache is enabled
|
||||
logic [CVA6Cfg.VLEN-1:0] vaddr_d, vaddr_q;
|
||||
logic paddr_is_nc; // asserted if physical address is non-cacheable
|
||||
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] cl_hit; // hit from tag compare
|
||||
logic paddr_is_nc_q, paddr_is_nc_d; // asserted if physical address is non-cacheable
|
||||
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] cl_hit, cl_hit2; // hit from tag compare
|
||||
|
||||
logic cache_rden; // triggers cache lookup
|
||||
logic cache_wren; // triggers write to cacheline
|
||||
logic
|
||||
|
@ -123,31 +129,43 @@ module cva6_icache
|
|||
FLUSH,
|
||||
IDLE,
|
||||
READ,
|
||||
READ_BIS,
|
||||
MISS,
|
||||
KILL_ATRANS,
|
||||
KILL_MISS
|
||||
} state_e;
|
||||
state_e state_d, state_q;
|
||||
|
||||
logic obi_valid, obi_grant;
|
||||
|
||||
logic [CVA6Cfg.FETCH_WIDTH-1:0] data_d, data_q, obi_rdata;
|
||||
logic [CVA6Cfg.FETCH_USER_WIDTH-1:0] userdata_d, userdata_q, obi_ruser;
|
||||
logic data_valid_obi, data_valid_obi_d, data_valid_obi_q;
|
||||
|
||||
//OBI
|
||||
assign obi_fetch_rsp_o.gnt = obi_grant;
|
||||
assign obi_fetch_rsp_o.gntpar = !obi_grant;
|
||||
assign obi_fetch_rsp_o.rvalid = obi_valid;
|
||||
assign obi_fetch_rsp_o.rvalidpar = !obi_valid;
|
||||
assign obi_fetch_rsp_o.r.rid = '0;
|
||||
assign obi_fetch_rsp_o.r.r_optional.exokay = '0;
|
||||
assign obi_fetch_rsp_o.r.r_optional.rchk = '0;
|
||||
assign obi_fetch_rsp_o.r.err = '0;
|
||||
assign obi_fetch_rsp_o.r.rdata = obi_rdata;
|
||||
assign obi_fetch_rsp_o.r.r_optional.ruser = obi_ruser;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// address -> cl_index mapping, interface plumbing
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
// extract tag from physical address, check if NC
|
||||
assign cl_tag_d = (areq_i.fetch_valid) ? areq_i.fetch_paddr[CVA6Cfg.ICACHE_TAG_WIDTH+CVA6Cfg.ICACHE_INDEX_WIDTH-1:CVA6Cfg.ICACHE_INDEX_WIDTH] : cl_tag_q;
|
||||
|
||||
// noncacheable if request goes to I/O space, or if cache is disabled
|
||||
assign paddr_is_nc = (~cache_en_q) | (~config_pkg::is_inside_cacheable_regions(
|
||||
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, cl_tag_d, {CVA6Cfg.ICACHE_INDEX_WIDTH{1'b0}}}
|
||||
));
|
||||
|
||||
// pass exception through
|
||||
assign dreq_o.ex = areq_i.fetch_exception;
|
||||
assign cl_tag_d = (obi_fetch_req_i.req && obi_grant) ? obi_fetch_req_i.a.addr[CVA6Cfg.ICACHE_TAG_WIDTH+CVA6Cfg.ICACHE_INDEX_WIDTH-1:CVA6Cfg.ICACHE_INDEX_WIDTH] : cl_tag_q;
|
||||
// memtype[1] = 1 is cacheable, memtype[1] = 0 is non cacheable
|
||||
assign paddr_is_nc_d = !cache_en_q || ((obi_fetch_req_i.req && obi_grant) ? !obi_fetch_req_i.a.a_optional.memtype[1] : paddr_is_nc_q);
|
||||
|
||||
// latch this in case we have to stall later on
|
||||
// make sure this is 32bit aligned
|
||||
assign vaddr_d = (dreq_o.ready & dreq_i.req) ? dreq_i.vaddr : vaddr_q;
|
||||
assign areq_o.fetch_vaddr = (vaddr_q >> CVA6Cfg.FETCH_ALIGN_BITS) << CVA6Cfg.FETCH_ALIGN_BITS;
|
||||
assign vaddr_d = (fetch_rsp_o.ready & fetch_req_i.req) ? fetch_req_i.vaddr : vaddr_q;
|
||||
|
||||
// split virtual address into index and offset to address cache arrays
|
||||
assign cl_index = vaddr_d[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
|
||||
|
@ -155,40 +173,120 @@ module cva6_icache
|
|||
|
||||
if (CVA6Cfg.NOCType == config_pkg::NOC_TYPE_AXI4_ATOP) begin : gen_axi_offset
|
||||
// if we generate a noncacheable access, the word will be at offset 0 or 4 in the cl coming from memory
|
||||
assign cl_offset_d = ( dreq_o.ready & dreq_i.req) ? (dreq_i.vaddr >> CVA6Cfg.FETCH_ALIGN_BITS) << CVA6Cfg.FETCH_ALIGN_BITS :
|
||||
( paddr_is_nc & mem_data_req_o ) ? {{ICACHE_OFFSET_WIDTH-1{1'b0}}, cl_offset_q[2]}<<2 : // needed since we transfer 32bit over a 64bit AXI bus in this case
|
||||
assign cl_offset_d = ( fetch_rsp_o.ready & fetch_req_i.req) ? (fetch_req_i.vaddr >> CVA6Cfg.FETCH_ALIGN_BITS) << CVA6Cfg.FETCH_ALIGN_BITS :
|
||||
( paddr_is_nc_d & mem_data_req_o ) ? {{ICACHE_OFFSET_WIDTH-1{1'b0}}, cl_offset_q[2]}<<2 : // needed since we transfer 32bit over a 64bit AXI bus in this case
|
||||
cl_offset_q;
|
||||
// request word address instead of cl address in case of NC access
|
||||
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:3], 3'b0} : // align to 64bit
|
||||
assign mem_data_o.paddr = (paddr_is_nc_d) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:3], 3'b0} : // align to 64bit
|
||||
{cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
|
||||
end else begin : gen_piton_offset
|
||||
// icache fills are either cachelines or 4byte fills, depending on whether they go to the Piton I/O space or not.
|
||||
// since the piton cache system replicates the data, we can always index the full CL
|
||||
assign cl_offset_d = (dreq_o.ready & dreq_i.req) ? {dreq_i.vaddr >> 2, 2'b0} : cl_offset_q;
|
||||
assign cl_offset_d = (fetch_rsp_o.ready & fetch_req_i.req) ? {fetch_req_i.vaddr >> 2, 2'b0} : cl_offset_q;
|
||||
|
||||
// request word address instead of cl address in case of NC access
|
||||
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:2], 2'b0} : // align to 32bit
|
||||
assign mem_data_o.paddr = (paddr_is_nc_d) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:2], 2'b0} : // align to 32bit
|
||||
{cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
|
||||
end
|
||||
|
||||
|
||||
assign mem_data_o.tid = RdTxId;
|
||||
|
||||
assign mem_data_o.nc = paddr_is_nc;
|
||||
assign mem_data_o.nc = paddr_is_nc_d;
|
||||
// way that is being replaced
|
||||
assign mem_data_o.way = repl_way;
|
||||
assign dreq_o.vaddr = vaddr_q;
|
||||
|
||||
// invalidations take two cycles
|
||||
assign inv_d = inv_en;
|
||||
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
OBI_R_IDLE,
|
||||
OBI_R_WAIT,
|
||||
OBI_R_VALID,
|
||||
OBI_R_KILLED
|
||||
} obi_r_state_e;
|
||||
obi_r_state_e obi_r_state_d, obi_r_state_q;
|
||||
|
||||
|
||||
// Common clocked process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_obi
|
||||
if (!rst_ni) begin
|
||||
obi_r_state_q <= OBI_R_IDLE;
|
||||
data_q <= '0;
|
||||
userdata_q <= '0;
|
||||
data_valid_obi_q <= '0;
|
||||
end else begin
|
||||
obi_r_state_q <= obi_r_state_d;
|
||||
data_q <= data_d;
|
||||
userdata_q <= userdata_d;
|
||||
data_valid_obi_q <= data_valid_obi_d;
|
||||
end
|
||||
end
|
||||
|
||||
// OBI CHANNEL R protocol FSM (combi)
|
||||
|
||||
always_comb begin : p_fsm_obi_r
|
||||
// default assignment
|
||||
obi_valid = '0;
|
||||
fetch_rsp_o.invalid_data = '0;
|
||||
obi_rdata = data_q;
|
||||
obi_ruser = userdata_q;
|
||||
obi_r_state_d = obi_r_state_q;
|
||||
|
||||
unique case (obi_r_state_q)
|
||||
OBI_R_IDLE: begin
|
||||
if (obi_fetch_req_i.req && obi_grant) begin
|
||||
if (!(fetch_req_i.kill_req || flush_d)) begin
|
||||
obi_r_state_d = OBI_R_WAIT;
|
||||
end else begin
|
||||
obi_r_state_d = OBI_R_KILLED;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
OBI_R_WAIT: begin
|
||||
if (fetch_req_i.kill_req || flush_d) begin
|
||||
obi_valid = '1;
|
||||
fetch_rsp_o.invalid_data = '1;
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end else if (data_valid_obi || data_valid_obi_q) begin
|
||||
obi_valid = '1;
|
||||
if (data_valid_obi) begin
|
||||
obi_rdata = data_d;
|
||||
obi_ruser = userdata_d;
|
||||
end
|
||||
obi_ruser = userdata_d;
|
||||
if (!(obi_fetch_req_i.req && obi_grant)) begin
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
OBI_R_KILLED: begin
|
||||
obi_valid = '1;
|
||||
fetch_rsp_o.invalid_data = '1;
|
||||
if (obi_fetch_req_i.req && obi_grant) begin
|
||||
if (!(fetch_req_i.kill_req || flush_d)) begin
|
||||
obi_r_state_d = OBI_R_WAIT;
|
||||
end
|
||||
end else begin
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
// we should never get here
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// main control logic
|
||||
///////////////////////////////////////////////////////
|
||||
logic addr_ni;
|
||||
assign addr_ni = config_pkg::is_inside_nonidempotent_regions(
|
||||
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, areq_i.fetch_paddr}
|
||||
);
|
||||
|
||||
always_comb begin : p_fsm
|
||||
// default assignment
|
||||
state_d = state_q;
|
||||
|
@ -199,14 +297,14 @@ module cva6_icache
|
|||
cache_wren = 1'b0;
|
||||
inv_en = 1'b0;
|
||||
flush_d = flush_q | flush_i; // register incoming flush
|
||||
|
||||
// interfaces
|
||||
dreq_o.ready = 1'b0;
|
||||
areq_o.fetch_req = 1'b0;
|
||||
dreq_o.valid = 1'b0;
|
||||
fetch_rsp_o.ready = 1'b0;
|
||||
mem_data_req_o = 1'b0;
|
||||
// performance counter
|
||||
miss_o = 1'b0;
|
||||
obi_grant = 1'b0;
|
||||
data_valid_obi = '0;
|
||||
data_valid_obi_d = '0;
|
||||
|
||||
// handle invalidations unconditionally
|
||||
// note: invald are mutually exclusive with
|
||||
|
@ -242,16 +340,17 @@ module cva6_icache
|
|||
end else begin
|
||||
// mem requests are for sure invals here
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
dreq_o.ready = 1'b1;
|
||||
// we have a new request
|
||||
if (dreq_i.req) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
// we have a new request not killed
|
||||
if (obi_fetch_req_i.req && !fetch_req_i.kill_req) begin
|
||||
cache_rden = 1'b1;
|
||||
state_d = READ;
|
||||
state_d = READ_BIS;
|
||||
obi_grant = 1'b1;
|
||||
end else if (fetch_req_i.req && !fetch_req_i.kill_req) begin
|
||||
cache_rden = 1'b1;
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
if (dreq_i.kill_s1) begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
|
@ -261,38 +360,37 @@ module cva6_icache
|
|||
// reuse the miss mechanism to handle
|
||||
// the request
|
||||
READ: begin
|
||||
areq_o.fetch_req = '1;
|
||||
// only enable tag comparison if cache is enabled
|
||||
cmp_en_d = cache_en_q;
|
||||
cmp_en_d = cache_en_q;
|
||||
// readout speculatively
|
||||
cache_rden = cache_en_q;
|
||||
cache_rden = cache_en_q;
|
||||
|
||||
if (obi_fetch_req_i.req) begin
|
||||
state_d = READ_BIS;
|
||||
obi_grant = 1'b1;
|
||||
|
||||
if (areq_i.fetch_valid && (!dreq_i.spec || ((CVA6Cfg.NonIdemPotenceEn && !addr_ni) || (!CVA6Cfg.NonIdemPotenceEn)))) begin
|
||||
// check if we have to flush
|
||||
if (flush_d) begin
|
||||
state_d = IDLE;
|
||||
// we have a hit or an exception output valid result
|
||||
end else if (((|cl_hit && cache_en_q) || areq_i.fetch_exception.valid) && !inv_q) begin
|
||||
dreq_o.valid = ~dreq_i.kill_s2; // just don't output in this case
|
||||
state_d = IDLE;
|
||||
|
||||
// we can accept another request
|
||||
// and stay here, but only if no inval is coming in
|
||||
// note: we are not expecting ifill return packets here...
|
||||
// we have an exception
|
||||
end else if (fetch_req_i.kill_req) begin
|
||||
state_d = IDLE;
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
dreq_o.ready = 1'b1;
|
||||
if (dreq_i.req) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
if (fetch_req_i.req) begin
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
// if a request is being killed at this stage,
|
||||
// we have to bail out and wait for the address translation to complete
|
||||
if (dreq_i.kill_s1) begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
// we have a miss / NC transaction
|
||||
end else if (dreq_i.kill_s2) begin
|
||||
// we have a hit
|
||||
end else if (|cl_hit && cache_en_q && !inv_q) begin
|
||||
data_valid_obi_d = '1;
|
||||
state_d = IDLE;
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
if (fetch_req_i.req) begin
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
end else if (!inv_q) begin
|
||||
cmp_en_d = 1'b0;
|
||||
// only count this as a miss if the cache is enabled, and
|
||||
|
@ -300,15 +398,80 @@ module cva6_icache
|
|||
// send out ifill request
|
||||
mem_data_req_o = 1'b1;
|
||||
if (mem_data_ack_i) begin
|
||||
miss_o = ~paddr_is_nc;
|
||||
miss_o = ~paddr_is_nc_d;
|
||||
state_d = MISS;
|
||||
end
|
||||
end
|
||||
// bail out if this request is being killed (and we missed on the TLB)
|
||||
end else if (dreq_i.kill_s2 || flush_d) begin
|
||||
state_d = KILL_ATRANS;
|
||||
end else if (flush_d) begin
|
||||
state_d = IDLE;
|
||||
end else if (fetch_req_i.kill_req) begin
|
||||
state_d = IDLE;
|
||||
// we can accept another request
|
||||
// and stay here, but only if no inval is coming in
|
||||
// note: we are not expecting ifill return packets here...
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
if (fetch_req_i.req) begin
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
end else if (fetch_req_i.req) begin
|
||||
//abort previous index and launch new one
|
||||
state_d = IDLE;
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
cache_rden = 1'b1;
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
READ_BIS: begin
|
||||
// only enable tag comparison if cache is enabled
|
||||
cmp_en_d = cache_en_q;
|
||||
// readout speculatively
|
||||
cache_rden = cache_en_q;
|
||||
|
||||
// check if we have to flush
|
||||
if (flush_d) begin
|
||||
state_d = IDLE;
|
||||
end else if (fetch_req_i.kill_req) begin
|
||||
state_d = IDLE;
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
if (fetch_req_i.req) begin
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
|
||||
// we have a hit
|
||||
end else if ((|cl_hit2 && cache_en_q && !inv_q)) begin
|
||||
state_d = IDLE;
|
||||
data_valid_obi = 1'b1;
|
||||
// we can accept another request
|
||||
// and stay here, but only if no inval is coming in
|
||||
// note: we are not expecting ifill return packets here...
|
||||
if (!mem_rtrn_vld_i) begin
|
||||
fetch_rsp_o.ready = 1'b1;
|
||||
if (fetch_req_i.req) begin
|
||||
state_d = READ;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (!inv_q) begin
|
||||
cmp_en_d = 1'b0;
|
||||
// only count this as a miss if the cache is enabled, and
|
||||
// the address is cacheable
|
||||
// send out ifill request
|
||||
mem_data_req_o = 1'b1;
|
||||
if (mem_data_ack_i) begin
|
||||
miss_o = ~paddr_is_nc_d;
|
||||
state_d = MISS;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//////////////////////////////////
|
||||
// wait until the memory transaction
|
||||
// returns. do not write to memory
|
||||
|
@ -319,27 +482,17 @@ module cva6_icache
|
|||
if (mem_rtrn_vld_i && mem_rtrn_i.rtype == ICACHE_IFILL_ACK) begin
|
||||
state_d = IDLE;
|
||||
// only return data if request is not being killed
|
||||
if (!(dreq_i.kill_s2 || flush_d)) begin
|
||||
dreq_o.valid = 1'b1;
|
||||
if (!(fetch_req_i.kill_req || flush_d)) begin
|
||||
// only write to cache if this address is cacheable
|
||||
cache_wren = ~paddr_is_nc;
|
||||
cache_wren = ~paddr_is_nc_d;
|
||||
data_valid_obi = '1;
|
||||
end
|
||||
// bail out if this request is being killed
|
||||
end else if (dreq_i.kill_s2 || flush_d) begin
|
||||
end else if (fetch_req_i.kill_req || flush_d) begin
|
||||
state_d = KILL_MISS;
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// killed address translation,
|
||||
// wait until paddr is valid, and go
|
||||
// back to idle
|
||||
KILL_ATRANS: begin
|
||||
areq_o.fetch_req = '1;
|
||||
if (areq_i.fetch_valid) begin
|
||||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
//////////////////////////////////
|
||||
// killed miss,
|
||||
// wait until memory responds and
|
||||
// go back to idle
|
||||
|
@ -348,6 +501,7 @@ module cva6_icache
|
|||
state_d = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
// we should never get here
|
||||
state_d = FLUSH;
|
||||
|
@ -425,6 +579,7 @@ module cva6_icache
|
|||
|
||||
for (genvar i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
|
||||
assign cl_hit[i] = (cl_tag_rdata[i] == cl_tag_d) & vld_rdata[i];
|
||||
assign cl_hit2[i] = (cl_tag_rdata[i] == cl_tag_q) & vld_rdata[i];
|
||||
assign cl_sel[i] = cl_rdata[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
|
||||
assign cl_user[i] = cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
|
||||
end
|
||||
|
@ -440,11 +595,11 @@ module cva6_icache
|
|||
|
||||
always_comb begin
|
||||
if (cmp_en_q) begin
|
||||
dreq_o.data = cl_sel[hit_idx];
|
||||
dreq_o.user = cl_user[hit_idx];
|
||||
data_d = cl_sel[hit_idx];
|
||||
userdata_d = cl_user[hit_idx];
|
||||
end else begin
|
||||
dreq_o.data = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
|
||||
dreq_o.user = mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
|
||||
data_d = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
|
||||
userdata_d = mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -516,6 +671,7 @@ module cva6_icache
|
|||
cl_offset_q <= '0;
|
||||
repl_way_oh_q <= '0;
|
||||
inv_q <= '0;
|
||||
paddr_is_nc_q <= '0;
|
||||
end else begin
|
||||
cl_tag_q <= cl_tag_d;
|
||||
flush_cnt_q <= flush_cnt_d;
|
||||
|
@ -527,6 +683,7 @@ module cva6_icache
|
|||
cl_offset_q <= cl_offset_d;
|
||||
repl_way_oh_q <= repl_way_oh_d;
|
||||
inv_q <= inv_d;
|
||||
paddr_is_nc_q <= paddr_is_nc_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -548,7 +705,7 @@ module cva6_icache
|
|||
|
||||
invalid_state :
|
||||
assert property (
|
||||
@(posedge clk_i) disable iff (!rst_ni) (state_q inside {FLUSH, IDLE, READ, MISS, KILL_ATRANS, KILL_MISS}))
|
||||
@(posedge clk_i) disable iff (!rst_ni) (state_q inside {FLUSH, IDLE, READ, READ_BIS, MISS, KILL_MISS}))
|
||||
else $fatal(1, "[l1 icache] fsm reached an invalid state");
|
||||
|
||||
hot1 :
|
||||
|
|
|
@ -18,10 +18,10 @@ module cva6_icache_axi_wrapper
|
|||
import wt_cache_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_dreq_t = logic,
|
||||
parameter type fetch_drsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
parameter type axi_req_t = logic,
|
||||
|
@ -34,15 +34,19 @@ module cva6_icache_axi_wrapper
|
|||
input logic flush_i, // flush the icache, flush and kill have to be asserted together
|
||||
input logic en_i, // enable icache
|
||||
output logic miss_o, // to performance counter
|
||||
// address translation requests
|
||||
input icache_areq_t areq_i,
|
||||
output icache_arsp_t areq_o,
|
||||
// data requests
|
||||
input icache_dreq_t dreq_i,
|
||||
output icache_drsp_t dreq_o,
|
||||
input fetch_dreq_t dreq_i,
|
||||
output fetch_drsp_t dreq_o,
|
||||
|
||||
// OBI Fetch Request channel - FRONTEND
|
||||
input obi_fetch_req_t fetch_obi_req_i,
|
||||
// OBI Fetch Response channel - FRONTEND
|
||||
output obi_fetch_rsp_t fetch_obi_rsp_o,
|
||||
|
||||
|
||||
// AXI refill port
|
||||
output axi_req_t axi_req_o,
|
||||
input axi_rsp_t axi_resp_i
|
||||
input axi_rsp_t axi_resp_i
|
||||
);
|
||||
|
||||
localparam AxiNumWords = (CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (CVA6Cfg.ICACHE_LINE_WIDTH > CVA6Cfg.DCACHE_LINE_WIDTH) +
|
||||
|
@ -108,28 +112,28 @@ module cva6_icache_axi_wrapper
|
|||
cva6_icache #(
|
||||
// use ID 0 for icache reads
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_dreq_t(fetch_dreq_t),
|
||||
.fetch_drsp_t(fetch_drsp_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.RdTxId(0)
|
||||
) i_cva6_icache (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (flush_i),
|
||||
.en_i (en_i),
|
||||
.miss_o (miss_o),
|
||||
.areq_i (areq_i),
|
||||
.areq_o (areq_o),
|
||||
.dreq_i (dreq_i),
|
||||
.dreq_o (dreq_o),
|
||||
.mem_rtrn_vld_i(icache_mem_rtrn_vld),
|
||||
.mem_rtrn_i (icache_mem_rtrn),
|
||||
.mem_data_req_o(icache_mem_data_req),
|
||||
.mem_data_ack_i(icache_mem_data_ack),
|
||||
.mem_data_o (icache_mem_data)
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (flush_i),
|
||||
.en_i (en_i),
|
||||
.miss_o (miss_o),
|
||||
.dreq_i (dreq_i),
|
||||
.dreq_o (dreq_o),
|
||||
.fetch_obi_req_i(fetch_obi_req_i),
|
||||
.fetch_obi_rsp_o(fetch_obi_rsp_o),
|
||||
.mem_rtrn_vld_i (icache_mem_rtrn_vld),
|
||||
.mem_rtrn_i (icache_mem_rtrn),
|
||||
.mem_data_req_o (icache_mem_data_req),
|
||||
.mem_data_ack_i (icache_mem_data_ack),
|
||||
.mem_data_o (icache_mem_data)
|
||||
);
|
||||
|
||||
// --------
|
||||
|
|
|
@ -20,10 +20,10 @@ module std_cache_subsystem
|
|||
import std_cache_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_dreq_t = logic,
|
||||
parameter type fetch_drsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
parameter type dcache_req_i_t = logic,
|
||||
|
@ -42,12 +42,15 @@ module std_cache_subsystem
|
|||
input logic icache_en_i, // enable icache (or bypass e.g: in debug mode)
|
||||
input logic icache_flush_i, // flush the icache, flush and kill have to be asserted together
|
||||
output logic icache_miss_o, // to performance counter
|
||||
// address translation requests
|
||||
input icache_areq_t icache_areq_i, // to/from frontend
|
||||
output icache_arsp_t icache_areq_o,
|
||||
// data requests
|
||||
input icache_dreq_t icache_dreq_i, // to/from frontend
|
||||
output icache_drsp_t icache_dreq_o,
|
||||
input fetch_dreq_t fetch_dreq_i, // to/from frontend
|
||||
output fetch_drsp_t fetch_dreq_o,
|
||||
|
||||
// OBI Fetch Request channel - FRONTEND
|
||||
input obi_fetch_req_t fetch_obi_req_i,
|
||||
// OBI Fetch Response channel - FRONTEND
|
||||
output obi_fetch_rsp_t fetch_obi_rsp_o,
|
||||
|
||||
// AMOs
|
||||
input amo_req_t amo_req_i,
|
||||
output amo_resp_t amo_resp_o,
|
||||
|
@ -77,27 +80,27 @@ module std_cache_subsystem
|
|||
|
||||
cva6_icache_axi_wrapper #(
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_dreq_t(fetch_dreq_t),
|
||||
.fetch_drsp_t(fetch_drsp_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.axi_req_t(axi_req_t),
|
||||
.axi_rsp_t(axi_rsp_t)
|
||||
) i_cva6_icache_axi_wrapper (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.priv_lvl_i(priv_lvl_i),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.areq_i (icache_areq_i),
|
||||
.areq_o (icache_areq_o),
|
||||
.dreq_i (icache_dreq_i),
|
||||
.dreq_o (icache_dreq_o),
|
||||
.axi_req_o (axi_req_icache),
|
||||
.axi_resp_i(axi_resp_icache)
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.priv_lvl_i (priv_lvl_i),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.dreq_i (fetch_dreq_i),
|
||||
.dreq_o (fetch_dreq_o),
|
||||
.fetch_obi_req_i(fetch_obi_req_i),
|
||||
.fetch_obi_rsp_o(fetch_obi_rsp_o),
|
||||
.axi_req_o (axi_req_icache),
|
||||
.axi_resp_i (axi_resp_icache)
|
||||
);
|
||||
|
||||
// decreasing priority
|
||||
|
@ -301,13 +304,13 @@ module std_cache_subsystem
|
|||
|
||||
a_invalid_instruction_fetch :
|
||||
assert property (
|
||||
@(posedge clk_i) disable iff (~rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
|
||||
@(posedge clk_i) disable iff (~rst_ni) (fetch_obi_rsp_o.rvalid && !fetch_dreq_o.invalid_data) |-> (|fetch_obi_rsp_o.r.rdata) !== 1'hX)
|
||||
else
|
||||
$warning(
|
||||
1,
|
||||
"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
|
||||
icache_dreq_o.vaddr,
|
||||
icache_dreq_o.data
|
||||
fetch_dreq_i.vaddr,
|
||||
fetch_obi_rsp_o.r.rdata
|
||||
);
|
||||
|
||||
a_invalid_write_data :
|
||||
|
|
|
@ -23,18 +23,18 @@ module wt_cache_subsystem
|
|||
import ariane_pkg::*;
|
||||
import wt_cache_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type dcache_req_i_t = logic,
|
||||
parameter type dcache_req_o_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
parameter int unsigned NumPorts = 4,
|
||||
parameter type noc_req_t = logic,
|
||||
parameter type noc_resp_t = logic
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type fetch_dreq_t = logic,
|
||||
parameter type fetch_drsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic,
|
||||
parameter type dcache_req_i_t = logic,
|
||||
parameter type dcache_req_o_t = logic,
|
||||
parameter type icache_req_t = logic,
|
||||
parameter type icache_rtrn_t = logic,
|
||||
parameter int unsigned NumPorts = 4,
|
||||
parameter type noc_req_t = logic,
|
||||
parameter type noc_resp_t = logic
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -42,12 +42,15 @@ module wt_cache_subsystem
|
|||
input logic icache_en_i, // enable icache (or bypass e.g: in debug mode)
|
||||
input logic icache_flush_i, // flush the icache, flush and kill have to be asserted together
|
||||
output logic icache_miss_o, // to performance counter
|
||||
// address translation requests
|
||||
input icache_areq_t icache_areq_i, // to/from frontend
|
||||
output icache_arsp_t icache_areq_o,
|
||||
// data requests
|
||||
input icache_dreq_t icache_dreq_i, // to/from frontend
|
||||
output icache_drsp_t icache_dreq_o,
|
||||
input fetch_dreq_t fetch_dreq_i, // to/from frontend
|
||||
output fetch_drsp_t fetch_dreq_o,
|
||||
|
||||
// OBI Fetch Request channel - FRONTEND
|
||||
input obi_fetch_req_t fetch_obi_req_i,
|
||||
// OBI Fetch Response channel - FRONTEND
|
||||
output obi_fetch_rsp_t fetch_obi_rsp_o,
|
||||
|
||||
// D$
|
||||
// Cache management
|
||||
input logic dcache_enable_i, // from CSR
|
||||
|
@ -115,28 +118,28 @@ module wt_cache_subsystem
|
|||
cva6_icache #(
|
||||
// use ID 0 for icache reads
|
||||
.CVA6Cfg(CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_dreq_t(fetch_dreq_t),
|
||||
.fetch_drsp_t(fetch_drsp_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.RdTxId(0)
|
||||
) i_cva6_icache (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.areq_i (icache_areq_i),
|
||||
.areq_o (icache_areq_o),
|
||||
.dreq_i (icache_dreq_i),
|
||||
.dreq_o (icache_dreq_o),
|
||||
.mem_rtrn_vld_i(adapter_icache_rtrn_vld),
|
||||
.mem_rtrn_i (adapter_icache),
|
||||
.mem_data_req_o(icache_adapter_data_req),
|
||||
.mem_data_ack_i(adapter_icache_data_ack),
|
||||
.mem_data_o (icache_adapter)
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (icache_flush_i),
|
||||
.en_i (icache_en_i),
|
||||
.miss_o (icache_miss_o),
|
||||
.dreq_i (fetch_dreq_i),
|
||||
.dreq_o (fetch_dreq_o),
|
||||
.fetch_obi_req_i(fetch_obi_req_i),
|
||||
.fetch_obi_rsp_o(fetch_obi_rsp_o),
|
||||
.mem_rtrn_vld_i (adapter_icache_rtrn_vld),
|
||||
.mem_rtrn_i (adapter_icache),
|
||||
.mem_data_req_o (icache_adapter_data_req),
|
||||
.mem_data_ack_i (adapter_icache_data_ack),
|
||||
.mem_data_o (icache_adapter)
|
||||
);
|
||||
|
||||
|
||||
|
@ -242,13 +245,13 @@ module wt_cache_subsystem
|
|||
`ifndef VERILATOR
|
||||
a_invalid_instruction_fetch :
|
||||
assert property (
|
||||
@(posedge clk_i) disable iff (!rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
|
||||
@(posedge clk_i) disable iff (~rst_ni) (fetch_obi_rsp_o.rvalid && !fetch_dreq_o.invalid_data) |-> (|fetch_obi_rsp_o.r.rdata) !== 1'hX)
|
||||
else
|
||||
$warning(
|
||||
1,
|
||||
"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
|
||||
icache_dreq_o.vaddr,
|
||||
icache_dreq_o.data
|
||||
fetch_dreq_i.vaddr,
|
||||
fetch_obi_rsp_o.r.rdata
|
||||
);
|
||||
|
||||
for (genvar j = 0; j < CVA6Cfg.XLEN / 8; j++) begin : gen_invalid_write_assertion
|
||||
|
|
154
core/cva6.sv
154
core/cva6.sv
|
@ -12,6 +12,8 @@
|
|||
// Date: 19.03.2017
|
||||
// Description: CVA6 Top-level module
|
||||
|
||||
`include "obi/typedef.svh"
|
||||
`include "obi/assign.svh"
|
||||
`include "rvfi_types.svh"
|
||||
`include "cvxif_types.svh"
|
||||
|
||||
|
@ -51,31 +53,25 @@ module cva6
|
|||
|
||||
// cache request ports
|
||||
// I$ address translation requests
|
||||
localparam type icache_areq_t = struct packed {
|
||||
logic fetch_valid; // address translation valid
|
||||
logic [CVA6Cfg.PLEN-1:0] fetch_paddr; // physical address in
|
||||
exception_t fetch_exception; // exception occurred during fetch
|
||||
},
|
||||
localparam type icache_arsp_t = struct packed {
|
||||
localparam type fetch_areq_t = struct packed {
|
||||
logic fetch_req; // address translation request
|
||||
logic [CVA6Cfg.VLEN-1:0] fetch_vaddr; // virtual address out
|
||||
},
|
||||
localparam type fetch_arsp_t = struct packed {
|
||||
exception_t fetch_exception; // exception occurred during fetch
|
||||
logic fetch_valid; // address translation valid
|
||||
logic [CVA6Cfg.PLEN-1:0] fetch_paddr; // physical address in
|
||||
},
|
||||
|
||||
// I$ data requests
|
||||
localparam type icache_dreq_t = struct packed {
|
||||
logic req; // we request a new word
|
||||
logic kill_s1; // kill the current request
|
||||
logic kill_s2; // kill the last request
|
||||
logic spec; // request is speculative
|
||||
logic [CVA6Cfg.VLEN-1:0] vaddr; // 1st cycle: 12 bit index is taken for lookup
|
||||
localparam type fetch_req_t = struct packed {
|
||||
logic req; // we request a new word
|
||||
logic kill_req; // kill the last request
|
||||
logic [CVA6Cfg.VLEN-1:0] vaddr; // 1st cycle: 12 bit index is taken for lookup
|
||||
},
|
||||
localparam type icache_drsp_t = struct packed {
|
||||
logic ready; // icache is ready
|
||||
logic valid; // signals a valid read
|
||||
logic [CVA6Cfg.FETCH_WIDTH-1:0] data; // 2+ cycle out: tag
|
||||
logic [CVA6Cfg.FETCH_USER_WIDTH-1:0] user; // User bits
|
||||
logic [CVA6Cfg.VLEN-1:0] vaddr; // virtual address out
|
||||
exception_t ex; // we've encountered an exception
|
||||
localparam type fetch_rsp_t = struct packed {
|
||||
logic ready; // fetch is ready
|
||||
logic invalid_data; // obi data is invalid caused by aborted request kill_req, use for debug
|
||||
},
|
||||
|
||||
// IF/ID Stage
|
||||
|
@ -330,6 +326,11 @@ module cva6
|
|||
input noc_resp_t noc_resp_i
|
||||
);
|
||||
|
||||
//OBI FETCH
|
||||
`OBI_TYPEDEF_ALL(obi_fetch, CVA6Cfg.ObiFetchbusCfg)
|
||||
//OBI DATA
|
||||
`OBI_TYPEDEF_ALL(obi_data, CVA6Cfg.ObiDatabusCfg)
|
||||
|
||||
localparam type interrupts_t = struct packed {
|
||||
logic [CVA6Cfg.XLEN-1:0] S_SW;
|
||||
logic [CVA6Cfg.XLEN-1:0] VS_SW;
|
||||
|
@ -614,10 +615,14 @@ module cva6
|
|||
logic flush_commit;
|
||||
logic flush_acc;
|
||||
|
||||
icache_areq_t icache_areq_ex_cache;
|
||||
icache_arsp_t icache_areq_cache_ex;
|
||||
icache_dreq_t icache_dreq_if_cache;
|
||||
icache_drsp_t icache_dreq_cache_if;
|
||||
fetch_arsp_t fetch_arsp_ex_frontend;
|
||||
fetch_areq_t fetch_areq_frontend_ex;
|
||||
fetch_req_t fetch_req_if_cache;
|
||||
fetch_rsp_t fetch_rsp_cache_if;
|
||||
|
||||
// OBI
|
||||
obi_fetch_req_t obi_fetch_req_if_cache;
|
||||
obi_fetch_rsp_t obi_fetch_rsp_cache_if;
|
||||
|
||||
amo_req_t amo_req;
|
||||
amo_resp_t amo_resp;
|
||||
|
@ -653,8 +658,12 @@ module cva6
|
|||
.CVA6Cfg(CVA6Cfg),
|
||||
.bp_resolve_t(bp_resolve_t),
|
||||
.fetch_entry_t(fetch_entry_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t)
|
||||
.fetch_areq_t(fetch_areq_t),
|
||||
.fetch_arsp_t(fetch_arsp_t),
|
||||
.fetch_req_t(fetch_req_t),
|
||||
.fetch_rsp_t(fetch_rsp_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t)
|
||||
) i_frontend (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
|
@ -671,8 +680,12 @@ module cva6
|
|||
.trap_vector_base_i (trap_vector_base_commit_pcgen),
|
||||
.set_debug_pc_i (set_debug_pc),
|
||||
.debug_mode_i (debug_mode),
|
||||
.icache_dreq_o (icache_dreq_if_cache),
|
||||
.icache_dreq_i (icache_dreq_cache_if),
|
||||
.areq_o (fetch_areq_frontend_ex),
|
||||
.arsp_i (fetch_arsp_ex_frontend),
|
||||
.fetch_req_o (fetch_req_if_cache),
|
||||
.fetch_rsp_i (fetch_rsp_cache_if),
|
||||
.obi_fetch_req_o (obi_fetch_req_if_cache), //OBI
|
||||
.obi_fetch_rsp_i (obi_fetch_rsp_cache_if), //OBI
|
||||
.fetch_entry_o (fetch_entry_if_id),
|
||||
.fetch_entry_valid_o(fetch_valid_if_id),
|
||||
.fetch_entry_ready_i(fetch_ready_id_if)
|
||||
|
@ -916,10 +929,8 @@ module cva6
|
|||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.exception_t(exception_t),
|
||||
.fu_data_t(fu_data_t),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_areq_t(fetch_areq_t),
|
||||
.fetch_arsp_t(fetch_arsp_t),
|
||||
.lsu_ctrl_t(lsu_ctrl_t),
|
||||
.x_result_t(x_result_t)
|
||||
) ex_stage_i (
|
||||
|
@ -1030,8 +1041,8 @@ module cva6
|
|||
.vs_asid_i (vs_asid_csr_ex), // from CSR
|
||||
.hgatp_ppn_i (hgatp_ppn_csr_ex), // from CSR
|
||||
.vmid_i (vmid_csr_ex), // from CSR
|
||||
.icache_areq_i (icache_areq_cache_ex),
|
||||
.icache_areq_o (icache_areq_ex_cache),
|
||||
.fetch_areq_i (fetch_areq_frontend_ex),
|
||||
.fetch_arsp_o (fetch_arsp_ex_frontend),
|
||||
// DCACHE interfaces
|
||||
.dcache_req_ports_i (dcache_req_ports_cache_ex),
|
||||
.dcache_req_ports_o (dcache_req_ports_ex_cache),
|
||||
|
@ -1193,7 +1204,8 @@ module cva6
|
|||
.bp_resolve_t(bp_resolve_t),
|
||||
.exception_t(exception_t),
|
||||
.scoreboard_entry_t(scoreboard_entry_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.fetch_req_t(fetch_req_t),
|
||||
.obi_fetch_req_t(fetch_req_t),
|
||||
.dcache_req_i_t(dcache_req_i_t),
|
||||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.NumPorts(NumPorts)
|
||||
|
@ -1220,9 +1232,11 @@ module cva6
|
|||
.eret_i (eret),
|
||||
.resolved_branch_i (resolved_branch),
|
||||
.branch_exceptions_i(flu_exception_ex_id),
|
||||
.l1_icache_access_i (icache_dreq_if_cache),
|
||||
.l1_fetch_access_i (fetch_dreq_if_cache),
|
||||
.l1_dcache_access_i (dcache_req_ports_ex_cache),
|
||||
.miss_vld_bits_i (miss_vld_bits),
|
||||
.fetch_req_i (fetch_req_if_cache),
|
||||
.fetch_obi_req_i (obi_fetch_req_if_cache),
|
||||
.i_tlb_flush_i (flush_tlb_ctrl_ex),
|
||||
.stall_issue_i (stall_issue),
|
||||
.mcountinhibit_i (mcountinhibit_csr_perf)
|
||||
|
@ -1321,11 +1335,11 @@ module cva6
|
|||
// this is a cache subsystem that is compatible with OpenPiton
|
||||
wt_cache_subsystem #(
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_dreq_t(fetch_dreq_t),
|
||||
.fetch_drsp_t(fetch_drsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.dcache_req_i_t(dcache_req_i_t),
|
||||
.dcache_req_o_t(dcache_req_o_t),
|
||||
|
@ -1340,10 +1354,10 @@ module cva6
|
|||
.icache_en_i (icache_en_csr),
|
||||
.icache_flush_i (icache_flush_ctrl_cache),
|
||||
.icache_miss_o (icache_miss_cache_perf),
|
||||
.icache_areq_i (icache_areq_ex_cache),
|
||||
.icache_areq_o (icache_areq_cache_ex),
|
||||
.icache_dreq_i (icache_dreq_if_cache),
|
||||
.icache_dreq_o (icache_dreq_cache_if),
|
||||
.fetch_dreq_i (fetch_dreq_if_cache),
|
||||
.fetch_dreq_o (fetch_dreq_cache_if),
|
||||
.fetch_obi_req_i (obi_fetch_req_if_cache), //OBI
|
||||
.fetch_obi_rsp_o (obi_fetch_rsp_cache_if), //OBI
|
||||
// D$
|
||||
.dcache_enable_i (dcache_en_csr_nbdcache),
|
||||
.dcache_flush_i (dcache_flush_ctrl_cache),
|
||||
|
@ -1373,14 +1387,14 @@ module cva6
|
|||
begin : gen_cache_hpd
|
||||
cva6_hpdcache_subsystem #(
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_req_t(fetch_req_t),
|
||||
.fetch_rsp_t(fetch_rsp_t),
|
||||
.icache_req_t(icache_req_t),
|
||||
.icache_rtrn_t(icache_rtrn_t),
|
||||
.dcache_req_i_t(dcache_req_i_t),
|
||||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.NumPorts (NumPorts),
|
||||
.axi_ar_chan_t(axi_ar_chan_t),
|
||||
.axi_aw_chan_t(axi_aw_chan_t),
|
||||
|
@ -1398,10 +1412,10 @@ module cva6
|
|||
.icache_en_i (icache_en_csr),
|
||||
.icache_flush_i(icache_flush_ctrl_cache),
|
||||
.icache_miss_o (icache_miss_cache_perf),
|
||||
.icache_areq_i (icache_areq_ex_cache),
|
||||
.icache_areq_o (icache_areq_cache_ex),
|
||||
.icache_dreq_i (icache_dreq_if_cache),
|
||||
.icache_dreq_o (icache_dreq_cache_if),
|
||||
.fetch_req_i (fetch_req_if_cache),
|
||||
.fetch_rsp_o (fetch_rsp_cache_if),
|
||||
.obi_fetch_req_i (obi_fetch_req_if_cache), //OBI
|
||||
.obi_fetch_rsp_o (obi_fetch_rsp_cache_if), //OBI
|
||||
|
||||
.dcache_enable_i (dcache_en_csr_nbdcache),
|
||||
.dcache_flush_i (dcache_flush_ctrl_cache),
|
||||
|
@ -1440,21 +1454,21 @@ module cva6
|
|||
// note: this only works with one cacheable region
|
||||
// not as important since this cache subsystem is about to be
|
||||
// deprecated
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.icache_areq_t (icache_areq_t),
|
||||
.icache_arsp_t (icache_arsp_t),
|
||||
.icache_dreq_t (icache_dreq_t),
|
||||
.icache_drsp_t (icache_drsp_t),
|
||||
.icache_req_t (icache_req_t),
|
||||
.icache_rtrn_t (icache_rtrn_t),
|
||||
.dcache_req_i_t(dcache_req_i_t),
|
||||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.NumPorts (NumPorts),
|
||||
.axi_ar_chan_t (axi_ar_chan_t),
|
||||
.axi_aw_chan_t (axi_aw_chan_t),
|
||||
.axi_w_chan_t (axi_w_chan_t),
|
||||
.axi_req_t (noc_req_t),
|
||||
.axi_rsp_t (noc_resp_t)
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.fetch_dreq_t (fetch_dreq_t),
|
||||
.fetch_drsp_t (fetch_drsp_t),
|
||||
.icache_req_t (icache_req_t),
|
||||
.icache_rtrn_t (icache_rtrn_t),
|
||||
.obi_fetch_req_t(obi_fetch_req_t),
|
||||
.obi_fetch_rsp_t(obi_fetch_rsp_t),
|
||||
.dcache_req_i_t (dcache_req_i_t),
|
||||
.dcache_req_o_t (dcache_req_o_t),
|
||||
.NumPorts (NumPorts),
|
||||
.axi_ar_chan_t (axi_ar_chan_t),
|
||||
.axi_aw_chan_t (axi_aw_chan_t),
|
||||
.axi_w_chan_t (axi_w_chan_t),
|
||||
.axi_req_t (noc_req_t),
|
||||
.axi_rsp_t (noc_resp_t)
|
||||
) i_cache_subsystem (
|
||||
// to D$
|
||||
.clk_i (clk_i),
|
||||
|
@ -1464,10 +1478,10 @@ module cva6
|
|||
.icache_en_i (icache_en_csr),
|
||||
.icache_flush_i (icache_flush_ctrl_cache),
|
||||
.icache_miss_o (icache_miss_cache_perf),
|
||||
.icache_areq_i (icache_areq_ex_cache),
|
||||
.icache_areq_o (icache_areq_cache_ex),
|
||||
.icache_dreq_i (icache_dreq_if_cache),
|
||||
.icache_dreq_o (icache_dreq_cache_if),
|
||||
.fetch_dreq_i (fetch_dreq_if_cache),
|
||||
.fetch_dreq_o (fetch_dreq_cache_if),
|
||||
.fetch_obi_req_i (obi_fetch_req_if_cache), //OBI
|
||||
.fetch_obi_rsp_o (obi_fetch_rsp_cache_if), //OBI
|
||||
// D$
|
||||
.dcache_enable_i (dcache_en_csr_nbdcache),
|
||||
.dcache_flush_i (dcache_flush_ctrl_cache),
|
||||
|
|
|
@ -26,10 +26,8 @@ module cva6_mmu
|
|||
import ariane_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_areq_t = logic,
|
||||
parameter type fetch_arsp_t = logic,
|
||||
parameter type dcache_req_i_t = logic,
|
||||
parameter type dcache_req_o_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
|
@ -44,8 +42,8 @@ module cva6_mmu
|
|||
input logic en_ld_st_translation_i, // enable virtual memory translation for load/stores
|
||||
input logic en_ld_st_g_translation_i, // enable G-Stage translation for load/stores
|
||||
// IF interface
|
||||
input icache_arsp_t icache_areq_i,
|
||||
output icache_areq_t icache_areq_o,
|
||||
input fetch_areq_t fetch_areq_i,
|
||||
output fetch_arsp_t fetch_arsp_o,
|
||||
// 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
|
||||
|
@ -169,7 +167,7 @@ module cva6_mmu
|
|||
|
||||
// Assignments
|
||||
|
||||
assign itlb_lu_access = icache_areq_i.fetch_req;
|
||||
assign itlb_lu_access = fetch_areq_i.fetch_req;
|
||||
assign dtlb_lu_access = lsu_req_i;
|
||||
assign itlb_lu_asid = v_i ? vs_asid_i : asid_i;
|
||||
assign dtlb_lu_asid = (ld_st_v_i || flush_tlb_vvma_i) ? vs_asid_i : asid_i;
|
||||
|
@ -194,7 +192,7 @@ module cva6_mmu
|
|||
.lu_access_i (itlb_lu_access),
|
||||
.lu_asid_i (itlb_lu_asid),
|
||||
.lu_vmid_i (vmid_i),
|
||||
.lu_vaddr_i (icache_areq_i.fetch_vaddr),
|
||||
.lu_vaddr_i (fetch_areq_i.fetch_vaddr),
|
||||
.lu_gpaddr_o (itlb_gpaddr),
|
||||
.lu_content_o (itlb_content),
|
||||
.lu_g_content_o(itlb_g_content),
|
||||
|
@ -264,7 +262,7 @@ module cva6_mmu
|
|||
// did we miss?
|
||||
.itlb_access_i(itlb_lu_access),
|
||||
.itlb_hit_i (itlb_lu_hit),
|
||||
.itlb_vaddr_i (icache_areq_i.fetch_vaddr),
|
||||
.itlb_vaddr_i (fetch_areq_i.fetch_vaddr),
|
||||
|
||||
.dtlb_access_i(dtlb_lu_access),
|
||||
.dtlb_hit_i (dtlb_lu_hit),
|
||||
|
@ -360,54 +358,54 @@ module cva6_mmu
|
|||
// The instruction interface is a simple request response interface
|
||||
always_comb begin : instr_interface
|
||||
// MMU disabled: just pass through
|
||||
icache_areq_o.fetch_valid = icache_areq_i.fetch_req;
|
||||
icache_areq_o.fetch_paddr = CVA6Cfg.PLEN'(icache_areq_i.fetch_vaddr[((CVA6Cfg.PLEN > CVA6Cfg.VLEN) ? CVA6Cfg.VLEN -1: CVA6Cfg.PLEN -1 ):0]);
|
||||
fetch_arsp_o.fetch_valid = fetch_areq_i.fetch_req;
|
||||
fetch_arsp_o.fetch_paddr = CVA6Cfg.PLEN'(fetch_areq_i.fetch_vaddr[((CVA6Cfg.PLEN > CVA6Cfg.VLEN) ? CVA6Cfg.VLEN -1: CVA6Cfg.PLEN -1 ):0]);
|
||||
// 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
|
||||
icache_areq_o.fetch_exception = '0;
|
||||
fetch_arsp_o.fetch_exception = '0;
|
||||
// Check whether we are allowed to access this memory region from a fetch perspective
|
||||
iaccess_err = icache_areq_i.fetch_req && enable_translation_i && //
|
||||
iaccess_err = fetch_areq_i.fetch_req && enable_translation_i && //
|
||||
(((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u) //
|
||||
|| ((priv_lvl_i == riscv::PRIV_LVL_S) && itlb_content.u));
|
||||
|
||||
if (CVA6Cfg.RVH)
|
||||
i_g_st_access_err = icache_areq_i.fetch_req && enable_g_translation_i && !itlb_g_content.u;
|
||||
i_g_st_access_err = fetch_areq_i.fetch_req && enable_g_translation_i && !itlb_g_content.u;
|
||||
// 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 || enable_g_translation_i)) begin
|
||||
// we work with SV39 or SV32, so if VM is enabled, check that all bits [CVA6Cfg.VLEN-1:CVA6Cfg.SV-1] are equal
|
||||
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b0)) begin
|
||||
if (fetch_areq_i.fetch_req && !((&fetch_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|fetch_areq_i.fetch_vaddr[CVA6Cfg.VLEN-1:CVA6Cfg.SV-1]) == 1'b0)) begin
|
||||
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn)
|
||||
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(icache_areq_i.fetch_vaddr);
|
||||
fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(fetch_areq_i.fetch_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_areq_o.fetch_exception.tval2 = '0;
|
||||
icache_areq_o.fetch_exception.tinst = '0;
|
||||
icache_areq_o.fetch_exception.gva = v_i;
|
||||
fetch_arsp_o.fetch_exception.tval2 = '0;
|
||||
fetch_arsp_o.fetch_exception.tinst = '0;
|
||||
fetch_arsp_o.fetch_exception.gva = v_i;
|
||||
end
|
||||
end
|
||||
|
||||
icache_areq_o.fetch_valid = 1'b0;
|
||||
fetch_arsp_o.fetch_valid = 1'b0;
|
||||
|
||||
icache_areq_o.fetch_paddr = {
|
||||
fetch_arsp_o.fetch_paddr = {
|
||||
(enable_g_translation_i && CVA6Cfg.RVH) ? itlb_g_content.ppn : itlb_content.ppn,
|
||||
icache_areq_i.fetch_vaddr[11:0]
|
||||
fetch_areq_i.fetch_vaddr[11:0]
|
||||
};
|
||||
|
||||
if (CVA6Cfg.PtLevels == 3 && itlb_is_page[CVA6Cfg.PtLevels-2]) begin
|
||||
|
||||
icache_areq_o.fetch_paddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels] = icache_areq_i.fetch_vaddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels];
|
||||
fetch_arsp_o.fetch_paddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels] = fetch_areq_i.fetch_vaddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels];
|
||||
|
||||
end
|
||||
|
||||
if (itlb_is_page[0]) begin
|
||||
|
||||
icache_areq_o.fetch_paddr[PPNWMin:12] = icache_areq_i.fetch_vaddr[PPNWMin:12];
|
||||
fetch_arsp_o.fetch_paddr[PPNWMin:12] = fetch_areq_i.fetch_vaddr[PPNWMin:12];
|
||||
|
||||
end
|
||||
// ---------//
|
||||
|
@ -415,23 +413,23 @@ module cva6_mmu
|
|||
// --------//
|
||||
// if we hit the ITLB output the request signal immediately
|
||||
if (itlb_lu_hit) begin
|
||||
icache_areq_o.fetch_valid = icache_areq_i.fetch_req;
|
||||
fetch_arsp_o.fetch_valid = fetch_areq_i.fetch_req;
|
||||
if (CVA6Cfg.RVH && i_g_st_access_err) begin
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_GUEST_PAGE_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_GUEST_PAGE_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn)
|
||||
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(icache_areq_i.fetch_vaddr);
|
||||
fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(fetch_areq_i.fetch_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_areq_o.fetch_exception.tval2 = itlb_gpaddr[CVA6Cfg.GPLEN-1:0];
|
||||
icache_areq_o.fetch_exception.tinst = '0;
|
||||
icache_areq_o.fetch_exception.gva = v_i;
|
||||
fetch_arsp_o.fetch_exception.tval2 = itlb_gpaddr[CVA6Cfg.GPLEN-1:0];
|
||||
fetch_arsp_o.fetch_exception.tinst = '0;
|
||||
fetch_arsp_o.fetch_exception.gva = v_i;
|
||||
end
|
||||
|
||||
// we got an access error
|
||||
end else if (iaccess_err) begin
|
||||
// throw a page fault
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn)
|
||||
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(icache_areq_i.fetch_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
|
@ -445,36 +443,36 @@ module cva6_mmu
|
|||
// ITLB Miss
|
||||
// ---------//
|
||||
// watch out for exceptions happening during walking the page table
|
||||
icache_areq_o.fetch_valid = ptw_error | ptw_access_exception;
|
||||
fetch_arsp_o.fetch_valid = ptw_error | ptw_access_exception;
|
||||
if (ptw_error) begin
|
||||
if (CVA6Cfg.RVH && ptw_error_at_g_st) begin
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_GUEST_PAGE_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_GUEST_PAGE_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_areq_o.fetch_exception.tval2 = ptw_bad_gpaddr[CVA6Cfg.GPLEN-1:0];
|
||||
icache_areq_o.fetch_exception.tinst=(ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0);
|
||||
icache_areq_o.fetch_exception.gva = v_i;
|
||||
fetch_arsp_o.fetch_exception.tval2 = ptw_bad_gpaddr[CVA6Cfg.GPLEN-1:0];
|
||||
fetch_arsp_o.fetch_exception.tinst=(ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0);
|
||||
fetch_arsp_o.fetch_exception.gva = v_i;
|
||||
end
|
||||
end else begin
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_areq_o.fetch_exception.tval2 = '0;
|
||||
icache_areq_o.fetch_exception.tinst = '0;
|
||||
icache_areq_o.fetch_exception.gva = v_i;
|
||||
fetch_arsp_o.fetch_exception.tval2 = '0;
|
||||
fetch_arsp_o.fetch_exception.tinst = '0;
|
||||
fetch_arsp_o.fetch_exception.gva = v_i;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
|
||||
icache_areq_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) //To confirm this is the right TVAL
|
||||
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
fetch_arsp_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
|
||||
fetch_arsp_o.fetch_exception.valid = 1'b1;
|
||||
if (CVA6Cfg.TvalEn) //To confirm this is the right TVAL
|
||||
fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_areq_o.fetch_exception.tval2 = '0;
|
||||
icache_areq_o.fetch_exception.tinst = '0;
|
||||
icache_areq_o.fetch_exception.gva = v_i;
|
||||
fetch_arsp_o.fetch_exception.tval2 = '0;
|
||||
fetch_arsp_o.fetch_exception.tinst = '0;
|
||||
fetch_arsp_o.fetch_exception.gva = v_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,10 +24,8 @@ module ex_stage
|
|||
parameter type dcache_req_o_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
parameter type fu_data_t = logic,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type fetch_areq_t = logic,
|
||||
parameter type fetch_arsp_t = logic,
|
||||
parameter type lsu_ctrl_t = logic,
|
||||
parameter type x_result_t = logic
|
||||
) (
|
||||
|
@ -203,10 +201,10 @@ module ex_stage
|
|||
input logic [CVA6Cfg.PPNW-1:0] hgatp_ppn_i,
|
||||
// TO_BE_COMPLETED - CSR_REGFILE
|
||||
input logic [CVA6Cfg.VMID_WIDTH-1:0] vmid_i,
|
||||
// icache translation response - CACHE
|
||||
input icache_arsp_t icache_areq_i,
|
||||
// icache translation request - CACHE
|
||||
output icache_areq_t icache_areq_o,
|
||||
// fetch translation request - FETCH
|
||||
input fetch_areq_t fetch_areq_i,
|
||||
// fetch translation response - FETCH
|
||||
output fetch_arsp_t fetch_arsp_o,
|
||||
// Data cache request ouput - CACHE
|
||||
input dcache_req_o_t [2:0] dcache_req_ports_i,
|
||||
// Data cache request input - CACHE
|
||||
|
@ -525,10 +523,8 @@ module ex_stage
|
|||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.exception_t(exception_t),
|
||||
.fu_data_t (fu_data_t),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_arsp_t(icache_arsp_t),
|
||||
.icache_dreq_t(icache_dreq_t),
|
||||
.icache_drsp_t(icache_drsp_t),
|
||||
.fetch_areq_t(fetch_areq_t),
|
||||
.fetch_arsp_t(fetch_arsp_t),
|
||||
.lsu_ctrl_t(lsu_ctrl_t)
|
||||
) lsu_i (
|
||||
.clk_i,
|
||||
|
@ -554,8 +550,8 @@ module ex_stage
|
|||
.enable_g_translation_i,
|
||||
.en_ld_st_translation_i,
|
||||
.en_ld_st_g_translation_i,
|
||||
.icache_areq_i,
|
||||
.icache_areq_o,
|
||||
.fetch_areq_i,
|
||||
.fetch_arsp_o,
|
||||
.priv_lvl_i,
|
||||
.v_i,
|
||||
.ld_st_priv_lvl_i,
|
||||
|
|
|
@ -15,14 +15,22 @@
|
|||
// This module interfaces with the instruction cache, handles control
|
||||
// change request from the back-end and does branch prediction.
|
||||
|
||||
// Additional contributions by:
|
||||
// 06.06.2024 - Yannick Casamatta, Thales
|
||||
// OBI Protocol
|
||||
|
||||
module frontend
|
||||
import ariane_pkg::*;
|
||||
#(
|
||||
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
|
||||
parameter type bp_resolve_t = logic,
|
||||
parameter type fetch_entry_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic
|
||||
parameter type fetch_req_t = logic,
|
||||
parameter type fetch_rsp_t = logic,
|
||||
parameter type fetch_areq_t = logic,
|
||||
parameter type fetch_arsp_t = logic,
|
||||
parameter type obi_fetch_req_t = logic,
|
||||
parameter type obi_fetch_rsp_t = logic
|
||||
) (
|
||||
// Subsystem Clock - SUBSYSTEM
|
||||
input logic clk_i,
|
||||
|
@ -54,10 +62,18 @@ module frontend
|
|||
input logic set_debug_pc_i,
|
||||
// Debug mode state - CSR
|
||||
input logic debug_mode_i,
|
||||
// address translation request chanel - EXECUTE
|
||||
input fetch_arsp_t arsp_i,
|
||||
// address translation response chanel - EXECUTE
|
||||
output fetch_areq_t areq_o,
|
||||
// Handshake between CACHE and FRONTEND (fetch) - CACHES
|
||||
output icache_dreq_t icache_dreq_o,
|
||||
output fetch_req_t fetch_req_o,
|
||||
// Handshake between CACHE and FRONTEND (fetch) - CACHES
|
||||
input icache_drsp_t icache_dreq_i,
|
||||
input fetch_rsp_t fetch_rsp_i,
|
||||
// OBI Fetch Request channel - CACHES
|
||||
output obi_fetch_req_t obi_fetch_req_o,
|
||||
// OBI Fetch Response channel - CACHES
|
||||
input obi_fetch_rsp_t obi_fetch_rsp_i,
|
||||
// Handshake's data between fetch and decode - ID_STAGE
|
||||
output fetch_entry_t [CVA6Cfg.NrIssuePorts-1:0] fetch_entry_o,
|
||||
// Handshake's valid between fetch and decode - ID_STAGE
|
||||
|
@ -89,13 +105,13 @@ module frontend
|
|||
};
|
||||
|
||||
// Instruction Cache Registers, from I$
|
||||
logic [ CVA6Cfg.FETCH_WIDTH-1:0] icache_data_q;
|
||||
logic icache_valid_q;
|
||||
ariane_pkg::frontend_exception_t icache_ex_valid_q;
|
||||
logic [ CVA6Cfg.VLEN-1:0] icache_vaddr_q;
|
||||
logic [ CVA6Cfg.GPLEN-1:0] icache_gpaddr_q;
|
||||
logic [ 31:0] icache_tinst_q;
|
||||
logic icache_gva_q;
|
||||
logic [ CVA6Cfg.FETCH_WIDTH-1:0] fetch_data_q;
|
||||
logic fetch_valid_q;
|
||||
ariane_pkg::frontend_exception_t fetch_ex_valid_q;
|
||||
logic [ CVA6Cfg.VLEN-1:0] fetch_vaddr_q;
|
||||
logic [ CVA6Cfg.GPLEN-1:0] fetch_gpaddr_q;
|
||||
logic [ 31:0] fetch_tinst_q;
|
||||
logic fetch_gva_q;
|
||||
logic instr_queue_ready;
|
||||
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] instr_queue_consumed;
|
||||
// upper-most branch-prediction from last cycle
|
||||
|
@ -106,16 +122,20 @@ module frontend
|
|||
logic [CVA6Cfg.VLEN-1:0] npc_d, npc_q; // next PC
|
||||
|
||||
// indicates whether we come out of reset (then we need to load boot_addr_i)
|
||||
logic npc_rst_load_q;
|
||||
logic npc_rst_load_q;
|
||||
|
||||
logic replay;
|
||||
logic [ CVA6Cfg.VLEN-1:0] replay_addr;
|
||||
logic replay;
|
||||
logic [CVA6Cfg.VLEN-1:0] replay_addr;
|
||||
|
||||
logic [CVA6Cfg.VLEN-1:0]
|
||||
npc_fetch_address, vaddr_d, obi_vaddr_q, obi_vaddr_d, vaddr_q, fetch_vaddr_d;
|
||||
logic [CVA6Cfg.PLEN-1:0] paddr_d, paddr_q;
|
||||
|
||||
// shift amount
|
||||
logic [$clog2(CVA6Cfg.INSTR_PER_FETCH)-1:0] shamt;
|
||||
// address will always be 16 bit aligned, make this explicit here
|
||||
if (CVA6Cfg.RVC) begin : gen_shamt
|
||||
assign shamt = icache_dreq_i.vaddr[$clog2(CVA6Cfg.INSTR_PER_FETCH):1];
|
||||
assign shamt = fetch_vaddr_d[$clog2(CVA6Cfg.INSTR_PER_FETCH):1];
|
||||
end else begin
|
||||
assign shamt = 1'b0;
|
||||
end
|
||||
|
@ -153,18 +173,20 @@ module frontend
|
|||
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] taken_rvi_cf;
|
||||
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] taken_rvc_cf;
|
||||
|
||||
logic serving_unaligned;
|
||||
logic kill_s1, kill_s2;
|
||||
|
||||
logic serving_unaligned;
|
||||
// Re-align instructions
|
||||
instr_realign #(
|
||||
.CVA6Cfg(CVA6Cfg)
|
||||
) i_instr_realign (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (icache_dreq_o.kill_s2),
|
||||
.valid_i (icache_valid_q),
|
||||
.flush_i (kill_s2),
|
||||
.valid_i (fetch_valid_q),
|
||||
.serving_unaligned_o(serving_unaligned),
|
||||
.address_i (icache_vaddr_q),
|
||||
.data_i (icache_data_q),
|
||||
.address_i (fetch_vaddr_q),
|
||||
.data_i (fetch_data_q),
|
||||
.valid_o (instruction_valid),
|
||||
.addr_o (addr),
|
||||
.instr_o (instr)
|
||||
|
@ -303,26 +325,413 @@ module frontend
|
|||
end
|
||||
assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;
|
||||
|
||||
// Cache interface
|
||||
assign icache_dreq_o.req = instr_queue_ready;
|
||||
assign if_ready = icache_dreq_i.ready & instr_queue_ready;
|
||||
logic spec_req_non_idempot;
|
||||
|
||||
// MMU interface
|
||||
assign areq_o.fetch_vaddr = (vaddr_q >> CVA6Cfg.FETCH_ALIGN_BITS) << CVA6Cfg.FETCH_ALIGN_BITS;
|
||||
|
||||
// CHECK PMA regions
|
||||
|
||||
logic paddr_is_cacheable, paddr_is_cacheable_q; // asserted if physical address is non-cacheable
|
||||
assign paddr_is_cacheable = config_pkg::is_inside_cacheable_regions(
|
||||
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, obi_fetch_req_o.a.addr} //TO DO CHECK GRANULARITY
|
||||
);
|
||||
|
||||
logic paddr_nonidempotent;
|
||||
assign paddr_nonidempotent = config_pkg::is_inside_nonidempotent_regions(
|
||||
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, obi_fetch_req_o.a.addr} //TO DO CHECK GRANULARITY
|
||||
);
|
||||
|
||||
// Caches optimisation signals
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
WAIT_NEW_REQ,
|
||||
WAIT_ATRANS,
|
||||
WAIT_OBI,
|
||||
WAIT_FLUSH
|
||||
} custom_state_e;
|
||||
custom_state_e custom_state_d, custom_state_q;
|
||||
|
||||
// Address translation signals
|
||||
logic atrans_req;
|
||||
logic atrans_kill;
|
||||
logic atrans_ready;
|
||||
logic atrans_valid;
|
||||
logic atrans_ex;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
IDLE,
|
||||
READ,
|
||||
KILL_ATRANS
|
||||
} atrans_state_e;
|
||||
atrans_state_e atrans_state_d, atrans_state_q;
|
||||
|
||||
// OBI signals
|
||||
logic obi_a_req;
|
||||
logic obi_a_ready;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
TRANSPARENT,
|
||||
REGISTRED
|
||||
} obi_a_state_e;
|
||||
obi_a_state_e obi_a_state_d, obi_a_state_q;
|
||||
|
||||
// OBI signals
|
||||
logic obi_r_req;
|
||||
logic data_valid_obi;
|
||||
logic data_valid_under_ex;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
OBI_R_IDLE,
|
||||
OBI_R_PENDING,
|
||||
OBI_R_KILLED
|
||||
} obi_r_state_e;
|
||||
obi_r_state_e obi_r_state_d, obi_r_state_q;
|
||||
|
||||
// We need to flush the cache pipeline if:
|
||||
// 1. We mispredicted
|
||||
// 2. Want to flush the whole processor front-end
|
||||
// 3. Need to replay an instruction because the fetch-fifo was full
|
||||
assign icache_dreq_o.kill_s1 = is_mispredict | flush_i | replay;
|
||||
assign kill_s1 = is_mispredict | flush_i | replay;
|
||||
// if we have a valid branch-prediction we need to only kill the last cache request
|
||||
// also if we killed the first stage we also need to kill the second stage (inclusive flush)
|
||||
assign icache_dreq_o.kill_s2 = icache_dreq_o.kill_s1 | bp_valid;
|
||||
assign kill_s2 = kill_s1 | bp_valid;
|
||||
|
||||
assign fetch_req_o.vaddr = vaddr_d;
|
||||
assign fetch_req_o.kill_req = kill_s1 | kill_s2 | atrans_ex;
|
||||
|
||||
// Common clocked process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if (!rst_ni) begin
|
||||
custom_state_q <= WAIT_NEW_REQ;
|
||||
atrans_state_q <= IDLE;
|
||||
obi_a_state_q <= TRANSPARENT;
|
||||
obi_r_state_q <= OBI_R_IDLE;
|
||||
vaddr_q <= '0;
|
||||
paddr_q <= '0;
|
||||
obi_vaddr_q <= '0;
|
||||
paddr_is_cacheable_q <= '0;
|
||||
end else begin
|
||||
custom_state_q <= custom_state_d;
|
||||
atrans_state_q <= atrans_state_d;
|
||||
obi_a_state_q <= obi_a_state_d;
|
||||
obi_r_state_q <= obi_r_state_d;
|
||||
vaddr_q <= vaddr_d;
|
||||
paddr_q <= paddr_d;
|
||||
obi_vaddr_q <= obi_vaddr_d;
|
||||
paddr_is_cacheable_q <= paddr_is_cacheable;
|
||||
end
|
||||
end
|
||||
|
||||
// custom protocol FSM (combi)
|
||||
|
||||
always_comb begin : p_fsm_common
|
||||
// default assignment
|
||||
custom_state_d = custom_state_q;
|
||||
atrans_req = '0;
|
||||
atrans_kill = '0;
|
||||
obi_a_req = '0;
|
||||
obi_vaddr_d = obi_vaddr_q;
|
||||
fetch_req_o.req = '0;
|
||||
data_valid_under_ex = '0;
|
||||
if_ready = '0;
|
||||
vaddr_d = vaddr_q;
|
||||
|
||||
unique case (custom_state_q)
|
||||
WAIT_NEW_REQ: begin
|
||||
vaddr_d = npc_fetch_address;
|
||||
if ((obi_a_state_q == TRANSPARENT || obi_r_req == '1) && instr_queue_ready && atrans_ready && !kill_s2) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
custom_state_d = WAIT_ATRANS;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_ATRANS: begin
|
||||
if (atrans_valid) begin
|
||||
if (kill_s2) begin
|
||||
vaddr_d = npc_fetch_address;
|
||||
if (instr_queue_ready && atrans_ready && !kill_s1) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else if (atrans_ex) begin
|
||||
obi_vaddr_d = vaddr_d;
|
||||
data_valid_under_ex = '1;
|
||||
custom_state_d = WAIT_FLUSH;
|
||||
end else if (obi_a_ready && !spec_req_non_idempot) begin
|
||||
obi_a_req = '1;
|
||||
obi_vaddr_d = vaddr_d;
|
||||
vaddr_d = npc_fetch_address;
|
||||
if (obi_r_req && instr_queue_ready && atrans_ready && !kill_s1) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_OBI;
|
||||
end
|
||||
end
|
||||
if (kill_s2) begin
|
||||
atrans_kill = '1;
|
||||
vaddr_d = npc_fetch_address;
|
||||
if (instr_queue_ready && atrans_ready && !kill_s1) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_OBI: begin
|
||||
if (kill_s2) begin
|
||||
vaddr_d = npc_fetch_address;
|
||||
if ((obi_a_state_q == TRANSPARENT || obi_r_req == '1) && instr_queue_ready && atrans_ready && !kill_s1) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
custom_state_d = WAIT_ATRANS;
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else if (obi_a_ready && !spec_req_non_idempot) begin
|
||||
obi_a_req = '1;
|
||||
obi_vaddr_d = vaddr_d;
|
||||
vaddr_d = npc_fetch_address;
|
||||
if (obi_r_req && instr_queue_ready && atrans_ready && !kill_s1) begin
|
||||
fetch_req_o.req = '1;
|
||||
if (fetch_rsp_i.ready) begin
|
||||
if_ready = '1;
|
||||
atrans_req = '1;
|
||||
custom_state_d = WAIT_ATRANS;
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end else begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_FLUSH: begin
|
||||
if (kill_s1) begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
custom_state_d = WAIT_NEW_REQ;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
// Address translation protocol FSM (combi)
|
||||
|
||||
always_comb begin : p_fsm_atrans
|
||||
// default assignment
|
||||
atrans_state_d = atrans_state_q;
|
||||
areq_o.fetch_req = 1'b0;
|
||||
atrans_ready = 1'b0;
|
||||
atrans_valid = 1'b0;
|
||||
paddr_d = paddr_q;
|
||||
atrans_ex = 1'b0;
|
||||
|
||||
unique case (atrans_state_q)
|
||||
IDLE: begin
|
||||
atrans_ready = 1'b1;
|
||||
if (atrans_req) begin
|
||||
atrans_state_d = READ;
|
||||
end
|
||||
end
|
||||
|
||||
READ: begin
|
||||
areq_o.fetch_req = '1;
|
||||
if (arsp_i.fetch_valid) begin
|
||||
atrans_ready = 1'b1;
|
||||
if (!atrans_kill) begin
|
||||
atrans_valid = 1'b1;
|
||||
paddr_d = arsp_i.fetch_paddr;
|
||||
atrans_ex = arsp_i.fetch_exception.valid;
|
||||
end
|
||||
if (!atrans_req) begin
|
||||
atrans_state_d = IDLE;
|
||||
end
|
||||
end else if (atrans_kill) begin
|
||||
atrans_state_d = KILL_ATRANS;
|
||||
end
|
||||
end
|
||||
|
||||
KILL_ATRANS: begin
|
||||
areq_o.fetch_req = '1;
|
||||
if (arsp_i.fetch_valid) begin
|
||||
atrans_ready = 1'b1;
|
||||
if (atrans_req) begin
|
||||
atrans_state_d = READ;
|
||||
end else begin
|
||||
atrans_state_d = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
atrans_state_d = IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// OBI CHANNEL A protocol FSM (combi)
|
||||
|
||||
always_comb begin : p_fsm_obi_a
|
||||
// default assignment
|
||||
obi_a_state_d = obi_a_state_q;
|
||||
obi_a_ready = 1'b0;
|
||||
obi_r_req = '0;
|
||||
//default obi state registred
|
||||
obi_fetch_req_o.req = 1'b1;
|
||||
obi_fetch_req_o.reqpar = 1'b0;
|
||||
obi_fetch_req_o.a.addr = paddr_q;
|
||||
obi_fetch_req_o.a.we = '0;
|
||||
obi_fetch_req_o.a.be = '1;
|
||||
obi_fetch_req_o.a.wdata= '0;
|
||||
obi_fetch_req_o.a.aid = '0;
|
||||
obi_fetch_req_o.a.a_optional.auser= '0;
|
||||
obi_fetch_req_o.a.a_optional.wuser= '0;
|
||||
obi_fetch_req_o.a.a_optional.atop= '0;
|
||||
obi_fetch_req_o.a.a_optional.memtype[0]='0;
|
||||
obi_fetch_req_o.a.a_optional.memtype[1]=paddr_is_cacheable_q;
|
||||
obi_fetch_req_o.a.a_optional.mid= '0;
|
||||
obi_fetch_req_o.a.a_optional.prot= '0;
|
||||
obi_fetch_req_o.a.a_optional.dbg= '0;
|
||||
obi_fetch_req_o.a.a_optional.achk= '0;
|
||||
|
||||
unique case (obi_a_state_q)
|
||||
TRANSPARENT: begin
|
||||
obi_a_ready = '1;
|
||||
if (obi_a_req) begin
|
||||
if (obi_fetch_rsp_i.gnt) begin
|
||||
obi_r_req = '1; //push pending request
|
||||
end else begin
|
||||
obi_a_state_d = REGISTRED;
|
||||
end
|
||||
end
|
||||
obi_fetch_req_o.req = obi_a_req;
|
||||
obi_fetch_req_o.reqpar = !obi_a_req;
|
||||
obi_fetch_req_o.a.addr = paddr_d;
|
||||
obi_fetch_req_o.a.we = '0;
|
||||
obi_fetch_req_o.a.be = '1;
|
||||
obi_fetch_req_o.a.wdata= '0;
|
||||
obi_fetch_req_o.a.aid = '0;
|
||||
obi_fetch_req_o.a.a_optional.auser= '0;
|
||||
obi_fetch_req_o.a.a_optional.wuser= '0;
|
||||
obi_fetch_req_o.a.a_optional.atop= '0;
|
||||
obi_fetch_req_o.a.a_optional.memtype[0]='0;
|
||||
obi_fetch_req_o.a.a_optional.memtype[1]=paddr_is_cacheable;
|
||||
obi_fetch_req_o.a.a_optional.mid= '0;
|
||||
obi_fetch_req_o.a.a_optional.prot= '0;
|
||||
obi_fetch_req_o.a.a_optional.dbg= '0;
|
||||
obi_fetch_req_o.a.a_optional.achk= '0;
|
||||
end
|
||||
|
||||
REGISTRED: begin
|
||||
if (obi_fetch_rsp_i.gnt) begin
|
||||
obi_r_req = '1; //push pending request
|
||||
obi_a_state_d = TRANSPARENT;
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
obi_a_state_d = TRANSPARENT;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// OBI CHANNEL R protocol FSM (combi)
|
||||
|
||||
always_comb begin : p_fsm_obi_r
|
||||
// default assignment
|
||||
obi_r_state_d = obi_r_state_q;
|
||||
data_valid_obi = '0;
|
||||
|
||||
unique case (obi_r_state_q)
|
||||
OBI_R_IDLE: begin
|
||||
if (obi_r_req) begin
|
||||
if (kill_s2) begin
|
||||
obi_r_state_d = OBI_R_KILLED;
|
||||
end else begin
|
||||
obi_r_state_d = OBI_R_PENDING;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
OBI_R_PENDING: begin
|
||||
if (obi_fetch_req_o.rready && obi_fetch_rsp_i.rvalid) begin
|
||||
data_valid_obi = !kill_s2;
|
||||
if (!obi_r_req) begin
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
end else if (kill_s2) begin
|
||||
obi_r_state_d = OBI_R_KILLED;
|
||||
end
|
||||
end
|
||||
|
||||
OBI_R_KILLED: begin
|
||||
if (obi_fetch_req_o.rready && obi_fetch_rsp_i.rvalid) begin
|
||||
if (obi_r_req) begin
|
||||
if (!kill_s2) begin
|
||||
obi_r_state_d = OBI_R_PENDING;
|
||||
end
|
||||
end else begin
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
obi_r_state_d = OBI_R_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
//always ready to get data
|
||||
assign obi_fetch_req_o.rready = '1;
|
||||
assign obi_fetch_req_o.rreadypar = !obi_fetch_req_o.rready;
|
||||
|
||||
// Update Control Flow Predictions
|
||||
bht_update_t bht_update;
|
||||
btb_update_t btb_update;
|
||||
|
||||
// assert on branch, deassert when resolved
|
||||
logic speculative_q, speculative_d;
|
||||
assign speculative_d = (speculative_q && !resolved_branch_i.valid || |is_branch || |is_return || |is_jalr) && !flush_i;
|
||||
assign icache_dreq_o.spec = speculative_d;
|
||||
|
||||
assign spec_req_non_idempot = CVA6Cfg.NonIdemPotenceEn ? speculative_d && paddr_nonidempotent : 1'b0;
|
||||
|
||||
|
||||
assign bht_update.valid = resolved_branch_i.valid
|
||||
& (resolved_branch_i.cf_type == ariane_pkg::Branch);
|
||||
|
@ -406,54 +815,59 @@ module frontend
|
|||
// enter debug on a hard-coded base-address
|
||||
if (CVA6Cfg.DebugEn && set_debug_pc_i)
|
||||
npc_d = CVA6Cfg.DmBaseAddress[CVA6Cfg.VLEN-1:0] + CVA6Cfg.HaltAddress[CVA6Cfg.VLEN-1:0];
|
||||
icache_dreq_o.vaddr = fetch_address;
|
||||
npc_fetch_address = fetch_address;
|
||||
end
|
||||
|
||||
logic [CVA6Cfg.FETCH_WIDTH-1:0] icache_data;
|
||||
logic [CVA6Cfg.FETCH_WIDTH-1:0] fetch_data;
|
||||
logic fetch_valid_d;
|
||||
|
||||
// re-align the cache line
|
||||
assign icache_data = icache_dreq_i.data >> {shamt, 4'b0};
|
||||
assign fetch_data = data_valid_under_ex ? '0 : obi_fetch_rsp_i.r.rdata >> {shamt, 4'b0};
|
||||
assign fetch_valid_d = data_valid_under_ex || data_valid_obi;
|
||||
assign fetch_vaddr_d = data_valid_under_ex ? vaddr_q : obi_vaddr_q;
|
||||
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
npc_rst_load_q <= 1'b1;
|
||||
npc_q <= '0;
|
||||
speculative_q <= '0;
|
||||
icache_data_q <= '0;
|
||||
icache_valid_q <= 1'b0;
|
||||
icache_vaddr_q <= 'b0;
|
||||
icache_gpaddr_q <= 'b0;
|
||||
icache_tinst_q <= 'b0;
|
||||
icache_gva_q <= 1'b0;
|
||||
icache_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
btb_q <= '0;
|
||||
bht_q <= '0;
|
||||
npc_rst_load_q <= 1'b1;
|
||||
npc_q <= '0;
|
||||
speculative_q <= '0;
|
||||
fetch_data_q <= '0;
|
||||
fetch_valid_q <= 1'b0;
|
||||
fetch_vaddr_q <= 'b0;
|
||||
fetch_gpaddr_q <= 'b0;
|
||||
fetch_tinst_q <= 'b0;
|
||||
fetch_gva_q <= 1'b0;
|
||||
fetch_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
btb_q <= '0;
|
||||
bht_q <= '0;
|
||||
end else begin
|
||||
npc_rst_load_q <= 1'b0;
|
||||
npc_q <= npc_d;
|
||||
speculative_q <= speculative_d;
|
||||
icache_valid_q <= icache_dreq_i.valid;
|
||||
if (icache_dreq_i.valid) begin
|
||||
icache_data_q <= icache_data;
|
||||
icache_vaddr_q <= icache_dreq_i.vaddr;
|
||||
npc_q <= npc_d;
|
||||
speculative_q <= speculative_d;
|
||||
fetch_valid_q <= fetch_valid_d;
|
||||
if (fetch_valid_d) begin
|
||||
fetch_data_q <= fetch_data;
|
||||
fetch_vaddr_q <= fetch_vaddr_d;
|
||||
if (CVA6Cfg.RVH) begin
|
||||
icache_gpaddr_q <= icache_dreq_i.ex.tval2[CVA6Cfg.GPLEN-1:0];
|
||||
icache_tinst_q <= icache_dreq_i.ex.tinst;
|
||||
icache_gva_q <= icache_dreq_i.ex.gva;
|
||||
fetch_gpaddr_q <= arsp_i.fetch_exception.tval2[CVA6Cfg.GPLEN-1:0];
|
||||
fetch_tinst_q <= arsp_i.fetch_exception.tinst;
|
||||
fetch_gva_q <= arsp_i.fetch_exception.gva;
|
||||
end else begin
|
||||
icache_gpaddr_q <= 'b0;
|
||||
icache_tinst_q <= 'b0;
|
||||
icache_gva_q <= 1'b0;
|
||||
fetch_gpaddr_q <= 'b0;
|
||||
fetch_tinst_q <= 'b0;
|
||||
fetch_gva_q <= 1'b0;
|
||||
end
|
||||
|
||||
// Map the only three exceptions which can occur in the frontend to a two bit enum
|
||||
if (CVA6Cfg.MmuPresent && icache_dreq_i.ex.cause == riscv::INSTR_GUEST_PAGE_FAULT) begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_INSTR_GUEST_PAGE_FAULT;
|
||||
end else if (CVA6Cfg.MmuPresent && icache_dreq_i.ex.cause == riscv::INSTR_PAGE_FAULT) begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_INSTR_PAGE_FAULT;
|
||||
end else if (icache_dreq_i.ex.cause == riscv::INSTR_ACCESS_FAULT) begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_INSTR_ACCESS_FAULT;
|
||||
if (CVA6Cfg.MmuPresent && arsp_i.fetch_exception.cause == riscv::INSTR_GUEST_PAGE_FAULT) begin
|
||||
fetch_ex_valid_q <= ariane_pkg::FE_INSTR_GUEST_PAGE_FAULT;
|
||||
end else if (CVA6Cfg.MmuPresent && arsp_i.fetch_exception.cause == riscv::INSTR_PAGE_FAULT) begin
|
||||
fetch_ex_valid_q <= ariane_pkg::FE_INSTR_PAGE_FAULT;
|
||||
end else if (arsp_i.fetch_exception.cause == riscv::INSTR_ACCESS_FAULT) begin
|
||||
fetch_ex_valid_q <= ariane_pkg::FE_INSTR_ACCESS_FAULT;
|
||||
end else begin
|
||||
icache_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
fetch_ex_valid_q <= ariane_pkg::FE_NONE;
|
||||
end
|
||||
// save the uppermost prediction
|
||||
btb_q <= btb_prediction[CVA6Cfg.INSTR_PER_FETCH-1];
|
||||
|
@ -484,8 +898,8 @@ module frontend
|
|||
//while for ASIC, BTB is implemented in D flip-flop
|
||||
//and can be read at the same cycle.
|
||||
//Same for BHT
|
||||
assign vpc_btb = (CVA6Cfg.FpgaEn) ? icache_dreq_i.vaddr : icache_vaddr_q;
|
||||
assign vpc_bht = (CVA6Cfg.FpgaEn && CVA6Cfg.FpgaAlteraEn && icache_dreq_i.valid) ? icache_dreq_i.vaddr : icache_vaddr_q;
|
||||
assign vpc_btb = (CVA6Cfg.FpgaEn) ? vaddr_q : fetch_vaddr_q;
|
||||
assign vpc_bht = (CVA6Cfg.FpgaEn && CVA6Cfg.FpgaAlteraEn && data_valid_obi) ? vaddr_q : fetch_vaddr_q;
|
||||
|
||||
if (CVA6Cfg.BTBEntries == 0) begin
|
||||
assign btb_prediction = '0;
|
||||
|
@ -556,11 +970,11 @@ module frontend
|
|||
.flush_i (flush_i),
|
||||
.instr_i (instr), // from re-aligner
|
||||
.addr_i (addr), // from re-aligner
|
||||
.exception_i (icache_ex_valid_q), // from I$
|
||||
.exception_addr_i (icache_vaddr_q),
|
||||
.exception_gpaddr_i (icache_gpaddr_q),
|
||||
.exception_tinst_i (icache_tinst_q),
|
||||
.exception_gva_i (icache_gva_q),
|
||||
.exception_i (fetch_ex_valid_q), // from I$
|
||||
.exception_addr_i (fetch_vaddr_q),
|
||||
.exception_gpaddr_i (fetch_gpaddr_q),
|
||||
.exception_tinst_i (fetch_tinst_q),
|
||||
.exception_gva_i (fetch_gva_q),
|
||||
.predict_address_i (predict_address),
|
||||
.cf_type_i (cf_type),
|
||||
.valid_i (instruction_valid), // from re-aligner
|
||||
|
|
|
@ -159,7 +159,8 @@ package build_config_pkg;
|
|||
cfg.AXI_USER_EN = CVA6Cfg.DataUserEn | CVA6Cfg.FetchUserEn;
|
||||
|
||||
cfg.FETCH_WIDTH = unsigned'(CVA6Cfg.SuperscalarEn ? 64 : 32);
|
||||
cfg.FETCH_ALIGN_BITS = $clog2(cfg.FETCH_WIDTH / 8);
|
||||
cfg.FETCH_BE_WIDTH = cfg.FETCH_WIDTH / 8;
|
||||
cfg.FETCH_ALIGN_BITS = $clog2(cfg.FETCH_BE_WIDTH);
|
||||
cfg.INSTR_PER_FETCH = cfg.FETCH_WIDTH / (CVA6Cfg.RVC ? 16 : 32);
|
||||
cfg.LOG2_INSTR_PER_FETCH = cfg.INSTR_PER_FETCH > 1 ? $clog2(cfg.INSTR_PER_FETCH) : 1;
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ package config_pkg;
|
|||
bit AXI_USER_EN;
|
||||
|
||||
int unsigned FETCH_WIDTH;
|
||||
int unsigned FETCH_BE_WIDTH;
|
||||
int unsigned FETCH_ALIGN_BITS;
|
||||
int unsigned INSTR_PER_FETCH;
|
||||
int unsigned LOG2_INSTR_PER_FETCH;
|
||||
|
|
|
@ -21,8 +21,8 @@ module load_store_unit
|
|||
parameter type dcache_req_o_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
parameter type fu_data_t = logic,
|
||||
parameter type icache_areq_t = logic,
|
||||
parameter type icache_arsp_t = logic,
|
||||
parameter type fetch_areq_t = logic,
|
||||
parameter type fetch_arsp_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type icache_drsp_t = logic,
|
||||
parameter type lsu_ctrl_t = logic
|
||||
|
@ -82,10 +82,10 @@ module load_store_unit
|
|||
// Enable G-Stage memory translation for load/stores - TO_BE_COMPLETED
|
||||
input logic en_ld_st_g_translation_i,
|
||||
|
||||
// Instruction cache input request - CACHES
|
||||
input icache_arsp_t icache_areq_i,
|
||||
// Instruction cache output request - CACHES
|
||||
output icache_areq_t icache_areq_o,
|
||||
// Instruction cache input request - FETCH
|
||||
input fetch_areq_t fetch_areq_i,
|
||||
// Instruction cache output response - FETCH
|
||||
output fetch_arsp_t fetch_arsp_o,
|
||||
|
||||
// Current privilege mode - CSR_REGFILE
|
||||
input riscv::priv_lvl_t priv_lvl_i,
|
||||
|
@ -205,33 +205,33 @@ module load_store_unit
|
|||
logic translation_req;
|
||||
logic translation_valid;
|
||||
logic [CVA6Cfg.VLEN-1:0] mmu_vaddr;
|
||||
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, lsu_paddr;
|
||||
logic [ 31:0] mmu_tinst;
|
||||
logic mmu_hs_ld_st_inst;
|
||||
logic mmu_hlvx_inst;
|
||||
exception_t mmu_exception;
|
||||
exception_t pmp_exception;
|
||||
icache_areq_t pmp_icache_areq_i;
|
||||
logic pmp_translation_valid;
|
||||
logic dtlb_hit;
|
||||
logic [ CVA6Cfg.PPNW-1:0] dtlb_ppn;
|
||||
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, fetch_vaddr_plen, lsu_paddr;
|
||||
logic [ 31:0] mmu_tinst;
|
||||
logic mmu_hs_ld_st_inst;
|
||||
logic mmu_hlvx_inst;
|
||||
exception_t mmu_exception;
|
||||
exception_t pmp_exception;
|
||||
fetch_arsp_t pmp_fetch_arsp;
|
||||
logic pmp_translation_valid;
|
||||
logic dtlb_hit;
|
||||
logic [ CVA6Cfg.PPNW-1:0] dtlb_ppn;
|
||||
|
||||
logic ld_valid;
|
||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
|
||||
logic [ CVA6Cfg.XLEN-1:0] ld_result;
|
||||
logic st_valid;
|
||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
|
||||
logic [ CVA6Cfg.XLEN-1:0] st_result;
|
||||
logic ld_valid;
|
||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
|
||||
logic [ CVA6Cfg.XLEN-1:0] ld_result;
|
||||
logic st_valid;
|
||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
|
||||
logic [ CVA6Cfg.XLEN-1:0] st_result;
|
||||
|
||||
logic [ 11:0] page_offset;
|
||||
logic page_offset_matches;
|
||||
logic [ 11:0] page_offset;
|
||||
logic page_offset_matches;
|
||||
|
||||
exception_t misaligned_exception;
|
||||
exception_t ld_ex;
|
||||
exception_t st_ex;
|
||||
exception_t misaligned_exception;
|
||||
exception_t ld_ex;
|
||||
exception_t st_ex;
|
||||
|
||||
logic hs_ld_st_inst;
|
||||
logic hlvx_inst;
|
||||
logic hs_ld_st_inst;
|
||||
logic hlvx_inst;
|
||||
|
||||
logic [1:0] sum, mxr;
|
||||
logic [CVA6Cfg.PPNW-1:0] satp_ppn[2:0];
|
||||
|
@ -247,10 +247,8 @@ module load_store_unit
|
|||
cva6_mmu #(
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.exception_t (exception_t),
|
||||
.icache_areq_t (icache_areq_t),
|
||||
.icache_arsp_t (icache_arsp_t),
|
||||
.icache_dreq_t (icache_dreq_t),
|
||||
.icache_drsp_t (icache_drsp_t),
|
||||
.fetch_areq_t (fetch_areq_t),
|
||||
.fetch_arsp_t (fetch_arsp_t),
|
||||
.dcache_req_i_t(dcache_req_i_t),
|
||||
.dcache_req_o_t(dcache_req_o_t),
|
||||
.HYP_EXT (HYP_EXT)
|
||||
|
@ -262,8 +260,8 @@ module load_store_unit
|
|||
.enable_g_translation_i(enable_g_translation_i),
|
||||
.en_ld_st_translation_i(en_ld_st_translation_i),
|
||||
.en_ld_st_g_translation_i(en_ld_st_g_translation_i),
|
||||
.icache_areq_i(icache_areq_i),
|
||||
.icache_areq_o(pmp_icache_areq_i),
|
||||
.fetch_areq_i(fetch_areq_i),
|
||||
.fetch_arsp_o(pmp_fetch_arsp),
|
||||
// misaligned bypass
|
||||
.misaligned_ex_i(misaligned_exception),
|
||||
.lsu_req_i(translation_req),
|
||||
|
@ -313,14 +311,14 @@ module load_store_unit
|
|||
.pmpaddr_i
|
||||
);
|
||||
end else begin : gen_no_mmu
|
||||
// icache request without MMU, virtual and physical address are identical
|
||||
assign pmp_icache_areq_i.fetch_valid = icache_areq_i.fetch_req;
|
||||
// fetch request without MMU, virtual and physical address are identical
|
||||
assign pmp_fetch_arsp.fetch_valid = fetch_areq_i.fetch_req;
|
||||
if (CVA6Cfg.VLEN >= CVA6Cfg.PLEN) begin : gen_virtual_physical_address_instruction_vlen_greater
|
||||
assign pmp_icache_areq_i.fetch_paddr = icache_areq_i.fetch_vaddr[CVA6Cfg.PLEN-1:0];
|
||||
assign pmp_fetch_arsp.fetch_paddr = fetch_areq_i.fetch_vaddr[CVA6Cfg.PLEN-1:0];
|
||||
end else begin : gen_virtual_physical_address_instruction_plen_greater
|
||||
assign pmp_icache_areq_i.fetch_paddr = CVA6Cfg.PLEN'(icache_areq_i.fetch_vaddr);
|
||||
assign pmp_fetch_arsp.fetch_paddr = CVA6Cfg.PLEN'(fetch_areq_i.fetch_vaddr);
|
||||
end
|
||||
assign pmp_icache_areq_i.fetch_exception = 'h0;
|
||||
assign pmp_fetch_arsp.fetch_exception = 'h0;
|
||||
// dcache request without mmu for load or store,
|
||||
// Delay of 1 cycle to match MMU latency giving the address tag
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
@ -363,14 +361,14 @@ module load_store_unit
|
|||
|
||||
pmp_data_if #(
|
||||
.CVA6Cfg (CVA6Cfg),
|
||||
.icache_areq_t(icache_areq_t),
|
||||
.icache_areq_t(fetch_arsp_t),
|
||||
.exception_t (exception_t)
|
||||
) i_pmp_data_if (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.icache_areq_i (pmp_icache_areq_i),
|
||||
.icache_areq_o (icache_areq_o),
|
||||
.icache_fetch_vaddr_i(icache_areq_i.fetch_vaddr),
|
||||
.icache_areq_i (pmp_fetch_arsp),
|
||||
.icache_areq_o (fetch_arsp_o),
|
||||
.icache_fetch_vaddr_i(fetch_areq_i.fetch_vaddr),
|
||||
.lsu_valid_i (pmp_translation_valid),
|
||||
.lsu_paddr_i (lsu_paddr),
|
||||
.lsu_vaddr_i (mmu_vaddr),
|
||||
|
|
|
@ -21,7 +21,7 @@ module perf_counters
|
|||
parameter type dcache_req_i_t = logic,
|
||||
parameter type dcache_req_o_t = logic,
|
||||
parameter type exception_t = logic,
|
||||
parameter type icache_dreq_t = logic,
|
||||
parameter type fetch_dreq_t = logic,
|
||||
parameter type scoreboard_entry_t = logic,
|
||||
parameter int unsigned NumPorts = 3 // number of miss ports
|
||||
) (
|
||||
|
@ -52,7 +52,7 @@ module perf_counters
|
|||
input bp_resolve_t resolved_branch_i,
|
||||
// for newly added events
|
||||
input exception_t branch_exceptions_i, //Branch exceptions->execute unit-> branch_exception_o
|
||||
input icache_dreq_t l1_icache_access_i,
|
||||
input fetch_dreq_t l1_fetch_access_i,
|
||||
input dcache_req_i_t [2:0] l1_dcache_access_i,
|
||||
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0]miss_vld_bits_i, //For Cache eviction (3ports-LOAD,STORE,PTW)
|
||||
input logic i_tlb_flush_i,
|
||||
|
@ -123,7 +123,7 @@ module perf_counters
|
|||
5'b01101: events[i] = |return_event; //Return
|
||||
5'b01110: events[i] = sb_full_i; //MSB Full
|
||||
5'b01111: events[i] = if_empty_i; //Instruction fetch Empty
|
||||
5'b10000: events[i] = l1_icache_access_i.req; //L1 I-Cache accesses
|
||||
5'b10000: events[i] = l1_fetch_access_i.req; //L1 I-Cache accesses
|
||||
5'b10001:
|
||||
events[i] = l1_dcache_access_i[0].data_req || l1_dcache_access_i[1].data_req || l1_dcache_access_i[2].data_req;//L1 D-Cache accesses
|
||||
5'b10010:
|
||||
|
|
|
@ -44,6 +44,7 @@ set_property include_dirs { \
|
|||
"src/axi_sd_bridge/include" \
|
||||
"../../vendor/pulp-platform/common_cells/include" \
|
||||
"../../vendor/pulp-platform/axi/include" \
|
||||
"../../vendor/pulp-platform/obi/include" \
|
||||
"../../core/cache_subsystem/hpdcache/rtl/include" \
|
||||
"../register_interface/include" \
|
||||
"../../core/include" \
|
||||
|
|
Loading…
Add table
Reference in a new issue