Fully support the Write-Back mode of the HPDcache in the CVA6 (#2691)
Some checks are pending
bender-up-to-date / bender-up-to-date (push) Waiting to run
ci / build-riscv-tests (push) Waiting to run
ci / execute-riscv64-tests (push) Blocked by required conditions
ci / execute-riscv32-tests (push) Blocked by required conditions

This PR modifies some components in the CVA6 to fully support the WB mode of the HPDcache.

When on WB mode, there may be coherency issues between the Instruction Cache and the Data Cache. This may happen when the software writes on instruction segments (e.g. to relocate a code in memory).

This PR contains the following modifications:

The CVA6 controller module rises the flush signal to the caches when executing a fence or fence.i instruction.
The HPDcache cache subsystem translates this fence signal to a FLUSH request to the cache (when the HPDcache is in WB mode).
Add new parameters in the CVA6 configuration packages:
DcacheFlushOnInvalidate: It changes the behavior of the CVA6 controller. When this parameter is set, the controller rises the Flush signal on fence instructions.
DcacheInvalidateOnFlush: It changes the behavior of the HPDcache request adapter. When issuing a flush, it also asks the HPDcache to invalidate the cachelines.
Add additional values to the DcacheType enum: HPDCACHE_WT, HPDCACHE_WB, HPDCACHE_WT_WB
In addition, it also fixes some issues with the rvfi_mem_paddr signal from the store_buffer.
This commit is contained in:
Cesar Fuguet 2025-01-10 17:57:32 +01:00 committed by GitHub
parent 71f96d4329
commit db568f3e1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 441 additions and 102 deletions

View file

@ -63,12 +63,15 @@ jobs:
strategy:
matrix:
testcase: [ cv64a6_imafdc_tests ]
config: [ cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdc_sv39_wb, cv64a6_imafdc_sv39 ]
config: [ cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdc_sv39_hpdcache_wb, cv64a6_imafdc_sv39_wb, cv64a6_imafdc_sv39 ]
simulator: [ veri-testharness ]
include:
- testcase: dv-riscv-arch-test
config: cv64a6_imafdc_sv39_hpdcache
simulator: veri-testharness
- testcase: dv-riscv-arch-test
config: cv64a6_imafdc_sv39_hpdcache_wb
simulator: veri-testharness
needs:
build-riscv-tests
steps:

View file

@ -22,7 +22,8 @@ module cva6_hpdcache_if_adapter
parameter type hpdcache_rsp_t = logic,
parameter type dcache_req_i_t = logic,
parameter type dcache_req_o_t = logic,
parameter bit is_load_port = 1'b1
parameter bit InvalidateOnFlush = 1'b0,
parameter bit IsLoadPort = 1'b1
)
// }}}
@ -42,6 +43,10 @@ module cva6_hpdcache_if_adapter
input ariane_pkg::amo_req_t cva6_amo_req_i,
output ariane_pkg::amo_resp_t cva6_amo_resp_o,
// Dcache flush signal
input logic cva6_dcache_flush_i,
output logic cva6_dcache_flush_ack_o,
// Request port to the L1 Dcache
output logic hpdcache_req_valid_o,
input logic hpdcache_req_ready_i,
@ -58,8 +63,13 @@ module cva6_hpdcache_if_adapter
// Internal nets and registers
// {{{
logic forward_store, forward_amo;
typedef enum {
FLUSH_IDLE,
FLUSH_PEND
} flush_fsm_t;
logic hpdcache_req_is_uncacheable;
hpdcache_req_t hpdcache_req;
// }}}
// Request forwarding
@ -67,7 +77,7 @@ module cva6_hpdcache_if_adapter
generate
// LOAD request
// {{{
if (is_load_port == 1'b1) begin : load_port_gen
if (IsLoadPort == 1'b1) begin : load_port_gen
assign hpdcache_req_is_uncacheable = !config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{
@ -79,19 +89,19 @@ module cva6_hpdcache_if_adapter
// Request forwarding
assign hpdcache_req_valid_o = cva6_req_i.data_req;
assign hpdcache_req_o.addr_offset = cva6_req_i.address_index;
assign hpdcache_req_o.wdata = '0;
assign hpdcache_req_o.op = hpdcache_pkg::HPDCACHE_REQ_LOAD;
assign hpdcache_req_o.be = cva6_req_i.data_be;
assign hpdcache_req_o.size = cva6_req_i.data_size;
assign hpdcache_req_o.sid = hpdcache_req_sid_i;
assign hpdcache_req_o.tid = cva6_req_i.data_id;
assign hpdcache_req_o.need_rsp = 1'b1;
assign hpdcache_req_o.phys_indexed = 1'b0;
assign hpdcache_req_o.addr_tag = '0; // unused on virtually indexed request
assign hpdcache_req_o.pma.uncacheable = 1'b0;
assign hpdcache_req_o.pma.io = 1'b0;
assign hpdcache_req_o.pma.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
assign hpdcache_req.addr_offset = cva6_req_i.address_index;
assign hpdcache_req.wdata = '0;
assign hpdcache_req.op = hpdcache_pkg::HPDCACHE_REQ_LOAD;
assign hpdcache_req.be = cva6_req_i.data_be;
assign hpdcache_req.size = cva6_req_i.data_size;
assign hpdcache_req.sid = hpdcache_req_sid_i;
assign hpdcache_req.tid = cva6_req_i.data_id;
assign hpdcache_req.need_rsp = 1'b1;
assign hpdcache_req.phys_indexed = 1'b0;
assign hpdcache_req.addr_tag = '0; // unused on virtually indexed request
assign hpdcache_req.pma.uncacheable = 1'b0;
assign hpdcache_req.pma.io = 1'b0;
assign hpdcache_req.pma.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
assign hpdcache_req_abort_o = cva6_req_i.kill_req;
assign hpdcache_req_tag_o = cva6_req_i.address_tag;
@ -104,6 +114,15 @@ module cva6_hpdcache_if_adapter
assign cva6_req_o.data_rdata = hpdcache_rsp_i.rdata;
assign cva6_req_o.data_rid = hpdcache_rsp_i.tid;
assign cva6_req_o.data_gnt = hpdcache_req_ready_i;
// Assertions
// {{{
// pragma translate_off
flush_on_load_port_assert :
assert property (@(posedge clk_i) disable iff (rst_ni !== 1'b1) (cva6_dcache_flush_i == 1'b0))
else $error("Flush unsupported on load adapters");
// pragma translate_on
// }}}
end // }}}
// {{{
@ -119,6 +138,53 @@ module cva6_hpdcache_if_adapter
logic [31:0] amo_resp_word;
logic amo_pending_q;
hpdcache_req_t hpdcache_req_amo;
hpdcache_req_t hpdcache_req_store;
hpdcache_req_t hpdcache_req_flush;
flush_fsm_t flush_fsm_q, flush_fsm_d;
logic forward_store, forward_amo, forward_flush;
// DCACHE flush request
// {{{
always_ff @(posedge clk_i or negedge rst_ni) begin : flush_ff
if (!rst_ni) begin
flush_fsm_q <= FLUSH_IDLE;
end else begin
flush_fsm_q <= flush_fsm_d;
end
end
always_comb begin : flush_comb
forward_flush = 1'b0;
cva6_dcache_flush_ack_o = 1'b0;
flush_fsm_d = flush_fsm_q;
case (flush_fsm_q)
FLUSH_IDLE: begin
if (cva6_dcache_flush_i) begin
forward_flush = 1'b1;
if (hpdcache_req_ready_i) begin
flush_fsm_d = FLUSH_PEND;
end
end
end
FLUSH_PEND: begin
if (hpdcache_rsp_valid_i) begin
if (hpdcache_rsp_i.tid == '0) begin
cva6_dcache_flush_ack_o = 1'b1;
flush_fsm_d = FLUSH_IDLE;
end
end
end
default: begin
end
endcase
end
// }}}
// AMO logic
// {{{
always_comb begin : amo_op_comb
@ -148,7 +214,7 @@ module cva6_hpdcache_if_adapter
CVA6Cfg,
{
{64 - CVA6Cfg.DCACHE_TAG_WIDTH{1'b0}}
, hpdcache_req_o.addr_tag,
, hpdcache_req.addr_tag,
{CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);
@ -163,23 +229,73 @@ module cva6_hpdcache_if_adapter
assign amo_data_be = 8'h0f;
end
assign hpdcache_req_amo = '{
addr_offset: amo_addr_offset,
wdata: amo_data,
op: amo_op,
be: amo_data_be,
size: cva6_amo_req_i.size,
sid: hpdcache_req_sid_i,
tid: '1,
need_rsp: 1'b1,
phys_indexed: 1'b1,
addr_tag: amo_tag,
pma: '{
uncacheable: hpdcache_req_is_uncacheable,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign hpdcache_req_store = '{
addr_offset: cva6_req_i.address_index,
wdata: cva6_req_i.data_wdata,
op: hpdcache_pkg::HPDCACHE_REQ_STORE,
be: cva6_req_i.data_be,
size: cva6_req_i.data_size,
sid: hpdcache_req_sid_i,
tid: '0,
need_rsp: 1'b0,
phys_indexed: 1'b1,
addr_tag: cva6_req_i.address_tag,
pma: '{
uncacheable: hpdcache_req_is_uncacheable,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign hpdcache_req_flush = '{
addr_offset: '0,
addr_tag: '0,
wdata: '0,
op:
InvalidateOnFlush
?
hpdcache_pkg::HPDCACHE_REQ_CMO_FLUSH_INVAL_ALL
:
hpdcache_pkg::HPDCACHE_REQ_CMO_FLUSH_ALL,
be: '0,
size: '0,
sid: hpdcache_req_sid_i,
tid: '0,
need_rsp: 1'b1,
phys_indexed: 1'b0,
pma: '{
uncacheable: 1'b0,
io: 1'b0,
wr_policy_hint: hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO
}
};
assign forward_store = cva6_req_i.data_req;
assign forward_amo = cva6_amo_req_i.req;
assign hpdcache_req_valid_o = forward_store | (forward_amo & ~amo_pending_q);
assign hpdcache_req_o.addr_offset = forward_amo ? amo_addr_offset : cva6_req_i.address_index;
assign hpdcache_req_o.wdata = forward_amo ? amo_data : cva6_req_i.data_wdata;
assign hpdcache_req_o.op = forward_amo ? amo_op : hpdcache_pkg::HPDCACHE_REQ_STORE;
assign hpdcache_req_o.be = forward_amo ? amo_data_be : cva6_req_i.data_be;
assign hpdcache_req_o.size = forward_amo ? cva6_amo_req_i.size : cva6_req_i.data_size;
assign hpdcache_req_o.sid = hpdcache_req_sid_i;
assign hpdcache_req_o.tid = forward_amo ? '1 : '0;
assign hpdcache_req_o.need_rsp = forward_amo;
assign hpdcache_req_o.phys_indexed = 1'b1;
assign hpdcache_req_o.addr_tag = forward_amo ? amo_tag : cva6_req_i.address_tag;
assign hpdcache_req_o.pma.uncacheable = hpdcache_req_is_uncacheable;
assign hpdcache_req_o.pma.io = 1'b0;
assign hpdcache_req_o.pma.wr_policy_hint = hpdcache_pkg::HPDCACHE_WR_POLICY_AUTO;
assign hpdcache_req_valid_o = (forward_amo & ~amo_pending_q) | forward_store | forward_flush;
assign hpdcache_req = forward_amo ? hpdcache_req_amo :
forward_store ? hpdcache_req_store : hpdcache_req_flush;
assign hpdcache_req_abort_o = 1'b0; // unused on physically indexed requests
assign hpdcache_req_tag_o = '0; // unused on physically indexed requests
assign hpdcache_req_pma_o.uncacheable = 1'b0;
@ -216,17 +332,21 @@ module cva6_hpdcache_if_adapter
(~cva6_amo_resp_o.ack & amo_pending_q);
end
end
// Assertions
// {{{
// pragma translate_off
forward_one_request_assert :
assert property (@(posedge clk_i) disable iff (rst_ni !== 1'b1) ($onehot0(
{forward_store, forward_amo, forward_flush}
)))
else $error("Only one request shall be forwarded");
// pragma translate_on
// }}}
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
assign hpdcache_req_o = hpdcache_req;
// }}}
endmodule

View file

@ -189,43 +189,52 @@ module cva6_hpdcache_subsystem
// NumPorts + 1: Hardware Memory Prefetcher (hwpf)
localparam int HPDCACHE_NREQUESTERS = NumPorts + 2;
localparam hpdcache_pkg::hpdcache_user_cfg_t HPDcacheUserCfg = '{
nRequesters: HPDCACHE_NREQUESTERS,
paWidth: CVA6Cfg.PLEN,
wordWidth: CVA6Cfg.XLEN,
sets: CVA6Cfg.DCACHE_NUM_WORDS,
ways: CVA6Cfg.DCACHE_SET_ASSOC,
clWords: CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.XLEN,
reqWords: 1,
reqTransIdWidth: CVA6Cfg.DcacheIdWidth,
reqSrcIdWidth: 3, // Up to 8 requesters
victimSel: hpdcache_pkg::HPDCACHE_VICTIM_RANDOM,
dataWaysPerRamWord: __minu(CVA6Cfg.DCACHE_SET_ASSOC, 128 / CVA6Cfg.XLEN),
dataSetsPerRam: CVA6Cfg.DCACHE_NUM_WORDS,
dataRamByteEnable: 1'b1,
accessWords: __maxu(CVA6Cfg.DCACHE_LINE_WIDTH / (2 * CVA6Cfg.XLEN), 1),
mshrSets: CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2,
mshrWays: CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2,
mshrWaysPerRamWord: CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2,
mshrSetsPerRam: CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2,
mshrRamByteEnable: 1'b1,
mshrUseRegbank: (CVA6Cfg.NrLoadBufEntries < 16),
refillCoreRspFeedthrough: 1'b1,
refillFifoDepth: 2,
wbufDirEntries: CVA6Cfg.WtDcacheWbufDepth,
wbufDataEntries: CVA6Cfg.WtDcacheWbufDepth,
wbufWords: 1,
wbufTimecntWidth: 3,
rtabEntries: 4,
flushEntries: 0,
flushFifoDepth: 0,
memAddrWidth: CVA6Cfg.AxiAddrWidth,
memIdWidth: CVA6Cfg.MEM_TID_WIDTH,
memDataWidth: CVA6Cfg.AxiDataWidth,
wtEn: 1'b1,
wbEn: 1'b0
};
function automatic hpdcache_pkg::hpdcache_user_cfg_t hpdcacheSetConfig();
hpdcache_pkg::hpdcache_user_cfg_t userCfg;
userCfg.nRequesters = HPDCACHE_NREQUESTERS;
userCfg.paWidth = CVA6Cfg.PLEN;
userCfg.wordWidth = CVA6Cfg.XLEN;
userCfg.sets = CVA6Cfg.DCACHE_NUM_WORDS;
userCfg.ways = CVA6Cfg.DCACHE_SET_ASSOC;
userCfg.clWords = CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.XLEN;
userCfg.reqWords = 1;
userCfg.reqTransIdWidth = CVA6Cfg.DcacheIdWidth;
userCfg.reqSrcIdWidth = 3; // Up to 8 requesters
userCfg.victimSel = hpdcache_pkg::HPDCACHE_VICTIM_RANDOM;
userCfg.dataWaysPerRamWord = __minu(CVA6Cfg.DCACHE_SET_ASSOC, 128 / CVA6Cfg.XLEN);
userCfg.dataSetsPerRam = CVA6Cfg.DCACHE_NUM_WORDS;
userCfg.dataRamByteEnable = 1'b1;
userCfg.accessWords = __maxu(CVA6Cfg.AxiDataWidth / CVA6Cfg.XLEN, 1 /*reqWords*/);
userCfg.mshrSets = CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2;
userCfg.mshrWays = CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2;
userCfg.mshrWaysPerRamWord = CVA6Cfg.NrLoadBufEntries < 16 ? CVA6Cfg.NrLoadBufEntries : 2;
userCfg.mshrSetsPerRam = CVA6Cfg.NrLoadBufEntries < 16 ? 1 : CVA6Cfg.NrLoadBufEntries / 2;
userCfg.mshrRamByteEnable = 1'b1;
userCfg.mshrUseRegbank = (CVA6Cfg.NrLoadBufEntries < 16);
userCfg.refillCoreRspFeedthrough = 1'b1;
userCfg.refillFifoDepth = 2;
userCfg.wbufDirEntries = CVA6Cfg.WtDcacheWbufDepth;
userCfg.wbufDataEntries = CVA6Cfg.WtDcacheWbufDepth;
userCfg.wbufWords = 1;
userCfg.wbufTimecntWidth = 3;
userCfg.rtabEntries = 4;
/*FIXME we should add additional CVA6 config parameters (flushEntries)*/
userCfg.flushEntries = CVA6Cfg.WtDcacheWbufDepth;
/*FIXME we should add additional CVA6 config parameters (flushFifoDepth)*/
userCfg.flushFifoDepth = CVA6Cfg.WtDcacheWbufDepth;
userCfg.memAddrWidth = CVA6Cfg.AxiAddrWidth;
userCfg.memIdWidth = CVA6Cfg.MEM_TID_WIDTH;
userCfg.memDataWidth = CVA6Cfg.AxiDataWidth;
userCfg.wtEn =
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT) ||
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT_WB);
userCfg.wbEn =
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WB) ||
(CVA6Cfg.DCacheType == config_pkg::HPDCACHE_WT_WB);
return userCfg;
endfunction
localparam hpdcache_pkg::hpdcache_user_cfg_t HPDcacheUserCfg = hpdcacheSetConfig();
localparam hpdcache_pkg::hpdcache_cfg_t HPDcacheCfg = hpdcache_pkg::hpdcacheBuildConfig(
HPDcacheUserCfg
);
@ -407,7 +416,7 @@ module cva6_hpdcache_subsystem
// {{{
// pragma translate_off
initial begin : initial_assertions
assert (HPDcacheCfg.u.reqSrcIdWidth >= $clog2(HPDCACHE_NREQUESTERS))
assert (HPDcacheCfg.u.reqSrcIdWidth >= $clog2(HPDcacheCfg.u.nRequesters))
else $fatal(1, "HPDCACHE_REQ_SRC_ID_WIDTH is not wide enough");
assert (CVA6Cfg.MEM_TID_WIDTH <= CVA6Cfg.AxiIdWidth)
else $fatal(1, "MEM_TID_WIDTH shall be less or equal to the AxiIdWidth");

View file

@ -155,7 +155,8 @@ module cva6_hpdcache_wrapper
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.is_load_port (1'b1)
.InvalidateOnFlush (1'b0),
.IsLoadPort (1'b1)
) i_cva6_hpdcache_load_if_adapter (
.clk_i,
.rst_ni,
@ -167,6 +168,9 @@ module cva6_hpdcache_wrapper
.cva6_amo_req_i ('0),
.cva6_amo_resp_o( /* unused */),
.cva6_dcache_flush_i (1'b0),
.cva6_dcache_flush_ack_o( /* unused */),
.hpdcache_req_valid_o(dcache_req_valid[r]),
.hpdcache_req_ready_i(dcache_req_ready[r]),
.hpdcache_req_o (dcache_req[r]),
@ -189,7 +193,8 @@ module cva6_hpdcache_wrapper
.hpdcache_rsp_t (hpdcache_rsp_t),
.dcache_req_i_t (dcache_req_i_t),
.dcache_req_o_t (dcache_req_o_t),
.is_load_port (1'b0)
.InvalidateOnFlush (CVA6Cfg.DcacheInvalidateOnFlush),
.IsLoadPort (1'b0)
) i_cva6_hpdcache_store_if_adapter (
.clk_i,
.rst_ni,
@ -201,6 +206,9 @@ module cva6_hpdcache_wrapper
.cva6_amo_req_i (dcache_amo_req_i),
.cva6_amo_resp_o(dcache_amo_resp_o),
.cva6_dcache_flush_i (dcache_flush_i),
.cva6_dcache_flush_ack_o(dcache_flush_ack_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]),
@ -413,12 +421,6 @@ module cva6_hpdcache_wrapper
);
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
// }}}
endmodule : cva6_hpdcache_wrapper

@ -1 +1 @@
Subproject commit edd501cc7424ad63d2187feacadc942650ec14af
Subproject commit 04de80896981527c34fbbd35d7b1ef787a082d7c

View file

@ -124,7 +124,7 @@ module controller
flush_ex_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -142,7 +142,7 @@ module controller
flush_icache_o = 1'b1;
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
@ -150,7 +150,7 @@ module controller
// this is not needed in the case since we
// have a write-through cache in this case
if (CVA6Cfg.DCacheType == config_pkg::WB) begin
if (CVA6Cfg.DcacheFlushOnFence) begin
// wait for the acknowledge here
if (flush_dcache_ack_i && fence_active_q) begin
fence_active_d = 1'b0;
@ -242,7 +242,7 @@ module controller
// ----------------------
always_comb begin
// halt the core if the fence is active
halt_o = halt_csr_i || halt_acc_i || (CVA6Cfg.DCacheType == config_pkg::WB && fence_active_q);
halt_o = halt_csr_i || halt_acc_i || (CVA6Cfg.DcacheFlushOnFence && fence_active_q);
end
// ----------------------

View file

@ -1326,7 +1326,11 @@ module cva6
.inval_valid_i (inval_valid),
.inval_ready_o (inval_ready)
);
end else if (CVA6Cfg.DCacheType == config_pkg::HPDCACHE) begin : gen_cache_hpd
end else if (CVA6Cfg.DCacheType inside {
config_pkg::HPDCACHE_WT,
config_pkg::HPDCACHE_WB,
config_pkg::HPDCACHE_WT_WB})
begin : gen_cache_hpd
cva6_hpdcache_subsystem #(
.CVA6Cfg (CVA6Cfg),
.icache_areq_t(icache_areq_t),

View file

@ -146,6 +146,9 @@ package build_config_pkg;
cfg.DCACHE_MAX_TX = unsigned'(2 ** CVA6Cfg.MemTidWidth);
cfg.DcacheFlushOnFence = CVA6Cfg.DcacheFlushOnFence;
cfg.DcacheInvalidateOnFlush = CVA6Cfg.DcacheInvalidateOnFlush;
cfg.DATA_USER_EN = CVA6Cfg.DataUserEn;
cfg.WtDcacheWbufDepth = CVA6Cfg.WtDcacheWbufDepth;
cfg.FETCH_USER_WIDTH = CVA6Cfg.FetchUserWidth;

View file

@ -27,10 +27,12 @@ package config_pkg;
} noc_type_e;
/// Cache type parameter
typedef enum logic [1:0] {
typedef enum logic [2:0] {
WB = 0,
WT = 1,
HPDCACHE = 2
HPDCACHE_WT = 2,
HPDCACHE_WB = 3,
HPDCACHE_WT_WB = 4
} cache_type_t;
/// Data and Address length
@ -164,6 +166,10 @@ package config_pkg;
int unsigned DcacheSetAssoc;
// Data cache line width
int unsigned DcacheLineWidth;
// Data cache flush on fence
bit DcacheFlushOnFence;
// Data cache invalidate on flush
bit DcacheInvalidateOnFlush;
// User field on data bus enable
int unsigned DataUserEn;
// Write-through data cache write buffer depth
@ -329,6 +335,9 @@ package config_pkg;
int unsigned DCACHE_MAX_TX;
bit DcacheFlushOnFence;
bit DcacheInvalidateOnFlush;
int unsigned DATA_USER_EN;
int unsigned WtDcacheWbufDepth;
int unsigned FETCH_USER_WIDTH;

View file

@ -84,10 +84,12 @@ package cva6_config_pkg;
IcacheByteSize: unsigned'(2048),
IcacheSetAssoc: unsigned'(2),
IcacheLineWidth: unsigned'(128),
DCacheType: config_pkg::HPDCACHE,
DCacheType: config_pkg::HPDCACHE_WT,
DcacheByteSize: unsigned'(2028),
DcacheSetAssoc: unsigned'(2),
DcacheLineWidth: unsigned'(128),
DcacheFlushOnFence: bit'(0),
DcacheInvalidateOnFlush: bit'(0),
DataUserEn: unsigned'(1),
WtDcacheWbufDepth: int'(8),
FetchUserWidth: unsigned'(32),

View file

@ -84,10 +84,12 @@ package cva6_config_pkg;
IcacheByteSize: unsigned'(2048),
IcacheSetAssoc: unsigned'(2),
IcacheLineWidth: unsigned'(128),
DCacheType: config_pkg::HPDCACHE,
DCacheType: config_pkg::HPDCACHE_WT,
DcacheByteSize: unsigned'(2028),
DcacheSetAssoc: unsigned'(2),
DcacheLineWidth: unsigned'(128),
DcacheFlushOnFence: bit'(0),
DcacheInvalidateOnFlush: bit'(0),
DataUserEn: unsigned'(1),
WtDcacheWbufDepth: int'(8),
FetchUserWidth: unsigned'(32),

View file

@ -63,7 +63,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE_WT;
localparam CVA6ConfigMmuPresent = 1;
@ -139,6 +139,8 @@ package cva6_config_pkg;
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DcacheFlushOnFence: bit'(0),
DcacheInvalidateOnFlush: bit'(0),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),

View file

@ -43,6 +43,9 @@ package cva6_config_pkg;
localparam CVA6ConfigDcacheSetAssoc = 8;
localparam CVA6ConfigDcacheLineWidth = 128;
localparam CVA6ConfigDcacheFlushOnFence = 1'b0;
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
localparam CVA6ConfigDcacheIdWidth = 1;
localparam CVA6ConfigMemTidWidth = 2;
@ -140,6 +143,8 @@ package cva6_config_pkg;
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DcacheFlushOnFence: unsigned'(CVA6ConfigDcacheFlushOnFence),
DcacheInvalidateOnFlush: unsigned'(CVA6ConfigDcacheInvalidateOnFlush),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),

View file

@ -50,6 +50,9 @@ package cva6_config_pkg;
localparam CVA6ConfigDcacheSetAssoc = 8;
localparam CVA6ConfigDcacheLineWidth = 128;
localparam CVA6ConfigDcacheFlushOnFence = 1'b0;
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
localparam CVA6ConfigDcacheIdWidth = 3;
localparam CVA6ConfigMemTidWidth = CVA6ConfigAxiIdWidth;
@ -71,7 +74,7 @@ package cva6_config_pkg;
localparam CVA6ConfigPerfCounterEn = 1;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE_WT;
localparam CVA6ConfigMmuPresent = 1;
@ -147,6 +150,8 @@ package cva6_config_pkg;
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DcacheFlushOnFence: bit'(CVA6ConfigDcacheFlushOnFence),
DcacheInvalidateOnFlush: bit'(CVA6ConfigDcacheInvalidateOnFlush),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),

View file

@ -0,0 +1,168 @@
// 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 CVA6ConfigRVF = 1;
localparam CVA6ConfigF16En = 0;
localparam CVA6ConfigF16AltEn = 0;
localparam CVA6ConfigF8En = 0;
localparam CVA6ConfigFVecEn = 0;
localparam CVA6ConfigCvxifEn = 1;
localparam CVA6ConfigCExtEn = 1;
localparam CVA6ConfigZcbExtEn = 1;
localparam CVA6ConfigZcmpExtEn = 0;
localparam CVA6ConfigAExtEn = 1;
localparam CVA6ConfigBExtEn = 1;
localparam CVA6ConfigVExtEn = 0;
localparam CVA6ConfigHExtEn = 0;
localparam CVA6ConfigRVZiCond = 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 CVA6ConfigDcacheFlushOnFence = 1'b1;
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
localparam CVA6ConfigDcacheIdWidth = 3;
localparam CVA6ConfigMemTidWidth = CVA6ConfigAxiIdWidth;
localparam CVA6ConfigWtDcacheWbufDepth = 8;
localparam CVA6ConfigNrScoreboardEntries = 8;
localparam CVA6ConfigNrLoadPipeRegs = 1;
localparam CVA6ConfigNrStorePipeRegs = 0;
localparam CVA6ConfigNrLoadBufEntries = 8;
localparam CVA6ConfigRASDepth = 2;
localparam CVA6ConfigBTBEntries = 32;
localparam CVA6ConfigBHTEntries = 128;
localparam CVA6ConfigTvalEn = 1;
localparam CVA6ConfigNrPMPEntries = 8;
localparam CVA6ConfigPerfCounterEn = 1;
localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE_WB;
localparam CVA6ConfigMmuPresent = 1;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
XLEN: unsigned'(CVA6ConfigXlen),
VLEN: unsigned'(64),
FpgaEn: bit'(0), // for Xilinx and Altera
FpgaAlteraEn: bit'(0), // for Altera (only)
TechnoCut: bit'(0),
SuperscalarEn: bit'(0),
NrCommitPorts: unsigned'(2),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth),
AxiUserWidth: unsigned'(CVA6ConfigDataUserWidth),
MemTidWidth: unsigned'(CVA6ConfigMemTidWidth),
NrLoadBufEntries: unsigned'(CVA6ConfigNrLoadBufEntries),
RVF: bit'(CVA6ConfigRVF),
RVD: bit'(CVA6ConfigRVF),
XF16: bit'(CVA6ConfigF16En),
XF16ALT: bit'(CVA6ConfigF16AltEn),
XF8: bit'(CVA6ConfigF8En),
RVA: bit'(CVA6ConfigAExtEn),
RVB: bit'(CVA6ConfigBExtEn),
ZKN: bit'(1),
RVV: bit'(CVA6ConfigVExtEn),
RVC: bit'(CVA6ConfigCExtEn),
RVH: bit'(CVA6ConfigHExtEn),
RVZCB: bit'(CVA6ConfigZcbExtEn),
RVZCMP: bit'(CVA6ConfigZcmpExtEn),
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
RVZiCond: bit'(CVA6ConfigRVZiCond),
RVZicntr: bit'(1),
RVZihpm: bit'(1),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
PerfCounterEn: bit'(CVA6ConfigPerfCounterEn),
MmuPresent: bit'(CVA6ConfigMmuPresent),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),
BTBEntries: unsigned'(CVA6ConfigBTBEntries),
BHTEntries: unsigned'(CVA6ConfigBHTEntries),
DmBaseAddress: 64'h0,
TvalEn: bit'(CVA6ConfigTvalEn),
DirectVecOnly: bit'(0),
NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries),
PMPCfgRstVal: {64{64'h0}},
PMPAddrRstVal: {64{64'h0}},
PMPEntryReadOnly: 64'd0,
PMPNapotEn: bit'(1),
NOCType: config_pkg::NOC_TYPE_AXI4_ATOP,
NrNonIdempotentRules: unsigned'(2),
NonIdempotentAddrBase: 1024'({64'b0, 64'b0}),
NonIdempotentLength: 1024'({64'b0, 64'b0}),
NrExecuteRegionRules: unsigned'(3),
ExecuteRegionAddrBase: 1024'({64'h8000_0000, 64'h1_0000, 64'h0}),
ExecuteRegionLength: 1024'({64'h40000000, 64'h10000, 64'h1000}),
NrCachedRegionRules: unsigned'(1),
CachedRegionAddrBase: 1024'({64'h8000_0000}),
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DCacheType: CVA6ConfigDcacheType,
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DcacheFlushOnFence: bit'(CVA6ConfigDcacheFlushOnFence),
DcacheInvalidateOnFlush: bit'(CVA6ConfigDcacheInvalidateOnFlush),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn),
InstrTlbEntries: int'(16),
DataTlbEntries: int'(16),
UseSharedTlb: bit'(0),
SharedTlbDepth: int'(64),
NrLoadPipeRegs: int'(CVA6ConfigNrLoadPipeRegs),
NrStorePipeRegs: int'(CVA6ConfigNrStorePipeRegs),
DcacheIdWidth: int'(CVA6ConfigDcacheIdWidth)
};
endpackage

View file

@ -43,6 +43,9 @@ package cva6_config_pkg;
localparam CVA6ConfigDcacheSetAssoc = 8;
localparam CVA6ConfigDcacheLineWidth = 128;
localparam CVA6ConfigDcacheFlushOnFence = 1'b1;
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
localparam CVA6ConfigDcacheIdWidth = 1;
localparam CVA6ConfigMemTidWidth = 2;
@ -140,6 +143,8 @@ package cva6_config_pkg;
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DcacheFlushOnFence: unsigned'(CVA6ConfigDcacheFlushOnFence),
DcacheInvalidateOnFlush: unsigned'(CVA6ConfigDcacheInvalidateOnFlush),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),

View file

@ -155,7 +155,7 @@ module load_store_unit
// RVFI inforamtion - RVFI
output lsu_ctrl_t rvfi_lsu_ctrl_o,
// RVFI information - RVFI
output [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o
output logic [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o
);
// data is misaligned

View file

@ -41,7 +41,7 @@ module store_buffer
input logic valid_without_flush_i, // just tell if the address is valid which we are current putting and do not take any further action
input logic [CVA6Cfg.PLEN-1:0] paddr_i, // physical address of store which needs to be placed in the queue
output [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o,
output logic [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o,
input logic [CVA6Cfg.XLEN-1:0] data_i, // data which is placed in the queue
input logic [(CVA6Cfg.XLEN/8)-1:0] be_i, // byte enable in
input logic [1:0] data_size_i, // type of request we are making (e.g.: bytes to write)
@ -150,7 +150,7 @@ module store_buffer
assign req_port_o.data_be = commit_queue_q[commit_read_pointer_q].be;
assign req_port_o.data_size = commit_queue_q[commit_read_pointer_q].data_size;
assign rvfi_mem_paddr_o = commit_queue_n[commit_read_pointer_n].address;
assign rvfi_mem_paddr_o = speculative_queue_q[speculative_read_pointer_q].address;
always_comb begin : store_if
automatic logic [$clog2(DEPTH_COMMIT):0] commit_status_cnt;

View file

@ -59,7 +59,7 @@ module store_unit
// Virtual address - TO_BE_COMPLETED
output logic [CVA6Cfg.VLEN-1:0] vaddr_o,
// RVFI information - RVFI
output [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o,
output logic [CVA6Cfg.PLEN-1:0] rvfi_mem_paddr_o,
// Transformed trap instruction out - TO_BE_COMPLETED
output logic [31:0] tinst_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED

View file

@ -880,7 +880,7 @@ def load_config(args, cwd):
elif base in ("cv64a6_imafdc_sv39_wb"):
args.mabi = "lp64d"
args.isa = "rv64gc_zba_zbb_zbs_zbc"
elif base in ("cv64a6_imafdc_sv39", "cv64a6_imafdc_sv39_hpdcache"):
elif base in ("cv64a6_imafdc_sv39", "cv64a6_imafdc_sv39_hpdcache", "cv64a6_imafdc_sv39_hpdcache_wb"):
args.mabi = "lp64d"
args.isa = "rv64gc_zba_zbb_zbs_zbc_zbkb"
elif base == "cv32a60x":