OBI protocol between Frontend to icache (#2205)

This commit is contained in:
Yannick Casamatta 2024-06-06 10:02:31 +00:00 committed by GitHub
parent 278649d3ed
commit 4b3280eb94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 1137 additions and 474 deletions

View file

@ -68,5 +68,6 @@ report = rb.Report(f'{cycles//1000} kCycles')
report.add_metric(score_metric)
report.dump()
if report.failed:
sys.exit(1)
#if report.failed:
# sys.exit(1)

3
.gitmodules vendored
View file

@ -49,3 +49,6 @@
[submodule "docs/06_cv32a65x_riscv/riscv-isa-manual"]
path = docs/06_cv32a65x_riscv/riscv-isa-manual
url = https://github.com/riscv/riscv-isa-manual.git
[submodule "core/obi"]
path = core/obi
url = https://github.com/pulp-platform/obi.git

View file

@ -31,6 +31,7 @@ ${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/AsyncDpRam.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/AsyncThreePortRam.sv
+incdir+${CVA6_REPO_DIR}/core/include/
+incdir+${CVA6_REPO_DIR}/core/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/
@ -57,6 +58,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}/core/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
@ -78,7 +81,7 @@ ${CVA6_REPO_DIR}/core/cvxif_example/cvxif_example_coprocessor.sv
${CVA6_REPO_DIR}/core/cvxif_example/instr_decoder.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
@ -97,6 +100,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}/core/obi/src/obi_atop_resolver.sv
${CVA6_REPO_DIR}/core/obi/src/obi_demux.sv
${CVA6_REPO_DIR}/core/obi/src/obi_err_sbr.sv
${CVA6_REPO_DIR}/core/obi/src/obi_intf.sv
${CVA6_REPO_DIR}/core/obi/src/obi_mux.sv
${CVA6_REPO_DIR}/core/obi/src/obi_sram_shim.sv
${CVA6_REPO_DIR}/core/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

View file

@ -9,6 +9,7 @@
#
+incdir+${CVA6_REPO_DIR}/core/include/
+incdir+${CVA6_REPO_DIR}/core/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/
@ -25,6 +26,7 @@ ${CVA6_REPO_DIR}/core/include/wt_cache_pkg.sv
${CVA6_REPO_DIR}/core/include/std_cache_pkg.sv
${CVA6_REPO_DIR}/core/include/instr_tracer_pkg.sv
${CVA6_REPO_DIR}/core/include/build_config_pkg.sv
${CVA6_REPO_DIR}/core/obi/src/obi_pkg.sv
//CVXIF
${CVA6_REPO_DIR}/core/include/cvxif_pkg.sv
@ -70,4 +72,3 @@ ${CVA6_REPO_DIR}/common/local/util/tc_sram_wrapper_cache_techno.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv
${CVA6_REPO_DIR}/common/local/util/sram.sv
${CVA6_REPO_DIR}/common/local/util/sram_cache.sv

View file

@ -311,9 +311,9 @@ module cache_ctrl
// two memory look-ups on a single-ported SRAM and therefore is non-atomic
if (!mshr_index_matches_i) begin
// store data, write dirty bit
req_o = hit_way_q;
addr_o = mem_req_q.index;
we_o = 1'b1;
req_o = hit_way_q;
addr_o = mem_req_q.index;
we_o = 1'b1;
be_o.vldrty = hit_way_q;

View file

@ -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_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,
@ -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_dreq_t fetch_dreq_i,
// Output Access request - 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$
@ -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_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(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),
.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 (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)
);
// }}}
@ -707,13 +709,13 @@ 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) (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 :

View file

@ -30,10 +30,10 @@ module cva6_icache
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,
/// ID to be used for read transactions
@ -43,17 +43,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_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,
// refill port
input logic mem_rtrn_vld_i,
input icache_rtrn_t mem_rtrn_i,
@ -123,31 +126,29 @@ module cva6_icache
FLUSH,
IDLE,
READ,
READ_BIS,
MISS,
KILL_ATRANS,
KILL_MISS
} state_e;
state_e state_d, state_q;
///////////////////////////////////////////////////////
// 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;
assign cl_tag_d = (fetch_obi_req_i.req && fetch_obi_rsp_o.gnt) ? fetch_obi_req_i.a.addr[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;
// 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;
// split virtual address into index and offset to address cache arrays
assign cl_index = vaddr_d[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
@ -177,18 +178,133 @@ module cva6_icache
assign mem_data_o.nc = paddr_is_nc;
// 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;
logic rvalid_d, rvalid_q;
logic invalid_data_d, invalid_data_q;
//OBI
assign fetch_obi_rsp_o.gntpar = !fetch_obi_rsp_o.gnt;
assign fetch_obi_rsp_o.rvalidpar = !fetch_obi_rsp_o.rvalid;
assign fetch_obi_rsp_o.r.rid = '0;
assign fetch_obi_rsp_o.r.r_optional.exokay = '0;
assign fetch_obi_rsp_o.r.r_optional.rchk = '0;
assign fetch_obi_rsp_o.r.err = '0;
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;
logic [CVA6Cfg.FETCH_WIDTH-1:0] data_d, data_q;
logic [CVA6Cfg.FETCH_USER_WIDTH-1:0] userdata_d, userdata_q;
logic data_valid_obi;
// 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;
end else begin
obi_r_state_q <= obi_r_state_d;
data_q <= data_d;
userdata_q <= userdata_d;
end
end
// OBI CHANNEL R protocol FSM (combi)
always_comb begin : p_fsm_obi_r
// default assignment
fetch_obi_rsp_o.rvalid = '0;
dreq_o.invalid_data = '0;
fetch_obi_rsp_o.r.rdata = data_d;
fetch_obi_rsp_o.r.r_optional.ruser = userdata_d;
obi_r_state_d = obi_r_state_q;
unique case (obi_r_state_q)
OBI_R_IDLE: begin
if (fetch_obi_req_i.req && fetch_obi_rsp_o.gnt) begin
if (dreq_i.kill_req || flush_d) begin
obi_r_state_d = OBI_R_KILLED;
end else if (data_valid_obi) begin
obi_r_state_d = OBI_R_VALID;
end else begin
obi_r_state_d = OBI_R_WAIT;
end
end
end
OBI_R_WAIT: begin
if (dreq_i.kill_req || flush_d) begin
fetch_obi_rsp_o.rvalid = '1;
dreq_o.invalid_data = '1;
obi_r_state_d = OBI_R_IDLE;
end else if (data_valid_obi) begin
fetch_obi_rsp_o.rvalid = '1;
fetch_obi_rsp_o.r.rdata = data_d;
fetch_obi_rsp_o.r.r_optional.ruser = userdata_d;
obi_r_state_d = OBI_R_IDLE;
end
end
OBI_R_VALID: begin
if (dreq_i.kill_req || flush_d) begin
fetch_obi_rsp_o.rvalid = '1;
dreq_o.invalid_data = '1;
end else begin
fetch_obi_rsp_o.rvalid = '1;
fetch_obi_rsp_o.r.rdata = data_q;
fetch_obi_rsp_o.r.r_optional.ruser = userdata_q;
end
if (fetch_obi_req_i.req && fetch_obi_rsp_o.gnt) begin
if (dreq_i.kill_req || flush_d) begin
obi_r_state_d = OBI_R_KILLED;
end else if (data_valid_obi) begin
obi_r_state_d = OBI_R_VALID;
end else begin
obi_r_state_d = OBI_R_WAIT;
end
end else begin
obi_r_state_d = OBI_R_IDLE;
end
end
OBI_R_KILLED: begin
fetch_obi_rsp_o.rvalid = '1;
dreq_o.invalid_data = '1;
if (fetch_obi_req_i.req && fetch_obi_rsp_o.gnt) begin
if (dreq_i.kill_req || flush_d) begin
obi_r_state_d = OBI_R_KILLED;
end else if (data_valid_obi) begin
obi_r_state_d = OBI_R_VALID;
end else 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 +315,13 @@ 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;
mem_data_req_o = 1'b0;
// performance counter
miss_o = 1'b0;
fetch_obi_rsp_o.gnt = 1'b0;
data_valid_obi = '0;
// handle invalidations unconditionally
// note: invald are mutually exclusive with
@ -243,15 +358,17 @@ module cva6_icache
// 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
// we have a new request not killed
if (dreq_i.req && !dreq_i.kill_req) begin
cache_rden = 1'b1;
state_d = READ;
if (fetch_obi_req_i.req) begin
state_d = READ_BIS;
fetch_obi_rsp_o.gnt = 1'b1;
end else begin
state_d = READ;
end
end
end
if (dreq_i.kill_s1) begin
state_d = IDLE;
end
end
end
//////////////////////////////////
@ -261,38 +378,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 (fetch_obi_req_i.req) begin
state_d = READ_BIS;
fetch_obi_rsp_o.gnt = 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 (dreq_i.kill_req) begin
state_d = IDLE;
if (!mem_rtrn_vld_i) begin
dreq_o.ready = 1'b1;
if (dreq_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 = '1;
state_d = IDLE;
if (!mem_rtrn_vld_i) begin
dreq_o.ready = 1'b1;
if (dreq_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
@ -305,10 +421,59 @@ module cva6_icache
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 (dreq_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
dreq_o.ready = 1'b1;
if (dreq_i.req) begin
state_d = READ;
end
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;
// we have a hit or an exception output valid result
end else if (((|cl_hit && cache_en_q && !inv_q) || dreq_i.kill_req)) begin
state_d = IDLE;
data_valid_obi = dreq_i.kill_req; // just don't output in this case
// 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
dreq_o.ready = 1'b1;
if (dreq_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;
state_d = MISS;
end
end
end
//////////////////////////////////
// wait until the memory transaction
// returns. do not write to memory
@ -319,27 +484,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 (!(dreq_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;
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 (dreq_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 +503,7 @@ module cva6_icache
state_d = IDLE;
end
end
default: begin
// we should never get here
state_d = FLUSH;
@ -440,11 +596,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
@ -506,27 +662,31 @@ module cva6_icache
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
cl_tag_q <= '0;
flush_cnt_q <= '0;
vaddr_q <= '0;
cmp_en_q <= '0;
cache_en_q <= '0;
flush_q <= '0;
state_q <= FLUSH;
cl_offset_q <= '0;
repl_way_oh_q <= '0;
inv_q <= '0;
cl_tag_q <= '0;
flush_cnt_q <= '0;
vaddr_q <= '0;
cmp_en_q <= '0;
cache_en_q <= '0;
flush_q <= '0;
state_q <= FLUSH;
cl_offset_q <= '0;
repl_way_oh_q <= '0;
inv_q <= '0;
rvalid_q <= '0;
invalid_data_q <= '0;
end else begin
cl_tag_q <= cl_tag_d;
flush_cnt_q <= flush_cnt_d;
vaddr_q <= vaddr_d;
cmp_en_q <= cmp_en_d;
cache_en_q <= cache_en_d;
flush_q <= flush_d;
state_q <= state_d;
cl_offset_q <= cl_offset_d;
repl_way_oh_q <= repl_way_oh_d;
inv_q <= inv_d;
cl_tag_q <= cl_tag_d;
flush_cnt_q <= flush_cnt_d;
vaddr_q <= vaddr_d;
cmp_en_q <= cmp_en_d;
cache_en_q <= cache_en_d;
flush_q <= flush_d;
state_q <= state_d;
cl_offset_q <= cl_offset_d;
repl_way_oh_q <= repl_way_oh_d;
inv_q <= inv_d;
rvalid_q <= rvalid_d;
invalid_data_q <= invalid_data_d;
end
end
@ -548,7 +708,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 :

View file

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

View file

@ -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
@ -290,13 +293,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 :

View file

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

View file

@ -12,8 +12,11 @@
// Date: 19.03.2017
// Description: CVA6 Top-level module
`include "obi/typedef.svh"
`include "obi/assign.svh"
`include "rvfi_types.svh"
module cva6
import ariane_pkg::*;
#(
@ -50,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_dreq_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_drsp_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
@ -303,6 +300,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;
@ -556,10 +558,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_dreq_t fetch_dreq_if_cache;
fetch_drsp_t fetch_dreq_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;
@ -593,16 +599,24 @@ 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_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)
) i_frontend (
.flush_i (flush_ctrl_if), // not entirely correct
.flush_bp_i (1'b0),
.halt_i (halt_ctrl),
.debug_mode_i (debug_mode),
.boot_addr_i (boot_addr_i[CVA6Cfg.VLEN-1:0]),
.icache_dreq_i (icache_dreq_cache_if),
.icache_dreq_o (icache_dreq_if_cache),
.arsp_i (fetch_arsp_ex_frontend),
.areq_o (fetch_areq_frontend_ex),
.fetch_dreq_i (fetch_dreq_cache_if),
.fetch_dreq_o (fetch_dreq_if_cache),
.fetch_obi_req_o (obi_fetch_req_if_cache), //OBI
.fetch_obi_rsp_i (obi_fetch_rsp_cache_if), //OBI
.resolved_branch_i (resolved_branch),
.pc_commit_i (pc_commit),
.set_pc_commit_i (set_pc_ctrl_pcgen),
@ -817,10 +831,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)
) ex_stage_i (
.clk_i(clk_i),
@ -924,8 +936,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),
@ -1082,7 +1094,7 @@ 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_dreq_t(fetch_dreq_t),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.NumPorts(NumPorts)
@ -1109,7 +1121,7 @@ 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),
.i_tlb_flush_i (flush_tlb_ctrl_ex),
@ -1197,11 +1209,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),
@ -1216,10 +1228,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),
@ -1245,14 +1257,14 @@ module cva6
end else if (CVA6Cfg.DCacheType == config_pkg::HPDCACHE) 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_dreq_t(fetch_dreq_t),
.fetch_drsp_t(fetch_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),
.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),
@ -1270,10 +1282,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
.dcache_enable_i (dcache_en_csr_nbdcache),
.dcache_flush_i (dcache_flush_ctrl_cache),
@ -1312,21 +1324,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),
@ -1336,10 +1348,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),

View file

@ -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
@ -166,7 +164,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;
@ -191,7 +189,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_content_o (itlb_content),
.lu_g_content_o(itlb_g_content),
.lu_gpaddr_o (itlb_gpaddr),
@ -255,7 +253,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),
@ -340,54 +338,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_ACCESS_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
// ---------//
@ -395,39 +393,39 @@ 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);
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 else if (!pmp_instr_allow) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_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
end else if (ptw_active && walking_instr) begin
@ -435,36 +433,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;
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
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
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
@ -473,25 +471,25 @@ module cva6_mmu
// if it didn't match any execute region throw an `Instruction Access Fault`
// or: if we are not translating, check PMPs immediately on the paddr
if ((!match_any_execute_region && !ptw_error) || (!(enable_translation_i || enable_g_translation_i) && !pmp_instr_allow)) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_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) begin //To confirm this is the right TVAL
if (enable_translation_i || enable_g_translation_i)
icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
fetch_arsp_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr);
else
icache_areq_o.fetch_exception.tval=CVA6Cfg.XLEN'(icache_areq_o.fetch_paddr[CVA6Cfg.PLEN-1:(CVA6Cfg.PLEN > CVA6Cfg.VLEN) ? (CVA6Cfg.PLEN - CVA6Cfg.VLEN) : 0]);
fetch_arsp_o.fetch_exception.tval=CVA6Cfg.XLEN'(fetch_arsp_o.fetch_paddr[CVA6Cfg.PLEN-1:(CVA6Cfg.PLEN > CVA6Cfg.VLEN) ? (CVA6Cfg.PLEN - CVA6Cfg.VLEN) : 0]);
end
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
// check for execute flag on memory
assign match_any_execute_region = config_pkg::is_inside_execute_regions(
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, icache_areq_o.fetch_paddr}
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, fetch_arsp_o.fetch_paddr}
);
// Instruction fetch
@ -502,7 +500,7 @@ module cva6_mmu
.NR_ENTRIES(CVA6Cfg.NrPMPEntries)
// .NR_ENTRIES ( ArianeCfg.NrPMPEntries ) // configuration used in hypervisor extension
) i_pmp_if (
.addr_i (icache_areq_o.fetch_paddr),
.addr_i (fetch_arsp_o.fetch_paddr),
.priv_lvl_i,
// we will always execute on the instruction fetch port
.access_type_i(riscv::ACCESS_EXEC),
@ -556,7 +554,7 @@ module cva6_mmu
// Check if the User flag is set, then we may only access it in supervisor mode
// if SUM is enabled
daccess_err = en_ld_st_translation_i &&
((ld_st_priv_lvl_i == riscv::PRIV_LVL_S && (ld_st_v_i ? !vs_sum_i : !sum_i ) && dtlb_pte_q.u) || // SUM is not set and we are trying to access a user page in supervisor mode
((ld_st_priv_lvl_i == riscv::PRIV_LVL_S && (ld_st_v_i ? !vs_sum_i : !sum_i ) && dtlb_pte_q.u) || // SUM is not set and we are trying to access a user page in supervisor mode
(ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u));
if (CVA6Cfg.RVH) begin

View file

@ -350,7 +350,7 @@ module cva6_rvfi
`CONNECT_RVFI_FULL(1'b1, mstatus, csr.mstatus_extended)
bit [31:0] mstatush_q;
`CONNECT_RVFI_FULL(1'b1, mstatush, mstatush_q)
`CONNECT_RVFI_FULL(1'b1, mstatush, mstatush_q)
`CONNECT_RVFI_FULL(1'b1, misa, IsaCode)

View file

@ -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
) (
// Subsystem Clock - SUBSYSTEM
@ -194,10 +192,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
@ -417,10 +415,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,
@ -446,8 +442,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,

View file

@ -21,8 +21,12 @@ module frontend
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_dreq_t = logic,
parameter type fetch_drsp_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 +58,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_dreq_t fetch_dreq_o,
// Handshake between CACHE and FRONTEND (fetch) - CACHES
input icache_drsp_t icache_dreq_i,
input fetch_drsp_t fetch_dreq_i,
// OBI Fetch Request channel - CACHES
output obi_fetch_req_t fetch_obi_req_o,
// OBI Fetch Response channel - CACHES
input obi_fetch_rsp_t fetch_obi_rsp_i,
// Handshake's data between fetch and decode - ID_STAGE
output fetch_entry_t [ariane_pkg::SUPERSCALAR:0] fetch_entry_o,
// Handshake's valid between fetch and decode - ID_STAGE
@ -89,13 +101,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 +118,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
@ -152,18 +168,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)
@ -304,26 +322,416 @@ 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;
// Caches optimisation signals
logic custom_req;
logic custom_kill;
logic custom_ready;
logic data_valid_under_ex;
logic save_vaddr;
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 obi_r_ready;
logic data_valid_obi;
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_dreq_o.vaddr = vaddr_d;
assign fetch_dreq_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;
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;
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_dreq_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 (instr_queue_ready && atrans_ready && !kill_s2) begin
fetch_dreq_o.req = '1;
if (fetch_dreq_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_dreq_o.req = '1;
if (fetch_dreq_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 (instr_queue_ready && atrans_ready && !kill_s1) begin
fetch_dreq_o.req = '1;
if (fetch_dreq_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_dreq_o.req = '1;
if (fetch_dreq_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 (instr_queue_ready && atrans_ready && !kill_s1) begin
fetch_dreq_o.req = '1;
if (fetch_dreq_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 (instr_queue_ready && atrans_ready && !kill_s1) begin
fetch_dreq_o.req = '1;
if (fetch_dreq_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
// we should never get here
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
// we should never get here
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
fetch_obi_req_o.req = 1'b1;
fetch_obi_req_o.reqpar = 1'b0;
fetch_obi_req_o.a.addr = paddr_q;
fetch_obi_req_o.a.we = '0;
fetch_obi_req_o.a.be = '1;
fetch_obi_req_o.a.wdata= '0;
fetch_obi_req_o.a.aid = '0;
fetch_obi_req_o.a.a_optional.auser= '0;
fetch_obi_req_o.a.a_optional.wuser= '0;
fetch_obi_req_o.a.a_optional.atop= '0;
fetch_obi_req_o.a.a_optional.memtype= '0;
fetch_obi_req_o.a.a_optional.mid= '0;
fetch_obi_req_o.a.a_optional.prot= '0;
fetch_obi_req_o.a.a_optional.dbg= '0;
fetch_obi_req_o.a.a_optional.achk= '0;
unique case (obi_a_state_q)
TRANSPARENT: begin
obi_a_ready = obi_r_ready;
if (obi_a_req) begin
if (fetch_obi_rsp_i.gnt) begin
obi_r_req = '1; //push pending request
end else begin
obi_a_state_d = REGISTRED;
end
end
fetch_obi_req_o.req = obi_a_req;
fetch_obi_req_o.reqpar = !obi_a_req;
fetch_obi_req_o.a.addr = paddr_d;
fetch_obi_req_o.a.we = '0;
fetch_obi_req_o.a.be = '1;
fetch_obi_req_o.a.wdata= '0;
fetch_obi_req_o.a.aid = '0;
fetch_obi_req_o.a.a_optional.auser= '0;
fetch_obi_req_o.a.a_optional.wuser= '0;
fetch_obi_req_o.a.a_optional.atop= '0;
fetch_obi_req_o.a.a_optional.memtype= '0;
fetch_obi_req_o.a.a_optional.mid= '0;
fetch_obi_req_o.a.a_optional.prot= '0;
fetch_obi_req_o.a.a_optional.dbg= '0;
fetch_obi_req_o.a.a_optional.achk= '0;
end
REGISTRED: begin
if (fetch_obi_rsp_i.gnt) begin
obi_r_req = '1; //push pending request
obi_a_state_d = TRANSPARENT;
end
end
default: begin
// we should never get here
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_ready = '0;
obi_r_state_d = obi_r_state_q;
data_valid_obi = '0;
unique case (obi_r_state_q)
OBI_R_IDLE: begin
obi_r_ready = '1;
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 (fetch_obi_req_o.rready && fetch_obi_rsp_i.rvalid) begin
data_valid_obi = !kill_s2;
obi_r_ready = '1;
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 (fetch_obi_req_o.rready && fetch_obi_rsp_i.rvalid) begin
obi_r_ready = '1;
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
// we should never get here
obi_r_state_d = OBI_R_IDLE;
end
endcase
end
//always ready to get data
assign fetch_obi_req_o.rready = '1;
assign fetch_obi_req_o.rreadypar = !fetch_obi_req_o.rready;
// Update Control Flow Predictions
bht_update_t bht_update;
btb_update_t btb_update;
// assert on branch, deassert when resolved
logic addr_ni;
assign addr_ni = config_pkg::is_inside_nonidempotent_regions(
CVA6Cfg, {{64 - CVA6Cfg.PLEN{1'b0}}, fetch_obi_req_o.a.addr}
);
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 = (speculative_d || ((CVA6Cfg.NonIdemPotenceEn && !addr_ni) || (!CVA6Cfg.NonIdemPotenceEn)));
assign bht_update.valid = resolved_branch_i.valid
& (resolved_branch_i.cf_type == ariane_pkg::Branch);
@ -407,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 : fetch_obi_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,7 +897,7 @@ module frontend
//For FPGA, BTB is implemented in read synchronous BRAM
//while for ASIC, BTB is implemented in D flip-flop
//and can be read at the same cycle.
assign vpc_btb = (CVA6Cfg.FpgaEn) ? icache_dreq_i.vaddr : icache_vaddr_q;
assign vpc_btb = (CVA6Cfg.FpgaEn) ? vaddr_q : fetch_vaddr_q;
if (CVA6Cfg.BTBEntries == 0) begin
assign btb_prediction = '0;
@ -517,7 +930,7 @@ module frontend
.rst_ni,
.flush_bp_i (flush_bp_i),
.debug_mode_i,
.vpc_i (icache_vaddr_q),
.vpc_i (fetch_vaddr_q),
.bht_update_i (bht_update),
.bht_prediction_o(bht_prediction)
);
@ -555,11 +968,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

View file

@ -138,7 +138,8 @@ package build_config_pkg;
cfg.AXI_USER_EN = CVA6Cfg.DataUserEn | CVA6Cfg.FetchUserEn;
cfg.FETCH_WIDTH = 32 << ariane_pkg::SUPERSCALAR;
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;
@ -157,6 +158,53 @@ package build_config_pkg;
cfg.VpnLen = VpnLen;
cfg.PtLevels = PtLevels;
cfg.IdWidth = cfg.AxiIdWidth; //to be changed
cfg.ObiFetchbusCfg = '{
UseRReady: 1'b1,
CombGnt: 1'b0,
AddrWidth: cfg.PLEN,
DataWidth: cfg.FETCH_WIDTH,
IdWidth: cfg.IdWidth,
Integrity: 1'b0,
BeFull: 1'b1,
OptionalCfg: '{
UseAtop: 1'b1,
UseMemtype: 1'b1,
UseProt: 1'b1,
UseDbg: 1'b1,
AUserWidth: 1,
WUserWidth: cfg.FETCH_USER_WIDTH,
RUserWidth: cfg.FETCH_USER_WIDTH,
MidWidth: 1,
AChkWidth: 1,
RChkWidth: 1
}
};
cfg.ObiDatabusCfg = '{
UseRReady: 1'b1,
CombGnt: 1'b0,
AddrWidth: cfg.PLEN,
DataWidth: cfg.XLEN,
IdWidth: cfg.IdWidth,
Integrity: 1'b0,
BeFull: 1'b1,
OptionalCfg: '{
UseAtop: 1'b1,
UseMemtype: 1'b1,
UseProt: 1'b1,
UseDbg: 1'b1,
AUserWidth: 1,
WUserWidth: cfg.DCACHE_USER_WIDTH,
RUserWidth: cfg.DCACHE_USER_WIDTH,
MidWidth: 1,
AChkWidth: 1,
RChkWidth: 1
}
};
return cfg;
endfunction

View file

@ -313,6 +313,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;
@ -325,6 +326,12 @@ package config_pkg;
vm_mode_t MODE_SV;
int unsigned SV;
int unsigned SVX;
int unsigned IdWidth;
obi_pkg::obi_cfg_t ObiFetchbusCfg;
obi_pkg::obi_cfg_t ObiDatabusCfg;
} cva6_cfg_t;
/// Empty configuration to sanity check proper parameter passing. Whenever

View file

@ -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,
@ -244,10 +244,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)
@ -255,8 +253,8 @@ module load_store_unit
.clk_i(clk_i),
.rst_ni(rst_ni),
.flush_i(flush_i),
.icache_areq_i(icache_areq_i),
.icache_areq_o(icache_areq_o),
.fetch_areq_i(fetch_areq_i),
.fetch_arsp_o(fetch_arsp_o),
// misaligned bypass
.misaligned_ex_i(misaligned_exception),
.lsu_req_i(translation_req),
@ -291,15 +289,15 @@ module load_store_unit
if (CVA6Cfg.VLEN > CVA6Cfg.PLEN) begin
assign mmu_vaddr_plen = mmu_vaddr[CVA6Cfg.PLEN-1:0];
assign fetch_vaddr_plen = icache_areq_i.fetch_vaddr[CVA6Cfg.PLEN-1:0];
assign fetch_vaddr_plen = fetch_areq_i.fetch_vaddr[CVA6Cfg.PLEN-1:0];
end else begin
assign mmu_vaddr_plen = {{{CVA6Cfg.PLEN - CVA6Cfg.VLEN} {1'b0}}, mmu_vaddr};
assign fetch_vaddr_plen = {{{CVA6Cfg.PLEN - CVA6Cfg.VLEN} {1'b0}}, icache_areq_i.fetch_vaddr};
assign mmu_vaddr_plen = {{{CVA6Cfg.PLEN - CVA6Cfg.VLEN} {1'b0}}, mmu_vaddr};
assign fetch_vaddr_plen = {{{CVA6Cfg.PLEN - CVA6Cfg.VLEN} {1'b0}}, fetch_areq_i.fetch_vaddr};
end
assign icache_areq_o.fetch_valid = icache_areq_i.fetch_req;
assign icache_areq_o.fetch_paddr = fetch_vaddr_plen;
assign icache_areq_o.fetch_exception = '0;
assign fetch_arsp_o.fetch_valid = fetch_areq_i.fetch_req;
assign fetch_arsp_o.fetch_paddr = fetch_vaddr_plen;
assign fetch_arsp_o.fetch_exception = '0;
assign dcache_req_ports_o[0].address_index = '0;
assign dcache_req_ports_o[0].address_tag = '0;

1
core/obi Submodule

@ -0,0 +1 @@
Subproject commit 1aa411df145c4ebdd61f8fed4d003c33f7b20636

View file

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