mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 12:17:19 -04:00
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:
parent
166c4b8ba1
commit
7de1345291
33 changed files with 1892 additions and 149 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
19
Makefile
19
Makefile
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
203
core/cache_subsystem/cva6_hpdcache_if_adapter.sv
Normal file
203
core/cache_subsystem/cva6_hpdcache_if_adapter.sv
Normal 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
|
588
core/cache_subsystem/cva6_hpdcache_subsystem.sv
Normal file
588
core/cache_subsystem/cva6_hpdcache_subsystem.sv
Normal 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
|
580
core/cache_subsystem/cva6_hpdcache_subsystem_axi_arbiter.sv
Normal file
580
core/cache_subsystem/cva6_hpdcache_subsystem_axi_arbiter.sv
Normal 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
|
1
core/cache_subsystem/hpdcache
Submodule
1
core/cache_subsystem/hpdcache
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f2bc700cdb53dac243258dcdff55ad8e5f602f72
|
|
@ -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;
|
||||
|
|
55
core/cva6.sv
55
core/cva6.sv
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
135
core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv
Normal file
135
core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv
Normal 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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
123
core/include/cva6_hpdcache_default_config_pkg.sv
Normal file
123
core/include/cva6_hpdcache_default_config_pkg.sv
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
75
util/flist_flattener.py
Executable 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)
|
2
verif/env/uvme/cov/uvme_cva6_config_covg.sv
vendored
2
verif/env/uvme/cov/uvme_cva6_config_covg.sv
vendored
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue