Add the HPDcache as cache subsystem (#1513)

Add the HPDcache as another alternative for the cache subsystem.
The HPDcache is a highly configurable L1 Dcache that mainly targets high-performance systems.
This commit is contained in:
Cesar Fuguet 2023-10-16 09:26:20 +02:00 committed by GitHub
parent 166c4b8ba1
commit 7de1345291
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 1892 additions and 149 deletions

3
.gitmodules vendored
View file

@ -37,3 +37,6 @@
[submodule "verif/core-v-verif"]
path = verif/core-v-verif
url = https://github.com/openhwgroup/core-v-verif
[submodule "core/cache_subsystem/hpdcache"]
path = core/cache_subsystem/hpdcache
url = https://github.com/openhwgroup/cv-hpdcache.git

View file

@ -94,6 +94,16 @@ ifndef TARGET_CFG
export TARGET_CFG = $(target)
endif
# HPDcache directory
HPDCACHE_DIR ?= $(CVA6_REPO_DIR)/core/cache_subsystem/hpdcache
export HPDCACHE_DIR
# Target HPDcache configuration package.
# The HPDCACHE_TARGET_CFG variable contains the path (relative or absolute)
# to your target configuration package
HPDCACHE_TARGET_CFG ?= ${CVA6_REPO_DIR}/core/include/cva6_hpdcache_default_config_pkg.sv
export HPDCACHE_TARGET_CFG
# Sources
# Package files -> compile first
ariane_pkg := \
@ -550,7 +560,7 @@ verilate_command := $(verilator) verilator_config.vlt
$(if $(PROFILE),--stats --stats-vars --profile-cfuncs,) \
$(if $(DEBUG), --trace-structs,) \
$(if $(TRACE_COMPACT), --trace-fst $(VL_INC_DIR)/verilated_fst_c.cpp) \
$(if $(TRACE_FAST), --trace $(VL_INC_DIR)/include/verilated_vcd_c.cpp) \
$(if $(TRACE_FAST), --trace $(VL_INC_DIR)/verilated_vcd_c.cpp) \
-LDFLAGS "-L$(RISCV)/lib -L$(SPIKE_INSTALL_DIR)/lib -Wl,-rpath,$(RISCV)/lib -Wl,-rpath,$(SPIKE_INSTALL_DIR)/lib -lfesvr$(if $(PROFILE), -g -pg,) -lpthread $(if $(TRACE_COMPACT), -lz,)" \
-CFLAGS "$(CFLAGS)$(if $(PROFILE), -g -pg,) -DVL_DEBUG" \
--cc --vpi \
@ -647,7 +657,12 @@ check-torture:
grep 'All signatures match for $(test-location)' $(riscv-torture-dir)/$(test-location).log
diff -s $(riscv-torture-dir)/$(test-location).spike.sig $(riscv-torture-dir)/$(test-location).rtlsim.sig
src_flist := $(addprefix $(root-dir), $(shell cat core/Flist.cva6|grep "$\{CVA6_REPO_DIR.\+sv"|sed "s/.*CVA6_REPO_DIR..//"|sed "s/..TARGET_CFG./$(target)/"))
src_flist = $(shell \
CVA6_REPO_DIR=$(CVA6_REPO_DIR) \
TARGET_CFG=$(TARGET_CFG) \
HPDCACHE_TARGET_CFG=$(HPDCACHE_TARGET_CFG) \
HPDCACHE_DIR=$(HPDCACHE_DIR) \
python3 util/flist_flattener.py core/Flist.cva6)
fpga_filter := $(addprefix $(root-dir), corev_apu/bootrom/bootrom.sv)
fpga_filter += $(addprefix $(root-dir), core/include/instr_tracer_pkg.sv)
fpga_filter += $(addprefix $(root-dir), src/util/ex_trace_item.sv)

View file

@ -16,7 +16,6 @@
//pragma translate_off
`include "ex_trace_item.svh"
`include "instr_trace_item.svh"
//pragma translate_on
module instr_tracer (
instr_tracer_if tracer_if,
@ -187,7 +186,6 @@ module instr_tracer (
bp = {};
endfunction
// pragma translate_off
function void printInstr(ariane_pkg::scoreboard_entry_t sbe, logic [31:0] instr, logic [63:0] result, logic [riscv::PLEN-1:0] paddr, riscv::priv_lvl_t priv_lvl, logic debug_mode, ariane_pkg::bp_resolve_t bp);
automatic instr_trace_item iti = new ($time, clk_ticks, sbe, instr, gp_reg_file, fp_reg_file, result, paddr, priv_lvl, debug_mode, bp);
// print instruction to console
@ -219,7 +217,7 @@ module instr_tracer (
final begin
close();
end
// pragma translate_on
endmodule : instr_tracer
//pragma translate_on
`endif

View file

@ -32,6 +32,7 @@ ${CVA6_REPO_DIR}/vendor/pulp-platform/fpga-support/rtl/AsyncThreePortRam.sv
+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/
+incdir+${CVA6_REPO_DIR}/common/local/util/
// Floating point unit
@ -154,6 +155,14 @@ ${CVA6_REPO_DIR}/core/cache_subsystem/cache_ctrl.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_icache_axi_wrapper.sv
${CVA6_REPO_DIR}/core/cache_subsystem/std_cache_subsystem.sv
${CVA6_REPO_DIR}/core/cache_subsystem/std_nbdcache.sv
${HPDCACHE_TARGET_CFG}
-F ${HPDCACHE_DIR}/rtl/hpdcache.Flist
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_subsystem.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_subsystem_axi_arbiter.sv
${CVA6_REPO_DIR}/core/cache_subsystem/cva6_hpdcache_if_adapter.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_1rw.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_wbyteenable_1rw.sv
${HPDCACHE_DIR}/rtl/src/common/macros/behav/hpdcache_sram_wmask_1rw.sv
// Physical Memory Protection
// NOTE: pmp.sv modified for DSIM (unchanged for other simulators)

View file

@ -0,0 +1,203 @@
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Authors: Cesar Fuguet
// Date: February, 2023
// Description: Interface adapter for the CVA6 core
module cva6_hpdcache_if_adapter
import hpdcache_pkg::*;
// Parameters
// {{{
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter bit is_load_port = 1'b1
)
// }}}
// Ports
// {{{
(
// Clock and active-low reset pins
input logic clk_i,
input logic rst_ni,
// Port ID
input hpdcache_pkg::hpdcache_req_sid_t hpdcache_req_sid_i,
// Request/response ports from/to the CVA6 core
input ariane_pkg::dcache_req_i_t cva6_req_i,
output ariane_pkg::dcache_req_o_t cva6_req_o,
input ariane_pkg::amo_req_t cva6_amo_req_i,
output ariane_pkg::amo_resp_t cva6_amo_resp_o,
// Request port to the L1 Dcache
output logic hpdcache_req_valid_o,
input logic hpdcache_req_ready_i,
output hpdcache_pkg::hpdcache_req_t hpdcache_req_o,
output logic hpdcache_req_abort_o,
output hpdcache_pkg::hpdcache_tag_t hpdcache_req_tag_o,
output hpdcache_pkg::hpdcache_pma_t hpdcache_req_pma_o,
// Response port from the L1 Dcache
input logic hpdcache_rsp_valid_i,
input hpdcache_pkg::hpdcache_rsp_t hpdcache_rsp_i
);
// }}}
// Internal nets and registers
// {{{
logic forward_store, forward_amo;
logic hpdcache_req_is_uncacheable;
// }}}
// Request forwarding
// {{{
generate
// LOAD request
// {{{
if (is_load_port == 1'b1) begin : load_port_gen
assign hpdcache_req_is_uncacheable =
!config_pkg::is_inside_cacheable_regions(CVA6Cfg,
{{64 - ariane_pkg::DCACHE_TAG_WIDTH{1'b0}}
, cva6_req_i.address_tag
, {ariane_pkg::DCACHE_INDEX_WIDTH{1'b0}}});
// Request forwarding
assign hpdcache_req_valid_o = cva6_req_i.data_req,
hpdcache_req_o.addr_offset = cva6_req_i.address_index,
hpdcache_req_o.wdata = '0,
hpdcache_req_o.op = hpdcache_pkg::HPDCACHE_REQ_LOAD,
hpdcache_req_o.be = cva6_req_i.data_be,
hpdcache_req_o.size = cva6_req_i.data_size,
hpdcache_req_o.sid = hpdcache_req_sid_i,
hpdcache_req_o.tid = cva6_req_i.data_id,
hpdcache_req_o.need_rsp = 1'b1,
hpdcache_req_o.phys_indexed = 1'b0,
hpdcache_req_o.addr_tag = '0, // unused on virtually indexed request
hpdcache_req_o.pma = '0; // unused on virtually indexed request
assign hpdcache_req_abort_o = cva6_req_i.kill_req,
hpdcache_req_tag_o = cva6_req_i.address_tag,
hpdcache_req_pma_o.uncacheable = hpdcache_req_is_uncacheable,
hpdcache_req_pma_o.io = 1'b0;
// Response forwarding
assign cva6_req_o.data_rvalid = hpdcache_rsp_valid_i,
cva6_req_o.data_rdata = hpdcache_rsp_i.rdata,
cva6_req_o.data_rid = hpdcache_rsp_i.tid,
cva6_req_o.data_gnt = hpdcache_req_ready_i;
end
// }}}
// STORE/AMO request
// {{{
else begin : store_amo_gen
hpdcache_req_addr_t amo_addr;
hpdcache_req_offset_t amo_addr_offset;
hpdcache_tag_t amo_tag;
logic amo_is_word, amo_is_word_hi;
hpdcache_req_data_t amo_data;
hpdcache_req_be_t amo_data_be;
hpdcache_req_op_t amo_op;
logic [31:0] amo_resp_word;
// AMO logic
// {{{
always_comb
begin : amo_op_comb
amo_addr = cva6_amo_req_i.operand_a;
amo_addr_offset = amo_addr[0 +: HPDCACHE_REQ_OFFSET_WIDTH];
amo_tag = amo_addr[HPDCACHE_REQ_OFFSET_WIDTH +: HPDCACHE_TAG_WIDTH];
amo_is_word = (cva6_amo_req_i.size == 2'b10);
amo_is_word_hi = cva6_amo_req_i.operand_a[2];
amo_data = amo_is_word ? {2{cva6_amo_req_i.operand_b[0 +: 32]}}
: cva6_amo_req_i.operand_b;
amo_data_be = amo_is_word_hi ? 8'hf0 :
amo_is_word ? 8'h0f : 8'hff;
unique case(cva6_amo_req_i.amo_op)
ariane_pkg::AMO_LR: amo_op = HPDCACHE_REQ_AMO_LR;
ariane_pkg::AMO_SC: amo_op = HPDCACHE_REQ_AMO_SC;
ariane_pkg::AMO_SWAP: amo_op = HPDCACHE_REQ_AMO_SWAP;
ariane_pkg::AMO_ADD: amo_op = HPDCACHE_REQ_AMO_ADD;
ariane_pkg::AMO_AND: amo_op = HPDCACHE_REQ_AMO_AND;
ariane_pkg::AMO_OR: amo_op = HPDCACHE_REQ_AMO_OR;
ariane_pkg::AMO_XOR: amo_op = HPDCACHE_REQ_AMO_XOR;
ariane_pkg::AMO_MAX: amo_op = HPDCACHE_REQ_AMO_MAX;
ariane_pkg::AMO_MAXU: amo_op = HPDCACHE_REQ_AMO_MAXU;
ariane_pkg::AMO_MIN: amo_op = HPDCACHE_REQ_AMO_MIN;
ariane_pkg::AMO_MINU: amo_op = HPDCACHE_REQ_AMO_MINU;
default: amo_op = HPDCACHE_REQ_LOAD;
endcase
end
assign amo_resp_word = amo_is_word_hi ? hpdcache_rsp_i.rdata[0][32 +: 32]
: hpdcache_rsp_i.rdata[0][0 +: 32];
// }}}
// Request forwarding
// {{{
assign hpdcache_req_is_uncacheable =
!config_pkg::is_inside_cacheable_regions(CVA6Cfg,
{{64 - ariane_pkg::DCACHE_TAG_WIDTH{1'b0}}
, hpdcache_req_o.addr_tag, {ariane_pkg::DCACHE_INDEX_WIDTH{1'b0}}});
assign forward_store = cva6_req_i.data_req,
forward_amo = cva6_amo_req_i.req;
assign hpdcache_req_valid_o = forward_store | forward_amo,
hpdcache_req_o.addr_offset = forward_amo ? amo_addr_offset
: cva6_req_i.address_index,
hpdcache_req_o.wdata = forward_amo ? amo_data
: cva6_req_i.data_wdata,
hpdcache_req_o.op = forward_amo ? amo_op
: hpdcache_pkg::HPDCACHE_REQ_STORE,
hpdcache_req_o.be = forward_amo ? amo_data_be
: cva6_req_i.data_be,
hpdcache_req_o.size = forward_amo ? cva6_amo_req_i.size
: cva6_req_i.data_size,
hpdcache_req_o.sid = hpdcache_req_sid_i,
hpdcache_req_o.tid = forward_amo ? '1 : '0,
hpdcache_req_o.need_rsp = forward_amo,
hpdcache_req_o.phys_indexed = 1'b1,
hpdcache_req_o.addr_tag = forward_amo ? amo_tag : cva6_req_i.address_tag,
hpdcache_req_o.pma.uncacheable = hpdcache_req_is_uncacheable,
hpdcache_req_o.pma.io = 1'b0,
hpdcache_req_abort_o = 1'b0, // unused on physically indexed requests
hpdcache_req_tag_o = '0, // unused on physically indexed requests
hpdcache_req_pma_o = '0; // unused on physically indexed requests
// }}}
// Response forwarding
// {{{
assign cva6_req_o.data_rvalid = hpdcache_rsp_valid_i && (hpdcache_rsp_i.tid != '1),
cva6_req_o.data_rdata = hpdcache_rsp_i.rdata,
cva6_req_o.data_rid = hpdcache_rsp_i.tid,
cva6_req_o.data_gnt = hpdcache_req_ready_i;
assign cva6_amo_resp_o.ack = hpdcache_rsp_valid_i && (hpdcache_rsp_i.tid == '1),
cva6_amo_resp_o.result = amo_is_word ? {{32{amo_resp_word[31]}}, amo_resp_word}
: hpdcache_rsp_i.rdata[0][63:0];
// }}}
end
// }}}
endgenerate
// }}}
// Assertions
// {{{
// pragma translate_off
forward_one_request_assert: assert property (@(posedge clk_i)
($onehot0({forward_store, forward_amo}))) else
$error("Only one request shall be forwarded");
// pragma translate_on
// }}}
endmodule

View file

@ -0,0 +1,588 @@
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Authors: Cesar Fuguet
// Date: February, 2023
// Description: CVA6 cache subsystem integrating standard CVA6's
// instruction cache and the Core-V High-Performance L1
// data cache (CV-HPDcache).
module cva6_hpdcache_subsystem
// Parameters
// {{{
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter int NumPorts = 4,
parameter int NrHwPrefetchers = 4,
parameter type noc_req_t = logic,
parameter type noc_resp_t = logic,
parameter type cmo_req_t = logic,
parameter type cmo_rsp_t = logic
)
// }}}
// Ports
// {{{
(
input logic clk_i,
input logic rst_ni,
// I$
// {{{
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 ariane_pkg::icache_areq_t icache_areq_i, // to/from frontend
output ariane_pkg::icache_arsp_t icache_areq_o,
// data requests
input ariane_pkg::icache_dreq_t icache_dreq_i, // to/from frontend
output ariane_pkg::icache_drsp_t icache_dreq_o,
// }}}
// D$
// {{{
// Cache management
input logic dcache_enable_i, // from CSR
input logic dcache_flush_i, // high until acknowledged
output logic dcache_flush_ack_o, // send a single cycle acknowledge signal when the cache is flushed
output logic dcache_miss_o, // we missed on a ld/st
// AMO interface
input ariane_pkg::amo_req_t dcache_amo_req_i, // from LSU
output ariane_pkg::amo_resp_t dcache_amo_resp_o, // to LSU
// CMO interface
input cmo_req_t dcache_cmo_req_i, // from CMO FU
output cmo_rsp_t dcache_cmo_resp_o, // to CMO FU
// Request ports
input ariane_pkg::dcache_req_i_t [NumPorts-1:0] dcache_req_ports_i, // from LSU
output ariane_pkg::dcache_req_o_t [NumPorts-1:0] dcache_req_ports_o, // to LSU
// Write Buffer status
output logic wbuffer_empty_o,
output logic wbuffer_not_ni_o,
// Hardware memory prefetcher configuration
input logic [NrHwPrefetchers-1:0] hwpf_base_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_base_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_base_o,
input logic [NrHwPrefetchers-1:0] hwpf_param_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_param_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_param_o,
input logic [NrHwPrefetchers-1:0] hwpf_throttle_set_i,
input logic [NrHwPrefetchers-1:0][63:0] hwpf_throttle_i,
output logic [NrHwPrefetchers-1:0][63:0] hwpf_throttle_o,
output logic [63:0] hwpf_status_o,
// }}}
// AXI port to upstream memory/peripherals
// {{{
output noc_req_t noc_req_o,
input noc_resp_t noc_resp_i
// }}}
);
// }}}
`include "axi/typedef.svh"
// I$ instantiation
// {{{
logic icache_miss_valid, icache_miss_ready;
wt_cache_pkg::icache_req_t icache_miss;
logic icache_miss_resp_valid;
wt_cache_pkg::icache_rtrn_t icache_miss_resp;
localparam int ICACHE_RDTXID = 1 << (ariane_pkg::MEM_TID_WIDTH - 1);
cva6_icache #(
.CVA6Cfg (CVA6Cfg),
.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)
);
// }}}
// D$ instantiation
// {{{
`include "hpdcache_typedef.svh"
// 0: Page-Table Walk (PTW)
// 1: Load unit
// 2: Accelerator load
// 3: Store/AMO
// .
// .
// .
// NumPorts: CMO
// NumPorts + 1: Hardware Memory Prefetcher (hwpf)
localparam int HPDCACHE_NREQUESTERS = NumPorts + 2;
typedef logic [CVA6Cfg.AxiAddrWidth-1:0] hpdcache_mem_addr_t;
typedef logic [ariane_pkg::MEM_TID_WIDTH-1:0] hpdcache_mem_id_t;
typedef logic [CVA6Cfg.AxiDataWidth-1:0] hpdcache_mem_data_t;
typedef logic [CVA6Cfg.AxiDataWidth/8-1:0] hpdcache_mem_be_t;
`HPDCACHE_TYPEDEF_MEM_REQ_T(hpdcache_mem_req_t, hpdcache_mem_addr_t, hpdcache_mem_id_t);
`HPDCACHE_TYPEDEF_MEM_RESP_R_T(hpdcache_mem_resp_r_t, hpdcache_mem_id_t, hpdcache_mem_data_t);
`HPDCACHE_TYPEDEF_MEM_REQ_W_T(hpdcache_mem_req_w_t, hpdcache_mem_data_t, hpdcache_mem_be_t);
`HPDCACHE_TYPEDEF_MEM_RESP_W_T(hpdcache_mem_resp_w_t, hpdcache_mem_id_t);
typedef logic [63:0] hwpf_stride_param_t;
logic dcache_req_valid [HPDCACHE_NREQUESTERS-1:0];
logic dcache_req_ready [HPDCACHE_NREQUESTERS-1:0];
hpdcache_pkg::hpdcache_req_t dcache_req [HPDCACHE_NREQUESTERS-1:0];
logic dcache_req_abort [HPDCACHE_NREQUESTERS-1:0];
hpdcache_pkg::hpdcache_tag_t dcache_req_tag [HPDCACHE_NREQUESTERS-1:0];
hpdcache_pkg::hpdcache_pma_t dcache_req_pma [HPDCACHE_NREQUESTERS-1:0];
logic dcache_rsp_valid [HPDCACHE_NREQUESTERS-1:0];
hpdcache_pkg::hpdcache_rsp_t dcache_rsp [HPDCACHE_NREQUESTERS-1:0];
logic dcache_read_miss, dcache_write_miss;
logic [2:0] snoop_valid;
logic [2:0] snoop_abort;
hpdcache_pkg::hpdcache_req_offset_t [2:0] snoop_addr_offset;
hpdcache_pkg::hpdcache_tag_t [2:0] snoop_addr_tag;
logic [2:0] snoop_phys_indexed;
logic dcache_cmo_req_is_prefetch;
logic dcache_miss_ready;
logic dcache_miss_valid;
hpdcache_mem_req_t dcache_miss;
logic dcache_miss_resp_ready;
logic dcache_miss_resp_valid;
hpdcache_mem_resp_r_t dcache_miss_resp;
logic dcache_wbuf_ready;
logic dcache_wbuf_valid;
hpdcache_mem_req_t dcache_wbuf;
logic dcache_wbuf_data_ready;
logic dcache_wbuf_data_valid;
hpdcache_mem_req_w_t dcache_wbuf_data;
logic dcache_wbuf_resp_ready;
logic dcache_wbuf_resp_valid;
hpdcache_mem_resp_w_t dcache_wbuf_resp;
logic dcache_uc_read_ready;
logic dcache_uc_read_valid;
hpdcache_mem_req_t dcache_uc_read;
logic dcache_uc_read_resp_ready;
logic dcache_uc_read_resp_valid;
hpdcache_mem_resp_r_t dcache_uc_read_resp;
logic dcache_uc_write_ready;
logic dcache_uc_write_valid;
hpdcache_mem_req_t dcache_uc_write;
logic dcache_uc_write_data_ready;
logic dcache_uc_write_data_valid;
hpdcache_mem_req_w_t dcache_uc_write_data;
logic dcache_uc_write_resp_ready;
logic dcache_uc_write_resp_valid;
hpdcache_mem_resp_w_t dcache_uc_write_resp;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_in;
hwpf_stride_pkg::hwpf_stride_throttle_t [NrHwPrefetchers-1:0] hwpf_throttle_out;
generate
ariane_pkg::dcache_req_i_t dcache_req_ports[HPDCACHE_NREQUESTERS-1:0];
for (genvar r = 0; r < (NumPorts-1); r++) begin : cva6_hpdcache_load_if_adapter_gen
assign dcache_req_ports[r] = dcache_req_ports_i[r];
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.is_load_port (1'b1)
) i_cva6_hpdcache_load_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i (hpdcache_pkg::hpdcache_req_sid_t'(r)),
.cva6_req_i (dcache_req_ports[r]),
.cva6_req_o (dcache_req_ports_o[r]),
.cva6_amo_req_i ('0),
.cva6_amo_resp_o (/* unused */),
.hpdcache_req_valid_o (dcache_req_valid[r]),
.hpdcache_req_ready_i (dcache_req_ready[r]),
.hpdcache_req_o (dcache_req[r]),
.hpdcache_req_abort_o (dcache_req_abort[r]),
.hpdcache_req_tag_o (dcache_req_tag[r]),
.hpdcache_req_pma_o (dcache_req_pma[r]),
.hpdcache_rsp_valid_i (dcache_rsp_valid[r]),
.hpdcache_rsp_i (dcache_rsp[r])
);
end
cva6_hpdcache_if_adapter #(
.CVA6Cfg (CVA6Cfg),
.is_load_port (1'b0)
) i_cva6_hpdcache_store_if_adapter (
.clk_i,
.rst_ni,
.hpdcache_req_sid_i (hpdcache_pkg::hpdcache_req_sid_t'(NumPorts-1)),
.cva6_req_i (dcache_req_ports_i[NumPorts-1]),
.cva6_req_o (dcache_req_ports_o[NumPorts-1]),
.cva6_amo_req_i (dcache_amo_req_i),
.cva6_amo_resp_o (dcache_amo_resp_o),
.hpdcache_req_valid_o (dcache_req_valid[NumPorts-1]),
.hpdcache_req_ready_i (dcache_req_ready[NumPorts-1]),
.hpdcache_req_o (dcache_req[NumPorts-1]),
.hpdcache_req_abort_o (dcache_req_abort[NumPorts-1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts-1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts-1]),
.hpdcache_rsp_valid_i (dcache_rsp_valid[NumPorts-1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts-1])
);
`ifdef HPDCACHE_ENABLE_CMO
cva6_hpdcache_cmo_if_adapter #(
.cmo_req_t (cmo_req_t),
.cmo_rsp_t (cmo_rsp_t)
) i_cva6_hpdcache_cmo_if_adapter (
.clk_i,
.rst_ni,
.dcache_req_sid_i (hpdcache_pkg::hpdcache_req_sid_t'(NumPorts)),
.cva6_cmo_req_i (dcache_cmo_req_i),
.cva6_cmo_resp_o (dcache_cmo_resp_o),
.dcache_req_valid_o (dcache_req_valid[NumPorts]),
.dcache_req_ready_i (dcache_req_ready[NumPorts]),
.dcache_req_o (dcache_req[NumPorts]),
.dcache_req_abort_o (dcache_req_abort[NumPorts]),
.dcache_req_tag_o (dcache_req_tag[NumPorts]),
.dcache_req_pma_o (dcache_req_pma[NumPorts]),
.dcache_rsp_valid_i (dcache_rsp_valid[NumPorts]),
.dcache_rsp_i (dcache_rsp[NumPorts])
);
`else
assign dcache_req_valid[NumPorts] = 1'b0,
dcache_req [NumPorts] = '0,
dcache_req_abort[NumPorts] = 1'b0,
dcache_req_tag [NumPorts] = '0,
dcache_req_pma [NumPorts] = '0;
`endif
endgenerate
// Snoop load port
assign snoop_valid[0] = dcache_req_valid[1] & dcache_req_ready[1],
snoop_abort[0] = dcache_req_abort[1],
snoop_addr_offset[0] = dcache_req[1].addr_offset,
snoop_addr_tag[0] = dcache_req_tag[1],
snoop_phys_indexed[0] = dcache_req[1].phys_indexed;
// Snoop Store/AMO port
assign snoop_valid[1] = dcache_req_valid[NumPorts-1] & dcache_req_ready[NumPorts-1],
snoop_abort[1] = dcache_req_abort[NumPorts-1],
snoop_addr_offset[1] = dcache_req[NumPorts-1].addr_offset,
snoop_addr_tag[1] = dcache_req_tag[NumPorts-1],
snoop_phys_indexed[1] = dcache_req[NumPorts-1].phys_indexed;
`ifdef HPDCACHE_ENABLE_CMO
// Snoop CMO port (in case of read prefetch accesses)
assign dcache_cmo_req_is_prefetch =
hpdcache_pkg::is_cmo_prefetch(dcache_req[NumPorts].op, dcache_req[NumPorts].size);
assign snoop_valid[2] = dcache_req_valid[NumPorts]
& dcache_req_ready[NumPorts]
& dcache_cmo_req_is_prefetch,
snoop_abort[2] = dcache_req_abort[NumPorts],
snoop_addr_offset[2] = dcache_req[NumPorts].addr_offset,
snoop_addr_tag[2] = dcache_req_tag[NumPorts],
snoop_phys_indexed[2] = dcache_req[NumPorts].phys_indexed;
`else
assign snoop_valid[2] = 1'b0,
snoop_abort[2] = 1'b0,
snoop_addr_offset[2] = '0,
snoop_addr_tag[2] = '0,
snoop_phys_indexed[2] = 1'b0;
`endif
generate
for (genvar h = 0; h < NrHwPrefetchers; h++) begin : hwpf_throttle_gen
assign hwpf_throttle_in[h] = hwpf_stride_pkg::hwpf_stride_throttle_t'(hwpf_throttle_i[h]),
hwpf_throttle_o[h] = hwpf_stride_pkg::hwpf_stride_param_t'(hwpf_throttle_out[h]);
end
endgenerate
hwpf_stride_wrapper #(
.NUM_HW_PREFETCH (NrHwPrefetchers),
.NUM_SNOOP_PORTS (3)
) i_hwpf_stride_wrapper (
.clk_i,
.rst_ni,
.hwpf_stride_base_set_i (hwpf_base_set_i),
.hwpf_stride_base_i (hwpf_base_i),
.hwpf_stride_base_o (hwpf_base_o),
.hwpf_stride_param_set_i (hwpf_param_set_i),
.hwpf_stride_param_i (hwpf_param_i),
.hwpf_stride_param_o (hwpf_param_o),
.hwpf_stride_throttle_set_i (hwpf_throttle_set_i),
.hwpf_stride_throttle_i (hwpf_throttle_in),
.hwpf_stride_throttle_o (hwpf_throttle_out),
.hwpf_stride_status_o (hwpf_status_o),
.snoop_valid_i (snoop_valid),
.snoop_abort_i (snoop_abort),
.snoop_addr_offset_i (snoop_addr_offset),
.snoop_addr_tag_i (snoop_addr_tag),
.snoop_phys_indexed_i (snoop_phys_indexed),
.hpdcache_req_sid_i (hpdcache_pkg::hpdcache_req_sid_t'(NumPorts+1)),
.hpdcache_req_valid_o (dcache_req_valid[NumPorts+1]),
.hpdcache_req_ready_i (dcache_req_ready[NumPorts+1]),
.hpdcache_req_o (dcache_req[NumPorts+1]),
.hpdcache_req_abort_o (dcache_req_abort[NumPorts+1]),
.hpdcache_req_tag_o (dcache_req_tag[NumPorts+1]),
.hpdcache_req_pma_o (dcache_req_pma[NumPorts+1]),
.hpdcache_rsp_valid_i (dcache_rsp_valid[NumPorts+1]),
.hpdcache_rsp_i (dcache_rsp[NumPorts+1])
);
hpdcache #(
.NREQUESTERS (HPDCACHE_NREQUESTERS),
.HPDcacheMemIdWidth (ariane_pkg::MEM_TID_WIDTH),
.HPDcacheMemDataWidth (CVA6Cfg.AxiDataWidth),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t),
.hpdcache_mem_resp_r_t (hpdcache_mem_resp_r_t),
.hpdcache_mem_resp_w_t (hpdcache_mem_resp_w_t)
) i_hpdcache(
.clk_i,
.rst_ni,
.wbuf_flush_i (dcache_flush_i),
.core_req_valid_i (dcache_req_valid),
.core_req_ready_o (dcache_req_ready),
.core_req_i (dcache_req),
.core_req_abort_i (dcache_req_abort),
.core_req_tag_i (dcache_req_tag),
.core_req_pma_i (dcache_req_pma),
.core_rsp_valid_o (dcache_rsp_valid),
.core_rsp_o (dcache_rsp),
.mem_req_miss_read_ready_i (dcache_miss_ready),
.mem_req_miss_read_valid_o (dcache_miss_valid),
.mem_req_miss_read_o (dcache_miss),
.mem_resp_miss_read_ready_o (dcache_miss_resp_ready),
.mem_resp_miss_read_valid_i (dcache_miss_resp_valid),
.mem_resp_miss_read_i (dcache_miss_resp),
.mem_req_wbuf_write_ready_i (dcache_wbuf_ready),
.mem_req_wbuf_write_valid_o (dcache_wbuf_valid),
.mem_req_wbuf_write_o (dcache_wbuf),
.mem_req_wbuf_write_data_ready_i (dcache_wbuf_data_ready),
.mem_req_wbuf_write_data_valid_o (dcache_wbuf_data_valid),
.mem_req_wbuf_write_data_o (dcache_wbuf_data),
.mem_resp_wbuf_write_ready_o (dcache_wbuf_resp_ready),
.mem_resp_wbuf_write_valid_i (dcache_wbuf_resp_valid),
.mem_resp_wbuf_write_i (dcache_wbuf_resp),
.mem_req_uc_read_ready_i (dcache_uc_read_ready),
.mem_req_uc_read_valid_o (dcache_uc_read_valid),
.mem_req_uc_read_o (dcache_uc_read),
.mem_resp_uc_read_ready_o (dcache_uc_read_resp_ready),
.mem_resp_uc_read_valid_i (dcache_uc_read_resp_valid),
.mem_resp_uc_read_i (dcache_uc_read_resp),
.mem_req_uc_write_ready_i (dcache_uc_write_ready),
.mem_req_uc_write_valid_o (dcache_uc_write_valid),
.mem_req_uc_write_o (dcache_uc_write),
.mem_req_uc_write_data_ready_i (dcache_uc_write_data_ready),
.mem_req_uc_write_data_valid_o (dcache_uc_write_data_valid),
.mem_req_uc_write_data_o (dcache_uc_write_data),
.mem_resp_uc_write_ready_o (dcache_uc_write_resp_ready),
.mem_resp_uc_write_valid_i (dcache_uc_write_resp_valid),
.mem_resp_uc_write_i (dcache_uc_write_resp),
.evt_cache_write_miss_o (dcache_write_miss),
.evt_cache_read_miss_o (dcache_read_miss),
.evt_uncached_req_o (/* unused */),
.evt_cmo_req_o (/* unused */),
.evt_write_req_o (/* unused */),
.evt_read_req_o (/* unused */),
.evt_prefetch_req_o (/* unused */),
.evt_req_on_hold_o (/* unused */),
.evt_rtab_rollback_o (/* unused */),
.evt_stall_refill_o (/* unused */),
.evt_stall_o (/* unused */),
.wbuf_empty_o (wbuffer_empty_o),
.cfg_enable_i (dcache_enable_i),
.cfg_wbuf_threshold_i (4'd2),
.cfg_wbuf_reset_timecnt_on_write_i (1'b1),
.cfg_wbuf_sequential_waw_i (1'b0),
.cfg_wbuf_inhibit_write_coalescing_i (1'b0),
.cfg_prefetch_updt_plru_i (1'b1),
.cfg_error_on_cacheable_amo_i (1'b0),
.cfg_rtab_single_entry_i (1'b0)
);
assign dcache_miss_o = dcache_read_miss,
wbuffer_not_ni_o = wbuffer_empty_o;
always_ff @(posedge clk_i or negedge rst_ni)
begin : dcache_flush_ff
if (!rst_ni) dcache_flush_ack_o <= 1'b0;
else dcache_flush_ack_o <= ~dcache_flush_ack_o & dcache_flush_i;
end
// }}}
// AXI arbiter instantiation
// {{{
typedef logic [CVA6Cfg.AxiAddrWidth-1:0] axi_addr_t;
typedef logic [CVA6Cfg.AxiDataWidth-1:0] axi_data_t;
typedef logic [CVA6Cfg.AxiDataWidth/8-1:0] axi_strb_t;
typedef logic [CVA6Cfg.AxiIdWidth-1:0] axi_id_t;
typedef logic [CVA6Cfg.AxiUserWidth-1:0] axi_user_t;
`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, axi_addr_t, axi_id_t, axi_user_t)
`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, axi_data_t, axi_strb_t, axi_user_t)
`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, axi_id_t, axi_user_t)
`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, axi_addr_t, axi_id_t, axi_user_t)
`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, axi_data_t, axi_id_t, axi_user_t)
cva6_hpdcache_subsystem_axi_arbiter #(
.HPDcacheMemIdWidth (ariane_pkg::MEM_TID_WIDTH),
.HPDcacheMemDataWidth (CVA6Cfg.AxiDataWidth),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t),
.hpdcache_mem_resp_r_t (hpdcache_mem_resp_r_t),
.hpdcache_mem_resp_w_t (hpdcache_mem_resp_w_t),
.AxiAddrWidth (CVA6Cfg.AxiAddrWidth),
.AxiDataWidth (CVA6Cfg.AxiDataWidth),
.AxiIdWidth (CVA6Cfg.AxiIdWidth),
.AxiUserWidth (CVA6Cfg.AxiUserWidth),
.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_axi_arbiter (
.clk_i,
.rst_ni,
.icache_miss_valid_i (icache_miss_valid),
.icache_miss_ready_o (icache_miss_ready),
.icache_miss_i (icache_miss),
.icache_miss_id_i (hpdcache_mem_id_t'(ICACHE_RDTXID)),
.icache_miss_resp_valid_o (icache_miss_resp_valid),
.icache_miss_resp_o (icache_miss_resp),
.dcache_miss_ready_o (dcache_miss_ready),
.dcache_miss_valid_i (dcache_miss_valid),
.dcache_miss_i (dcache_miss),
.dcache_miss_resp_ready_i (dcache_miss_resp_ready),
.dcache_miss_resp_valid_o (dcache_miss_resp_valid),
.dcache_miss_resp_o (dcache_miss_resp),
.dcache_wbuf_ready_o (dcache_wbuf_ready),
.dcache_wbuf_valid_i (dcache_wbuf_valid),
.dcache_wbuf_i (dcache_wbuf),
.dcache_wbuf_data_ready_o (dcache_wbuf_data_ready),
.dcache_wbuf_data_valid_i (dcache_wbuf_data_valid),
.dcache_wbuf_data_i (dcache_wbuf_data),
.dcache_wbuf_resp_ready_i (dcache_wbuf_resp_ready),
.dcache_wbuf_resp_valid_o (dcache_wbuf_resp_valid),
.dcache_wbuf_resp_o (dcache_wbuf_resp),
.dcache_uc_read_ready_o (dcache_uc_read_ready),
.dcache_uc_read_valid_i (dcache_uc_read_valid),
.dcache_uc_read_i (dcache_uc_read),
.dcache_uc_read_id_i ('1),
.dcache_uc_read_resp_ready_i (dcache_uc_read_resp_ready),
.dcache_uc_read_resp_valid_o (dcache_uc_read_resp_valid),
.dcache_uc_read_resp_o (dcache_uc_read_resp),
.dcache_uc_write_ready_o (dcache_uc_write_ready),
.dcache_uc_write_valid_i (dcache_uc_write_valid),
.dcache_uc_write_i (dcache_uc_write),
.dcache_uc_write_id_i ('1),
.dcache_uc_write_data_ready_o (dcache_uc_write_data_ready),
.dcache_uc_write_data_valid_i (dcache_uc_write_data_valid),
.dcache_uc_write_data_i (dcache_uc_write_data),
.dcache_uc_write_resp_ready_i (dcache_uc_write_resp_ready),
.dcache_uc_write_resp_valid_o (dcache_uc_write_resp_valid),
.dcache_uc_write_resp_o (dcache_uc_write_resp),
.axi_req_o (noc_req_o),
.axi_resp_i (noc_resp_i)
);
// }}}
// Assertions
// {{{
// pragma translate_off
initial assert (hpdcache_pkg::HPDCACHE_REQ_SRC_ID_WIDTH >= $clog2(HPDCACHE_NREQUESTERS))
else $fatal(1, "HPDCACHE_REQ_SRC_ID_WIDTH is not wide enough");
a_invalid_instruction_fetch: assert property (
@(posedge clk_i) disable iff (!rst_ni) icache_dreq_o.valid |-> (|icache_dreq_o.data) !== 1'hX)
else $warning(1,"[l1 dcache] reading invalid instructions: vaddr=%08X, data=%08X",
icache_dreq_o.vaddr, icache_dreq_o.data);
a_invalid_write_data: assert property (
@(posedge clk_i) disable iff (!rst_ni) dcache_req_ports_i[2].data_req |-> |dcache_req_ports_i[2].data_be |-> (|dcache_req_ports_i[2].data_wdata) !== 1'hX)
else $warning(1,"[l1 dcache] writing invalid data: paddr=%016X, be=%02X, data=%016X",
{dcache_req_ports_i[2].address_tag, dcache_req_ports_i[2].address_index}, dcache_req_ports_i[2].data_be, dcache_req_ports_i[2].data_wdata);
for (genvar j=0; j<2; j++) begin : gen_assertion
a_invalid_read_data: assert property (
@(posedge clk_i) disable iff (!rst_ni) dcache_req_ports_o[j].data_rvalid && ~dcache_req_ports_i[j].kill_req |-> (|dcache_req_ports_o[j].data_rdata) !== 1'hX)
else $warning(1,"[l1 dcache] reading invalid data on port %01d: data=%016X",
j, dcache_req_ports_o[j].data_rdata);
end
// pragma translate_on
// }}}
endmodule : cva6_hpdcache_subsystem

View file

@ -0,0 +1,580 @@
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Authors: Cesar Fuguet
// Date: February, 2023
// Description: AXI arbiter for the CVA6 cache subsystem integrating standard
// CVA6's instruction cache and the Core-V High-Performance
// L1 Dcache (CV-HPDcache).
module cva6_hpdcache_subsystem_axi_arbiter
// Parameters
// {{{
#(
parameter int HPDcacheMemIdWidth = 8,
parameter int HPDcacheMemDataWidth = 512,
parameter type hpdcache_mem_req_t = logic,
parameter type hpdcache_mem_req_w_t = logic,
parameter type hpdcache_mem_resp_r_t = logic,
parameter type hpdcache_mem_resp_w_t = logic,
parameter int unsigned AxiAddrWidth = 1,
parameter int unsigned AxiDataWidth = 1,
parameter int unsigned AxiIdWidth = 1,
parameter int unsigned AxiUserWidth = 1,
parameter type axi_ar_chan_t = logic,
parameter type axi_aw_chan_t = logic,
parameter type axi_w_chan_t = logic,
parameter type axi_req_t = logic,
parameter type axi_rsp_t = logic,
localparam type hpdcache_mem_id_t = logic [HPDcacheMemIdWidth-1:0]
)
// }}}
// Ports
// {{{
(
input logic clk_i,
input logic rst_ni,
// Interfaces from/to I$
// {{{
input logic icache_miss_valid_i,
output logic icache_miss_ready_o,
input wt_cache_pkg::icache_req_t icache_miss_i,
input hpdcache_mem_id_t icache_miss_id_i,
output logic icache_miss_resp_valid_o,
output wt_cache_pkg::icache_rtrn_t icache_miss_resp_o,
// }}}
// Interfaces from/to D$
// {{{
output logic dcache_miss_ready_o,
input logic dcache_miss_valid_i,
input hpdcache_mem_req_t dcache_miss_i,
input logic dcache_miss_resp_ready_i,
output logic dcache_miss_resp_valid_o,
output hpdcache_mem_resp_r_t dcache_miss_resp_o,
// Write-buffer write interface
output logic dcache_wbuf_ready_o,
input logic dcache_wbuf_valid_i,
input hpdcache_mem_req_t dcache_wbuf_i,
output logic dcache_wbuf_data_ready_o,
input logic dcache_wbuf_data_valid_i,
input hpdcache_mem_req_w_t dcache_wbuf_data_i,
input logic dcache_wbuf_resp_ready_i,
output logic dcache_wbuf_resp_valid_o,
output hpdcache_mem_resp_w_t dcache_wbuf_resp_o,
// Uncached read interface
output logic dcache_uc_read_ready_o,
input logic dcache_uc_read_valid_i,
input hpdcache_mem_req_t dcache_uc_read_i,
input hpdcache_mem_id_t dcache_uc_read_id_i,
input logic dcache_uc_read_resp_ready_i,
output logic dcache_uc_read_resp_valid_o,
output hpdcache_mem_resp_r_t dcache_uc_read_resp_o,
// Uncached write interface
output logic dcache_uc_write_ready_o,
input logic dcache_uc_write_valid_i,
input hpdcache_mem_req_t dcache_uc_write_i,
input hpdcache_mem_id_t dcache_uc_write_id_i,
output logic dcache_uc_write_data_ready_o,
input logic dcache_uc_write_data_valid_i,
input hpdcache_mem_req_w_t dcache_uc_write_data_i,
input logic dcache_uc_write_resp_ready_i,
output logic dcache_uc_write_resp_valid_o,
output hpdcache_mem_resp_w_t dcache_uc_write_resp_o,
// }}}
// AXI port to upstream memory/peripherals
// {{{
output axi_req_t axi_req_o,
input axi_rsp_t axi_resp_i
// }}}
);
// }}}
// Internal type definitions
// {{{
typedef struct packed {
logic [AxiIdWidth-1:0] id;
logic [AxiDataWidth-1:0] data;
axi_pkg::resp_t resp;
logic last;
logic [AxiUserWidth-1:0] user;
} axi_r_chan_t;
typedef struct packed {
logic [AxiIdWidth-1:0] id;
axi_pkg::resp_t resp;
logic [AxiUserWidth-1:0] user;
} axi_b_chan_t;
localparam int MEM_RESP_RT_DEPTH = (1 << HPDcacheMemIdWidth);
typedef hpdcache_mem_id_t [MEM_RESP_RT_DEPTH-1:0] mem_resp_rt_t;
typedef logic [ariane_pkg::ICACHE_LINE_WIDTH-1:0] icache_resp_data_t;
// }}}
// Adapt the I$ interface to the HPDcache memory interface
// {{{
localparam int ICACHE_CL_WORDS = ariane_pkg::ICACHE_LINE_WIDTH/64;
localparam int ICACHE_CL_WORD_INDEX = $clog2(ICACHE_CL_WORDS);
localparam int ICACHE_CL_SIZE = $clog2(ariane_pkg::ICACHE_LINE_WIDTH/8);
localparam int ICACHE_WORD_SIZE = 3;
localparam int ICACHE_MEM_REQ_CL_LEN =
(ariane_pkg::ICACHE_LINE_WIDTH + HPDcacheMemDataWidth - 1)/HPDcacheMemDataWidth;
localparam int ICACHE_MEM_REQ_CL_SIZE =
(HPDcacheMemDataWidth <= ariane_pkg::ICACHE_LINE_WIDTH) ?
$clog2(HPDcacheMemDataWidth/8) : ICACHE_CL_SIZE;
// I$ request
hpdcache_mem_req_t icache_miss_req_wdata;
logic icache_miss_req_w, icache_miss_req_wok;
hpdcache_mem_req_t icache_miss_req_rdata;
logic icache_miss_req_r, icache_miss_req_rok;
logic icache_miss_pending_q;
// This FIFO has two functionnalities:
// - Stabilize the ready-valid protocol. The ICACHE can abort a valid
// transaction without receiving the corresponding ready signal. This
// behavior is not supported by AXI.
// - Cut a possible long timing path.
hpdcache_fifo_reg #(
.FIFO_DEPTH (1),
.fifo_data_t (hpdcache_mem_req_t)
) i_icache_miss_req_fifo(
.clk_i,
.rst_ni,
.w_i (icache_miss_req_w),
.wok_o (icache_miss_req_wok),
.wdata_i (icache_miss_req_wdata),
.r_i (icache_miss_req_r),
.rok_o (icache_miss_req_rok),
.rdata_o (icache_miss_req_rdata)
);
assign icache_miss_req_w = icache_miss_valid_i,
icache_miss_ready_o = icache_miss_req_wok;
assign icache_miss_req_wdata.mem_req_addr = icache_miss_i.paddr,
icache_miss_req_wdata.mem_req_len = icache_miss_i.nc ? 0 : ICACHE_MEM_REQ_CL_LEN - 1,
icache_miss_req_wdata.mem_req_size = icache_miss_i.nc ? ICACHE_WORD_SIZE : ICACHE_MEM_REQ_CL_SIZE,
icache_miss_req_wdata.mem_req_id = icache_miss_i.tid,
icache_miss_req_wdata.mem_req_command = hpdcache_pkg::HPDCACHE_MEM_READ,
icache_miss_req_wdata.mem_req_atomic = hpdcache_pkg::hpdcache_mem_atomic_e'(0),
icache_miss_req_wdata.mem_req_cacheable = ~icache_miss_i.nc;
// I$ response
logic icache_miss_resp_w, icache_miss_resp_wok;
hpdcache_mem_resp_r_t icache_miss_resp_wdata;
logic icache_miss_resp_data_w, icache_miss_resp_data_wok;
logic icache_miss_resp_data_r, icache_miss_resp_data_rok;
icache_resp_data_t icache_miss_resp_data_rdata;
logic icache_miss_resp_meta_w, icache_miss_resp_meta_wok;
logic icache_miss_resp_meta_r, icache_miss_resp_meta_rok;
hpdcache_mem_id_t icache_miss_resp_meta_id;
icache_resp_data_t icache_miss_rdata;
generate
if (HPDcacheMemDataWidth < ariane_pkg::ICACHE_LINE_WIDTH) begin
hpdcache_fifo_reg #(
.FIFO_DEPTH (1),
.fifo_data_t (hpdcache_mem_id_t)
) i_icache_refill_meta_fifo (
.clk_i,
.rst_ni,
.w_i (icache_miss_resp_meta_w),
.wok_o (icache_miss_resp_meta_wok),
.wdata_i (icache_miss_resp_wdata.mem_resp_r_id),
.r_i (icache_miss_resp_meta_r),
.rok_o (icache_miss_resp_meta_rok),
.rdata_o (icache_miss_resp_meta_id)
);
hpdcache_data_upsize #(
.WR_WIDTH (HPDcacheMemDataWidth),
.RD_WIDTH (ariane_pkg::ICACHE_LINE_WIDTH),
.DEPTH (1)
) i_icache_hpdcache_data_upsize (
.clk_i,
.rst_ni,
.w_i (icache_miss_resp_data_w),
.wlast_i (icache_miss_resp_wdata.mem_resp_r_last),
.wok_o (icache_miss_resp_data_wok),
.wdata_i (icache_miss_resp_wdata.mem_resp_r_data),
.r_i (icache_miss_resp_data_r),
.rok_o (icache_miss_resp_data_rok),
.rdata_o (icache_miss_resp_data_rdata)
);
assign icache_miss_resp_meta_r = 1'b1,
icache_miss_resp_data_r = 1'b1;
assign icache_miss_resp_meta_w = icache_miss_resp_w &
icache_miss_resp_wdata.mem_resp_r_last;
assign icache_miss_resp_data_w = icache_miss_resp_w;
assign icache_miss_resp_wok = icache_miss_resp_data_wok & (
icache_miss_resp_meta_wok | ~icache_miss_resp_wdata.mem_resp_r_last);
assign icache_miss_rdata = icache_miss_resp_data_rdata;
end else begin
assign icache_miss_resp_data_rok = icache_miss_resp_w;
assign icache_miss_resp_meta_rok = icache_miss_resp_w;
assign icache_miss_resp_wok = 1'b1;
assign icache_miss_resp_meta_id = icache_miss_resp_wdata.mem_resp_r_id;
assign icache_miss_resp_data_rdata = icache_miss_resp_wdata.mem_resp_r_data;
// In the case of uncacheable accesses, the Icache expects the data to be right-aligned
always_comb
begin : icache_miss_resp_data_comb
if (!icache_miss_req_rdata.mem_req_cacheable) begin
automatic logic [ICACHE_CL_WORD_INDEX - 1: 0] icache_miss_word_index;
automatic logic [63:0] icache_miss_word;
icache_miss_word_index = icache_miss_req_rdata.mem_req_addr[3 +: ICACHE_CL_WORD_INDEX];
icache_miss_word = icache_miss_resp_data_rdata[icache_miss_word_index*64 +: 64];
icache_miss_rdata = {{ariane_pkg::ICACHE_LINE_WIDTH-64{1'b0}}, icache_miss_word};
end else begin
icache_miss_rdata = icache_miss_resp_data_rdata;
end
end
end
endgenerate
assign icache_miss_resp_valid_o = icache_miss_resp_meta_rok,
icache_miss_resp_o.rtype = wt_cache_pkg::ICACHE_IFILL_ACK,
icache_miss_resp_o.user = '0,
icache_miss_resp_o.inv = '0,
icache_miss_resp_o.tid = icache_miss_resp_meta_id,
icache_miss_resp_o.data = icache_miss_rdata;
// consume the Icache miss on the arrival of the response. The request
// metadata is decoded to forward the correct word in case of uncacheable
// Icache access
assign icache_miss_req_r = icache_miss_resp_meta_rok;
// }}}
// Read request arbiter
// {{{
logic mem_req_read_ready [2:0];
logic mem_req_read_valid [2:0];
hpdcache_mem_req_t mem_req_read [2:0];
logic mem_req_read_ready_arb;
logic mem_req_read_valid_arb;
hpdcache_mem_req_t mem_req_read_arb;
assign mem_req_read_valid[0] = icache_miss_req_rok & ~icache_miss_pending_q,
mem_req_read[0] = icache_miss_req_rdata;
assign dcache_miss_ready_o = mem_req_read_ready[1],
mem_req_read_valid[1] = dcache_miss_valid_i,
mem_req_read[1] = dcache_miss_i;
assign dcache_uc_read_ready_o = mem_req_read_ready[2],
mem_req_read_valid[2] = dcache_uc_read_valid_i,
mem_req_read[2] = dcache_uc_read_i;
hpdcache_mem_req_read_arbiter #(
.N (3),
.hpdcache_mem_req_t (hpdcache_mem_req_t)
) i_mem_req_read_arbiter (
.clk_i,
.rst_ni,
.mem_req_read_ready_o (mem_req_read_ready),
.mem_req_read_valid_i (mem_req_read_valid),
.mem_req_read_i (mem_req_read),
.mem_req_read_ready_i (mem_req_read_ready_arb),
.mem_req_read_valid_o (mem_req_read_valid_arb),
.mem_req_read_o (mem_req_read_arb)
);
// }}}
// Read response demultiplexor
// {{{
logic mem_resp_read_ready;
logic mem_resp_read_valid;
hpdcache_mem_resp_r_t mem_resp_read;
logic mem_resp_read_ready_arb [2:0];
logic mem_resp_read_valid_arb [2:0];
hpdcache_mem_resp_r_t mem_resp_read_arb [2:0];
mem_resp_rt_t mem_resp_read_rt;
always_comb
begin
for (int i = 0; i < MEM_RESP_RT_DEPTH; i++) begin
mem_resp_read_rt[i] = (i == int'( icache_miss_id_i)) ? 0 :
(i == int'(dcache_uc_read_id_i)) ? 2 : 1;
end
end
hpdcache_mem_resp_demux #(
.N (3),
.resp_t (hpdcache_mem_resp_r_t),
.resp_id_t (hpdcache_mem_id_t)
) i_mem_resp_read_demux (
.clk_i,
.rst_ni,
.mem_resp_ready_o (mem_resp_read_ready),
.mem_resp_valid_i (mem_resp_read_valid),
.mem_resp_id_i (mem_resp_read.mem_resp_r_id),
.mem_resp_i (mem_resp_read),
.mem_resp_ready_i (mem_resp_read_ready_arb),
.mem_resp_valid_o (mem_resp_read_valid_arb),
.mem_resp_o (mem_resp_read_arb),
.mem_resp_rt_i (mem_resp_read_rt)
);
assign icache_miss_resp_w = mem_resp_read_valid_arb[0],
icache_miss_resp_wdata = mem_resp_read_arb[0],
mem_resp_read_ready_arb[0] = icache_miss_resp_wok;
assign dcache_miss_resp_valid_o = mem_resp_read_valid_arb[1],
dcache_miss_resp_o = mem_resp_read_arb[1],
mem_resp_read_ready_arb[1] = dcache_miss_resp_ready_i;
assign dcache_uc_read_resp_valid_o = mem_resp_read_valid_arb[2],
dcache_uc_read_resp_o = mem_resp_read_arb[2],
mem_resp_read_ready_arb[2] = dcache_uc_read_resp_ready_i;
// }}}
// Write request arbiter
// {{{
logic mem_req_write_ready [1:0];
logic mem_req_write_valid [1:0];
hpdcache_mem_req_t mem_req_write [1:0];
logic mem_req_write_data_ready [1:0];
logic mem_req_write_data_valid [1:0];
hpdcache_mem_req_w_t mem_req_write_data [1:0];
logic mem_req_write_ready_arb;
logic mem_req_write_valid_arb;
hpdcache_mem_req_t mem_req_write_arb;
logic mem_req_write_data_ready_arb;
logic mem_req_write_data_valid_arb;
hpdcache_mem_req_w_t mem_req_write_data_arb;
assign dcache_wbuf_ready_o = mem_req_write_ready[0],
mem_req_write_valid[0] = dcache_wbuf_valid_i,
mem_req_write[0] = dcache_wbuf_i;
assign dcache_wbuf_data_ready_o = mem_req_write_data_ready[0],
mem_req_write_data_valid[0] = dcache_wbuf_data_valid_i,
mem_req_write_data[0] = dcache_wbuf_data_i;
assign dcache_uc_write_ready_o = mem_req_write_ready[1],
mem_req_write_valid[1] = dcache_uc_write_valid_i,
mem_req_write[1] = dcache_uc_write_i;
assign dcache_uc_write_data_ready_o = mem_req_write_data_ready[1],
mem_req_write_data_valid[1] = dcache_uc_write_data_valid_i,
mem_req_write_data[1] = dcache_uc_write_data_i;
hpdcache_mem_req_write_arbiter #(
.N (2),
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t)
) i_mem_req_write_arbiter (
.clk_i,
.rst_ni,
.mem_req_write_ready_o (mem_req_write_ready),
.mem_req_write_valid_i (mem_req_write_valid),
.mem_req_write_i (mem_req_write),
.mem_req_write_data_ready_o (mem_req_write_data_ready),
.mem_req_write_data_valid_i (mem_req_write_data_valid),
.mem_req_write_data_i (mem_req_write_data),
.mem_req_write_ready_i (mem_req_write_ready_arb),
.mem_req_write_valid_o (mem_req_write_valid_arb),
.mem_req_write_o (mem_req_write_arb),
.mem_req_write_data_ready_i (mem_req_write_data_ready_arb),
.mem_req_write_data_valid_o (mem_req_write_data_valid_arb),
.mem_req_write_data_o (mem_req_write_data_arb)
);
// }}}
// Write response demultiplexor
// {{{
logic mem_resp_write_ready;
logic mem_resp_write_valid;
hpdcache_mem_resp_w_t mem_resp_write;
logic mem_resp_write_ready_arb [1:0];
logic mem_resp_write_valid_arb [1:0];
hpdcache_mem_resp_w_t mem_resp_write_arb [1:0];
mem_resp_rt_t mem_resp_write_rt;
always_comb
begin
for (int i = 0; i < MEM_RESP_RT_DEPTH; i++) begin
mem_resp_write_rt[i] = (i == int'(dcache_uc_write_id_i)) ? 1 : 0;
end
end
hpdcache_mem_resp_demux #(
.N (2),
.resp_t (hpdcache_mem_resp_w_t),
.resp_id_t (hpdcache_mem_id_t)
) i_hpdcache_mem_resp_write_demux (
.clk_i,
.rst_ni,
.mem_resp_ready_o (mem_resp_write_ready),
.mem_resp_valid_i (mem_resp_write_valid),
.mem_resp_id_i (mem_resp_write.mem_resp_w_id),
.mem_resp_i (mem_resp_write),
.mem_resp_ready_i (mem_resp_write_ready_arb),
.mem_resp_valid_o (mem_resp_write_valid_arb),
.mem_resp_o (mem_resp_write_arb),
.mem_resp_rt_i (mem_resp_write_rt)
);
assign dcache_wbuf_resp_valid_o = mem_resp_write_valid_arb[0],
dcache_wbuf_resp_o = mem_resp_write_arb[0],
mem_resp_write_ready_arb[0] = dcache_wbuf_resp_ready_i;
assign dcache_uc_write_resp_valid_o = mem_resp_write_valid_arb[1],
dcache_uc_write_resp_o = mem_resp_write_arb[1],
mem_resp_write_ready_arb[1] = dcache_uc_write_resp_ready_i;
// }}}
// I$ miss pending
// {{{
always_ff @(posedge clk_i or negedge rst_ni)
begin : icache_miss_pending_ff
if (!rst_ni) begin
icache_miss_pending_q <= 1'b0;
end else begin
icache_miss_pending_q <= ( (icache_miss_req_rok & mem_req_read_ready[0]) & ~icache_miss_pending_q) |
(~(icache_miss_req_r & icache_miss_req_rok) & icache_miss_pending_q);
end
end
// }}}
// AXI adapters
// {{{
axi_req_t axi_req;
axi_rsp_t axi_resp;
hpdcache_mem_to_axi_write #(
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_req_w_t (hpdcache_mem_req_w_t),
.hpdcache_mem_resp_w_t (hpdcache_mem_resp_w_t),
.aw_chan_t (axi_aw_chan_t),
.w_chan_t (axi_w_chan_t),
.b_chan_t (axi_b_chan_t)
) i_hpdcache_mem_to_axi_write (
.req_ready_o (mem_req_write_ready_arb),
.req_valid_i (mem_req_write_valid_arb),
.req_i (mem_req_write_arb),
.req_data_ready_o (mem_req_write_data_ready_arb),
.req_data_valid_i (mem_req_write_data_valid_arb),
.req_data_i (mem_req_write_data_arb),
.resp_ready_i (mem_resp_write_ready),
.resp_valid_o (mem_resp_write_valid),
.resp_o (mem_resp_write),
.axi_aw_valid_o (axi_req.aw_valid),
.axi_aw_o (axi_req.aw),
.axi_aw_ready_i (axi_resp.aw_ready),
.axi_w_valid_o (axi_req.w_valid),
.axi_w_o (axi_req.w),
.axi_w_ready_i (axi_resp.w_ready),
.axi_b_valid_i (axi_resp.b_valid),
.axi_b_i (axi_resp.b),
.axi_b_ready_o (axi_req.b_ready)
);
hpdcache_mem_to_axi_read #(
.hpdcache_mem_req_t (hpdcache_mem_req_t),
.hpdcache_mem_resp_r_t (hpdcache_mem_resp_r_t),
.ar_chan_t (axi_ar_chan_t),
.r_chan_t (axi_r_chan_t)
) i_hpdcache_mem_to_axi_read (
.req_ready_o (mem_req_read_ready_arb),
.req_valid_i (mem_req_read_valid_arb),
.req_i (mem_req_read_arb),
.resp_ready_i (mem_resp_read_ready),
.resp_valid_o (mem_resp_read_valid),
.resp_o (mem_resp_read),
.axi_ar_valid_o (axi_req.ar_valid),
.axi_ar_o (axi_req.ar),
.axi_ar_ready_i (axi_resp.ar_ready),
.axi_r_valid_i (axi_resp.r_valid),
.axi_r_i (axi_resp.r),
.axi_r_ready_o (axi_req.r_ready)
);
assign axi_req_o = axi_req;
assign axi_resp = axi_resp_i;
// }}}
// Assertions
// {{{
// pragma translate_off
initial assert (HPDcacheMemIdWidth <= AxiIdWidth) else
$fatal("HPDcacheMemIdWidth shall be less or equal to AxiIdWidth");
initial assert (HPDcacheMemIdWidth >= (hpdcache_pkg::HPDCACHE_MSHR_SET_WIDTH + hpdcache_pkg::HPDCACHE_MSHR_WAY_WIDTH + 1)) else
$fatal("HPDcacheMemIdWidth shall be wide enough to identify all pending HPDcache misses and Icache misses");
initial assert (HPDcacheMemIdWidth >= (hpdcache_pkg::HPDCACHE_WBUF_DIR_PTR_WIDTH + 1)) else
$fatal("HPDcacheMemIdWidth shall be wide enough to identify all pending HPDcache cacheable writes and uncacheable writes");
initial assert (HPDcacheMemDataWidth <= ariane_pkg::ICACHE_LINE_WIDTH) else
$fatal("HPDcacheMemDataWidth shall be less or equal to the width of a Icache line");
initial assert (HPDcacheMemDataWidth <= ariane_pkg::DCACHE_LINE_WIDTH) else
$fatal("HPDcacheMemDataWidth shall be less or equal to the width of a Dcache line");
// pragma translate_on
// }}}
endmodule : cva6_hpdcache_subsystem_axi_arbiter

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

View file

@ -85,7 +85,7 @@ module controller import ariane_pkg::*; #(
flush_ex_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (DCACHE_TYPE == int'(cva6_config_pkg::WB)) begin
if (DCACHE_TYPE == int'(config_pkg::WB)) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -103,7 +103,7 @@ module controller import ariane_pkg::*; #(
flush_icache_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (DCACHE_TYPE == int'(cva6_config_pkg::WB)) begin
if (DCACHE_TYPE == int'(config_pkg::WB)) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -111,7 +111,7 @@ module controller import ariane_pkg::*; #(
// this is not needed in the case since we
// have a write-through cache in this case
if (DCACHE_TYPE == int'(cva6_config_pkg::WB)) begin
if (DCACHE_TYPE == int'(config_pkg::WB)) begin
// wait for the acknowledge here
if (flush_dcache_ack_i && fence_active_q) begin
fence_active_d = 1'b0;

View file

@ -929,7 +929,7 @@ module cva6 import ariane_pkg::*; #(
dcache_req_ports_cache_acc[1].data_gnt &= !dcache_req_ports_ex_cache[2].data_req;
end
if (DCACHE_TYPE == int'(cva6_config_pkg::WT)) begin : gen_cache_wt
if (DCACHE_TYPE == int'(config_pkg::WT)) begin : gen_cache_wt
// this is a cache subsystem that is compatible with OpenPiton
wt_cache_subsystem #(
.CVA6Cfg ( CVA6ExtendCfg ),
@ -970,8 +970,59 @@ module cva6 import ariane_pkg::*; #(
.inval_valid_i ( inval_valid ),
.inval_ready_o ( inval_ready )
);
end else begin : gen_cache_wb
end else if (DCACHE_TYPE == int'(config_pkg::HPDCACHE)) begin : gen_cache_hpd
cva6_hpdcache_subsystem #(
.CVA6Cfg ( CVA6ExtendCfg ),
.NumPorts ( NumPorts ),
.noc_req_t ( noc_req_t ),
.noc_resp_t ( noc_resp_t ),
.cmo_req_t ( logic /*FIXME*/ ),
.cmo_rsp_t ( logic /*FIXME*/ )
) i_cache_subsystem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.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 ),
.dcache_enable_i ( dcache_en_csr_nbdcache ),
.dcache_flush_i ( dcache_flush_ctrl_cache ),
.dcache_flush_ack_o ( dcache_flush_ack_cache_ctrl ),
.dcache_miss_o ( dcache_miss_cache_perf ),
.dcache_amo_req_i ( amo_req ),
.dcache_amo_resp_o ( amo_resp ),
.dcache_cmo_req_i ( '0/*FIXME*/ ),
.dcache_cmo_resp_o ( /*FIXME*/ ),
.dcache_req_ports_i ( dcache_req_to_cache ),
.dcache_req_ports_o ( dcache_req_from_cache ),
.wbuffer_empty_o ( dcache_commit_wbuffer_empty ),
.wbuffer_not_ni_o ( dcache_commit_wbuffer_not_ni ),
.hwpf_base_set_i ( '0/*FIXME*/ ),
.hwpf_base_i ( '0/*FIXME*/ ),
.hwpf_base_o ( /*FIXME*/ ),
.hwpf_param_set_i ( '0/*FIXME*/ ),
.hwpf_param_i ( '0/*FIXME*/ ),
.hwpf_param_o ( /*FIXME*/ ),
.hwpf_throttle_set_i ( '0/*FIXME*/ ),
.hwpf_throttle_i ( '0/*FIXME*/ ),
.hwpf_throttle_o ( /*FIXME*/ ),
.hwpf_status_o ( /*FIXME*/ ),
.noc_req_o ( noc_req_o ),
.noc_resp_i ( noc_resp_i )
);
assign inval_ready = 1'b1;
end else begin : gen_cache_wb
std_cache_subsystem #(
// note: this only works with one cacheable region
// not as important since this cache subsystem is about to be

View file

@ -26,6 +26,13 @@ package config_pkg;
NOC_TYPE_L15_LITTLE_ENDIAN
} noc_type_e;
/// Cache type parameter
typedef enum logic [1:0] {
WB = 0,
WT = 1,
HPDCACHE = 2
} cache_type_t ;
localparam NrMaxRules = 16;
typedef struct packed {

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 0;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 0;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -9,11 +9,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 0;
@ -70,7 +65,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 0;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 0;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 0;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 0;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 0;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 0;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 32;
localparam CVA6ConfigFpuEn = 1;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WB;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WB;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
@ -70,7 +65,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam cache_type_t CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -0,0 +1,135 @@
// Copyright 2021 Thales DIS design services SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Jean-Roch COULON - Thales
//
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Author: Cesar Fuguet - CEA
// Date: August, 2023
// Description: CVA6 configuration package using the HPDcache as cache subsystem
package cva6_config_pkg;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
localparam CVA6ConfigF16En = 0;
localparam CVA6ConfigF16AltEn = 0;
localparam CVA6ConfigF8En = 0;
localparam CVA6ConfigFVecEn = 0;
localparam CVA6ConfigCvxifEn = 1;
localparam CVA6ConfigCExtEn = 1;
localparam CVA6ConfigZcbExtEn = 1;
localparam CVA6ConfigAExtEn = 1;
localparam CVA6ConfigBExtEn = 1;
localparam CVA6ConfigVExtEn = 0;
localparam CVA6ConfigZiCondExtEn = 1;
localparam CVA6ConfigAxiIdWidth = 4;
localparam CVA6ConfigAxiAddrWidth = 64;
localparam CVA6ConfigAxiDataWidth = 64;
localparam CVA6ConfigFetchUserEn = 0;
localparam CVA6ConfigFetchUserWidth = CVA6ConfigXlen;
localparam CVA6ConfigDataUserEn = 0;
localparam CVA6ConfigDataUserWidth = CVA6ConfigXlen;
localparam CVA6ConfigIcacheByteSize = 16384;
localparam CVA6ConfigIcacheSetAssoc = 4;
localparam CVA6ConfigIcacheLineWidth = 128;
localparam CVA6ConfigDcacheByteSize = 32768;
localparam CVA6ConfigDcacheSetAssoc = 8;
localparam CVA6ConfigDcacheLineWidth = 128;
localparam CVA6ConfigDcacheIdWidth = 3;
localparam CVA6ConfigMemTidWidth = CVA6ConfigAxiIdWidth;
localparam CVA6ConfigWtDcacheWbufDepth = 8;
localparam CVA6ConfigNrCommitPorts = 2;
localparam CVA6ConfigNrScoreboardEntries = 8;
localparam CVA6ConfigFPGAEn = 0;
localparam CVA6ConfigNrLoadPipeRegs = 1;
localparam CVA6ConfigNrStorePipeRegs = 0;
localparam CVA6ConfigNrLoadBufEntries = 8;
localparam CVA6ConfigInstrTlbEntries = 16;
localparam CVA6ConfigDataTlbEntries = 16;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigNrPMPEntries = 8;
localparam CVA6ConfigPerfCounterEn = 1;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE;
localparam CVA6ConfigMmuPresent = 1;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_cfg_t cva6_cfg = '{
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth),
AxiUserWidth: unsigned'(CVA6ConfigDataUserWidth),
NrLoadBufEntries: unsigned'(CVA6ConfigNrLoadBufEntries),
FpuEn: bit'(CVA6ConfigFpuEn),
XF16: bit'(CVA6ConfigF16En),
XF16ALT: bit'(CVA6ConfigF16AltEn),
XF8: bit'(CVA6ConfigF8En),
RVA: bit'(CVA6ConfigAExtEn),
RVV: bit'(CVA6ConfigVExtEn),
RVC: bit'(CVA6ConfigCExtEn),
RVZCB: bit'(CVA6ConfigZcbExtEn),
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
// Extended
RVF: bit'(0),
RVD: bit'(0),
FpPresent: bit'(0),
NSX: bit'(0),
FLen: unsigned'(0),
RVFVec: bit'(0),
XF16Vec: bit'(0),
XF16ALTVec: bit'(0),
XF8Vec: bit'(0),
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
DmBaseAddress: 64'h0,
NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries),
NOCType: config_pkg::NOC_TYPE_AXI4_ATOP,
// idempotent region
NrNonIdempotentRules: unsigned'(2),
NonIdempotentAddrBase: 1024'({64'b0, 64'b0}),
NonIdempotentLength: 1024'({64'b0, 64'b0}),
NrExecuteRegionRules: unsigned'(3),
// DRAM, Boot ROM, Debug Module
ExecuteRegionAddrBase: 1024'({64'h8000_0000, 64'h1_0000, 64'h0}),
ExecuteRegionLength: 1024'({64'h40000000, 64'h10000, 64'h1000}),
// cached region
NrCachedRegionRules: unsigned'(1),
CachedRegionAddrBase: 1024'({64'h8000_0000}),
CachedRegionLength: 1024'({64'h40000000})
};
endpackage

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam cache_type_t CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
@ -71,7 +66,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WB;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WB;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -10,11 +10,6 @@
package cva6_config_pkg;
typedef enum logic {
WB = 0,
WT = 1
} cache_type_t ;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigFpuEn = 1;
@ -70,7 +65,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam CVA6ConfigDcacheType = WT;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WT;
localparam CVA6ConfigMmuPresent = 1;

View file

@ -0,0 +1,123 @@
// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
// Alternatives (CEA)
//
// Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Authors: Cesar Fuguet
// Date: February, 2023
// Description:
// Default package with parameters for the HPDcache in a CVA6 platform.
// Users can copy this file, rename it, and adapt the configuration values as
// needed.
package hpdcache_params_pkg;
// Imports from the CVA6 configuration package
// {{{
import cva6_config_pkg::CVA6ConfigXlen;
import cva6_config_pkg::CVA6ConfigDcacheByteSize;
import cva6_config_pkg::CVA6ConfigDcacheSetAssoc;
import cva6_config_pkg::CVA6ConfigDcacheLineWidth;
import cva6_config_pkg::CVA6ConfigDcacheIdWidth;
import cva6_config_pkg::CVA6ConfigWtDcacheWbufDepth;
import cva6_config_pkg::CVA6ConfigNrLoadBufEntries;
// }}}
// Definition of constants used only in this file
// {{{
localparam int unsigned __BYTES_PER_WAY =
CVA6ConfigDcacheByteSize/CVA6ConfigDcacheSetAssoc;
localparam int unsigned __BYTES_PER_CACHELINE =
CVA6ConfigDcacheLineWidth/8;
// }}}
// Definition of global constants for the HPDcache data and directory
// {{{
// HPDcache physical address width (in bits)
localparam int unsigned PARAM_PA_WIDTH = riscv::PLEN;
// HPDcache number of sets
localparam int unsigned PARAM_SETS = __BYTES_PER_WAY/__BYTES_PER_CACHELINE;
// HPDcache number of ways
localparam int unsigned PARAM_WAYS = CVA6ConfigDcacheSetAssoc;
// HPDcache word width (bits)
localparam int unsigned PARAM_WORD_WIDTH = CVA6ConfigXlen;
// HPDcache cache-line width (bits)
localparam int unsigned PARAM_CL_WORDS = CVA6ConfigDcacheLineWidth/PARAM_WORD_WIDTH;
// HPDcache number of words in the request data channels (request and response)
localparam int unsigned PARAM_REQ_WORDS = 1;
// HPDcache request transaction ID width (bits)
localparam int unsigned PARAM_REQ_TRANS_ID_WIDTH = CVA6ConfigDcacheIdWidth;
// HPDcache request source ID width (bits)
localparam int unsigned PARAM_REQ_SRC_ID_WIDTH = 3;
// }}}
// Definition of constants and types for HPDcache data memory
// {{{
localparam int unsigned PARAM_DATA_WAYS_PER_RAM_WORD = 128/PARAM_WORD_WIDTH;
localparam int unsigned PARAM_DATA_SETS_PER_RAM = PARAM_SETS;
// HPDcache DATA RAM macros whether implements:
// - Write byte enable (1'b1)
// - Write bit mask (1'b0)
localparam bit PARAM_DATA_RAM_WBYTEENABLE = 1'b1;
// Define the number of memory contiguous words that can be accessed
// simultaneously from the cache.
// - This limits the maximum width for the data channel from requesters
// - This impacts the refill latency (more ACCESS_WORDS -> less REFILL LATENCY)
localparam int unsigned PARAM_ACCESS_WORDS = PARAM_CL_WORDS/2;
// }}}
// Definition of constants and types for the Miss Status Holding Register (MSHR)
// {{{
// HPDcache MSHR number of sets
localparam int unsigned PARAM_MSHR_SETS = 2;
// HPDcache MSHR number of ways
localparam int unsigned PARAM_MSHR_WAYS = (CVA6ConfigNrLoadBufEntries > 4) ? 4 : 2;
// HPDcache MSHR number of ways in the same SRAM word
localparam int unsigned PARAM_MSHR_WAYS_PER_RAM_WORD = PARAM_MSHR_WAYS > 1 ? 2 : 1;
// HPDcache MSHR number of sets in the same SRAM
localparam int unsigned PARAM_MSHR_SETS_PER_RAM = PARAM_MSHR_SETS;
// HPDcache MSHR RAM whether implements:
// - Write byte enable (1'b1)
// - Write bit mask (1'b0)
localparam bit PARAM_MSHR_RAM_WBYTEENABLE = 1'b1;
// HPDcache MSHR whether uses FFs or SRAM
localparam bit PARAM_MSHR_USE_REGBANK = (PARAM_MSHR_SETS*PARAM_MSHR_WAYS) <= 16;
// }}}
// Definition of constants and types for the Write Buffer (WBUF)
// {{{
// HPDcache Write-Buffer number of entries in the directory
localparam int unsigned PARAM_WBUF_DIR_ENTRIES = CVA6ConfigWtDcacheWbufDepth;
// HPDcache Write-Buffer number of entries in the data buffer
localparam int unsigned PARAM_WBUF_DATA_ENTRIES = CVA6ConfigWtDcacheWbufDepth;
// HPDcache Write-Buffer number of words per entry
localparam int unsigned PARAM_WBUF_WORDS = PARAM_REQ_WORDS;
// HPDcache Write-Buffer threshold counter width (in bits)
localparam int unsigned PARAM_WBUF_TIMECNT_WIDTH = 3;
// }}}
// Definition of constants and types for the Replay Table (RTAB)
// {{{
localparam int PARAM_RTAB_ENTRIES = 4;
// }}}
endpackage

View file

@ -38,7 +38,13 @@ read_ip { \
}
# read_ip xilinx/xlnx_protocol_checker/ip/xlnx_protocol_checker.xci
set_property include_dirs { "src/axi_sd_bridge/include" "../../vendor/pulp-platform/common_cells/include" "../../vendor/pulp-platform/axi/include" "../register_interface/include"} [current_fileset]
set_property include_dirs { \
"src/axi_sd_bridge/include" \
"../../vendor/pulp-platform/common_cells/include" \
"../../vendor/pulp-platform/axi/include" \
"../../core/cache_subsystem/hpdcache/rtl/include" \
"../register_interface/include" \
} [current_fileset]
source scripts/add_sources.tcl

View file

@ -21,9 +21,11 @@ package ariane_axi_soc;
localparam AddrWidth = ariane_axi::AddrWidth;
localparam DataWidth = ariane_axi::DataWidth;
localparam StrbWidth = DataWidth / 8;
localparam IdWidth = ariane_axi::IdWidth;
localparam IdWidthSlave = IdWidth + $clog2(ariane_soc::NrSlaves);
typedef logic [ariane_axi::IdWidth-1:0] id_t;
typedef logic [ariane_soc::IdWidthSlave-1:0] id_slv_t;
typedef logic [IdWidth-1:0] id_t;
typedef logic [IdWidthSlave-1:0] id_slv_t;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [StrbWidth-1:0] strb_t;

View file

@ -19,10 +19,6 @@ package ariane_soc;
localparam NrSlaves = 2; // actually masters, but slaves on the crossbar
// 4 is recommended by AXI standard, so lets stick to it, do not change
localparam IdWidth = 4;
localparam IdWidthSlave = IdWidth + $clog2(NrSlaves);
typedef enum int unsigned {
DRAM = 0,
GPIO = 1,

View file

@ -104,17 +104,17 @@ module ariane_testharness #(
assign test_en = 1'b0;
AXI_BUS #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidth ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidth ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) slave[ariane_soc::NrSlaves-1:0]();
AXI_BUS #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) master[ariane_soc::NB_PERIPHERALS-1:0]();
rstgen i_rstgen_main (
@ -290,10 +290,10 @@ module ariane_testharness #(
axi2mem #(
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_dm_axi2mem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -347,10 +347,10 @@ module ariane_testharness #(
logic [AXI_DATA_WIDTH-1:0] rom_rdata;
axi2mem #(
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_axi2rom (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
@ -383,9 +383,9 @@ module ariane_testharness #(
`AXI_ASSIGN_TO_REQ(gpio_req, master[ariane_soc::GPIO])
`AXI_ASSIGN_FROM_RESP(master[ariane_soc::GPIO], gpio_resp)
axi_err_slv #(
.AxiIdWidth ( ariane_soc::IdWidthSlave ),
.req_t ( ariane_axi_soc::req_slv_t ),
.resp_t ( ariane_axi_soc::resp_slv_t )
.AxiIdWidth ( ariane_axi_soc::IdWidthSlave ),
.req_t ( ariane_axi_soc::req_slv_t ),
.resp_t ( ariane_axi_soc::resp_slv_t )
) i_gpio_err_slv (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
@ -399,10 +399,10 @@ module ariane_testharness #(
// Memory + Exclusive Access
// ------------------------------
AXI_BUS #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) dram();
logic req;
@ -415,10 +415,10 @@ module ariane_testharness #(
logic [AXI_USER_WIDTH-1:0] ruser;
axi_riscv_atomics_wrap #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_MAX_WRITE_TXNS ( 1 ),
.RISCV_WORD_WIDTH ( 64 )
) i_axi_riscv_atomics (
@ -429,21 +429,21 @@ module ariane_testharness #(
);
AXI_BUS #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) dram_delayed();
axi_delayer_intf #(
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.STALL_RANDOM_INPUT ( StallRandomInput ),
.STALL_RANDOM_OUTPUT ( StallRandomOutput ),
.FIXED_DELAY_INPUT ( 0 ),
.FIXED_DELAY_OUTPUT ( 0 )
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.STALL_RANDOM_INPUT ( StallRandomInput ),
.STALL_RANDOM_OUTPUT ( StallRandomOutput ),
.FIXED_DELAY_INPUT ( 0 ),
.FIXED_DELAY_OUTPUT ( 0 )
) i_axi_delayer (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
@ -452,10 +452,10 @@ module ariane_testharness #(
);
axi2mem #(
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH )
) i_axi2mem (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
@ -519,8 +519,8 @@ module ariane_testharness #(
MaxSlvTrans: unsigned'(1), // Probably requires update
FallThrough: 1'b0,
LatencyMode: axi_pkg::NO_LATENCY,
AxiIdWidthSlvPorts: unsigned'(ariane_soc::IdWidth),
AxiIdUsedSlvPorts: unsigned'(ariane_soc::IdWidth),
AxiIdWidthSlvPorts: unsigned'(ariane_axi_soc::IdWidth),
AxiIdUsedSlvPorts: unsigned'(ariane_axi_soc::IdWidth),
UniqueIds: 1'b0,
AxiAddrWidth: unsigned'(AXI_ADDRESS_WIDTH),
AxiDataWidth: unsigned'(AXI_DATA_WIDTH),
@ -552,12 +552,12 @@ module ariane_testharness #(
ariane_axi_soc::resp_slv_t axi_clint_resp;
clint #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.NR_CORES ( 1 ),
.axi_req_t ( ariane_axi_soc::req_slv_t ),
.axi_resp_t ( ariane_axi_soc::resp_slv_t )
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.NR_CORES ( 1 ),
.axi_req_t ( ariane_axi_soc::req_slv_t ),
.axi_resp_t ( ariane_axi_soc::resp_slv_t )
) i_clint (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
@ -579,10 +579,10 @@ module ariane_testharness #(
logic [1:0] irqs;
ariane_peripherals #(
.AxiAddrWidth ( AXI_ADDRESS_WIDTH ),
.AxiDataWidth ( AXI_DATA_WIDTH ),
.AxiIdWidth ( ariane_soc::IdWidthSlave ),
.AxiUserWidth ( AXI_USER_WIDTH ),
.AxiAddrWidth ( AXI_ADDRESS_WIDTH ),
.AxiDataWidth ( AXI_DATA_WIDTH ),
.AxiIdWidth ( ariane_axi_soc::IdWidthSlave ),
.AxiUserWidth ( AXI_USER_WIDTH ),
`ifndef VERILATOR
// disable UART when using Spike, as we need to rely on the mockuart
`ifdef SPIKE_TANDEM
@ -696,8 +696,8 @@ module ariane_testharness #(
// to use it
Axi4PC #(
.DATA_WIDTH(ariane_axi_soc::DataWidth),
.WID_WIDTH(ariane_soc::IdWidthSlave),
.RID_WIDTH(ariane_soc::IdWidthSlave),
.WID_WIDTH(ariane_axi_soc::IdWidthSlave),
.RID_WIDTH(ariane_axi_soc::IdWidthSlave),
.AWUSER_WIDTH(ariane_axi_soc::UserWidth),
.WUSER_WIDTH(ariane_axi_soc::UserWidth),
.BUSER_WIDTH(ariane_axi_soc::UserWidth),

75
util/flist_flattener.py Executable file
View file

@ -0,0 +1,75 @@
#!/bin/env python3
# Copyright 2023 Commissariat a l'Energie Atomique et aux Energies
# Alternatives (CEA)
#
# Licensed under the Solderpad Hardware License, Version 2.1 (the “License”);
# you may not use this file except in compliance with the License.
# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
# You may obtain a copy of the License at https://solderpad.org/licenses/
#
# Authors: Cesar Fuguet
# Date: October, 2023
# Description: script to flatten a Flist file. Flattening consist on:
# - expanding environment variables in the file
# - expanding included Flist files
import sys;
import argparse;
import os;
def printLine(outf, line, printNewline):
if printNewline:
outf.write(f'{line}\n')
else:
outf.write(line + ' ')
def parseFlist(inFlist, outFlist, printIncdir, printNewline):
lines = iter(inFlist.read().splitlines())
for line in lines:
line = line.strip()
if (line.startswith('#') or
line.startswith('//') or
line.startswith('/*')):
continue
line = os.path.expandvars(line)
if line.startswith('+incdir+'):
if printIncdir:
printLine(outFlist, line, printNewline)
elif line.startswith('-F'):
includedFilename = line.lstrip('-F').strip()
if not os.path.exists(includedFilename):
raise (RuntimeError(f'{includedFilename} not found'))
with open(includedFilename, 'r') as includedFlist:
parseFlist(includedFlist, outFlist, printIncdir, printNewline)
elif line:
printLine(outFlist, line, printNewline)
def getArguments():
parser = argparse.ArgumentParser(description='Flatten a Flist file')
parser.add_argument(
'--print_incdir',
action="store_true",
help='Print incdir statements in the output')
parser.add_argument(
'--print_newline',
action="store_true",
help='Print newline in the output after each line')
parser.add_argument(
'inFlist',
nargs='?',
type=argparse.FileType('r'),
default=sys.stdin,
help='Input Flist file (default to stdin)')
parser.add_argument(
'outFlist',
nargs='?',
type=argparse.FileType('w'),
default=sys.stdout,
help='Output flattened Flist file (default to stdout)')
return parser.parse_args()
if __name__ == "__main__":
args = getArguments()
parseFlist(args.inFlist, args.outFlist, args.print_incdir, args.print_newline)

View file

@ -145,7 +145,7 @@ covergroup cg_cva6_config(string name) with function sample();
bins PerfCounterEn ={0};
}
cp_DcacheType : coverpoint cva6_config_pkg::CVA6ConfigDcacheType {
bins DcacheType ={cva6_config_pkg::WT};
bins DcacheType ={config_pkg::WT};
}
cp_MmuPresent : coverpoint cva6_config_pkg::CVA6ConfigMmuPresent {
bins MmuPresent ={0};

View file

@ -19,6 +19,11 @@ ifndef TARGET_CFG
export TARGET_CFG = $(target)
endif
HPDCACHE_DIR ?= $(CVA6_REPO_DIR)/core/cache_subsystem/hpdcache
export HPDCACHE_DIR
HPDCACHE_TARGET_CFG ?= ${CVA6_REPO_DIR}/core/include/cva6_hpdcache_default_config_pkg.sv
export HPDCACHE_TARGET_CFG
.DEFAULT_GOAL := help
FLIST_TB := $(CVA6_TB_DIR)/Flist.cva6_tb

View file

@ -31,6 +31,7 @@ ${CVA6_REPO_DIR}/corev_apu/axi_mem_if/src/axi2mem.sv
${CVA6_REPO_DIR}/corev_apu/tb/ariane_soc_pkg.sv
${CVA6_REPO_DIR}/corev_apu/tb/axi_intf.sv
${CVA6_REPO_DIR}/corev_apu/tb/ariane_axi_pkg.sv
${CVA6_REPO_DIR}/corev_apu/tb/ariane_axi_soc_pkg.sv
// RVFI tracer
${CVA6_REPO_DIR}/corev_apu/tb/rvfi_tracer.sv

View file

@ -184,10 +184,10 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
AXI_BUS #(
.AXI_ADDR_WIDTH ( CVA6Cfg.AxiAddrWidth ),
.AXI_DATA_WIDTH ( CVA6Cfg.AxiDataWidth ),
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( CVA6Cfg.AxiUserWidth )
.AXI_ADDR_WIDTH ( CVA6Cfg.AxiAddrWidth ),
.AXI_DATA_WIDTH ( CVA6Cfg.AxiDataWidth ),
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_USER_WIDTH ( CVA6Cfg.AxiUserWidth )
) cva6_axi_bus();
axi_master_connect #(
@ -198,10 +198,10 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
);
axi2mem #(
.AXI_ID_WIDTH ( ariane_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( CVA6Cfg.AxiAddrWidth ),
.AXI_DATA_WIDTH ( CVA6Cfg.AxiDataWidth ),
.AXI_USER_WIDTH ( CVA6Cfg.AxiUserWidth )
.AXI_ID_WIDTH ( ariane_axi_soc::IdWidthSlave ),
.AXI_ADDR_WIDTH ( CVA6Cfg.AxiAddrWidth ),
.AXI_DATA_WIDTH ( CVA6Cfg.AxiDataWidth ),
.AXI_USER_WIDTH ( CVA6Cfg.AxiUserWidth )
) i_cva6_axi2mem (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),