mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
OBI protocol between Frontend to icache (#2205)
This commit is contained in:
parent
278649d3ed
commit
4b3280eb94
20 changed files with 1137 additions and 474 deletions
|
@ -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
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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
|
||||
|
@ -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 :
|
||||
|
|
|
@ -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
|
||||
|
|
152
core/cva6.sv
152
core/cva6.sv
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1
core/obi
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 1aa411df145c4ebdd61f8fed4d003c33f7b20636
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue