Parametrization step 3 (#1935)

This is the third step for #1451. Many values are moved but not all values are moved yet

* move NR_SB_ENTRIES & TRANS_ID_BITS
* remove default rvfi_instr_t from spike.sv
* fifo_v3: ariane_pkg::FPGA_EN becomes a param
* move FPGA_EN
* inline wt_cache_pkg::L15_SET_ASSOC
* move wt_cache_pkg::L15_WAY_WIDTH
* inline wt_cache_pkg::L1I_SET_ASSOC
* inline wt_cache_pkg::L1D_SET_ASSOC
* move wt_cache_pkg::DCACHE_CL_IDX_WIDTH
* move ICACHE_TAG_WIDTH
* move DCACHE_TAG_WIDTH
* move ICACHE_INDEX_WIDTH
* move ICACHE_SET_ASSOC
* use ICACHE_SET_ASSOC_WIDTH instead of $clog2(ICACHE_SET_ASSOC)
* move DCACHE_NUM_WORDS
* move DCACHE_INDEX_WIDTH
* move DCACHE_OFFSET_WIDTH
* move DCACHE_BYTE_OFFSET
* move DCACHE_DIRTY_WIDTH
* move DCACHE_SET_ASSOC_WIDTH
* move DCACHE_SET_ASSOC
* move CONFIG_L1I_SIZE
* move CONFIG_L1D_SIZE
* move DCACHE_LINE_WIDTH
* move ICACHE_LINE_WIDTH
* move ICACHE_USER_LINE_WIDTH
* move DCACHE_USER_LINE_WIDTH
* DATA_USER_WIDTH = DCACHE_USER_WIDTH
* move DCACHE_USER_WIDTH
* move FETCH_USER_WIDTH
* move FETCH_USER_EN
* move LOG2_INSTR_PER_FETCH
* move INSTR_PER_FETCH
* move FETCH_WIDTH
* transform SSTATUS_SD and SMODE_STATUS_READ_MASK into functions
* move [SM]_{SW,TIMER,EXT}_INTERRUPT into a structure
* move SV
* move vm_mode_t to config_pkg
* move MODE_SV
* move VPN2
* move PPNW
* move ASIDW
* move ModeW
* move XLEN_ALIGN_BYTES
* move DATA_USER_EN
* format: apply verible
This commit is contained in:
Côme 2024-03-15 18:21:34 +01:00 committed by GitHub
parent f0887e4ec5
commit 987c645bb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 1419 additions and 1192 deletions

View file

@ -14,7 +14,9 @@
`ifndef VERILATOR
class ex_trace_item #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
);
// contains a human readable form of the cause value
@ -42,12 +44,12 @@ class ex_trace_item #(
riscv::INSTR_PAGE_FAULT: this.cause_s = "Instruction Page Fault";
riscv::LOAD_PAGE_FAULT: this.cause_s = "Load Page Fault";
riscv::STORE_PAGE_FAULT: this.cause_s = "Store Page Fault";
riscv::S_SW_INTERRUPT: this.cause_s = "Supervisor Software Interrupt";
riscv::M_SW_INTERRUPT: this.cause_s = "Machine Software Interrupt";
riscv::S_TIMER_INTERRUPT: this.cause_s = "Supervisor Timer Interrupt";
riscv::M_TIMER_INTERRUPT: this.cause_s = "Machine Timer Interrupt";
riscv::S_EXT_INTERRUPT: this.cause_s = "Supervisor External Interrupt";
riscv::M_EXT_INTERRUPT: this.cause_s = "Machine External Interrupt";
INTERRUPTS.S_SW: this.cause_s = "Supervisor Software Interrupt";
INTERRUPTS.M_SW: this.cause_s = "Machine Software Interrupt";
INTERRUPTS.S_TIMER: this.cause_s = "Supervisor Timer Interrupt";
INTERRUPTS.M_TIMER: this.cause_s = "Machine Timer Interrupt";
INTERRUPTS.S_EXT: this.cause_s = "Supervisor External Interrupt";
INTERRUPTS.M_EXT: this.cause_s = "Machine External Interrupt";
riscv::DEBUG_REQUEST: this.cause_s = "Request Debug Mode";
default: this.cause_s = "Interrupt";
endcase
@ -64,12 +66,12 @@ class ex_trace_item #(
riscv::ENV_CALL_MMODE,
riscv::ENV_CALL_SMODE,
riscv::ENV_CALL_UMODE,
riscv::S_SW_INTERRUPT,
riscv::M_SW_INTERRUPT,
riscv::S_TIMER_INTERRUPT,
riscv::M_TIMER_INTERRUPT,
riscv::S_EXT_INTERRUPT,
riscv::M_EXT_INTERRUPT
INTERRUPTS.S_SW,
INTERRUPTS.M_SW,
INTERRUPTS.S_TIMER,
INTERRUPTS.M_TIMER,
INTERRUPTS.S_EXT,
INTERRUPTS.M_EXT
}))
s = $sformatf("%s, \n\t\t\t\ttval: %h", s, this.tval);
return s;

View file

@ -20,7 +20,9 @@
module instr_tracer #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type bp_resolve_t = logic,
parameter type scoreboard_entry_t = logic
parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
)(
instr_tracer_if tracer_if,
input logic[riscv::XLEN-1:0] hart_id_i
@ -206,7 +208,9 @@ module instr_tracer #(
function void printException(logic [riscv::VLEN-1:0] pc, logic [63:0] cause, logic [63:0] tval);
automatic ex_trace_item #(
.CVA6Cfg(CVA6Cfg)
.CVA6Cfg(CVA6Cfg),
.interrupts_t(interrupts_t),
.INTERRUPTS(INTERRUPTS)
) eti = new (pc, cause, tval);
automatic string print_ex = eti.printException();
$fwrite(f, {print_ex, "\n"});

View file

@ -24,34 +24,34 @@ module acc_dispatcher
parameter type fu_data_t = logic,
parameter type scoreboard_entry_t = logic,
localparam type accelerator_req_t = struct packed {
logic req_valid;
logic resp_ready;
riscv::instruction_t insn;
logic [riscv::XLEN-1:0] rs1;
logic [riscv::XLEN-1:0] rs2;
fpnew_pkg::roundmode_e frm;
logic [ariane_pkg::TRANS_ID_BITS-1:0] trans_id;
logic store_pending;
logic req_valid;
logic resp_ready;
riscv::instruction_t insn;
logic [riscv::XLEN-1:0] rs1;
logic [riscv::XLEN-1:0] rs2;
fpnew_pkg::roundmode_e frm;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
logic store_pending;
// Invalidation interface
logic acc_cons_en;
logic inval_ready;
logic acc_cons_en;
logic inval_ready;
},
parameter type acc_req_t = accelerator_req_t,
parameter type acc_resp_t = struct packed {
logic req_ready;
logic resp_valid;
logic [riscv::XLEN-1:0] result;
logic [ariane_pkg::TRANS_ID_BITS-1:0] trans_id;
logic error;
logic req_ready;
logic resp_valid;
logic [riscv::XLEN-1:0] result;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
logic error;
// Metadata
logic store_pending;
logic store_complete;
logic load_complete;
logic [4:0] fflags;
logic fflags_valid;
logic store_pending;
logic store_complete;
logic load_complete;
logic [4:0] fflags;
logic fflags_valid;
// Invalidation interface
logic inval_valid;
logic [63:0] inval_addr;
logic inval_valid;
logic [63:0] inval_addr;
},
parameter type acc_cfg_t = logic,
parameter acc_cfg_t AccCfg = '0
@ -75,7 +75,7 @@ module acc_dispatcher
output logic issue_stall_o,
input fu_data_t fu_data_i,
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_i,
output logic [TRANS_ID_BITS-1:0] acc_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] acc_trans_id_o,
output logic [riscv::XLEN-1:0] acc_result_o,
output logic acc_valid_o,
output exception_t acc_exception_o,
@ -161,14 +161,15 @@ module acc_dispatcher
logic acc_insn_queue_empty;
logic [idx_width(InstructionQueueDepth)-1:0] acc_insn_queue_usage;
logic acc_commit;
logic [ TRANS_ID_BITS-1:0] acc_commit_trans_id;
logic [ CVA6Cfg.TRANS_ID_BITS-1:0] acc_commit_trans_id;
assign acc_data = acc_valid_ex_o ? fu_data_i : '0;
fifo_v3 #(
.DEPTH (InstructionQueueDepth),
.FALL_THROUGH(1'b1),
.dtype (fu_data_t)
.dtype (fu_data_t),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_acc_insn_queue (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -191,13 +192,13 @@ module acc_dispatcher
**********************************/
// Keep track of the instructions that were received by the dispatcher.
logic [NR_SB_ENTRIES-1:0] insn_pending_d, insn_pending_q;
logic [CVA6Cfg.NR_SB_ENTRIES-1:0] insn_pending_d, insn_pending_q;
`FF(insn_pending_q, insn_pending_d, '0)
// Only non-speculative instructions can be issued to the accelerators.
// The following block keeps track of which transaction IDs reached the
// top of the scoreboard, and are therefore no longer speculative.
logic [NR_SB_ENTRIES-1:0] insn_ready_d, insn_ready_q;
logic [CVA6Cfg.NR_SB_ENTRIES-1:0] insn_ready_d, insn_ready_q;
`FF(insn_ready_q, insn_ready_d, '0)
always_comb begin : p_non_speculative_ff

View file

@ -63,8 +63,9 @@ module amo_buffer #(
assign flush_amo_buffer = flush_i & !amo_valid_commit_i;
fifo_v3 #(
.DEPTH(1),
.dtype(amo_op_t)
.DEPTH (1),
.dtype (amo_op_t),
.FPGA_EN(CVA6Cfg.FPGA_EN)
) i_amo_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),

View file

@ -37,15 +37,15 @@ module cache_ctrl
input dcache_req_i_t req_port_i,
output dcache_req_o_t req_port_o,
// SRAM interface
output logic [DCACHE_SET_ASSOC-1:0] req_o, // req is valid
output logic [DCACHE_INDEX_WIDTH-1:0] addr_o, // address into cache array
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] req_o, // req is valid
output logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] addr_o, // address into cache array
input logic gnt_i,
output cache_line_t data_o,
output cl_be_t be_o,
output logic [DCACHE_TAG_WIDTH-1:0] tag_o, //valid one cycle later
input cache_line_t [DCACHE_SET_ASSOC-1:0] data_i,
output logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_o, //valid one cycle later
input cache_line_t [CVA6Cfg.DCACHE_SET_ASSOC-1:0] data_i,
output logic we_o,
input logic [DCACHE_SET_ASSOC-1:0] hit_way_i,
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] hit_way_i,
// Miss handling
output miss_req_t miss_req_o,
// return
@ -79,29 +79,30 @@ module cache_ctrl
state_d, state_q;
typedef struct packed {
logic [DCACHE_INDEX_WIDTH-1:0] index;
logic [DCACHE_TAG_WIDTH-1:0] tag;
logic [DCACHE_TID_WIDTH-1:0] id;
logic [7:0] be;
logic [1:0] size;
logic we;
logic [63:0] wdata;
logic bypass;
logic killed;
logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] index;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag;
logic [DCACHE_TID_WIDTH-1:0] id;
logic [7:0] be;
logic [1:0] size;
logic we;
logic [63:0] wdata;
logic bypass;
logic killed;
} mem_req_t;
logic [DCACHE_SET_ASSOC-1:0] hit_way_d, hit_way_q;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] hit_way_d, hit_way_q;
mem_req_t mem_req_d, mem_req_q;
assign busy_o = (state_q != IDLE);
assign tag_o = mem_req_d.tag;
logic [DCACHE_LINE_WIDTH-1:0] cl_i;
logic [CVA6Cfg.DCACHE_LINE_WIDTH-1:0] cl_i;
always_comb begin : way_select
cl_i = '0;
for (int unsigned i = 0; i < DCACHE_SET_ASSOC; i++) if (hit_way_i[i]) cl_i = data_i[i].data;
for (int unsigned i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++)
if (hit_way_i[i]) cl_i = data_i[i].data;
// cl_i = data_i[one_hot_to_bin(hit_way_i)].data;
end
@ -110,10 +111,10 @@ module cache_ctrl
// Cache FSM
// --------------
always_comb begin : cache_ctrl_fsm
automatic logic [$clog2(DCACHE_LINE_WIDTH)-1:0] cl_offset;
automatic logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
// incoming cache-line -> this is needed as synthesis is not supporting +: indexing in a multi-dimensional array
// cache-line offset -> multiple of 64
cl_offset = mem_req_q.index[DCACHE_BYTE_OFFSET-1:3] << 6; // shift by 6 to the left
cl_offset = mem_req_q.index[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3] << 6; // shift by 6 to the left
// default assignments
state_d = state_q;
mem_req_d = mem_req_q;
@ -256,7 +257,7 @@ module cache_ctrl
// Check for cache-ability
// -------------------------
if (!config_pkg::is_inside_cacheable_regions(
CVA6Cfg, {{{64 - riscv::PLEN} {1'b0}}, tag_o, {DCACHE_INDEX_WIDTH{1'b0}}}
CVA6Cfg, {{{64 - riscv::PLEN} {1'b0}}, tag_o, {CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}}
)) begin
mem_req_d.bypass = 1'b1;
state_d = WAIT_REFILL_GNT;
@ -460,7 +461,7 @@ module cache_ctrl
//pragma translate_off
`ifndef VERILATOR
initial begin
assert (DCACHE_LINE_WIDTH == 128)
assert (CVA6Cfg.DCACHE_LINE_WIDTH == 128)
else
$error(
"Cacheline width has to be 128 for the moment. But only small changes required in data select logic"

View file

@ -67,9 +67,9 @@ module cva6_hpdcache_if_adapter
assign hpdcache_req_is_uncacheable = !config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{
{64 - ariane_pkg::DCACHE_TAG_WIDTH{1'b0}}
{64 - CVA6Cfg.DCACHE_TAG_WIDTH{1'b0}}
, cva6_req_i.address_tag
, {ariane_pkg::DCACHE_INDEX_WIDTH{1'b0}}
, {CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);
@ -140,9 +140,9 @@ module cva6_hpdcache_if_adapter
assign hpdcache_req_is_uncacheable = !config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{
{64 - ariane_pkg::DCACHE_TAG_WIDTH{1'b0}}
{64 - CVA6Cfg.DCACHE_TAG_WIDTH{1'b0}}
, hpdcache_req_o.addr_tag,
{ariane_pkg::DCACHE_INDEX_WIDTH{1'b0}}
{CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);

View file

@ -520,8 +520,7 @@ module cva6_hpdcache_subsystem
// AXI arbiter instantiation
// {{{
cva6_hpdcache_subsystem_axi_arbiter #(
.HPDcacheMemIdWidth (CVA6Cfg.MEM_TID_WIDTH),
.HPDcacheMemDataWidth (CVA6Cfg.AxiDataWidth),
.CVA6Cfg (CVA6Cfg),
.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),

View file

@ -16,8 +16,7 @@ module cva6_hpdcache_subsystem_axi_arbiter
// Parameters
// {{{
#(
parameter int HPDcacheMemIdWidth = 8,
parameter int HPDcacheMemDataWidth = 512,
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type hpdcache_mem_req_t = logic,
parameter type hpdcache_mem_req_w_t = logic,
parameter type hpdcache_mem_resp_r_t = logic,
@ -37,7 +36,7 @@ module cva6_hpdcache_subsystem_axi_arbiter
parameter type axi_req_t = logic,
parameter type axi_rsp_t = logic,
localparam type hpdcache_mem_id_t = logic [HPDcacheMemIdWidth-1:0]
localparam type hpdcache_mem_id_t = logic [CVA6Cfg.MEM_TID_WIDTH-1:0]
)
// }}}
@ -117,23 +116,23 @@ module cva6_hpdcache_subsystem_axi_arbiter
// Internal type definitions
// {{{
localparam int MEM_RESP_RT_DEPTH = (1 << HPDcacheMemIdWidth);
localparam int MEM_RESP_RT_DEPTH = (1 << CVA6Cfg.MEM_TID_WIDTH);
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;
typedef logic [CVA6Cfg.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_WORDS = CVA6Cfg.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_CL_SIZE = $clog2(CVA6Cfg.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;
(CVA6Cfg.ICACHE_LINE_WIDTH + CVA6Cfg.AxiDataWidth - 1)/CVA6Cfg.AxiDataWidth;
localparam int ICACHE_MEM_REQ_CL_SIZE =
(HPDcacheMemDataWidth <= ariane_pkg::ICACHE_LINE_WIDTH) ?
(CVA6Cfg.AxiDataWidth <= CVA6Cfg.ICACHE_LINE_WIDTH) ?
$clog2(
HPDcacheMemDataWidth / 8
CVA6Cfg.AxiDataWidth / 8
) : ICACHE_CL_SIZE;
// I$ request
@ -192,7 +191,7 @@ module cva6_hpdcache_subsystem_axi_arbiter
icache_resp_data_t icache_miss_rdata;
generate
if (HPDcacheMemDataWidth < ariane_pkg::ICACHE_LINE_WIDTH) begin
if (CVA6Cfg.AxiDataWidth < CVA6Cfg.ICACHE_LINE_WIDTH) begin
hpdcache_fifo_reg #(
.FIFO_DEPTH (1),
.fifo_data_t(hpdcache_mem_id_t)
@ -210,8 +209,8 @@ module cva6_hpdcache_subsystem_axi_arbiter
);
hpdcache_data_upsize #(
.WR_WIDTH(HPDcacheMemDataWidth),
.RD_WIDTH(ariane_pkg::ICACHE_LINE_WIDTH),
.WR_WIDTH(CVA6Cfg.AxiDataWidth),
.RD_WIDTH(CVA6Cfg.ICACHE_LINE_WIDTH),
.DEPTH (1)
) i_icache_hpdcache_data_upsize (
.clk_i,
@ -252,7 +251,7 @@ module cva6_hpdcache_subsystem_axi_arbiter
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};
icache_miss_rdata = {{CVA6Cfg.ICACHE_LINE_WIDTH - 64{1'b0}}, icache_miss_word};
end else begin
icache_miss_rdata = icache_miss_resp_data_rdata;
end
@ -547,26 +546,26 @@ module cva6_hpdcache_subsystem_axi_arbiter
// {{{
// pragma translate_off
initial
assert (HPDcacheMemIdWidth <= AxiIdWidth)
else $fatal("HPDcacheMemIdWidth shall be less or equal to AxiIdWidth");
assert (CVA6Cfg.MEM_TID_WIDTH <= AxiIdWidth)
else $fatal("MEM_TID_WIDTH shall be less or equal to AxiIdWidth");
initial
assert (HPDcacheMemIdWidth >= (hpdcache_pkg::HPDCACHE_MSHR_SET_WIDTH + hpdcache_pkg::HPDCACHE_MSHR_WAY_WIDTH + 1))
assert (CVA6Cfg.MEM_TID_WIDTH >= (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"
"MEM_TID_WIDTH shall be wide enough to identify all pending HPDcache misses and Icache misses"
);
initial
assert (HPDcacheMemIdWidth >= (hpdcache_pkg::HPDCACHE_WBUF_DIR_PTR_WIDTH + 1))
assert (CVA6Cfg.MEM_TID_WIDTH >= (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"
"MEM_TID_WIDTH 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");
assert (CVA6Cfg.AxiDataWidth <= CVA6Cfg.ICACHE_LINE_WIDTH)
else $fatal("AxiDataWidth 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");
assert (CVA6Cfg.AxiDataWidth <= CVA6Cfg.DCACHE_LINE_WIDTH)
else $fatal("AxiDataWidth shall be less or equal to the width of a Dcache line");
// pragma translate_on
// }}}

View file

@ -62,14 +62,14 @@ module cva6_icache
output icache_req_t mem_data_o
);
localparam ICACHE_OFFSET_WIDTH = $clog2(ariane_pkg::ICACHE_LINE_WIDTH / 8);
localparam ICACHE_NUM_WORDS = 2 ** (ariane_pkg::ICACHE_INDEX_WIDTH - ICACHE_OFFSET_WIDTH);
localparam ICACHE_OFFSET_WIDTH = $clog2(CVA6Cfg.ICACHE_LINE_WIDTH / 8);
localparam ICACHE_NUM_WORDS = 2 ** (CVA6Cfg.ICACHE_INDEX_WIDTH - ICACHE_OFFSET_WIDTH);
localparam ICACHE_CL_IDX_WIDTH = $clog2(ICACHE_NUM_WORDS); // excluding byte offset
// functions
function automatic logic [ariane_pkg::ICACHE_SET_ASSOC-1:0] icache_way_bin2oh(
input logic [L1I_WAY_WIDTH-1:0] in);
logic [ariane_pkg::ICACHE_SET_ASSOC-1:0] out;
function automatic logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] icache_way_bin2oh(
input logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] in);
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] out;
out = '0;
out[in] = 1'b1;
return out;
@ -78,21 +78,21 @@ module cva6_icache
// signals
logic cache_en_d, cache_en_q; // cache is enabled
logic [riscv::VLEN-1:0] vaddr_d, vaddr_q;
logic paddr_is_nc; // asserted if physical address is non-cacheable
logic [ICACHE_SET_ASSOC-1:0] cl_hit; // hit from tag compare
logic cache_rden; // triggers cache lookup
logic cache_wren; // triggers write to cacheline
logic paddr_is_nc; // asserted if physical address is non-cacheable
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] cl_hit; // hit from tag compare
logic cache_rden; // triggers cache lookup
logic cache_wren; // triggers write to cacheline
logic
cmp_en_d,
cmp_en_q; // enable tag comparison in next cycle. used to cut long path due to NC signal.
logic flush_d, flush_q; // used to register and signal pending flushes
// replacement strategy
logic update_lfsr; // shift the LFSR
logic [$clog2(ICACHE_SET_ASSOC)-1:0] inv_way; // first non-valid encountered
logic [$clog2(ICACHE_SET_ASSOC)-1:0] rnd_way; // random index for replacement
logic [$clog2(ICACHE_SET_ASSOC)-1:0] repl_way; // way to replace
logic [ICACHE_SET_ASSOC-1:0] repl_way_oh_d, repl_way_oh_q; // way to replace (onehot)
logic update_lfsr; // shift the LFSR
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] inv_way; // first non-valid encountered
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] rnd_way; // random index for replacement
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] repl_way; // way to replace
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] repl_way_oh_d, repl_way_oh_q; // way to replace (onehot)
logic all_ways_valid; // we need to switch repl strategy since all are valid
// invalidations / flushing
@ -102,20 +102,20 @@ module cva6_icache
logic [ICACHE_CL_IDX_WIDTH-1:0] flush_cnt_d, flush_cnt_q; // used to flush cache entries
// mem arrays
logic cl_we; // write enable to memory array
logic [ ICACHE_SET_ASSOC-1:0] cl_req; // request to memory array
logic [ICACHE_CL_IDX_WIDTH-1:0] cl_index; // this is a cache-line index, to memory array
logic cl_we; // write enable to memory array
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] cl_req; // request to memory array
logic [ ICACHE_CL_IDX_WIDTH-1:0] cl_index; // this is a cache-line index, to memory array
logic [ICACHE_OFFSET_WIDTH-1:0] cl_offset_d, cl_offset_q; // offset in cache line
logic [ICACHE_TAG_WIDTH-1:0] cl_tag_d, cl_tag_q; // this is the cache tag
logic [ICACHE_TAG_WIDTH-1:0] cl_tag_rdata [ICACHE_SET_ASSOC-1:0]; // these are the tags coming from the tagmem
logic [ICACHE_LINE_WIDTH-1:0] cl_rdata [ICACHE_SET_ASSOC-1:0]; // these are the cachelines coming from the cache
logic [ICACHE_USER_LINE_WIDTH-1:0] cl_ruser[ICACHE_SET_ASSOC-1:0]; // these are the cachelines coming from the user cache
logic [ICACHE_SET_ASSOC-1:0][FETCH_WIDTH-1:0] cl_sel; // selected word from each cacheline
logic [ICACHE_SET_ASSOC-1:0][FETCH_USER_WIDTH-1:0] cl_user; // selected word from each cacheline
logic [ICACHE_SET_ASSOC-1:0] vld_req; // bit enable for valid regs
logic [CVA6Cfg.ICACHE_TAG_WIDTH-1:0] cl_tag_d, cl_tag_q; // this is the cache tag
logic [CVA6Cfg.ICACHE_TAG_WIDTH-1:0] cl_tag_rdata [CVA6Cfg.ICACHE_SET_ASSOC-1:0]; // these are the tags coming from the tagmem
logic [CVA6Cfg.ICACHE_LINE_WIDTH-1:0] cl_rdata [CVA6Cfg.ICACHE_SET_ASSOC-1:0]; // these are the cachelines coming from the cache
logic [CVA6Cfg.ICACHE_USER_LINE_WIDTH-1:0] cl_ruser[CVA6Cfg.ICACHE_SET_ASSOC-1:0]; // these are the cachelines coming from the user cache
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0][CVA6Cfg.FETCH_WIDTH-1:0] cl_sel; // selected word from each cacheline
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0][CVA6Cfg.FETCH_USER_WIDTH-1:0] cl_user; // selected word from each cacheline
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] vld_req; // bit enable for valid regs
logic vld_we; // valid bits write enable
logic [ICACHE_SET_ASSOC-1:0] vld_wdata; // valid bits to write
logic [ICACHE_SET_ASSOC-1:0] vld_rdata; // valid bits coming from valid regs
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] vld_wdata; // valid bits to write
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] vld_rdata; // valid bits coming from valid regs
logic [ICACHE_CL_IDX_WIDTH-1:0] vld_addr; // valid bit
// cpmtroller FSM
@ -134,11 +134,11 @@ module cva6_icache
///////////////////////////////////////////////////////
// extract tag from physical address, check if NC
assign cl_tag_d = (areq_i.fetch_valid) ? areq_i.fetch_paddr[ICACHE_TAG_WIDTH+ICACHE_INDEX_WIDTH-1:ICACHE_INDEX_WIDTH] : cl_tag_q;
assign cl_tag_d = (areq_i.fetch_valid) ? areq_i.fetch_paddr[CVA6Cfg.ICACHE_TAG_WIDTH+CVA6Cfg.ICACHE_INDEX_WIDTH-1:CVA6Cfg.ICACHE_INDEX_WIDTH] : cl_tag_q;
// noncacheable if request goes to I/O space, or if cache is disabled
assign paddr_is_nc = (~cache_en_q) | (~config_pkg::is_inside_cacheable_regions(
CVA6Cfg, {{64 - riscv::PLEN{1'b0}}, cl_tag_d, {ICACHE_INDEX_WIDTH{1'b0}}}
CVA6Cfg, {{64 - riscv::PLEN{1'b0}}, cl_tag_d, {CVA6Cfg.ICACHE_INDEX_WIDTH{1'b0}}}
));
// pass exception through
@ -150,7 +150,7 @@ module cva6_icache
assign areq_o.fetch_vaddr = {vaddr_q[riscv::VLEN-1:2], 2'b0};
// split virtual address into index and offset to address cache arrays
assign cl_index = vaddr_d[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
assign cl_index = vaddr_d[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH];
if (CVA6Cfg.NOCType == config_pkg::NOC_TYPE_AXI4_ATOP) begin : gen_axi_offset
@ -159,16 +159,16 @@ module cva6_icache
( paddr_is_nc & mem_data_req_o ) ? {{ICACHE_OFFSET_WIDTH-1{1'b0}}, cl_offset_q[2]}<<2 : // needed since we transfer 32bit over a 64bit AXI bus in this case
cl_offset_q;
// request word address instead of cl address in case of NC access
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:3], 3'b0} : // align to 64bit
{cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:3], 3'b0} : // align to 64bit
{cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
end else begin : gen_piton_offset
// icache fills are either cachelines or 4byte fills, depending on whether they go to the Piton I/O space or not.
// since the piton cache system replicates the data, we can always index the full CL
assign cl_offset_d = (dreq_o.ready & dreq_i.req) ? {dreq_i.vaddr >> 2, 2'b0} : cl_offset_q;
// request word address instead of cl address in case of NC access
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:2], 2'b0} : // align to 32bit
{cl_tag_d, vaddr_q[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
assign mem_data_o.paddr = (paddr_is_nc) ? {cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:2], 2'b0} : // align to 32bit
{cl_tag_d, vaddr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH], {ICACHE_OFFSET_WIDTH{1'b0}}}; // align to cl
end
@ -371,7 +371,7 @@ module cva6_icache
// invalidation/clearing address
// flushing takes precedence over invals
assign vld_addr = (flush_en) ? flush_cnt_q :
(inv_en) ? mem_rtrn_i.inv.idx[ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH] :
(inv_en) ? mem_rtrn_i.inv.idx[CVA6Cfg.ICACHE_INDEX_WIDTH-1:ICACHE_OFFSET_WIDTH] :
cl_index;
assign vld_req = (flush_en || cache_rden) ? '1 :
@ -398,7 +398,7 @@ module cva6_icache
// find invalid cache line
lzc #(
.WIDTH(ICACHE_SET_ASSOC)
.WIDTH(CVA6Cfg.ICACHE_SET_ASSOC)
) i_lzc (
.in_i (~vld_rdata),
.cnt_o (inv_way),
@ -408,7 +408,7 @@ module cva6_icache
// generate random cacheline index
lfsr #(
.LfsrWidth(8),
.OutWidth ($clog2(ariane_pkg::ICACHE_SET_ASSOC))
.OutWidth (CVA6Cfg.ICACHE_SET_ASSOC_WIDTH)
) i_lfsr (
.clk_i (clk_i),
.rst_ni(rst_ni),
@ -421,17 +421,17 @@ module cva6_icache
// tag comparison, hit generation
///////////////////////////////////////////////////////
logic [$clog2(ICACHE_SET_ASSOC)-1:0] hit_idx;
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] hit_idx;
for (genvar i = 0; i < ICACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
for (genvar i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
assign cl_hit[i] = (cl_tag_rdata[i] == cl_tag_d) & vld_rdata[i];
assign cl_sel[i] = cl_rdata[i][{cl_offset_q, 3'b0}+:FETCH_WIDTH];
assign cl_user[i] = cl_ruser[i][{cl_offset_q, 3'b0}+:FETCH_USER_WIDTH];
assign cl_sel[i] = cl_rdata[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
assign cl_user[i] = cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
end
lzc #(
.WIDTH(ICACHE_SET_ASSOC)
.WIDTH(CVA6Cfg.ICACHE_SET_ASSOC)
) i_lzc_hit (
.in_i (cl_hit),
.cnt_o (hit_idx),
@ -443,8 +443,8 @@ module cva6_icache
dreq_o.data = cl_sel[hit_idx];
dreq_o.user = cl_user[hit_idx];
end else begin
dreq_o.data = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:FETCH_WIDTH];
dreq_o.user = mem_rtrn_i.user[{cl_offset_q, 3'b0}+:FETCH_USER_WIDTH];
dreq_o.data = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_WIDTH];
dreq_o.user = mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
end
end
@ -453,13 +453,13 @@ module cva6_icache
///////////////////////////////////////////////////////
logic [ICACHE_TAG_WIDTH:0] cl_tag_valid_rdata[ICACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.ICACHE_TAG_WIDTH:0] cl_tag_valid_rdata[CVA6Cfg.ICACHE_SET_ASSOC-1:0];
for (genvar i = 0; i < ICACHE_SET_ASSOC; i++) begin : gen_sram
for (genvar i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin : gen_sram
// Tag RAM
sram #(
// tag + valid bit
.DATA_WIDTH(ICACHE_TAG_WIDTH + 1),
.DATA_WIDTH(CVA6Cfg.ICACHE_TAG_WIDTH + 1),
.NUM_WORDS (ICACHE_NUM_WORDS)
) tag_sram (
.clk_i (clk_i),
@ -476,14 +476,14 @@ module cva6_icache
.rdata_o(cl_tag_valid_rdata[i])
);
assign cl_tag_rdata[i] = cl_tag_valid_rdata[i][ICACHE_TAG_WIDTH-1:0];
assign vld_rdata[i] = cl_tag_valid_rdata[i][ICACHE_TAG_WIDTH];
assign cl_tag_rdata[i] = cl_tag_valid_rdata[i][CVA6Cfg.ICACHE_TAG_WIDTH-1:0];
assign vld_rdata[i] = cl_tag_valid_rdata[i][CVA6Cfg.ICACHE_TAG_WIDTH];
// Data RAM
sram #(
.USER_WIDTH(ICACHE_USER_LINE_WIDTH),
.DATA_WIDTH(ICACHE_LINE_WIDTH),
.USER_EN (ariane_pkg::FETCH_USER_EN),
.USER_WIDTH(CVA6Cfg.ICACHE_USER_LINE_WIDTH),
.DATA_WIDTH(CVA6Cfg.ICACHE_LINE_WIDTH),
.USER_EN (CVA6Cfg.FETCH_USER_EN),
.NUM_WORDS (ICACHE_NUM_WORDS)
) data_sram (
.clk_i (clk_i),
@ -555,16 +555,16 @@ module cva6_icache
else $fatal(1, "[l1 icache] cl_hit signal must be hot1");
// this is only used for verification!
logic vld_mirror[ICACHE_NUM_WORDS-1:0][ariane_pkg::ICACHE_SET_ASSOC-1:0];
logic [ariane_pkg::ICACHE_TAG_WIDTH-1:0] tag_mirror[ICACHE_NUM_WORDS-1:0][ariane_pkg::ICACHE_SET_ASSOC-1:0];
logic [ariane_pkg::ICACHE_SET_ASSOC-1:0] tag_write_duplicate_test;
logic vld_mirror[ICACHE_NUM_WORDS-1:0][CVA6Cfg.ICACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.ICACHE_TAG_WIDTH-1:0] tag_mirror[ICACHE_NUM_WORDS-1:0][CVA6Cfg.ICACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.ICACHE_SET_ASSOC-1:0] tag_write_duplicate_test;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_mirror
if (!rst_ni) begin
vld_mirror <= '{default: '0};
tag_mirror <= '{default: '0};
end else begin
for (int i = 0; i < ICACHE_SET_ASSOC; i++) begin
for (int i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin
if (vld_req[i] & vld_we) begin
vld_mirror[vld_addr][i] <= vld_wdata[i];
tag_mirror[vld_addr][i] <= cl_tag_q;
@ -573,7 +573,7 @@ module cva6_icache
end
end
for (genvar i = 0; i < ICACHE_SET_ASSOC; i++) begin : gen_tag_dupl
for (genvar i = 0; i < CVA6Cfg.ICACHE_SET_ASSOC; i++) begin : gen_tag_dupl
assign tag_write_duplicate_test[i] = (tag_mirror[vld_addr][i] == cl_tag_q) & vld_mirror[vld_addr][i] & (|vld_wdata);
end
@ -585,7 +585,7 @@ module cva6_icache
initial begin
// assert wrong parameterizations
assert (ICACHE_INDEX_WIDTH <= 12)
assert (CVA6Cfg.ICACHE_INDEX_WIDTH <= 12)
else $fatal(1, "[l1 icache] cache index width can be maximum 12bit since VM uses 4kB pages");
end
`endif

View file

@ -45,8 +45,8 @@ module cva6_icache_axi_wrapper
input axi_rsp_t axi_resp_i
);
localparam AxiNumWords = (ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (ICACHE_LINE_WIDTH > DCACHE_LINE_WIDTH) +
(DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (ICACHE_LINE_WIDTH <= DCACHE_LINE_WIDTH) ;
localparam AxiNumWords = (CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (CVA6Cfg.ICACHE_LINE_WIDTH > CVA6Cfg.DCACHE_LINE_WIDTH) +
(CVA6Cfg.DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (CVA6Cfg.ICACHE_LINE_WIDTH <= CVA6Cfg.DCACHE_LINE_WIDTH) ;
logic icache_mem_rtrn_vld;
icache_rtrn_t icache_mem_rtrn;
@ -71,7 +71,7 @@ module cva6_icache_axi_wrapper
logic req_valid_d, req_valid_q;
icache_req_t req_data_d, req_data_q;
logic first_d, first_q;
logic [ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
logic [CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
rd_shift_d, rd_shift_q;
// Keep read request asserted until we have an AXI grant. This is not guaranteed by icache (but
@ -86,7 +86,7 @@ module cva6_icache_axi_wrapper
assign axi_rd_addr = CVA6Cfg.AxiAddrWidth'(req_data_d.paddr);
// Fetch a full cache line on a cache miss, or a single word on a bypassed access
assign axi_rd_blen = (req_data_d.nc) ? '0 : ariane_pkg::ICACHE_LINE_WIDTH / 64 - 1;
assign axi_rd_blen = (req_data_d.nc) ? '0 : CVA6Cfg.ICACHE_LINE_WIDTH / 64 - 1;
assign axi_rd_size = $clog2(CVA6Cfg.AxiDataWidth / 8); // Maximum
assign axi_rd_id_in = req_data_d.tid;
assign axi_rd_rdy = 1'b1;
@ -183,10 +183,10 @@ module cva6_icache_axi_wrapper
if (axi_rd_valid) begin
first_d = axi_rd_last;
if (ICACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
if (CVA6Cfg.ICACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
rd_shift_d = axi_rd_data;
end else begin
rd_shift_d = {axi_rd_data, rd_shift_q[ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]};
rd_shift_d = {axi_rd_data, rd_shift_q[CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]};
end
// If this is a single word transaction, we need to make sure that word is placed at offset 0

View file

@ -60,11 +60,11 @@ module miss_handler
input amo_req_t amo_req_i,
output amo_resp_t amo_resp_o,
// Port to SRAMs, for refill and eviction
output logic [DCACHE_SET_ASSOC-1:0] req_o,
output logic [DCACHE_INDEX_WIDTH-1:0] addr_o, // address into cache array
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] req_o,
output logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] addr_o, // address into cache array
output cache_line_t data_o,
output cl_be_t be_o,
input cache_line_t [DCACHE_SET_ASSOC-1:0] data_i,
input cache_line_t [CVA6Cfg.DCACHE_SET_ASSOC-1:0] data_i,
output logic we_o
);
@ -72,18 +72,18 @@ module miss_handler
parameter NR_BYPASS_PORTS = NR_PORTS + 1;
// convert one hot to bin for -> needed for cache replacement
function automatic logic [std_cache_pkg::DCACHE_SET_ASSOC_WIDTH-1:0] one_hot_to_bin(
input logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] in);
for (int unsigned i = 0; i < ariane_pkg::DCACHE_SET_ASSOC; i++) begin
function automatic logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] one_hot_to_bin(
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] in);
for (int unsigned i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin
if (in[i]) return i;
end
endfunction
// get the first bit set, returns one hot value
function automatic logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] get_victim_cl(
input logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] valid_dirty);
function automatic logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] get_victim_cl(
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] valid_dirty);
// one-hot return vector
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] oh = '0;
for (int unsigned i = 0; i < ariane_pkg::DCACHE_SET_ASSOC; i++) begin
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] oh = '0;
for (int unsigned i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin
if (valid_dirty[i]) begin
oh[i] = 1'b1;
return oh;
@ -112,61 +112,61 @@ module miss_handler
// Registers
mshr_t mshr_d, mshr_q;
logic [DCACHE_INDEX_WIDTH-1:0] cnt_d, cnt_q;
logic [DCACHE_SET_ASSOC-1:0] evict_way_d, evict_way_q;
logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] cnt_d, cnt_q;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] evict_way_d, evict_way_q;
// cache line to evict
cache_line_t evict_cl_d, evict_cl_q;
logic serve_amo_d, serve_amo_q;
// Request from one FSM
logic [ NR_PORTS-1:0] miss_req_valid;
logic [ NR_PORTS-1:0] miss_req_bypass;
logic [ NR_PORTS-1:0][63:0] miss_req_addr;
logic [ NR_PORTS-1:0][63:0] miss_req_wdata;
logic [ NR_PORTS-1:0] miss_req_we;
logic [ NR_PORTS-1:0][ 7:0] miss_req_be;
logic [ NR_PORTS-1:0][ 1:0] miss_req_size;
logic [ NR_PORTS-1:0] miss_req_valid;
logic [ NR_PORTS-1:0] miss_req_bypass;
logic [ NR_PORTS-1:0][63:0] miss_req_addr;
logic [ NR_PORTS-1:0][63:0] miss_req_wdata;
logic [ NR_PORTS-1:0] miss_req_we;
logic [ NR_PORTS-1:0][ 7:0] miss_req_be;
logic [ NR_PORTS-1:0][ 1:0] miss_req_size;
// Bypass AMO port
bypass_req_t amo_bypass_req;
bypass_rsp_t amo_bypass_rsp;
bypass_req_t amo_bypass_req;
bypass_rsp_t amo_bypass_rsp;
// Bypass ports <-> Arbiter
bypass_req_t [ NR_BYPASS_PORTS-1:0] bypass_ports_req;
bypass_rsp_t [ NR_BYPASS_PORTS-1:0] bypass_ports_rsp;
bypass_req_t [ NR_BYPASS_PORTS-1:0] bypass_ports_req;
bypass_rsp_t [ NR_BYPASS_PORTS-1:0] bypass_ports_rsp;
// Arbiter <-> Bypass AXI adapter
bypass_req_t bypass_adapter_req;
bypass_rsp_t bypass_adapter_rsp;
bypass_req_t bypass_adapter_req;
bypass_rsp_t bypass_adapter_rsp;
// Cache Line Refill <-> AXI
logic req_fsm_miss_valid;
logic [ 63:0] req_fsm_miss_addr;
logic [ DCACHE_LINE_WIDTH-1:0] req_fsm_miss_wdata;
logic req_fsm_miss_we;
logic [ (DCACHE_LINE_WIDTH/8)-1:0] req_fsm_miss_be;
ariane_pkg::ad_req_t req_fsm_miss_req;
logic [ 1:0] req_fsm_miss_size;
logic req_fsm_miss_valid;
logic [ 63:0] req_fsm_miss_addr;
logic [ CVA6Cfg.DCACHE_LINE_WIDTH-1:0] req_fsm_miss_wdata;
logic req_fsm_miss_we;
logic [ (CVA6Cfg.DCACHE_LINE_WIDTH/8)-1:0] req_fsm_miss_be;
ariane_pkg::ad_req_t req_fsm_miss_req;
logic [ 1:0] req_fsm_miss_size;
logic gnt_miss_fsm;
logic valid_miss_fsm;
logic [ (DCACHE_LINE_WIDTH/64)-1:0][63:0] data_miss_fsm;
logic gnt_miss_fsm;
logic valid_miss_fsm;
logic [ (CVA6Cfg.DCACHE_LINE_WIDTH/64)-1:0][63:0] data_miss_fsm;
// Cache Management <-> LFSR
logic lfsr_enable;
logic [ DCACHE_SET_ASSOC-1:0] lfsr_oh;
logic [$clog2(DCACHE_SET_ASSOC-1)-1:0] lfsr_bin;
logic lfsr_enable;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] lfsr_oh;
logic [$clog2(CVA6Cfg.DCACHE_SET_ASSOC-1)-1:0] lfsr_bin;
// AMOs
ariane_pkg::amo_t amo_op;
logic [ 63:0] amo_operand_b;
ariane_pkg::amo_t amo_op;
logic [ 63:0] amo_operand_b;
// ------------------------------
// Cache Management
// ------------------------------
always_comb begin : cache_management
automatic logic [DCACHE_SET_ASSOC-1:0] evict_way, valid_way;
automatic logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] evict_way, valid_way;
for (int unsigned i = 0; i < DCACHE_SET_ASSOC; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin
evict_way[i] = data_i[i].valid & data_i[i].dirty;
valid_way[i] = data_i[i].valid;
end
@ -242,16 +242,16 @@ module miss_handler
for (int unsigned i = 0; i < NR_PORTS; i++) begin
// here comes the refill portion of code
if (miss_req_valid[i] && !miss_req_bypass[i]) begin
state_d = MISS;
state_d = MISS;
// we are taking another request so don't take the AMO
serve_amo_d = 1'b0;
serve_amo_d = 1'b0;
// save to MSHR
mshr_d.valid = 1'b1;
mshr_d.we = miss_req_we[i];
mshr_d.id = i;
mshr_d.addr = miss_req_addr[i][DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:0];
mshr_d.we = miss_req_we[i];
mshr_d.id = i;
mshr_d.addr = miss_req_addr[i][CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
mshr_d.wdata = miss_req_wdata[i];
mshr_d.be = miss_req_be[i];
mshr_d.be = miss_req_be[i];
break;
end
end
@ -262,7 +262,7 @@ module miss_handler
// 1. Check if there is an empty cache-line
// 2. If not -> evict one
req_o = '1;
addr_o = mshr_q.addr[DCACHE_INDEX_WIDTH-1:0];
addr_o = mshr_q.addr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
state_d = MISS_REPL;
miss_o = 1'b1;
end
@ -278,7 +278,7 @@ module miss_handler
state_d = WB_CACHELINE_MISS;
evict_cl_d.tag = data_i[lfsr_bin].tag;
evict_cl_d.data = data_i[lfsr_bin].data;
cnt_d = mshr_q.addr[DCACHE_INDEX_WIDTH-1:0];
cnt_d = mshr_q.addr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
// no - we can request a cache line now
end else state_d = REQ_CACHELINE;
// we have at least one free way
@ -303,18 +303,18 @@ module miss_handler
// ~> replace the cacheline
SAVE_CACHELINE: begin
// calculate cacheline offset
automatic logic [$clog2(DCACHE_LINE_WIDTH)-1:0] cl_offset;
cl_offset = mshr_q.addr[DCACHE_BYTE_OFFSET-1:3] << 6;
automatic logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
cl_offset = mshr_q.addr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3] << 6;
// we've got a valid response from refill unit
if (valid_miss_fsm) begin
addr_o = mshr_q.addr[DCACHE_INDEX_WIDTH-1:0];
req_o = evict_way_q;
we_o = 1'b1;
be_o = '1;
be_o.vldrty = evict_way_q;
data_o.tag = mshr_q.addr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
data_o.data = data_miss_fsm;
addr_o = mshr_q.addr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
req_o = evict_way_q;
we_o = 1'b1;
be_o = '1;
be_o.vldrty = evict_way_q;
data_o.tag = mshr_q.addr[CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
data_o.data = data_miss_fsm;
data_o.valid = 1'b1;
data_o.dirty = 1'b0;
@ -344,8 +344,8 @@ module miss_handler
req_fsm_miss_valid = 1'b1;
req_fsm_miss_addr = {
evict_cl_q.tag,
cnt_q[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET],
{{DCACHE_BYTE_OFFSET} {1'b0}}
cnt_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH],
{{CVA6Cfg.DCACHE_OFFSET_WIDTH} {1'b0}}
};
req_fsm_miss_be = '1;
req_fsm_miss_we = 1'b1;
@ -386,14 +386,14 @@ module miss_handler
// not dirty ~> increment and continue
end else begin
// increment and re-request
cnt_d = cnt_q + (1'b1 << DCACHE_BYTE_OFFSET);
cnt_d = cnt_q + (1'b1 << CVA6Cfg.DCACHE_OFFSET_WIDTH);
state_d = FLUSH_REQ_STATUS;
addr_o = cnt_q;
req_o = 1'b1;
be_o.vldrty = INVALIDATE_ON_FLUSH ? '1 : '0;
we_o = 1'b1;
// finished with flushing operation, go back to idle
if (cnt_q[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET] == DCACHE_NUM_WORDS - 1) begin
if (cnt_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == CVA6Cfg.DCACHE_NUM_WORDS - 1) begin
// only acknowledge if the flush wasn't triggered by an atomic
flush_ack_o = ~serve_amo_q;
// if we are flushing because of an AMO go to serve it
@ -415,9 +415,10 @@ module miss_handler
we_o = 1'b1;
// only write the dirty array
be_o.vldrty = '1;
cnt_d = cnt_q + (1'b1 << DCACHE_BYTE_OFFSET);
cnt_d = cnt_q + (1'b1 << CVA6Cfg.DCACHE_OFFSET_WIDTH);
// finished initialization
if (cnt_q[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET] == DCACHE_NUM_WORDS - 1) state_d = IDLE;
if (cnt_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == CVA6Cfg.DCACHE_NUM_WORDS - 1)
state_d = IDLE;
end
// ----------------------
// AMOs
@ -501,12 +502,12 @@ module miss_handler
for (int i = 0; i < NR_PORTS; i++) begin
// check mshr for potential matching of other units, exclude the unit currently being served
if (mshr_q.valid && mshr_addr_i[i][55:DCACHE_BYTE_OFFSET] == mshr_q.addr[55:DCACHE_BYTE_OFFSET]) begin
if (mshr_q.valid && mshr_addr_i[i][55:CVA6Cfg.DCACHE_OFFSET_WIDTH] == mshr_q.addr[55:CVA6Cfg.DCACHE_OFFSET_WIDTH]) begin
mshr_addr_matches_o[i] = 1'b1;
end
// same as previous, but checking only the index
if (mshr_q.valid && mshr_addr_i[i][DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET] == mshr_q.addr[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET]) begin
if (mshr_q.valid && mshr_addr_i[i][CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == mshr_q.addr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]) begin
mshr_index_matches_o[i] = 1'b1;
end
end
@ -597,7 +598,7 @@ module miss_handler
axi_adapter #(
.CVA6Cfg (CVA6Cfg),
.DATA_WIDTH (64),
.CACHELINE_BYTE_OFFSET(DCACHE_BYTE_OFFSET),
.CACHELINE_BYTE_OFFSET(CVA6Cfg.DCACHE_OFFSET_WIDTH),
.axi_req_t (axi_req_t),
.axi_rsp_t (axi_rsp_t)
) i_bypass_axi_adapter (
@ -631,8 +632,8 @@ module miss_handler
axi_adapter #(
.CVA6Cfg (CVA6Cfg),
.DATA_WIDTH (DCACHE_LINE_WIDTH),
.CACHELINE_BYTE_OFFSET(DCACHE_BYTE_OFFSET),
.DATA_WIDTH (CVA6Cfg.DCACHE_LINE_WIDTH),
.CACHELINE_BYTE_OFFSET(CVA6Cfg.DCACHE_OFFSET_WIDTH),
.axi_req_t (axi_req_t),
.axi_rsp_t (axi_rsp_t)
) i_miss_axi_adapter (
@ -661,7 +662,7 @@ module miss_handler
// Replacement LFSR
// -----------------
lfsr_8bit #(
.WIDTH(DCACHE_SET_ASSOC)
.WIDTH(CVA6Cfg.DCACHE_SET_ASSOC)
) i_lfsr (
.en_i (lfsr_enable),
.refill_way_oh (lfsr_oh),

View file

@ -183,7 +183,8 @@ module std_cache_subsystem
.DATA_WIDTH (2),
// we can have a maximum of 4 oustanding transactions as each port is blocking
.DEPTH (4),
.FALL_THROUGH(1'b1)
.FALL_THROUGH(1'b1),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_fifo_w_channel (
.clk_i (clk_i),
.rst_ni (rst_ni),

View file

@ -46,16 +46,18 @@ module std_nbdcache
import std_cache_pkg::*;
localparam DCACHE_DIRTY_WIDTH = CVA6Cfg.DCACHE_SET_ASSOC * 2;
localparam type cache_line_t = struct packed {
logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] tag; // tag array
logic [ariane_pkg::DCACHE_LINE_WIDTH-1:0] data; // data array
logic valid; // state array
logic dirty; // state array
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag; // tag array
logic [CVA6Cfg.DCACHE_LINE_WIDTH-1:0] data; // data array
logic valid; // state array
logic dirty; // state array
};
localparam type cl_be_t = struct packed {
logic [(ariane_pkg::DCACHE_TAG_WIDTH+7)/8-1:0] tag; // byte enable into tag array
logic [(ariane_pkg::DCACHE_LINE_WIDTH+7)/8-1:0] data; // byte enable into data array
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] vldrty; // bit enable into state array (valid for a pair of dirty/valid bits)
logic [(CVA6Cfg.DCACHE_TAG_WIDTH+7)/8-1:0] tag; // byte enable into tag array
logic [(CVA6Cfg.DCACHE_LINE_WIDTH+7)/8-1:0] data; // byte enable into data array
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] vldrty; // bit enable into state array (valid for a pair of dirty/valid bits)
};
// -------------------------------
@ -66,42 +68,42 @@ module std_nbdcache
// 3. Load Unit
// 4. Accelerator
// 5. Store unit
logic [ NumPorts:0][ DCACHE_SET_ASSOC-1:0] req;
logic [ NumPorts:0][DCACHE_INDEX_WIDTH-1:0] addr;
logic [ NumPorts:0] gnt;
cache_line_t [ DCACHE_SET_ASSOC-1:0] rdata;
logic [ NumPorts:0][ DCACHE_TAG_WIDTH-1:0] tag;
logic [ NumPorts:0][ CVA6Cfg.DCACHE_SET_ASSOC-1:0] req;
logic [ NumPorts:0][CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] addr;
logic [ NumPorts:0] gnt;
cache_line_t [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] rdata;
logic [ NumPorts:0][ CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag;
cache_line_t [ NumPorts:0] wdata;
logic [ NumPorts:0] we;
cl_be_t [ NumPorts:0] be;
logic [ DCACHE_SET_ASSOC-1:0] hit_way;
cache_line_t [ NumPorts:0] wdata;
logic [ NumPorts:0] we;
cl_be_t [ NumPorts:0] be;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] hit_way;
// -------------------------------
// Controller <-> Miss unit
// -------------------------------
logic [ NumPorts-1:0] busy;
logic [ NumPorts-1:0][ 55:0] mshr_addr;
logic [ NumPorts-1:0] mshr_addr_matches;
logic [ NumPorts-1:0] mshr_index_matches;
logic [ 63:0] critical_word;
logic critical_word_valid;
logic [ NumPorts-1:0] busy;
logic [ NumPorts-1:0][ 55:0] mshr_addr;
logic [ NumPorts-1:0] mshr_addr_matches;
logic [ NumPorts-1:0] mshr_index_matches;
logic [ 63:0] critical_word;
logic critical_word_valid;
logic [ NumPorts-1:0][ $bits(miss_req_t)-1:0] miss_req;
logic [ NumPorts-1:0] miss_gnt;
logic [ NumPorts-1:0] active_serving;
logic [ NumPorts-1:0][ $bits(miss_req_t)-1:0] miss_req;
logic [ NumPorts-1:0] miss_gnt;
logic [ NumPorts-1:0] active_serving;
logic [ NumPorts-1:0] bypass_gnt;
logic [ NumPorts-1:0] bypass_valid;
logic [ NumPorts-1:0][ 63:0] bypass_data;
logic [ NumPorts-1:0] bypass_gnt;
logic [ NumPorts-1:0] bypass_valid;
logic [ NumPorts-1:0][ 63:0] bypass_data;
// -------------------------------
// Arbiter <-> Datram,
// -------------------------------
logic [ DCACHE_SET_ASSOC-1:0] req_ram;
logic [DCACHE_INDEX_WIDTH-1:0] addr_ram;
logic we_ram;
cache_line_t wdata_ram;
cache_line_t [ DCACHE_SET_ASSOC-1:0] rdata_ram;
cl_be_t be_ram;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] req_ram;
logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] addr_ram;
logic we_ram;
cache_line_t wdata_ram;
cache_line_t [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] rdata_ram;
cl_be_t be_ram;
// ------------------
// Cache Controller
@ -193,15 +195,15 @@ module std_nbdcache
// --------------
// Memory Arrays
// --------------
for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : sram_block
for (genvar i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin : sram_block
sram #(
.DATA_WIDTH(DCACHE_LINE_WIDTH),
.NUM_WORDS (DCACHE_NUM_WORDS)
.DATA_WIDTH(CVA6Cfg.DCACHE_LINE_WIDTH),
.NUM_WORDS (CVA6Cfg.DCACHE_NUM_WORDS)
) data_sram (
.req_i (req_ram[i]),
.rst_ni (rst_ni),
.we_i (we_ram),
.addr_i (addr_ram[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET]),
.addr_i (addr_ram[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]),
.wuser_i('0),
.wdata_i(wdata_ram.data),
.be_i (be_ram.data),
@ -211,13 +213,13 @@ module std_nbdcache
);
sram #(
.DATA_WIDTH(DCACHE_TAG_WIDTH),
.NUM_WORDS (DCACHE_NUM_WORDS)
.DATA_WIDTH(CVA6Cfg.DCACHE_TAG_WIDTH),
.NUM_WORDS (CVA6Cfg.DCACHE_NUM_WORDS)
) tag_sram (
.req_i (req_ram[i]),
.rst_ni (rst_ni),
.we_i (we_ram),
.addr_i (addr_ram[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET]),
.addr_i (addr_ram[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]),
.wuser_i('0),
.wdata_i(wdata_ram.tag),
.be_i (be_ram.tag),
@ -237,7 +239,7 @@ module std_nbdcache
// you can use it here to save the extra 4x overhead introduced by this workaround.
logic [4*DCACHE_DIRTY_WIDTH-1:0] dirty_wdata, dirty_rdata;
for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin
for (genvar i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin
assign dirty_wdata[8*i] = wdata_ram.dirty;
assign dirty_wdata[8*i+1] = wdata_ram.valid;
assign rdata_ram[i].dirty = dirty_rdata[8*i];
@ -247,13 +249,13 @@ module std_nbdcache
sram #(
.USER_WIDTH(1),
.DATA_WIDTH(4 * DCACHE_DIRTY_WIDTH),
.NUM_WORDS (DCACHE_NUM_WORDS)
.NUM_WORDS (CVA6Cfg.DCACHE_NUM_WORDS)
) valid_dirty_sram (
.clk_i (clk_i),
.rst_ni (rst_ni),
.req_i (|req_ram),
.we_i (we_ram),
.addr_i (addr_ram[DCACHE_INDEX_WIDTH-1:DCACHE_BYTE_OFFSET]),
.addr_i (addr_ram[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]),
.wuser_i('0),
.wdata_i(dirty_wdata),
.be_i (be_ram.vldrty),
@ -265,12 +267,11 @@ module std_nbdcache
// Tag Comparison and memory arbitration
// ------------------------------------------------
tag_cmp #(
.CVA6Cfg (CVA6Cfg),
.NR_PORTS (NumPorts + 1),
.ADDR_WIDTH (DCACHE_INDEX_WIDTH),
.l_data_t (cache_line_t),
.l_be_t (cl_be_t),
.DCACHE_SET_ASSOC(DCACHE_SET_ASSOC)
.CVA6Cfg (CVA6Cfg),
.NR_PORTS (NumPorts + 1),
.ADDR_WIDTH(CVA6Cfg.DCACHE_INDEX_WIDTH),
.l_data_t (cache_line_t),
.l_be_t (cl_be_t)
) i_tag_cmp (
.req_i (req),
.gnt_o (gnt),
@ -294,7 +295,7 @@ module std_nbdcache
//pragma translate_off
initial begin
assert (DCACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth inside {2, 4, 8, 16})
assert (CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth inside {2, 4, 8, 16})
else $fatal(1, "Cache line size needs to be a power of two multiple of AxiDataWidth");
end
//pragma translate_on

View file

@ -16,46 +16,45 @@
// checks for hit or miss on cache
//
module tag_cmp #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter int unsigned NR_PORTS = 3,
parameter int unsigned ADDR_WIDTH = 64,
parameter type l_data_t = logic,
parameter type l_be_t = logic,
parameter int unsigned DCACHE_SET_ASSOC = 8
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter int unsigned NR_PORTS = 3,
parameter int unsigned ADDR_WIDTH = 64,
parameter type l_data_t = logic,
parameter type l_be_t = logic
) (
input logic clk_i,
input logic rst_ni,
input logic [NR_PORTS-1:0][DCACHE_SET_ASSOC-1:0] req_i,
input logic [NR_PORTS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] req_i,
output logic [NR_PORTS-1:0] gnt_o,
input logic [NR_PORTS-1:0][ADDR_WIDTH-1:0] addr_i,
input l_data_t [NR_PORTS-1:0] wdata_i,
input logic [NR_PORTS-1:0] we_i,
input l_be_t [NR_PORTS-1:0] be_i,
output l_data_t [DCACHE_SET_ASSOC-1:0] rdata_o,
input logic [NR_PORTS-1:0][ariane_pkg::DCACHE_TAG_WIDTH-1:0] tag_i, // tag in - comes one cycle later
output logic [DCACHE_SET_ASSOC-1:0] hit_way_o, // we've got a hit on the corresponding way
output l_data_t [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rdata_o,
input logic [NR_PORTS-1:0][CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_i, // tag in - comes one cycle later
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] hit_way_o, // we've got a hit on the corresponding way
output logic [DCACHE_SET_ASSOC-1:0] req_o,
output logic [ ADDR_WIDTH-1:0] addr_o,
output l_data_t wdata_o,
output logic we_o,
output l_be_t be_o,
input l_data_t [DCACHE_SET_ASSOC-1:0] rdata_i
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] req_o,
output logic [ ADDR_WIDTH-1:0] addr_o,
output l_data_t wdata_o,
output logic we_o,
output l_be_t be_o,
input l_data_t [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rdata_i
);
assign rdata_o = rdata_i;
// one hot encoded
logic [NR_PORTS-1:0] id_d, id_q;
logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] sel_tag;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] sel_tag;
always_comb begin : tag_sel
sel_tag = '0;
for (int unsigned i = 0; i < NR_PORTS; i++) if (id_q[i]) sel_tag = tag_i[i];
end
for (genvar j = 0; j < DCACHE_SET_ASSOC; j++) begin : tag_cmp
for (genvar j = 0; j < CVA6Cfg.DCACHE_SET_ASSOC; j++) begin : tag_cmp
assign hit_way_o[j] = (sel_tag == rdata_i[j].tag) ? rdata_i[j].valid : 1'b0;
end

View file

@ -59,11 +59,11 @@ module wt_axi_adapter
);
// support up to 512bit cache lines
localparam AxiNumWords = (ariane_pkg::ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (ariane_pkg::ICACHE_LINE_WIDTH > ariane_pkg::DCACHE_LINE_WIDTH) +
(ariane_pkg::DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (ariane_pkg::ICACHE_LINE_WIDTH <= ariane_pkg::DCACHE_LINE_WIDTH) ;
localparam AxiNumWords = (CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (CVA6Cfg.ICACHE_LINE_WIDTH > CVA6Cfg.DCACHE_LINE_WIDTH) +
(CVA6Cfg.DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth) * (CVA6Cfg.ICACHE_LINE_WIDTH <= CVA6Cfg.DCACHE_LINE_WIDTH) ;
localparam MaxNumWords = $clog2(CVA6Cfg.AxiDataWidth / 8);
localparam AxiRdBlenIcache = ariane_pkg::ICACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
localparam AxiRdBlenDcache = ariane_pkg::DCACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
localparam AxiRdBlenIcache = CVA6Cfg.ICACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
localparam AxiRdBlenDcache = CVA6Cfg.DCACHE_LINE_WIDTH / CVA6Cfg.AxiDataWidth - 1;
///////////////////////////////////////////////////////
// request path
@ -311,8 +311,9 @@ module wt_axi_adapter
end
fifo_v3 #(
.dtype(icache_req_t),
.DEPTH(ReqFifoDepth)
.dtype (icache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FPGA_EN)
) i_icache_data_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -328,8 +329,9 @@ module wt_axi_adapter
);
fifo_v3 #(
.dtype(dcache_req_t),
.DEPTH(ReqFifoDepth)
.dtype (dcache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FPGA_EN)
) i_dcache_data_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -353,7 +355,8 @@ module wt_axi_adapter
fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth)
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_rd_icache_id (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -370,7 +373,8 @@ module wt_axi_adapter
fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth)
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_rd_dcache_id (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -387,7 +391,8 @@ module wt_axi_adapter
fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth)
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_wr_dcache_id (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -417,7 +422,8 @@ module wt_axi_adapter
fifo_v3 #(
.DATA_WIDTH (CVA6Cfg.AxiIdWidth + 1),
.DEPTH (MetaFifoDepth),
.FALL_THROUGH(1'b1)
.FALL_THROUGH(1'b1),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_b_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -434,13 +440,13 @@ module wt_axi_adapter
// buffer read responses in shift regs
logic icache_first_d, icache_first_q, dcache_first_d, dcache_first_q;
logic [ICACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:0][CVA6Cfg.AxiUserWidth-1:0]
logic [CVA6Cfg.ICACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:0][CVA6Cfg.AxiUserWidth-1:0]
icache_rd_shift_user_d, icache_rd_shift_user_q;
logic [DCACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:0][CVA6Cfg.AxiUserWidth-1:0]
logic [CVA6Cfg.DCACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:0][CVA6Cfg.AxiUserWidth-1:0]
dcache_rd_shift_user_d, dcache_rd_shift_user_q;
logic [ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
logic [CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
icache_rd_shift_d, icache_rd_shift_q;
logic [DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
logic [CVA6Cfg.DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:0][CVA6Cfg.AxiDataWidth-1:0]
dcache_rd_shift_d, dcache_rd_shift_q;
wt_cache_pkg::dcache_in_t dcache_rtrn_type_d, dcache_rtrn_type_q;
dcache_inval_t dcache_rtrn_inv_d, dcache_rtrn_inv_q;
@ -473,15 +479,15 @@ module wt_axi_adapter
if (icache_rtrn_rd_en) begin
icache_first_d = axi_rd_last;
if (ICACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
if (CVA6Cfg.ICACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
icache_rd_shift_d[0] = axi_rd_data;
end else begin
icache_rd_shift_d = {
axi_rd_data, icache_rd_shift_q[ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]
axi_rd_data, icache_rd_shift_q[CVA6Cfg.ICACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]
};
end
icache_rd_shift_user_d = {
axi_rd_user, icache_rd_shift_user_q[ICACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:1]
axi_rd_user, icache_rd_shift_user_q[CVA6Cfg.ICACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:1]
};
// if this is a single word transaction, we need to make sure that word is placed at offset 0
if (icache_first_q) begin
@ -492,15 +498,15 @@ module wt_axi_adapter
if (dcache_rtrn_rd_en) begin
dcache_first_d = axi_rd_last;
if (DCACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
if (CVA6Cfg.DCACHE_LINE_WIDTH == CVA6Cfg.AxiDataWidth) begin
dcache_rd_shift_d[0] = axi_rd_data;
end else begin
dcache_rd_shift_d = {
axi_rd_data, dcache_rd_shift_q[DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]
axi_rd_data, dcache_rd_shift_q[CVA6Cfg.DCACHE_LINE_WIDTH/CVA6Cfg.AxiDataWidth-1:1]
};
end
dcache_rd_shift_user_d = {
axi_rd_user, dcache_rd_shift_user_q[DCACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:1]
axi_rd_user, dcache_rd_shift_user_q[CVA6Cfg.DCACHE_USER_LINE_WIDTH/CVA6Cfg.AxiUserWidth-1:1]
};
// if this is a single word transaction, we need to make sure that word is placed at offset 0
if (dcache_first_q) begin
@ -549,7 +555,7 @@ module wt_axi_adapter
dcache_rtrn_type_d = wt_cache_pkg::DCACHE_INV_REQ;
dcache_rtrn_vld_d = 1'b1;
dcache_rtrn_inv_d.all = 1'b1;
dcache_rtrn_inv_d.idx = inval_addr_i[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
dcache_rtrn_inv_d.idx = inval_addr_i[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
//////////////////////////////////////
// dcache needs some special treatment
// for arbitration and decoding of atomics
@ -563,7 +569,7 @@ module wt_axi_adapter
dcache_rtrn_vld_d = 1'b1;
dcache_rtrn_inv_d.all = 1'b1;
dcache_rtrn_inv_d.idx = dcache_data.paddr[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
dcache_rtrn_inv_d.idx = dcache_data.paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
//////////////////////////////////////
// read responses
// note that in case of atomics, the dcache sequentializes requests and

View file

@ -55,7 +55,7 @@ module wt_cache_subsystem
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
// For Performance Counter
output logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits_o,
output logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits_o,
// AMO interface
input amo_req_t dcache_amo_req_i,
output amo_resp_t dcache_amo_resp_o,
@ -79,17 +79,17 @@ module wt_cache_subsystem
localparam type dcache_inval_t = struct packed {
logic vld; // invalidate only affected way
logic all; // invalidate all ways
logic [ariane_pkg::DCACHE_INDEX_WIDTH-1:0] idx; // physical address to invalidate
logic [L15_WAY_WIDTH-1:0] way; // way to invalidate
logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] idx; // physical address to invalidate
logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] way; // way to invalidate
};
localparam type dcache_req_t = struct packed {
wt_cache_pkg::dcache_out_t rtype; // see definitions above
logic [2:0] size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
logic [L1D_WAY_WIDTH-1:0] way; // way to replace
logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] way; // way to replace
logic [riscv::PLEN-1:0] paddr; // physical address
logic [riscv::XLEN-1:0] data; // word width of processor (no block stores at the moment)
logic [ariane_pkg::DATA_USER_WIDTH-1:0] user; // user width of processor (no block stores at the moment)
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] user; // user width of processor (no block stores at the moment)
logic nc; // noncacheable
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] tid; // threadi id (used as transaction id in Ariane)
ariane_pkg::amo_t amo_op; // amo opcode
@ -97,8 +97,8 @@ module wt_cache_subsystem
localparam type dcache_rtrn_t = struct packed {
wt_cache_pkg::dcache_in_t rtype; // see definitions above
logic [ariane_pkg::DCACHE_LINE_WIDTH-1:0] data; // full cache line width
logic [ariane_pkg::DCACHE_USER_LINE_WIDTH-1:0] user; // user bits
logic [CVA6Cfg.DCACHE_LINE_WIDTH-1:0] data; // full cache line width
logic [CVA6Cfg.DCACHE_USER_LINE_WIDTH-1:0] user; // user bits
dcache_inval_t inv; // invalidation vector
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] tid; // threadi id (used as transaction id in Ariane)
};

View file

@ -46,7 +46,7 @@ module wt_dcache
input dcache_req_i_t [NumPorts-1:0] req_ports_i,
output dcache_req_o_t [NumPorts-1:0] req_ports_o,
output logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits_o,
output logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits_o,
input logic mem_rtrn_vld_i,
input dcache_rtrn_t mem_rtrn_i,
@ -55,72 +55,74 @@ module wt_dcache
output dcache_req_t mem_data_o
);
localparam DCACHE_CL_IDX_WIDTH = $clog2(CVA6Cfg.DCACHE_NUM_WORDS);
localparam type wbuffer_t = struct packed {
logic [ariane_pkg::DCACHE_TAG_WIDTH+(ariane_pkg::DCACHE_INDEX_WIDTH-riscv::XLEN_ALIGN_BYTES)-1:0] wtag;
logic [CVA6Cfg.DCACHE_TAG_WIDTH+(CVA6Cfg.DCACHE_INDEX_WIDTH-CVA6Cfg.XLEN_ALIGN_BYTES)-1:0] wtag;
logic [riscv::XLEN-1:0] data;
logic [ariane_pkg::DCACHE_USER_WIDTH-1:0] user;
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] user;
logic [(riscv::XLEN/8)-1:0] dirty; // byte is dirty
logic [(riscv::XLEN/8)-1:0] valid; // byte is valid
logic [(riscv::XLEN/8)-1:0] txblock; // byte is part of transaction in-flight
logic checked; // if cache state of this word has been checked
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] hit_oh; // valid way in the cache
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] hit_oh; // valid way in the cache
};
// miss unit <-> read controllers
logic cache_en;
logic cache_en;
// miss unit <-> memory
logic wr_cl_vld;
logic wr_cl_nc;
logic [ DCACHE_SET_ASSOC-1:0] wr_cl_we;
logic [ DCACHE_TAG_WIDTH-1:0] wr_cl_tag;
logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx;
logic [ DCACHE_OFFSET_WIDTH-1:0] wr_cl_off;
logic [ DCACHE_LINE_WIDTH-1:0] wr_cl_data;
logic [DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user;
logic [ DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be;
logic [ DCACHE_SET_ASSOC-1:0] wr_vld_bits;
logic [ DCACHE_SET_ASSOC-1:0] wr_req;
logic wr_ack;
logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_idx;
logic [ DCACHE_OFFSET_WIDTH-1:0] wr_off;
logic [ riscv::XLEN-1:0] wr_data;
logic [ (riscv::XLEN/8)-1:0] wr_data_be;
logic [ DCACHE_USER_WIDTH-1:0] wr_user;
logic wr_cl_vld;
logic wr_cl_nc;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_cl_we;
logic [ CVA6Cfg.DCACHE_TAG_WIDTH-1:0] wr_cl_tag;
logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx;
logic [ CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_cl_off;
logic [ CVA6Cfg.DCACHE_LINE_WIDTH-1:0] wr_cl_data;
logic [CVA6Cfg.DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user;
logic [ CVA6Cfg.DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_vld_bits;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_req;
logic wr_ack;
logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_idx;
logic [ CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_off;
logic [ riscv::XLEN-1:0] wr_data;
logic [ (riscv::XLEN/8)-1:0] wr_data_be;
logic [ CVA6Cfg.DCACHE_USER_WIDTH-1:0] wr_user;
// miss unit <-> controllers/wbuffer
logic [ NumPorts-1:0] miss_req;
logic [ NumPorts-1:0] miss_ack;
logic [ NumPorts-1:0] miss_nc;
logic [ NumPorts-1:0] miss_we;
logic [ NumPorts-1:0][ riscv::XLEN-1:0] miss_wdata;
logic [ NumPorts-1:0][ DCACHE_USER_WIDTH-1:0] miss_wuser;
logic [ NumPorts-1:0][ riscv::PLEN-1:0] miss_paddr;
logic [ NumPorts-1:0][ 2:0] miss_size;
logic [ NumPorts-1:0][CVA6Cfg.MEM_TID_WIDTH-1:0] miss_id;
logic [ NumPorts-1:0] miss_replay;
logic [ NumPorts-1:0] miss_rtrn_vld;
logic [ CVA6Cfg.MEM_TID_WIDTH-1:0] miss_rtrn_id;
logic [ NumPorts-1:0] miss_req;
logic [ NumPorts-1:0] miss_ack;
logic [ NumPorts-1:0] miss_nc;
logic [ NumPorts-1:0] miss_we;
logic [ NumPorts-1:0][ riscv::XLEN-1:0] miss_wdata;
logic [ NumPorts-1:0][ CVA6Cfg.DCACHE_USER_WIDTH-1:0] miss_wuser;
logic [ NumPorts-1:0][ riscv::PLEN-1:0] miss_paddr;
logic [ NumPorts-1:0][ 2:0] miss_size;
logic [ NumPorts-1:0][ CVA6Cfg.MEM_TID_WIDTH-1:0] miss_id;
logic [ NumPorts-1:0] miss_replay;
logic [ NumPorts-1:0] miss_rtrn_vld;
logic [ CVA6Cfg.MEM_TID_WIDTH-1:0] miss_rtrn_id;
// memory <-> read controllers/miss unit
logic [ NumPorts-1:0] rd_prio;
logic [ NumPorts-1:0] rd_tag_only;
logic [ NumPorts-1:0] rd_req;
logic [ NumPorts-1:0] rd_ack;
logic [ NumPorts-1:0][ DCACHE_TAG_WIDTH-1:0] rd_tag;
logic [ NumPorts-1:0][ DCACHE_CL_IDX_WIDTH-1:0] rd_idx;
logic [ NumPorts-1:0][ DCACHE_OFFSET_WIDTH-1:0] rd_off;
logic [ riscv::XLEN-1:0] rd_data;
logic [ DCACHE_USER_WIDTH-1:0] rd_user;
logic [ DCACHE_SET_ASSOC-1:0] rd_vld_bits;
logic [ DCACHE_SET_ASSOC-1:0] rd_hit_oh;
logic [ NumPorts-1:0] rd_prio;
logic [ NumPorts-1:0] rd_tag_only;
logic [ NumPorts-1:0] rd_req;
logic [ NumPorts-1:0] rd_ack;
logic [ NumPorts-1:0][ CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag;
logic [ NumPorts-1:0][ DCACHE_CL_IDX_WIDTH-1:0] rd_idx;
logic [ NumPorts-1:0][CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] rd_off;
logic [ riscv::XLEN-1:0] rd_data;
logic [ CVA6Cfg.DCACHE_USER_WIDTH-1:0] rd_user;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_vld_bits;
logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_hit_oh;
// miss unit <-> wbuffer
logic [ CVA6Cfg.DCACHE_MAX_TX-1:0][ riscv::PLEN-1:0] tx_paddr;
logic [ CVA6Cfg.DCACHE_MAX_TX-1:0] tx_vld;
logic [ CVA6Cfg.DCACHE_MAX_TX-1:0][ riscv::PLEN-1:0] tx_paddr;
logic [ CVA6Cfg.DCACHE_MAX_TX-1:0] tx_vld;
// wbuffer <-> memory
wbuffer_t [ DCACHE_WBUF_DEPTH-1:0] wbuffer_data;
wbuffer_t [ DCACHE_WBUF_DEPTH-1:0] wbuffer_data;
///////////////////////////////////////////////////////
@ -129,6 +131,7 @@ module wt_dcache
wt_dcache_missunit #(
.CVA6Cfg(CVA6Cfg),
.DCACHE_CL_IDX_WIDTH(DCACHE_CL_IDX_WIDTH),
.dcache_req_t(dcache_req_t),
.dcache_rtrn_t(dcache_rtrn_t),
.AmoTxId(RdAmoTxId),
@ -192,6 +195,7 @@ module wt_dcache
assign rd_prio[k] = 1'b1;
wt_dcache_ctrl #(
.CVA6Cfg(CVA6Cfg),
.DCACHE_CL_IDX_WIDTH(DCACHE_CL_IDX_WIDTH),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.RdTxId(RdAmoTxId)
@ -235,15 +239,15 @@ module wt_dcache
assign miss_req[k] = 1'b0;
assign miss_we[k] = 1'b0;
assign miss_wdata[k] = {{riscv::XLEN} {1'b0}};
assign miss_wuser[k] = {{DCACHE_USER_WIDTH} {1'b0}};
assign miss_vld_bits_o[k] = {{DCACHE_SET_ASSOC} {1'b0}};
assign miss_wuser[k] = {{CVA6Cfg.DCACHE_USER_WIDTH} {1'b0}};
assign miss_vld_bits_o[k] = {{CVA6Cfg.DCACHE_SET_ASSOC} {1'b0}};
assign miss_paddr[k] = {{riscv::PLEN} {1'b0}};
assign miss_nc[k] = 1'b0;
assign miss_size[k] = 3'b0;
assign miss_id[k] = {{CVA6Cfg.MEM_TID_WIDTH} {1'b0}};
assign rd_tag[k] = {{DCACHE_TAG_WIDTH} {1'b0}};
assign rd_tag[k] = {{CVA6Cfg.DCACHE_TAG_WIDTH} {1'b0}};
assign rd_idx[k] = {{DCACHE_CL_IDX_WIDTH} {1'b0}};
assign rd_off[k] = {{DCACHE_OFFSET_WIDTH} {1'b0}};
assign rd_off[k] = {{CVA6Cfg.DCACHE_OFFSET_WIDTH} {1'b0}};
assign rd_req[k] = 1'b0;
assign rd_tag_only[k] = 1'b0;
end
@ -258,6 +262,7 @@ module wt_dcache
wt_dcache_wbuffer #(
.CVA6Cfg(CVA6Cfg),
.DCACHE_CL_IDX_WIDTH(DCACHE_CL_IDX_WIDTH),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.wbuffer_t(wbuffer_t)
@ -317,9 +322,10 @@ module wt_dcache
///////////////////////////////////////////////////////
wt_dcache_mem #(
.CVA6Cfg (CVA6Cfg),
.CVA6Cfg(CVA6Cfg),
.DCACHE_CL_IDX_WIDTH(DCACHE_CL_IDX_WIDTH),
.wbuffer_t(wbuffer_t),
.NumPorts (NumPorts)
.NumPorts(NumPorts)
) i_wt_dcache_mem (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -374,7 +380,7 @@ module wt_dcache
initial begin
// assert wrong parameterizations
assert (DCACHE_INDEX_WIDTH <= 12)
assert (CVA6Cfg.DCACHE_INDEX_WIDTH <= 12)
else $fatal(1, "[l1 dcache] cache index width can be maximum 12bit since VM uses 4kB pages");
end
`endif

View file

@ -18,6 +18,7 @@ module wt_dcache_ctrl
import wt_cache_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter DCACHE_CL_IDX_WIDTH = 0,
parameter type dcache_req_i_t = logic,
parameter type dcache_req_o_t = logic,
parameter logic [CVA6Cfg.MEM_TID_WIDTH-1:0] RdTxId = 1
@ -33,8 +34,8 @@ module wt_dcache_ctrl
input logic miss_ack_i,
output logic miss_we_o, // unused (set to 0)
output logic [riscv::XLEN-1:0] miss_wdata_o, // unused (set to 0)
output logic [DCACHE_USER_WIDTH-1:0] miss_wuser_o, // unused (set to 0)
output logic [DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // valid bits at the missed index
output logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] miss_wuser_o, // unused (set to 0)
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // valid bits at the missed index
output logic [riscv::PLEN-1:0] miss_paddr_o,
output logic miss_nc_o, // request to I/O space
output logic [2:0] miss_size_o, // 00: 1byte, 01: 2byte, 10: 4byte, 11: 8byte, 111: cacheline
@ -44,16 +45,16 @@ module wt_dcache_ctrl
// used to detect readout mux collisions
input logic wr_cl_vld_i,
// cache memory interface
output logic [DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
output logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
output logic [DCACHE_CL_IDX_WIDTH-1:0] rd_idx_o,
output logic [DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
output logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
output logic rd_req_o, // read the word at offset off_i[:3] in all ways
output logic rd_tag_only_o, // set to zero here
input logic rd_ack_i,
input logic [riscv::XLEN-1:0] rd_data_i,
input logic [DCACHE_USER_WIDTH-1:0] rd_user_i,
input logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_i,
input logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_i
input logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] rd_user_i,
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_vld_bits_i,
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_hit_oh_i
);
// controller FSM
@ -69,11 +70,11 @@ module wt_dcache_ctrl
} state_e;
state_e state_d, state_q;
logic [DCACHE_TAG_WIDTH-1:0] address_tag_d, address_tag_q;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] address_tag_d, address_tag_q;
logic [DCACHE_CL_IDX_WIDTH-1:0] address_idx_d, address_idx_q;
logic [DCACHE_OFFSET_WIDTH-1:0] address_off_d, address_off_q;
logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] address_off_d, address_off_q;
logic [DCACHE_TID_WIDTH-1:0] id_d, id_q;
logic [DCACHE_SET_ASSOC-1:0] vld_data_d, vld_data_q;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] vld_data_d, vld_data_q;
logic save_tag, rd_req_d, rd_req_q, rd_ack_d, rd_ack_q;
logic [1:0] data_size_d, data_size_q;
@ -84,8 +85,8 @@ module wt_dcache_ctrl
// map address to tag/idx/offset and save
assign vld_data_d = (rd_req_q) ? rd_vld_bits_i : vld_data_q;
assign address_tag_d = (save_tag) ? req_port_i.address_tag : address_tag_q;
assign address_idx_d = (req_port_o.data_gnt) ? req_port_i.address_index[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH] : address_idx_q;
assign address_off_d = (req_port_o.data_gnt) ? req_port_i.address_index[DCACHE_OFFSET_WIDTH-1:0] : address_off_q;
assign address_idx_d = (req_port_o.data_gnt) ? req_port_i.address_index[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] : address_idx_q;
assign address_off_d = (req_port_o.data_gnt) ? req_port_i.address_index[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] : address_off_q;
assign id_d = (req_port_o.data_gnt) ? req_port_i.data_id : id_q;
assign data_size_d = (req_port_o.data_gnt) ? req_port_i.data_size : data_size_q;
assign rd_tag_o = address_tag_d;
@ -104,7 +105,7 @@ module wt_dcache_ctrl
// noncacheable if request goes to I/O space, or if cache is disabled
assign miss_nc_o = (~cache_en_i) | (~config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{{{64-DCACHE_TAG_WIDTH-DCACHE_INDEX_WIDTH}{1'b0}}, address_tag_q, {DCACHE_INDEX_WIDTH{1'b0}}}
{{{64-CVA6Cfg.DCACHE_TAG_WIDTH-CVA6Cfg.DCACHE_INDEX_WIDTH}{1'b0}}, address_tag_q, {CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}}
));
@ -291,7 +292,7 @@ module wt_dcache_ctrl
initial begin
// assert wrong parameterizations
assert (DCACHE_INDEX_WIDTH <= 12)
assert (CVA6Cfg.DCACHE_INDEX_WIDTH <= 12)
else
$fatal(1, "[l1 dcache ctrl] cache index width can be maximum 12bit since VM uses 4kB pages");
end

View file

@ -30,52 +30,53 @@ module wt_dcache_mem
import ariane_pkg::*;
import wt_cache_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type wbuffer_t = logic,
parameter int unsigned NumPorts = 3
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter DCACHE_CL_IDX_WIDTH = 0,
parameter type wbuffer_t = logic,
parameter int unsigned NumPorts = 3
) (
input logic clk_i,
input logic rst_ni,
// ports
input logic [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0] rd_tag_i, // tag in - comes one cycle later
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag_i, // tag in - comes one cycle later
input logic [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0] rd_idx_i,
input logic [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0] rd_off_i,
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] rd_off_i,
input logic [NumPorts-1:0] rd_req_i, // read the word at offset off_i[:3] in all ways
input logic [NumPorts-1:0] rd_tag_only_i, // only do a tag/valid lookup, no access to data arrays
input logic [NumPorts-1:0] rd_prio_i, // 0: low prio, 1: high prio
output logic [NumPorts-1:0] rd_ack_o,
output logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_o,
output logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_vld_bits_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_hit_oh_o,
output logic [riscv::XLEN-1:0] rd_data_o,
output logic [DCACHE_USER_WIDTH-1:0] rd_user_o,
output logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] rd_user_o,
// only available on port 0, uses address signals of port 0
input logic wr_cl_vld_i,
input logic wr_cl_nc_i, // noncacheable access
input logic [ DCACHE_SET_ASSOC-1:0] wr_cl_we_i, // writes a full cacheline
input logic [ DCACHE_TAG_WIDTH-1:0] wr_cl_tag_i,
input logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx_i,
input logic [ DCACHE_OFFSET_WIDTH-1:0] wr_cl_off_i,
input logic [ DCACHE_LINE_WIDTH-1:0] wr_cl_data_i,
input logic [DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user_i,
input logic [ DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be_i,
input logic [ DCACHE_SET_ASSOC-1:0] wr_vld_bits_i,
input logic wr_cl_vld_i,
input logic wr_cl_nc_i, // noncacheable access
input logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_cl_we_i, // writes a full cacheline
input logic [ CVA6Cfg.DCACHE_TAG_WIDTH-1:0] wr_cl_tag_i,
input logic [ DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx_i,
input logic [ CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_cl_off_i,
input logic [ CVA6Cfg.DCACHE_LINE_WIDTH-1:0] wr_cl_data_i,
input logic [CVA6Cfg.DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user_i,
input logic [ CVA6Cfg.DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be_i,
input logic [ CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_vld_bits_i,
// separate port for single word write, no tag access
input logic [DCACHE_SET_ASSOC-1:0] wr_req_i, // write a single word to offset off_i[:3]
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_req_i, // write a single word to offset off_i[:3]
output logic wr_ack_o,
input logic [DCACHE_CL_IDX_WIDTH-1:0] wr_idx_i,
input logic [DCACHE_OFFSET_WIDTH-1:0] wr_off_i,
input logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_off_i,
input logic [riscv::XLEN-1:0] wr_data_i,
input logic [DCACHE_USER_WIDTH-1:0] wr_user_i,
input logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] wr_user_i,
input logic [(riscv::XLEN/8)-1:0] wr_data_be_i,
// forwarded wbuffer
input wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data_i
);
localparam DCACHE_NUM_BANKS = ariane_pkg::DCACHE_LINE_WIDTH / riscv::XLEN;
localparam DCACHE_NUM_BANKS = CVA6Cfg.DCACHE_LINE_WIDTH / riscv::XLEN;
localparam DCACHE_NUM_BANKS_WIDTH = $clog2(DCACHE_NUM_BANKS);
// functions
@ -95,25 +96,25 @@ module wt_dcache_mem
CVA6Cfg.AxiDataWidth / 8
);
logic [DCACHE_NUM_BANKS-1:0] bank_req;
logic [DCACHE_NUM_BANKS-1:0] bank_we;
logic [DCACHE_NUM_BANKS-1:0][ DCACHE_SET_ASSOC-1:0][(riscv::XLEN/8)-1:0] bank_be;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_CL_IDX_WIDTH-1:0] bank_idx;
logic [DCACHE_NUM_BANKS-1:0] bank_req;
logic [DCACHE_NUM_BANKS-1:0] bank_we;
logic [DCACHE_NUM_BANKS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0][(riscv::XLEN/8)-1:0] bank_be;
logic [DCACHE_NUM_BANKS-1:0][ DCACHE_CL_IDX_WIDTH-1:0] bank_idx;
logic [DCACHE_CL_IDX_WIDTH-1:0] bank_idx_d, bank_idx_q;
logic [DCACHE_OFFSET_WIDTH-1:0] bank_off_d, bank_off_q;
logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] bank_off_d, bank_off_q;
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_wdata; //
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_rdata; //
logic [DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] rdata_cl; // selected word from each cacheline
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][DCACHE_USER_WIDTH-1:0] bank_wuser; //
logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][DCACHE_USER_WIDTH-1:0] bank_ruser; //
logic [DCACHE_SET_ASSOC-1:0][DCACHE_USER_WIDTH-1:0] ruser_cl; // selected word from each cacheline
logic [DCACHE_NUM_BANKS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_wdata; //
logic [DCACHE_NUM_BANKS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] bank_rdata; //
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0][riscv::XLEN-1:0] rdata_cl; // selected word from each cacheline
logic [DCACHE_NUM_BANKS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0][CVA6Cfg.DCACHE_USER_WIDTH-1:0] bank_wuser; //
logic [DCACHE_NUM_BANKS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0][CVA6Cfg.DCACHE_USER_WIDTH-1:0] bank_ruser; //
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0][CVA6Cfg.DCACHE_USER_WIDTH-1:0] ruser_cl; // selected word from each cacheline
logic [DCACHE_TAG_WIDTH-1:0] rd_tag;
logic [DCACHE_SET_ASSOC-1:0] vld_req; // bit enable for valid regs
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] vld_req; // bit enable for valid regs
logic vld_we; // valid bits write enable
logic [DCACHE_SET_ASSOC-1:0] vld_wdata; // valid bits to write
logic [DCACHE_SET_ASSOC-1:0][DCACHE_TAG_WIDTH-1:0] tag_rdata; // these are the tags coming from the tagmem
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] vld_wdata; // valid bits to write
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0][CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_rdata; // these are the tags coming from the tagmem
logic [DCACHE_CL_IDX_WIDTH-1:0] vld_addr; // valid bit
logic [$clog2(NumPorts)-1:0] vld_sel_d, vld_sel_q;
@ -121,7 +122,7 @@ module wt_dcache_mem
logic [DCACHE_WBUF_DEPTH-1:0] wbuffer_hit_oh;
logic [ (riscv::XLEN/8)-1:0] wbuffer_be;
logic [riscv::XLEN-1:0] wbuffer_rdata, rdata;
logic [DCACHE_USER_WIDTH-1:0] wbuffer_ruser, ruser;
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] wbuffer_ruser, ruser;
logic [riscv::PLEN-1:0] wbuffer_cmp_addr;
logic cmp_en_d, cmp_en_q;
@ -141,13 +142,13 @@ module wt_dcache_mem
// byte enable mapping
for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_bank
for (genvar j = 0; j < DCACHE_SET_ASSOC; j++) begin : gen_bank_way
for (genvar j = 0; j < CVA6Cfg.DCACHE_SET_ASSOC; j++) begin : gen_bank_way
assign bank_be[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_be_i[k*(riscv::XLEN/8) +: (riscv::XLEN/8)] :
(wr_req_i[j] & wr_ack_o) ? wr_data_be_i :
'0;
assign bank_wdata[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_data_i[k*riscv::XLEN +: riscv::XLEN] :
wr_data_i;
assign bank_wuser[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_user_i[k*DCACHE_USER_WIDTH +: DCACHE_USER_WIDTH] :
assign bank_wuser[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ? wr_cl_user_i[k*CVA6Cfg.DCACHE_USER_WIDTH +: CVA6Cfg.DCACHE_USER_WIDTH] :
wr_user_i;
end
end
@ -193,7 +194,7 @@ module wt_dcache_mem
bank_idx = '{default: wr_idx_i};
for (int k = 0; k < NumPorts; k++) begin
bank_collision[k] = rd_off_i[k][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES] == wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
bank_collision[k] = rd_off_i[k][CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES] == wr_off_i[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES];
end
if (wr_cl_vld_i & |wr_cl_we_i) begin
@ -203,17 +204,20 @@ module wt_dcache_mem
end else begin
if (rd_acked) begin
if (!rd_tag_only_i[vld_sel_d]) begin
bank_req =
dcache_cl_bin2oh(rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
bank_idx[rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]] = rd_idx_i[vld_sel_d];
bank_req = dcache_cl_bin2oh(
rd_off_i[vld_sel_d][CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]);
bank_idx[rd_off_i[vld_sel_d][CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]] = rd_idx_i[vld_sel_d];
end
end
if (|wr_req_i) begin
if (rd_tag_only_i[vld_sel_d] || !(rd_ack_o[vld_sel_d] && bank_collision[vld_sel_d])) begin
wr_ack_o = 1'b1;
bank_req |= dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
bank_we = dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]);
bank_req |= dcache_cl_bin2oh(
wr_off_i[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]
);
bank_we =
dcache_cl_bin2oh(wr_off_i[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]);
end
end
end
@ -223,10 +227,10 @@ module wt_dcache_mem
// tag comparison, hit generatio, readoud muxes
///////////////////////////////////////////////////////
logic [DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES-1:0] wr_cl_off;
logic [DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES-1:0] wr_cl_nc_off;
logic [ $clog2(DCACHE_WBUF_DEPTH)-1:0] wbuffer_hit_idx;
logic [ $clog2(DCACHE_SET_ASSOC)-1:0] rd_hit_idx;
logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-CVA6Cfg.XLEN_ALIGN_BYTES-1:0] wr_cl_off;
logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-CVA6Cfg.XLEN_ALIGN_BYTES-1:0] wr_cl_nc_off;
logic [ $clog2(DCACHE_WBUF_DEPTH)-1:0] wbuffer_hit_idx;
logic [ $clog2(CVA6Cfg.DCACHE_SET_ASSOC)-1:0] rd_hit_idx;
assign cmp_en_d = (|vld_req) & ~vld_we;
@ -234,16 +238,16 @@ module wt_dcache_mem
assign wbuffer_cmp_addr = (wr_cl_vld_i) ? {wr_cl_tag_i, wr_cl_idx_i, wr_cl_off_i} :
{rd_tag, bank_idx_q, bank_off_q};
// hit generation
for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
for (genvar i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin : gen_tag_cmpsel
// tag comparison of ways >0
assign rd_hit_oh_o[i] = (rd_tag == tag_rdata[i]) & rd_vld_bits_o[i] & cmp_en_q;
// byte offset mux of ways >0
assign rdata_cl[i] = bank_rdata[bank_off_q[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]][i];
assign ruser_cl[i] = bank_ruser[bank_off_q[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]][i];
assign rdata_cl[i] = bank_rdata[bank_off_q[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]][i];
assign ruser_cl[i] = bank_ruser[bank_off_q[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]][i];
end
for (genvar k = 0; k < DCACHE_WBUF_DEPTH; k++) begin : gen_wbuffer_hit
assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & ({{riscv::XLEN_ALIGN_BYTES{1'b0}}, wbuffer_data_i[k].wtag} == (wbuffer_cmp_addr >> riscv::XLEN_ALIGN_BYTES));
assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & ({{CVA6Cfg.XLEN_ALIGN_BYTES{1'b0}}, wbuffer_data_i[k].wtag} == (wbuffer_cmp_addr >> CVA6Cfg.XLEN_ALIGN_BYTES));
end
lzc #(
@ -255,7 +259,7 @@ module wt_dcache_mem
);
lzc #(
.WIDTH(DCACHE_SET_ASSOC)
.WIDTH(CVA6Cfg.DCACHE_SET_ASSOC)
) i_lzc_rd_hit (
.in_i (rd_hit_oh_o),
.cnt_o (rd_hit_idx),
@ -269,16 +273,16 @@ module wt_dcache_mem
if (CVA6Cfg.NOCType == config_pkg::NOC_TYPE_AXI4_ATOP) begin : gen_axi_offset
// In case of an uncached read, return the desired XLEN-bit segment of the most recent AXI read
assign wr_cl_off = (wr_cl_nc_i) ? (CVA6Cfg.AxiDataWidth == riscv::XLEN) ? '0 :
{{DCACHE_OFFSET_WIDTH-AXI_OFFSET_WIDTH{1'b0}}, wr_cl_off_i[AXI_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES]} :
wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:riscv::XLEN_ALIGN_BYTES];
{{CVA6Cfg.DCACHE_OFFSET_WIDTH-AXI_OFFSET_WIDTH{1'b0}}, wr_cl_off_i[AXI_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]} :
wr_cl_off_i[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES];
end else begin : gen_piton_offset
assign wr_cl_off = wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
assign wr_cl_off = wr_cl_off_i[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3];
end
always_comb begin
if (wr_cl_vld_i) begin
rdata = wr_cl_data_i[wr_cl_off*riscv::XLEN+:riscv::XLEN];
ruser = wr_cl_user_i[wr_cl_off*DCACHE_USER_WIDTH+:DCACHE_USER_WIDTH];
ruser = wr_cl_user_i[wr_cl_off*CVA6Cfg.DCACHE_USER_WIDTH+:CVA6Cfg.DCACHE_USER_WIDTH];
end else begin
rdata = rdata_cl[rd_hit_idx];
ruser = ruser_cl[rd_hit_idx];
@ -289,7 +293,7 @@ module wt_dcache_mem
for (genvar k = 0; k < (riscv::XLEN / 8); k++) begin : gen_rd_data
assign rd_data_o[8*k+:8] = (wbuffer_be[k]) ? wbuffer_rdata[8*k+:8] : rdata[8*k+:8];
end
for (genvar k = 0; k < DCACHE_USER_WIDTH / 8; k++) begin : gen_rd_user
for (genvar k = 0; k < CVA6Cfg.DCACHE_USER_WIDTH / 8; k++) begin : gen_rd_user
assign rd_user_o[8*k+:8] = (wbuffer_be[k]) ? wbuffer_ruser[8*k+:8] : ruser[8*k+:8];
end
@ -297,15 +301,15 @@ module wt_dcache_mem
// memory arrays and regs
///////////////////////////////////////////////////////
logic [DCACHE_TAG_WIDTH:0] vld_tag_rdata[DCACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.DCACHE_TAG_WIDTH:0] vld_tag_rdata[CVA6Cfg.DCACHE_SET_ASSOC-1:0];
for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_data_banks
// Data RAM
sram #(
.USER_WIDTH(ariane_pkg::DCACHE_SET_ASSOC * DATA_USER_WIDTH),
.DATA_WIDTH(ariane_pkg::DCACHE_SET_ASSOC * riscv::XLEN),
.USER_EN (ariane_pkg::DATA_USER_EN),
.NUM_WORDS (wt_cache_pkg::DCACHE_NUM_WORDS)
.USER_WIDTH(CVA6Cfg.DCACHE_SET_ASSOC * CVA6Cfg.DCACHE_USER_WIDTH),
.DATA_WIDTH(CVA6Cfg.DCACHE_SET_ASSOC * riscv::XLEN),
.USER_EN (CVA6Cfg.DATA_USER_EN),
.NUM_WORDS (CVA6Cfg.DCACHE_NUM_WORDS)
) i_data_sram (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -320,16 +324,16 @@ module wt_dcache_mem
);
end
for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_srams
for (genvar i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin : gen_tag_srams
assign tag_rdata[i] = vld_tag_rdata[i][DCACHE_TAG_WIDTH-1:0];
assign rd_vld_bits_o[i] = vld_tag_rdata[i][DCACHE_TAG_WIDTH];
assign tag_rdata[i] = vld_tag_rdata[i][CVA6Cfg.DCACHE_TAG_WIDTH-1:0];
assign rd_vld_bits_o[i] = vld_tag_rdata[i][CVA6Cfg.DCACHE_TAG_WIDTH];
// Tag RAM
sram #(
// tag + valid bit
.DATA_WIDTH(ariane_pkg::DCACHE_TAG_WIDTH + 1),
.NUM_WORDS (wt_cache_pkg::DCACHE_NUM_WORDS)
.DATA_WIDTH(CVA6Cfg.DCACHE_TAG_WIDTH + 1),
.NUM_WORDS (CVA6Cfg.DCACHE_NUM_WORDS)
) i_tag_sram (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -366,7 +370,7 @@ module wt_dcache_mem
`ifndef VERILATOR
initial begin
cach_line_width_axi :
assert (DCACHE_LINE_WIDTH >= CVA6Cfg.AxiDataWidth)
assert (CVA6Cfg.DCACHE_LINE_WIDTH >= CVA6Cfg.AxiDataWidth)
else $fatal(1, "[l1 dcache] cache line size needs to be greater or equal AXI data width");
end
@ -378,7 +382,7 @@ module wt_dcache_mem
initial begin
cach_line_width_xlen :
assert (DCACHE_LINE_WIDTH > riscv::XLEN)
assert (CVA6Cfg.DCACHE_LINE_WIDTH > riscv::XLEN)
else $fatal(1, "[l1 dcache] cache_line_size needs to be greater than XLEN");
end
@ -399,16 +403,16 @@ module wt_dcache_mem
else $fatal(1, "[l1 dcache] wbuffer_hit_oh signal must be hot1");
// this is only used for verification!
logic vld_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] tag_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] tag_write_duplicate_test;
logic vld_mirror[CVA6Cfg.DCACHE_NUM_WORDS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_mirror[CVA6Cfg.DCACHE_NUM_WORDS-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0];
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] tag_write_duplicate_test;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_mirror
if (!rst_ni) begin
vld_mirror <= '{default: '0};
tag_mirror <= '{default: '0};
end else begin
for (int i = 0; i < DCACHE_SET_ASSOC; i++) begin
for (int i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin
if (vld_req[i] & vld_we) begin
vld_mirror[vld_addr][i] <= vld_wdata[i];
tag_mirror[vld_addr][i] <= wr_cl_tag_i;
@ -417,7 +421,7 @@ module wt_dcache_mem
end
end
for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_dubl_test
for (genvar i = 0; i < CVA6Cfg.DCACHE_SET_ASSOC; i++) begin : gen_tag_dubl_test
assign tag_write_duplicate_test[i] = (tag_mirror[vld_addr][i] == wr_cl_tag_i) & vld_mirror[vld_addr][i] & (|vld_wdata);
end

View file

@ -19,6 +19,7 @@ module wt_dcache_missunit
import wt_cache_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter DCACHE_CL_IDX_WIDTH = 0,
parameter type dcache_req_t = logic,
parameter type dcache_rtrn_t = logic,
parameter logic [CVA6Cfg.MEM_TID_WIDTH-1:0] AmoTxId = 1, // TX id to be used for AMOs
@ -43,9 +44,9 @@ module wt_dcache_missunit
input logic [NumPorts-1:0] miss_nc_i,
input logic [NumPorts-1:0] miss_we_i,
input logic [NumPorts-1:0][riscv::XLEN-1:0] miss_wdata_i,
input logic [NumPorts-1:0][DCACHE_USER_WIDTH-1:0] miss_wuser_i,
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_USER_WIDTH-1:0] miss_wuser_i,
input logic [NumPorts-1:0][riscv::PLEN-1:0] miss_paddr_i,
input logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits_i,
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits_i,
input logic [NumPorts-1:0][2:0] miss_size_i,
input logic [NumPorts-1:0][CVA6Cfg.MEM_TID_WIDTH-1:0] miss_id_i, // used as transaction ID
// signals that the request collided with a pending read
@ -59,14 +60,14 @@ module wt_dcache_missunit
// write interface to cache memory
output logic wr_cl_vld_o, // writes a full cacheline
output logic wr_cl_nc_o, // writes a full cacheline
output logic [DCACHE_SET_ASSOC-1:0] wr_cl_we_o, // writes a full cacheline
output logic [DCACHE_TAG_WIDTH-1:0] wr_cl_tag_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_cl_we_o, // writes a full cacheline
output logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] wr_cl_tag_o,
output logic [DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx_o,
output logic [DCACHE_OFFSET_WIDTH-1:0] wr_cl_off_o,
output logic [DCACHE_LINE_WIDTH-1:0] wr_cl_data_o,
output logic [DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user_o,
output logic [DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be_o,
output logic [DCACHE_SET_ASSOC-1:0] wr_vld_bits_o,
output logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_cl_off_o,
output logic [CVA6Cfg.DCACHE_LINE_WIDTH-1:0] wr_cl_data_o,
output logic [CVA6Cfg.DCACHE_USER_LINE_WIDTH-1:0] wr_cl_user_o,
output logic [CVA6Cfg.DCACHE_LINE_WIDTH/8-1:0] wr_cl_data_be_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_vld_bits_o,
// memory interface
input logic mem_rtrn_vld_i,
input dcache_rtrn_t mem_rtrn_i,
@ -76,9 +77,9 @@ module wt_dcache_missunit
);
// functions
function automatic logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] dcache_way_bin2oh(
input logic [L1D_WAY_WIDTH-1:0] in);
logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] out;
function automatic logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] dcache_way_bin2oh(
input logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] in);
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] out;
out = '0;
out[in] = 1'b1;
return out;
@ -98,7 +99,7 @@ module wt_dcache_missunit
3'b001: out[0:0] = '0;
3'b010: out[1:0] = '0;
3'b011: out[2:0] = '0;
3'b111: out[DCACHE_OFFSET_WIDTH-1:0] = '0;
3'b111: out[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] = '0;
default: ;
endcase
return out;
@ -118,17 +119,17 @@ module wt_dcache_missunit
// MSHR for reads
typedef struct packed {
logic [riscv::PLEN-1:0] paddr;
logic [2:0] size;
logic [DCACHE_SET_ASSOC-1:0] vld_bits;
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] id;
logic nc;
logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way;
logic [$clog2(NumPorts)-1:0] miss_port_idx;
logic [riscv::PLEN-1:0] paddr;
logic [2:0] size;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] vld_bits;
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] id;
logic nc;
logic [$clog2(CVA6Cfg.DCACHE_SET_ASSOC)-1:0] repl_way;
logic [$clog2(NumPorts)-1:0] miss_port_idx;
} mshr_t;
mshr_t mshr_d, mshr_q;
logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way, inv_way, rnd_way;
logic [$clog2(CVA6Cfg.DCACHE_SET_ASSOC)-1:0] repl_way, inv_way, rnd_way;
logic mshr_vld_d, mshr_vld_q, mshr_vld_q1;
logic mshr_allocate;
logic update_lfsr, all_ways_valid;
@ -141,7 +142,7 @@ module wt_dcache_missunit
logic amo_req_d, amo_req_q;
logic [63:0] amo_rtrn_mux;
logic [riscv::XLEN-1:0] amo_data, amo_data_a, amo_data_b;
logic [riscv::XLEN-1:0] amo_user; //DCACHE USER ? DATA_USER_WIDTH
logic [riscv::XLEN-1:0] amo_user; //DCACHE USER ? CVA6Cfg.DCACHE_USER_WIDTH
logic [riscv::PLEN-1:0] tmp_paddr;
logic [$clog2(NumPorts)-1:0] miss_port_idx;
logic [DCACHE_CL_IDX_WIDTH-1:0] cnt_d, cnt_q;
@ -160,7 +161,7 @@ module wt_dcache_missunit
assign cache_en_o = enable_q;
assign cnt_d = (flush_en) ? cnt_q + 1 : '0;
assign flush_done = (cnt_q == wt_cache_pkg::DCACHE_NUM_WORDS - 1);
assign flush_done = (cnt_q == CVA6Cfg.DCACHE_NUM_WORDS - 1);
assign miss_req_masked_d = (lock_reqs) ? miss_req_masked_q :
(mask_reads) ? miss_we_i & miss_req_i : miss_req_i;
@ -188,7 +189,7 @@ module wt_dcache_missunit
// find invalid cache line
lzc #(
.WIDTH(ariane_pkg::DCACHE_SET_ASSOC)
.WIDTH(CVA6Cfg.DCACHE_SET_ASSOC)
) i_lzc_inv (
.in_i (~miss_vld_bits_i[miss_port_idx]),
.cnt_o (inv_way),
@ -198,7 +199,7 @@ module wt_dcache_missunit
// generate random cacheline index
lfsr #(
.LfsrWidth(8),
.OutWidth ($clog2(ariane_pkg::DCACHE_SET_ASSOC))
.OutWidth ($clog2(CVA6Cfg.DCACHE_SET_ASSOC))
) i_lfsr_inv (
.clk_i (clk_i),
.rst_ni(rst_ni),
@ -223,19 +224,19 @@ module wt_dcache_missunit
for (genvar k = 0; k < NumPorts; k++) begin : gen_rdrd_collision
assign mshr_rdrd_collision[k] = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && (mshr_vld_q | mshr_vld_q1);
assign mshr_rdrd_collision[k] = (mshr_q.paddr[riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == miss_paddr_i[k][riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]) && (mshr_vld_q | mshr_vld_q1);
assign mshr_rdrd_collision_d[k] = (!miss_req_i[k]) ? 1'b0 : mshr_rdrd_collision_q[k] | mshr_rdrd_collision[k];
end
// read/write collision, stalls the corresponding request
// write port[NumPorts-1] collides with MSHR_Q
assign mshr_rdwr_collision = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;
assign mshr_rdwr_collision = (mshr_q.paddr[riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]) && mshr_vld_q;
// read collides with inflight TX
always_comb begin : p_tx_coll
tx_rdwr_collision = 1'b0;
for (int k = 0; k < CVA6Cfg.DCACHE_MAX_TX; k++) begin
tx_rdwr_collision |= (miss_paddr_i[miss_port_idx][riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == tx_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && tx_vld_i[k];
tx_rdwr_collision |= (miss_paddr_i[miss_port_idx][riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] == tx_paddr_i[k][riscv::PLEN-1:CVA6Cfg.DCACHE_OFFSET_WIDTH]) && tx_vld_i[k];
end
end
@ -265,7 +266,7 @@ module wt_dcache_missunit
end else begin
amo_data = amo_data_a;
end
if (ariane_pkg::DATA_USER_EN) begin
if (CVA6Cfg.DATA_USER_EN) begin
amo_user = amo_data;
end else begin
amo_user = '0;
@ -284,7 +285,7 @@ module wt_dcache_missunit
assign amo_rtrn_mux = mem_rtrn_i.data[0+:64];
end
end else begin : gen_piton_rtrn_mux
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64+:64];
assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3]*64+:64];
end
// always sign extend 32bit values
@ -410,11 +411,11 @@ module wt_dcache_missunit
) : '0;
assign wr_cl_idx_o = (flush_en) ? cnt_q :
(inv_vld) ? mem_rtrn_i.inv.idx[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH] :
mshr_q.paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];
(inv_vld) ? mem_rtrn_i.inv.idx[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH] :
mshr_q.paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH];
assign wr_cl_tag_o = mshr_q.paddr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
assign wr_cl_off_o = mshr_q.paddr[DCACHE_OFFSET_WIDTH-1:0];
assign wr_cl_tag_o = mshr_q.paddr[CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
assign wr_cl_off_o = mshr_q.paddr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0];
assign wr_cl_data_o = mem_rtrn_i.data;
assign wr_cl_user_o = mem_rtrn_i.user;
assign wr_cl_data_be_o = (cl_write_en) ? '1 : '0;// we only write complete cachelines into the memory

View file

@ -54,6 +54,7 @@ module wt_dcache_wbuffer
import wt_cache_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter DCACHE_CL_IDX_WIDTH = 0,
parameter type dcache_req_i_t = logic,
parameter type dcache_req_o_t = logic,
parameter type wbuffer_t = logic
@ -73,8 +74,8 @@ module wt_dcache_wbuffer
output logic miss_req_o,
output logic miss_we_o, // always 1 here
output logic [riscv::XLEN-1:0] miss_wdata_o,
output logic [DCACHE_USER_WIDTH-1:0] miss_wuser_o,
output logic [DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // unused here (set to 0)
output logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] miss_wuser_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits_o, // unused here (set to 0)
output logic miss_nc_o, // request to I/O space
output logic [2:0] miss_size_o, //
output logic [CVA6Cfg.MEM_TID_WIDTH-1:0] miss_id_o, // ID of this transaction (wbuffer uses all IDs from 0 to DCACHE_MAX_TX-1)
@ -82,26 +83,26 @@ module wt_dcache_wbuffer
input logic miss_rtrn_vld_i,
input logic [CVA6Cfg.MEM_TID_WIDTH-1:0] miss_rtrn_id_i, // transaction ID to clear
// cache read interface
output logic [DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
output logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag_o, // tag in - comes one cycle later
output logic [DCACHE_CL_IDX_WIDTH-1:0] rd_idx_o,
output logic [DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
output logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] rd_off_o,
output logic rd_req_o, // read the word at offset off_i[:3] in all ways
output logic rd_tag_only_o, // set to 1 here as we do not have to read the data arrays
input logic rd_ack_i,
input logic [riscv::XLEN-1:0] rd_data_i, // unused
input logic [DCACHE_SET_ASSOC-1:0] rd_vld_bits_i, // unused
input logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_i,
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_vld_bits_i, // unused
input logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_hit_oh_i,
// cacheline writes
input logic wr_cl_vld_i,
input logic [DCACHE_CL_IDX_WIDTH-1:0] wr_cl_idx_i,
// cache word write interface
output logic [DCACHE_SET_ASSOC-1:0] wr_req_o,
output logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] wr_req_o,
input logic wr_ack_i,
output logic [DCACHE_CL_IDX_WIDTH-1:0] wr_idx_o,
output logic [DCACHE_OFFSET_WIDTH-1:0] wr_off_o,
output logic [CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0] wr_off_o,
output logic [riscv::XLEN-1:0] wr_data_o,
output logic [(riscv::XLEN/8)-1:0] wr_data_be_o,
output logic [DCACHE_USER_WIDTH-1:0] wr_user_o,
output logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] wr_user_o,
// to forwarding logic and miss unit
output wbuffer_t [DCACHE_WBUF_DEPTH-1:0] wbuffer_data_o,
output logic [CVA6Cfg.DCACHE_MAX_TX-1:0][riscv::PLEN-1:0] tx_paddr_o, // used to check for address collisions with read operations
@ -109,7 +110,7 @@ module wt_dcache_wbuffer
);
function automatic logic [(riscv::XLEN/8)-1:0] to_byte_enable8(
input logic [riscv::XLEN_ALIGN_BYTES-1:0] offset, input logic [1:0] size);
input logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] offset, input logic [1:0] size);
logic [(riscv::XLEN/8)-1:0] be;
be = '0;
unique case (size)
@ -122,7 +123,7 @@ module wt_dcache_wbuffer
endfunction : to_byte_enable8
function automatic logic [(riscv::XLEN/8)-1:0] to_byte_enable4(
input logic [riscv::XLEN_ALIGN_BYTES-1:0] offset, input logic [1:0] size);
input logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] offset, input logic [1:0] size);
logic [3:0] be;
be = '0;
unique case (size)
@ -135,7 +136,7 @@ module wt_dcache_wbuffer
// openpiton requires the data to be replicated in case of smaller sizes than dwords
function automatic logic [riscv::XLEN-1:0] repData64(
input logic [riscv::XLEN-1:0] data, input logic [riscv::XLEN_ALIGN_BYTES-1:0] offset,
input logic [riscv::XLEN-1:0] data, input logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] offset,
input logic [1:0] size);
logic [riscv::XLEN-1:0] out;
unique case (size)
@ -148,7 +149,7 @@ module wt_dcache_wbuffer
endfunction : repData64
function automatic logic [riscv::XLEN-1:0] repData32(
input logic [riscv::XLEN-1:0] data, input logic [riscv::XLEN_ALIGN_BYTES-1:0] offset,
input logic [riscv::XLEN-1:0] data, input logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] offset,
input logic [1:0] size);
logic [riscv::XLEN-1:0] out;
unique case (size)
@ -178,11 +179,11 @@ module wt_dcache_wbuffer
next_ptr, dirty_ptr, hit_ptr, wr_ptr, check_ptr_d, check_ptr_q, check_ptr_q1, rtrn_ptr;
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] tx_id, rtrn_id;
logic [riscv::XLEN_ALIGN_BYTES-1:0] bdirty_off;
logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] bdirty_off;
logic [(riscv::XLEN/8)-1:0] tx_be;
logic [riscv::PLEN-1:0] wr_paddr, rd_paddr, extract_tag;
logic [DCACHE_TAG_WIDTH-1:0] rd_tag_d, rd_tag_q;
logic [DCACHE_SET_ASSOC-1:0] rd_hit_oh_d, rd_hit_oh_q;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] rd_tag_d, rd_tag_q;
logic [CVA6Cfg.DCACHE_SET_ASSOC-1:0] rd_hit_oh_d, rd_hit_oh_q;
logic check_en_d, check_en_q, check_en_q1;
logic full, dirty_rd_en, rdy;
logic rtrn_empty, evict;
@ -200,14 +201,16 @@ module wt_dcache_wbuffer
///////////////////////////////////////////////////////
// misc
///////////////////////////////////////////////////////
logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] miss_tag;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] miss_tag;
logic is_nc_miss;
logic is_ni;
assign miss_tag = miss_paddr_o[ariane_pkg::DCACHE_INDEX_WIDTH+:ariane_pkg::DCACHE_TAG_WIDTH];
assign miss_tag = miss_paddr_o[CVA6Cfg.DCACHE_INDEX_WIDTH+:CVA6Cfg.DCACHE_TAG_WIDTH];
assign is_nc_miss = !config_pkg::is_inside_cacheable_regions(
CVA6Cfg,
{
{64 - DCACHE_TAG_WIDTH - DCACHE_INDEX_WIDTH{1'b0}}, miss_tag, {DCACHE_INDEX_WIDTH{1'b0}}
{64 - CVA6Cfg.DCACHE_TAG_WIDTH - CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}},
miss_tag,
{CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);
assign miss_nc_o = !cache_en_i || is_nc_miss;
@ -215,9 +218,9 @@ module wt_dcache_wbuffer
assign is_ni = config_pkg::is_inside_nonidempotent_regions(
CVA6Cfg,
{
{64 - DCACHE_TAG_WIDTH - DCACHE_INDEX_WIDTH{1'b0}},
{64 - CVA6Cfg.DCACHE_TAG_WIDTH - CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}},
req_port_i.address_tag,
{DCACHE_INDEX_WIDTH{1'b0}}
{CVA6Cfg.DCACHE_INDEX_WIDTH{1'b0}}
}
);
@ -228,7 +231,7 @@ module wt_dcache_wbuffer
for (genvar k = 0; k < CVA6Cfg.DCACHE_MAX_TX; k++) begin : gen_tx_vld
assign tx_vld_o[k] = tx_stat_q[k].vld;
assign tx_paddr_o[k] = {
{riscv::XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[tx_stat_q[k].ptr].wtag << riscv::XLEN_ALIGN_BYTES
{CVA6Cfg.XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[tx_stat_q[k].ptr].wtag << CVA6Cfg.XLEN_ALIGN_BYTES
};
end
@ -275,7 +278,7 @@ module wt_dcache_wbuffer
) : repData32(
wbuffer_dirty_mux.data, bdirty_off, miss_size_o[1:0]
);
if (ariane_pkg::DATA_USER_EN) begin
if (CVA6Cfg.DATA_USER_EN) begin
assign miss_wuser_o = riscv::IS_XLEN64 ? repData64(
wbuffer_dirty_mux.user, bdirty_off, miss_size_o[1:0]
) : repData32(
@ -299,7 +302,8 @@ module wt_dcache_wbuffer
fifo_v3 #(
.FALL_THROUGH(1'b0),
.DATA_WIDTH ($clog2(CVA6Cfg.DCACHE_MAX_TX)),
.DEPTH (CVA6Cfg.DCACHE_MAX_TX)
.DEPTH (CVA6Cfg.DCACHE_MAX_TX),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_rtrn_id_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -368,18 +372,18 @@ module wt_dcache_wbuffer
// cache readout & update
///////////////////////////////////////////////////////
assign extract_tag = rd_paddr >> DCACHE_INDEX_WIDTH;
assign rd_tag_d = extract_tag[DCACHE_TAG_WIDTH-1:0];
assign extract_tag = rd_paddr >> CVA6Cfg.DCACHE_INDEX_WIDTH;
assign rd_tag_d = extract_tag[CVA6Cfg.DCACHE_TAG_WIDTH-1:0];
// trigger TAG readout in cache
assign rd_tag_only_o = 1'b1;
assign rd_paddr = {
{riscv::XLEN_ALIGN_BYTES{1'b0}}, wbuffer_check_mux.wtag << riscv::XLEN_ALIGN_BYTES
{CVA6Cfg.XLEN_ALIGN_BYTES{1'b0}}, wbuffer_check_mux.wtag << CVA6Cfg.XLEN_ALIGN_BYTES
};
assign rd_req_o = |tocheck;
assign rd_tag_o = rd_tag_q; //delay by one cycle
assign rd_idx_o = rd_paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];
assign rd_off_o = rd_paddr[DCACHE_OFFSET_WIDTH-1:0];
assign rd_idx_o = rd_paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH];
assign rd_off_o = rd_paddr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0];
assign check_en_d = rd_req_o & rd_ack_i;
// cache update port
@ -388,10 +392,10 @@ module wt_dcache_wbuffer
// when the TX returns
assign wr_data_be_o = tx_stat_q[rtrn_id].be & (~wbuffer_q[rtrn_ptr].dirty);
assign wr_paddr = {
{riscv::XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[rtrn_ptr].wtag << riscv::XLEN_ALIGN_BYTES
{CVA6Cfg.XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[rtrn_ptr].wtag << CVA6Cfg.XLEN_ALIGN_BYTES
};
assign wr_idx_o = wr_paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];
assign wr_off_o = wr_paddr[DCACHE_OFFSET_WIDTH-1:0];
assign wr_idx_o = wr_paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_OFFSET_WIDTH];
assign wr_off_o = wr_paddr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:0];
assign wr_data_o = wbuffer_q[rtrn_ptr].data;
assign wr_user_o = wbuffer_q[rtrn_ptr].user;
@ -409,7 +413,7 @@ module wt_dcache_wbuffer
// only for debug, will be pruned
if (CVA6Cfg.DebugEn) begin
assign debug_paddr[k] = {
{riscv::XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[k].wtag << riscv::XLEN_ALIGN_BYTES
{CVA6Cfg.XLEN_ALIGN_BYTES{1'b0}}, wbuffer_q[k].wtag << CVA6Cfg.XLEN_ALIGN_BYTES
};
end
@ -421,12 +425,12 @@ module wt_dcache_wbuffer
assign dirty[k] = |bdirty[k];
assign valid[k] = |wbuffer_q[k].valid;
assign wbuffer_hit_oh[k] = valid[k] & (wbuffer_q[k].wtag == {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:riscv::XLEN_ALIGN_BYTES]});
assign wbuffer_hit_oh[k] = valid[k] & (wbuffer_q[k].wtag == {req_port_i.address_tag, req_port_i.address_index[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]});
// checks if an invalidation/cache refill hits a particular word
// note: an invalidation can hit multiple words!
// need to respect previous cycle, too, since we add a cycle of latency to the rd_hit_oh_i signal...
assign wtag_comp[k] = wbuffer_q[k].wtag[DCACHE_INDEX_WIDTH-riscv::XLEN_ALIGN_BYTES-1:DCACHE_OFFSET_WIDTH-riscv::XLEN_ALIGN_BYTES];
assign wtag_comp[k] = wbuffer_q[k].wtag[CVA6Cfg.DCACHE_INDEX_WIDTH-CVA6Cfg.XLEN_ALIGN_BYTES-1:CVA6Cfg.DCACHE_OFFSET_WIDTH-CVA6Cfg.XLEN_ALIGN_BYTES];
assign inval_hit[k] = (wr_cl_vld_d & valid[k] & (wtag_comp[k] == wr_cl_idx_d)) |
(wr_cl_vld_q & valid[k] & (wtag_comp[k] == wr_cl_idx_q));
@ -579,7 +583,7 @@ module wt_dcache_wbuffer
wbuffer_d[wr_ptr].checked = 1'b0;
wbuffer_d[wr_ptr].wtag = {
req_port_i.address_tag,
req_port_i.address_index[DCACHE_INDEX_WIDTH-1:riscv::XLEN_ALIGN_BYTES]
req_port_i.address_index[CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.XLEN_ALIGN_BYTES]
};
// mark bytes as dirty
@ -588,7 +592,7 @@ module wt_dcache_wbuffer
wbuffer_d[wr_ptr].valid[k] = 1'b1;
wbuffer_d[wr_ptr].dirty[k] = 1'b1;
wbuffer_d[wr_ptr].data[k*8+:8] = req_port_i.data_wdata[k*8+:8];
if (ariane_pkg::DATA_USER_EN) begin
if (CVA6Cfg.DATA_USER_EN) begin
wbuffer_d[wr_ptr].user[k*8+:8] = req_port_i.data_wuser[k*8+:8];
end else begin
wbuffer_d[wr_ptr].user[k*8+:8] = '0;

View file

@ -94,7 +94,7 @@ module wt_l15_adapter
logic l15_invalidate_cacheline; // unused by Ariane as L1 has no ECC at the moment
logic l15_blockstore; // unused in openpiton
logic l15_blockinitstore; // unused in openpiton
logic [wt_cache_pkg::L15_WAY_WIDTH-1:0] l15_l1rplway; // way to replace
logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] l15_l1rplway; // way to replace
logic [39:0] l15_address; // physical address
logic [63:0] l15_data; // word to write
logic [63:0] l15_data_next_entry; // unused in Ariane (only used for CAS atomic requests)
@ -121,10 +121,10 @@ module wt_l15_adapter
logic l15_inval_dcache_all_way; // unused in openpiton
logic [15:4] l15_inval_address_15_4; // invalidate selected cacheline
logic l15_cross_invalidate; // unused in openpiton
logic [wt_cache_pkg::L15_WAY_WIDTH-1:0] l15_cross_invalidate_way; // unused in openpiton
logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] l15_cross_invalidate_way; // unused in openpiton
logic l15_inval_dcache_inval; // invalidate selected cacheline and way
logic l15_inval_icache_inval; // unused in openpiton
logic [wt_cache_pkg::L15_WAY_WIDTH-1:0] l15_inval_way; // way to invalidate
logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] l15_inval_way; // way to invalidate
logic l15_blockinitstore; // unused in openpiton
};
@ -153,7 +153,7 @@ module wt_l15_adapter
// logic [2:0] l15_req_o.l15_size; // transaction size: 000=Byte 001=2Byte; 010=4Byte; 011=8Byte; 111=Cache line (16/32Byte)
// logic [CVA6Cfg.MEM_TID_WIDTH-1:0] l15_req_o.l15_threadid; // currently 0 or 1
// logic l15_req_o.l15_invalidate_cacheline; // unused by Ariane as L1 has no ECC at the moment
// logic [L15_WAY_WIDTH-1:0] l15_req_o.l15_l1rplway; // way to replace
// logic [CVA6Cfg.DCACHE_SET_ASSOC_WIDTH-1:0] l15_req_o.l15_l1rplway; // way to replace
// logic [39:0] l15_req_o.l15_address; // physical address
// logic [63:0] l15_req_o.l15_data; // word to write
// logic [63:0] l15_req_o.l15_data_next_entry; // unused in Ariane (only used for CAS atomic requests)
@ -438,19 +438,19 @@ module wt_l15_adapter
initial begin
// assert wrong parameterizations
assert (L15_SET_ASSOC >= ICACHE_SET_ASSOC)
assert (CVA6Cfg.DCACHE_SET_ASSOC >= CVA6Cfg.ICACHE_SET_ASSOC)
else
$fatal(
1, "[l15_adapter] number of icache ways must be smaller or equal the number of L15 ways"
);
// assert wrong parameterizations
assert (L15_SET_ASSOC >= DCACHE_SET_ASSOC)
assert (CVA6Cfg.DCACHE_SET_ASSOC >= CVA6Cfg.DCACHE_SET_ASSOC)
else
$fatal(
1, "[l15_adapter] number of dcache ways must be smaller or equal the number of L15 ways"
);
// invalidation address returned by L1.5 is 16 bit
assert (16 >= DCACHE_INDEX_WIDTH && 16 >= ICACHE_INDEX_WIDTH)
assert (16 >= CVA6Cfg.DCACHE_INDEX_WIDTH && 16 >= CVA6Cfg.ICACHE_INDEX_WIDTH)
else $fatal(1, "[l15_adapter] maximum number of index bits supported by L1.5 is 16");
end
`endif

View file

@ -67,7 +67,7 @@ module commit_stage
// Commit buffer of LSU is ready - EX_STAGE
input logic commit_lsu_ready_i,
// Transaction id of first commit port - ID_STAGE
output logic [TRANS_ID_BITS-1:0] commit_tran_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] commit_tran_id_o,
// Valid AMO in commit stage - EX_STAGE
output logic amo_valid_commit_o,
// no store is pending - EX_STAGE

View file

@ -98,7 +98,7 @@ module csr_regfile
// Make Executable Readable - EX_STAGE
output logic mxr_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [riscv::PPNW-1:0] satp_ppn_o,
output logic [CVA6Cfg.PPNW-1:0] satp_ppn_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [AsidWidth-1:0] asid_o,
// external interrupt in - SUBSYSTEM
@ -144,10 +144,12 @@ module csr_regfile
output rvfi_probes_csr_t rvfi_csr_o
);
localparam logic [63:0] SMODE_STATUS_READ_MASK = ariane_pkg::smode_status_read_mask(CVA6Cfg);
typedef struct packed {
logic [riscv::ModeW-1:0] mode;
logic [riscv::ASIDW-1:0] asid;
logic [riscv::PPNW-1:0] ppn;
logic [CVA6Cfg.ModeW-1:0] mode;
logic [CVA6Cfg.ASIDW-1:0] asid;
logic [CVA6Cfg.PPNW-1:0] ppn;
} satp_t;
// internal signal to keep track of access exceptions
@ -298,8 +300,7 @@ module csr_regfile
riscv::CSR_TDATA3: read_access_exception = 1'b1; // not implemented
// supervisor registers
riscv::CSR_SSTATUS: begin
if (CVA6Cfg.RVS)
csr_rdata = mstatus_extended & ariane_pkg::SMODE_STATUS_READ_MASK[riscv::XLEN-1:0];
if (CVA6Cfg.RVS) csr_rdata = mstatus_extended & SMODE_STATUS_READ_MASK[riscv::XLEN-1:0];
else read_access_exception = 1'b1;
end
riscv::CSR_SIE:
@ -829,10 +830,10 @@ module csr_regfile
else begin
satp = satp_t'(csr_wdata);
// only make ASID_LEN - 1 bit stick, that way software can figure out how many ASID bits are supported
satp.asid = satp.asid & {{(riscv::ASIDW - AsidWidth) {1'b0}}, {AsidWidth{1'b1}}};
satp.asid = satp.asid & {{(CVA6Cfg.ASIDW - AsidWidth) {1'b0}}, {AsidWidth{1'b1}}};
// only update if we actually support this mode
if (riscv::vm_mode_t'(satp.mode) == riscv::ModeOff ||
riscv::vm_mode_t'(satp.mode) == riscv::MODE_SV)
if (config_pkg::vm_mode_t'(satp.mode) == config_pkg::ModeOff ||
config_pkg::vm_mode_t'(satp.mode) == CVA6Cfg.MODE_SV)
satp_d = satp;
end
// changing the mode can have side-effects on address translation (e.g.: other instructions), re-fetch
@ -1306,7 +1307,7 @@ module csr_regfile
// ------------------------------
// Set the address translation at which the load and stores should occur
// we can use the previous values since changing the address translation will always involve a pipeline flush
if (ariane_pkg::MMU_PRESENT && mprv && CVA6Cfg.RVS && riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV && (mstatus_q.mpp != riscv::PRIV_LVL_M))
if (ariane_pkg::MMU_PRESENT && mprv && CVA6Cfg.RVS && config_pkg::vm_mode_t'(satp_q.mode) == CVA6Cfg.MODE_SV && (mstatus_q.mpp != riscv::PRIV_LVL_M))
en_ld_st_translation_d = 1'b1;
else // otherwise we go with the regular settings
en_ld_st_translation_d = en_translation_o;
@ -1553,7 +1554,7 @@ module csr_regfile
assign asid_o = satp_q.asid[AsidWidth-1:0];
assign sum_o = mstatus_q.sum;
// we support bare memory addressing and SV39
assign en_translation_o = ((CVA6Cfg.RVS && riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV) &&
assign en_translation_o = ((CVA6Cfg.RVS && config_pkg::vm_mode_t'(satp_q.mode) == CVA6Cfg.MODE_SV) &&
priv_lvl_o != riscv::PRIV_LVL_M)
? 1'b1
: 1'b0;

View file

@ -66,12 +66,12 @@ module cva6
logic [riscv::VLEN-1:0] vaddr; // 1st cycle: 12 bit index is taken for lookup
},
localparam type icache_drsp_t = struct packed {
logic ready; // icache is ready
logic valid; // signals a valid read
logic [ariane_pkg::FETCH_WIDTH-1:0] data; // 2+ cycle out: tag
logic [ariane_pkg::FETCH_USER_WIDTH-1:0] user; // User bits
logic [riscv::VLEN-1:0] vaddr; // virtual address out
exception_t ex; // we've encountered an exception
logic ready; // icache is ready
logic valid; // signals a valid read
logic [CVA6Cfg.FETCH_WIDTH-1:0] data; // 2+ cycle out: tag
logic [CVA6Cfg.FETCH_USER_WIDTH-1:0] user; // User bits
logic [riscv::VLEN-1:0] vaddr; // virtual address out
exception_t ex; // we've encountered an exception
},
// IF/ID Stage
@ -86,8 +86,8 @@ module cva6
// ID/EX/WB Stage
localparam type scoreboard_entry_t = struct packed {
logic [riscv::VLEN-1:0] pc; // PC of instruction
logic [TRANS_ID_BITS-1:0] trans_id; // this can potentially be simplified, we could index the scoreboard entry
// with the transaction id in any case make the width more generic
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id; // this can potentially be simplified, we could index the scoreboard entry
// with the transaction id in any case make the width more generic
fu_t fu; // functional unit to use
fu_op op; // operation to perform in each functional unit
logic [REG_ADDR_SIZE-1:0] rs1; // register source address 1
@ -135,65 +135,65 @@ module cva6
},
localparam type lsu_ctrl_t = struct packed {
logic valid;
logic [riscv::VLEN-1:0] vaddr;
logic overflow;
logic [riscv::XLEN-1:0] data;
logic [(riscv::XLEN/8)-1:0] be;
fu_t fu;
fu_op operation;
logic [ariane_pkg::TRANS_ID_BITS-1:0] trans_id;
logic valid;
logic [riscv::VLEN-1:0] vaddr;
logic overflow;
logic [riscv::XLEN-1:0] data;
logic [(riscv::XLEN/8)-1:0] be;
fu_t fu;
fu_op operation;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
},
localparam type fu_data_t = struct packed {
fu_t fu;
fu_op operation;
logic [riscv::XLEN-1:0] operand_a;
logic [riscv::XLEN-1:0] operand_b;
logic [riscv::XLEN-1:0] imm;
logic [ariane_pkg::TRANS_ID_BITS-1:0] trans_id;
fu_t fu;
fu_op operation;
logic [riscv::XLEN-1:0] operand_a;
logic [riscv::XLEN-1:0] operand_b;
logic [riscv::XLEN-1:0] imm;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
},
localparam type icache_req_t = struct packed {
logic [$clog2(ariane_pkg::ICACHE_SET_ASSOC)-1:0] way; // way to replace
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] way; // way to replace
logic [riscv::PLEN-1:0] paddr; // physical address
logic nc; // noncacheable
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] tid; // threadi id (used as transaction id in Ariane)
},
localparam type icache_rtrn_t = struct packed {
wt_cache_pkg::icache_in_t rtype; // see definitions above
logic [ariane_pkg::ICACHE_LINE_WIDTH-1:0] data; // full cache line width
logic [ariane_pkg::ICACHE_USER_LINE_WIDTH-1:0] user; // user bits
logic [CVA6Cfg.ICACHE_LINE_WIDTH-1:0] data; // full cache line width
logic [CVA6Cfg.ICACHE_USER_LINE_WIDTH-1:0] user; // user bits
struct packed {
logic vld; // invalidate only affected way
logic all; // invalidate all ways
logic [ariane_pkg::ICACHE_INDEX_WIDTH-1:0] idx; // physical address to invalidate
logic [wt_cache_pkg::L1I_WAY_WIDTH-1:0] way; // way to invalidate
logic [CVA6Cfg.ICACHE_INDEX_WIDTH-1:0] idx; // physical address to invalidate
logic [CVA6Cfg.ICACHE_SET_ASSOC_WIDTH-1:0] way; // way to invalidate
} inv; // invalidation vector
logic [CVA6Cfg.MEM_TID_WIDTH-1:0] tid; // threadi id (used as transaction id in Ariane)
},
// D$ data requests
localparam type dcache_req_i_t = struct packed {
logic [DCACHE_INDEX_WIDTH-1:0] address_index;
logic [DCACHE_TAG_WIDTH-1:0] address_tag;
logic [riscv::XLEN-1:0] data_wdata;
logic [DCACHE_USER_WIDTH-1:0] data_wuser;
logic data_req;
logic data_we;
logic [(riscv::XLEN/8)-1:0] data_be;
logic [1:0] data_size;
logic [DCACHE_TID_WIDTH-1:0] data_id;
logic kill_req;
logic tag_valid;
logic [CVA6Cfg.DCACHE_INDEX_WIDTH-1:0] address_index;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] address_tag;
logic [riscv::XLEN-1:0] data_wdata;
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] data_wuser;
logic data_req;
logic data_we;
logic [(riscv::XLEN/8)-1:0] data_be;
logic [1:0] data_size;
logic [DCACHE_TID_WIDTH-1:0] data_id;
logic kill_req;
logic tag_valid;
},
localparam type dcache_req_o_t = struct packed {
logic data_gnt;
logic data_rvalid;
logic [DCACHE_TID_WIDTH-1:0] data_rid;
logic [riscv::XLEN-1:0] data_rdata;
logic [DCACHE_USER_WIDTH-1:0] data_ruser;
logic data_gnt;
logic data_rvalid;
logic [DCACHE_TID_WIDTH-1:0] data_rid;
logic [riscv::XLEN-1:0] data_rdata;
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] data_ruser;
},
// AXI types
@ -295,6 +295,24 @@ module cva6
input noc_resp_t noc_resp_i
);
localparam type interrupts_t = struct packed {
logic [riscv::XLEN-1:0] S_SW;
logic [riscv::XLEN-1:0] M_SW;
logic [riscv::XLEN-1:0] S_TIMER;
logic [riscv::XLEN-1:0] M_TIMER;
logic [riscv::XLEN-1:0] S_EXT;
logic [riscv::XLEN-1:0] M_EXT;
};
localparam interrupts_t INTERRUPTS = '{
S_SW: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_S_SOFT),
M_SW: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_M_SOFT),
S_TIMER: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_S_TIMER),
M_TIMER: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_M_TIMER),
S_EXT: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_S_EXT),
M_EXT: (1 << (riscv::XLEN - 1)) | riscv::XLEN'(riscv::IRQ_M_EXT)
};
// ------------------------------------------
// Global Signals
// Signals connecting more than one module
@ -343,7 +361,7 @@ module cva6
logic is_compressed_instr_id_ex;
// fixed latency units
logic flu_ready_ex_id;
logic [TRANS_ID_BITS-1:0] flu_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] flu_trans_id_ex_id;
logic flu_valid_ex_id;
logic [riscv::XLEN-1:0] flu_result_ex_id;
exception_t flu_exception_ex_id;
@ -358,13 +376,13 @@ module cva6
logic lsu_valid_id_ex;
logic lsu_ready_ex_id;
logic [TRANS_ID_BITS-1:0] load_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] load_trans_id_ex_id;
logic [riscv::XLEN-1:0] load_result_ex_id;
logic load_valid_ex_id;
exception_t load_exception_ex_id;
logic [riscv::XLEN-1:0] store_result_ex_id;
logic [TRANS_ID_BITS-1:0] store_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] store_trans_id_ex_id;
logic store_valid_ex_id;
exception_t store_exception_ex_id;
// MULT
@ -374,7 +392,7 @@ module cva6
logic fpu_valid_id_ex;
logic [1:0] fpu_fmt_id_ex;
logic [2:0] fpu_rm_id_ex;
logic [TRANS_ID_BITS-1:0] fpu_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] fpu_trans_id_ex_id;
logic [riscv::XLEN-1:0] fpu_result_ex_id;
logic fpu_valid_ex_id;
exception_t fpu_exception_ex_id;
@ -382,7 +400,7 @@ module cva6
logic stall_acc_id;
scoreboard_entry_t issue_instr_id_acc;
logic issue_instr_hs_id_acc;
logic [TRANS_ID_BITS-1:0] acc_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] acc_trans_id_ex_id;
logic [riscv::XLEN-1:0] acc_result_ex_id;
logic acc_valid_ex_id;
exception_t acc_exception_ex_id;
@ -393,7 +411,7 @@ module cva6
// CSR
logic csr_valid_id_ex;
// CVXIF
logic [TRANS_ID_BITS-1:0] x_trans_id_ex_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_ex_id;
logic [riscv::XLEN-1:0] x_result_ex_id;
logic x_valid_ex_id;
exception_t x_exception_ex_id;
@ -411,7 +429,7 @@ module cva6
// LSU Commit
logic lsu_commit_commit_ex;
logic lsu_commit_ready_ex_commit;
logic [TRANS_ID_BITS-1:0] lsu_commit_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] lsu_commit_trans_id;
logic stall_st_pending_ex;
logic no_st_pending_ex;
logic no_st_pending_commit;
@ -425,8 +443,8 @@ module cva6
// --------------
// RVFI
// --------------
logic [TRANS_ID_BITS-1:0] rvfi_issue_pointer;
logic [CVA6Cfg.NrCommitPorts-1:0][TRANS_ID_BITS-1:0] rvfi_commit_pointer;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_issue_pointer;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_commit_pointer;
// --------------
// COMMIT <-> ID
// --------------
@ -447,7 +465,7 @@ module cva6
riscv::priv_lvl_t ld_st_priv_lvl_csr_ex;
logic sum_csr_ex;
logic mxr_csr_ex;
logic [riscv::PPNW-1:0] satp_ppn_csr_ex;
logic [CVA6Cfg.PPNW-1:0] satp_ppn_csr_ex;
logic [ASID_WIDTH-1:0] asid_csr_ex;
logic [11:0] csr_addr_ex_csr;
fu_op csr_op_commit_csr;
@ -472,66 +490,66 @@ module cva6
// ----------------------------
logic [11:0] addr_csr_perf;
logic [riscv::XLEN-1:0] data_csr_perf, data_perf_csr;
logic we_csr_perf;
logic we_csr_perf;
logic icache_flush_ctrl_cache;
logic itlb_miss_ex_perf;
logic dtlb_miss_ex_perf;
logic dcache_miss_cache_perf;
logic icache_miss_cache_perf;
logic [ NumPorts-1:0][DCACHE_SET_ASSOC-1:0] miss_vld_bits;
logic stall_issue;
logic icache_flush_ctrl_cache;
logic itlb_miss_ex_perf;
logic dtlb_miss_ex_perf;
logic dcache_miss_cache_perf;
logic icache_miss_cache_perf;
logic [ NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0] miss_vld_bits;
logic stall_issue;
// --------------
// CTRL <-> *
// --------------
logic set_pc_ctrl_pcgen;
logic flush_csr_ctrl;
logic flush_unissued_instr_ctrl_id;
logic flush_ctrl_if;
logic flush_ctrl_id;
logic flush_ctrl_ex;
logic flush_ctrl_bp;
logic flush_tlb_ctrl_ex;
logic fence_i_commit_controller;
logic fence_commit_controller;
logic sfence_vma_commit_controller;
logic halt_ctrl;
logic halt_csr_ctrl;
logic dcache_flush_ctrl_cache;
logic dcache_flush_ack_cache_ctrl;
logic set_debug_pc;
logic flush_commit;
logic flush_acc;
logic set_pc_ctrl_pcgen;
logic flush_csr_ctrl;
logic flush_unissued_instr_ctrl_id;
logic flush_ctrl_if;
logic flush_ctrl_id;
logic flush_ctrl_ex;
logic flush_ctrl_bp;
logic flush_tlb_ctrl_ex;
logic fence_i_commit_controller;
logic fence_commit_controller;
logic sfence_vma_commit_controller;
logic halt_ctrl;
logic halt_csr_ctrl;
logic dcache_flush_ctrl_cache;
logic dcache_flush_ack_cache_ctrl;
logic set_debug_pc;
logic flush_commit;
logic flush_acc;
icache_areq_t icache_areq_ex_cache;
icache_arsp_t icache_areq_cache_ex;
icache_dreq_t icache_dreq_if_cache;
icache_drsp_t icache_dreq_cache_if;
icache_areq_t icache_areq_ex_cache;
icache_arsp_t icache_areq_cache_ex;
icache_dreq_t icache_dreq_if_cache;
icache_drsp_t icache_dreq_cache_if;
amo_req_t amo_req;
amo_resp_t amo_resp;
logic sb_full;
amo_req_t amo_req;
amo_resp_t amo_resp;
logic sb_full;
// ----------------
// DCache <-> *
// ----------------
dcache_req_i_t [ 2:0] dcache_req_ports_ex_cache;
dcache_req_o_t [ 2:0] dcache_req_ports_cache_ex;
dcache_req_i_t [ 1:0] dcache_req_ports_acc_cache;
dcache_req_o_t [ 1:0] dcache_req_ports_cache_acc;
logic dcache_commit_wbuffer_empty;
logic dcache_commit_wbuffer_not_ni;
dcache_req_i_t [ 2:0] dcache_req_ports_ex_cache;
dcache_req_o_t [ 2:0] dcache_req_ports_cache_ex;
dcache_req_i_t [ 1:0] dcache_req_ports_acc_cache;
dcache_req_o_t [ 1:0] dcache_req_ports_cache_acc;
logic dcache_commit_wbuffer_empty;
logic dcache_commit_wbuffer_not_ni;
//RVFI
lsu_ctrl_t rvfi_lsu_ctrl;
logic [riscv::PLEN-1:0] rvfi_mem_paddr;
logic rvfi_is_compressed;
rvfi_probes_csr_t rvfi_csr;
lsu_ctrl_t rvfi_lsu_ctrl;
logic [riscv::PLEN-1:0] rvfi_mem_paddr;
logic rvfi_is_compressed;
rvfi_probes_csr_t rvfi_csr;
// Accelerator port
logic [ 63:0] inval_addr;
logic inval_valid;
logic inval_ready;
logic [ 63:0] inval_addr;
logic inval_valid;
logic inval_ready;
// --------------
// Frontend
@ -573,7 +591,9 @@ module cva6
.exception_t(exception_t),
.fetch_entry_t(fetch_entry_t),
.irq_ctrl_t(irq_ctrl_t),
.scoreboard_entry_t(scoreboard_entry_t)
.scoreboard_entry_t(scoreboard_entry_t),
.interrupts_t(interrupts_t),
.INTERRUPTS(INTERRUPTS)
) id_stage_i (
.clk_i,
.rst_ni,
@ -604,7 +624,7 @@ module cva6
.tsr_i (tsr_csr_id)
);
logic [CVA6Cfg.NrWbPorts-1:0][TRANS_ID_BITS-1:0] trans_id_ex_id;
logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_ex_id;
logic [CVA6Cfg.NrWbPorts-1:0][riscv::XLEN-1:0] wbdata_ex_id;
exception_t [CVA6Cfg.NrWbPorts-1:0] ex_ex_ex_id; // exception from execute, ex_stage to id_stage
logic [CVA6Cfg.NrWbPorts-1:0] wt_valid_ex_id;
@ -1373,7 +1393,8 @@ module cva6
for (genvar i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin : gen_pc_fifo
fifo_v3 #(
.DATA_WIDTH(64),
.DEPTH(PC_QUEUE_DEPTH)
.DEPTH(PC_QUEUE_DEPTH),
.FPGA_EN(CVA6Cfg.FPGA_EN)
) i_pc_fifo (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -1455,7 +1476,9 @@ module cva6
instr_tracer #(
.CVA6Cfg(CVA6Cfg),
.bp_resolve_t(bp_resolve_t),
.scoreboard_entry_t(scoreboard_entry_t)
.scoreboard_entry_t(scoreboard_entry_t),
.interrupts_t(interrupts_t),
.INTERRUPTS(INTERRUPTS)
) instr_tracer_i (
.tracer_if(tracer_if),
.hart_id_i

View file

@ -54,14 +54,17 @@ module cva6_rvfi
| ((riscv::XLEN == 64 ? 2 : 1) << riscv::XLEN - 2); // MXL
localparam logic [riscv::XLEN-1:0] hart_id_i = '0;
localparam logic [63:0] SMODE_STATUS_READ_MASK = ariane_pkg::smode_status_read_mask(CVA6Cfg);
logic flush;
logic issue_instr_ack;
logic fetch_entry_valid;
logic [31:0] instruction;
logic is_compressed;
logic [TRANS_ID_BITS-1:0] issue_pointer;
logic [CVA6Cfg.NrCommitPorts-1:0][TRANS_ID_BITS-1:0] commit_pointer;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer;
logic flush_unissued_instr;
logic decoded_instr_valid;
@ -71,7 +74,7 @@ module cva6_rvfi
logic [riscv::XLEN-1:0] rs2_forwarding;
logic [CVA6Cfg.NrCommitPorts-1:0][riscv::VLEN-1:0] commit_instr_pc;
fu_op [CVA6Cfg.NrCommitPorts-1:0][TRANS_ID_BITS-1:0] commit_instr_op;
fu_op [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_instr_op;
logic [CVA6Cfg.NrCommitPorts-1:0][REG_ADDR_SIZE-1:0] commit_instr_rs1;
logic [CVA6Cfg.NrCommitPorts-1:0][REG_ADDR_SIZE-1:0] commit_instr_rs2;
logic [CVA6Cfg.NrCommitPorts-1:0][REG_ADDR_SIZE-1:0] commit_instr_rd;
@ -86,7 +89,7 @@ module cva6_rvfi
logic [riscv::VLEN-1:0] lsu_ctrl_vaddr;
fu_t lsu_ctrl_fu;
logic [(riscv::XLEN/8)-1:0] lsu_ctrl_be;
logic [TRANS_ID_BITS-1:0] lsu_ctrl_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] lsu_ctrl_trans_id;
logic [((CVA6Cfg.CvxifEn || CVA6Cfg.RVV) ? 5 : 4)-1:0][riscv::XLEN-1:0] wbdata;
logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack;
@ -97,7 +100,7 @@ module cva6_rvfi
logic [riscv::VLEN-1:0] lsu_addr;
logic [(riscv::XLEN/8)-1:0] lsu_rmask;
logic [(riscv::XLEN/8)-1:0] lsu_wmask;
logic [TRANS_ID_BITS-1:0] lsu_addr_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] lsu_addr_trans_id;
riscv::pmpcfg_t [15:0] pmpcfg_q, pmpcfg_d;
@ -201,7 +204,7 @@ module cva6_rvfi
logic [riscv::XLEN-1:0] lsu_wdata;
logic [31:0] instr;
} sb_mem_t;
sb_mem_t [NR_SB_ENTRIES-1:0] mem_q, mem_n;
sb_mem_t [CVA6Cfg.NR_SB_ENTRIES-1:0] mem_q, mem_n;
always_comb begin : issue_fifo
mem_n = mem_q;
@ -311,8 +314,8 @@ module cva6_rvfi
: '0;
rvfi_csr_o.sstatus = CVA6Cfg.RVS ?
'{
rdata: csr.mstatus_extended & ariane_pkg::SMODE_STATUS_READ_MASK[riscv::XLEN-1:0],
wdata: csr.mstatus_extended & ariane_pkg::SMODE_STATUS_READ_MASK[riscv::XLEN-1:0],
rdata: csr.mstatus_extended & SMODE_STATUS_READ_MASK[riscv::XLEN-1:0],
wdata: csr.mstatus_extended & SMODE_STATUS_READ_MASK[riscv::XLEN-1:0],
rmask: '1,
wmask: '1
}

View file

@ -28,8 +28,8 @@ module cva6_rvfi_probes
input logic [31:0] instruction_i,
input logic is_compressed_i,
input logic [TRANS_ID_BITS-1:0] issue_pointer_i,
input logic [CVA6Cfg.NrCommitPorts-1:0][TRANS_ID_BITS-1:0] commit_pointer_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_i,
input logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer_i,
input logic flush_unissued_instr_i,
input logic decoded_instr_valid_i,

View file

@ -12,7 +12,9 @@
module cvxif_example_coprocessor
import cvxif_pkg::*;
import cvxif_instr_pkg::*;
(
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input cvxif_req_t cvxif_req_i,
@ -109,10 +111,11 @@ module cvxif_example_coprocessor
end
fifo_v3 #(
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
.DATA_WIDTH (64),
.DEPTH (8),
.dtype (x_issue_t)
.dtype (x_issue_t),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) fifo_commit_i (
.clk_i (clk_i),
.rst_ni (rst_ni),

View file

@ -18,38 +18,38 @@ module cvxif_fu
parameter type fu_data_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
input logic rst_ni,
// FU data needed to execute instruction - ISSUE_STAGE
input fu_data_t fu_data_i,
input fu_data_t fu_data_i,
// Current privilege mode - CSR_REGFILE
input riscv::priv_lvl_t priv_lvl_i,
input riscv::priv_lvl_t priv_lvl_i,
// CVXIF instruction is valid - ISSUE_STAGE
input logic x_valid_i,
input logic x_valid_i,
// CVXIF is ready - ISSUE_STAGE
output logic x_ready_o,
output logic x_ready_o,
// Offloaded instruction - ISSUE_STAGE
input logic [ 31:0] x_off_instr_i,
input logic [ 31:0] x_off_instr_i,
// CVXIF transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] x_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
// CVXIF exception - ISSUE_STAGE
output exception_t x_exception_o,
output exception_t x_exception_o,
// CVXIF FU result - ISSUE_STAGE
output logic [ riscv::XLEN-1:0] x_result_o,
output logic [ riscv::XLEN-1:0] x_result_o,
// CVXIF result valid - ISSUE_STAGE
output logic x_valid_o,
output logic x_valid_o,
// CVXIF write enable - ISSUE_STAGE
output logic x_we_o,
output logic x_we_o,
// CVXIF request - SUBSYSTEM
output cvxif_pkg::cvxif_req_t cvxif_req_o,
output cvxif_pkg::cvxif_req_t cvxif_req_o,
// CVXIF response - SUBSYSTEM
input cvxif_pkg::cvxif_resp_t cvxif_resp_i
input cvxif_pkg::cvxif_resp_t cvxif_resp_i
);
localparam X_NUM_RS = ariane_pkg::NR_RGPR_PORTS;
logic illegal_n, illegal_q;
logic [TRANS_ID_BITS-1:0] illegal_id_n, illegal_id_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] illegal_id_n, illegal_id_q;
logic [31:0] illegal_instr_n, illegal_instr_q;
logic [X_NUM_RS-1:0] rs_valid;

View file

@ -26,7 +26,9 @@ module decoder
parameter type branchpredict_sbe_t = logic,
parameter type exception_t = logic,
parameter type irq_ctrl_t = logic,
parameter type scoreboard_entry_t = logic
parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
) (
// Debug (async) request - SUBSYSTEM
input logic debug_req_i,
@ -1397,29 +1399,29 @@ module decoder
// for two privilege levels: Supervisor and Machine Mode
// Supervisor Timer Interrupt
if (irq_ctrl_i.mie[riscv::IRQ_S_TIMER] && irq_ctrl_i.mip[riscv::IRQ_S_TIMER]) begin
interrupt_cause = riscv::S_TIMER_INTERRUPT;
interrupt_cause = INTERRUPTS.S_TIMER;
end
// Supervisor Software Interrupt
if (irq_ctrl_i.mie[riscv::IRQ_S_SOFT] && irq_ctrl_i.mip[riscv::IRQ_S_SOFT]) begin
interrupt_cause = riscv::S_SW_INTERRUPT;
interrupt_cause = INTERRUPTS.S_SW;
end
// Supervisor External Interrupt
// The logical-OR of the software-writable bit and the signal from the external interrupt controller is
// used to generate external interrupts to the supervisor
if (irq_ctrl_i.mie[riscv::IRQ_S_EXT] && (irq_ctrl_i.mip[riscv::IRQ_S_EXT] | irq_i[ariane_pkg::SupervisorIrq])) begin
interrupt_cause = riscv::S_EXT_INTERRUPT;
interrupt_cause = INTERRUPTS.S_EXT;
end
// Machine Timer Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_TIMER] && irq_ctrl_i.mie[riscv::IRQ_M_TIMER]) begin
interrupt_cause = riscv::M_TIMER_INTERRUPT;
interrupt_cause = INTERRUPTS.M_TIMER;
end
// Machine Mode Software Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_SOFT] && irq_ctrl_i.mie[riscv::IRQ_M_SOFT]) begin
interrupt_cause = riscv::M_SW_INTERRUPT;
interrupt_cause = INTERRUPTS.M_SW;
end
// Machine Mode External Interrupt
if (irq_ctrl_i.mip[riscv::IRQ_M_EXT] && irq_ctrl_i.mie[riscv::IRQ_M_EXT]) begin
interrupt_cause = riscv::M_EXT_INTERRUPT;
interrupt_cause = INTERRUPTS.M_EXT;
end
if (interrupt_cause[riscv::XLEN-1] && irq_ctrl_i.global_enable) begin

View file

@ -52,7 +52,7 @@ module ex_stage
// Fixed Latency Unit result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] flu_result_o,
// ID of the scoreboard entry at which a=to write back - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] flu_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] flu_trans_id_o,
// Fixed Latency Unit exception - ISSUE_STAGE
output exception_t flu_exception_o,
// FLU is ready - ISSUE_STAGE
@ -86,7 +86,7 @@ module ex_stage
// Load result valid - ISSUE_STAGE
output logic [riscv::XLEN-1:0] load_result_o,
// Load instruction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] load_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] load_trans_id_o,
// Exception generated by load instruction - ISSUE_STAGE
output exception_t load_exception_o,
// Store result is valid - ISSUe_STAGE
@ -94,7 +94,7 @@ module ex_stage
// Store result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] store_result_o,
// Store instruction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] store_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] store_trans_id_o,
// Exception generated by store instruction - ISSUE_STAGE
output exception_t store_exception_o,
// LSU commit - COMMIT_STAGE
@ -102,7 +102,7 @@ module ex_stage
// Commit queue ready to accept another commit request - COMMIT_STAGE
output logic lsu_commit_ready_o,
// Commit transaction ID - COMMIT_STAGE
input logic [TRANS_ID_BITS-1:0] commit_tran_id_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] commit_tran_id_i,
// TO_BE_COMPLETED - ACC_DISPATCHER
input logic stall_st_pending_i,
// TO_BE_COMPLETED - COMMIT_STAGE
@ -122,7 +122,7 @@ module ex_stage
// FPU precision control - CSR_REGFILE
input logic [6:0] fpu_prec_i,
// FPU transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] fpu_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] fpu_trans_id_o,
// FPU result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] fpu_result_o,
// FPU valid - ISSUE_STAGE
@ -136,7 +136,7 @@ module ex_stage
// undecoded instruction - ISSUE_STAGE
input logic [31:0] x_off_instr_i,
// CVXIF transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] x_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] x_trans_id_o,
// CVXIF exception - ISSUE_STAGE
output exception_t x_exception_o,
// CVXIF result - ISSUE_STAGE
@ -166,7 +166,7 @@ module ex_stage
// Make executable readable - CSR_REGFILE
input logic mxr_i,
// TO_BE_COMPLETED - CSR_REGFILE
input logic [riscv::PPNW-1:0] satp_ppn_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i,
// TO_BE_COMPLETED - CSR_REGFILE
input logic [ASID_WIDTH-1:0] asid_i,
// icache translation response - CACHE
@ -231,7 +231,7 @@ module ex_stage
logic [riscv::XLEN-1:0] alu_result, csr_result, mult_result;
logic [riscv::VLEN-1:0] branch_result;
logic csr_ready, mult_ready;
logic [TRANS_ID_BITS-1:0] mult_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] mult_trans_id;
logic mult_valid;
// 1. ALU (combinatorial)

View file

@ -27,14 +27,14 @@ module fpu_wrap
output logic fpu_ready_o,
input fu_data_t fu_data_i,
input logic [ 1:0] fpu_fmt_i,
input logic [ 2:0] fpu_rm_i,
input logic [ 2:0] fpu_frm_i,
input logic [ 6:0] fpu_prec_i,
output logic [TRANS_ID_BITS-1:0] fpu_trans_id_o,
output logic [ CVA6Cfg.FLen-1:0] result_o,
output logic fpu_valid_o,
output exception_t fpu_exception_o
input logic [ 1:0] fpu_fmt_i,
input logic [ 2:0] fpu_rm_i,
input logic [ 2:0] fpu_frm_i,
input logic [ 6:0] fpu_prec_i,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] fpu_trans_id_o,
output logic [ CVA6Cfg.FLen-1:0] result_o,
output logic fpu_valid_o,
output exception_t fpu_exception_o
);
// this is a workaround
@ -110,7 +110,7 @@ module fpu_wrap
logic [2:0] fpu_rm_d, fpu_rm_q, fpu_rm;
logic fpu_vec_op_d, fpu_vec_op_q, fpu_vec_op;
logic [TRANS_ID_BITS-1:0] fpu_tag_d, fpu_tag_q, fpu_tag;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] fpu_tag_d, fpu_tag_q, fpu_tag;
logic fpu_in_ready, fpu_in_valid;
logic fpu_out_ready, fpu_out_valid;
@ -531,7 +531,7 @@ module fpu_wrap
fpnew_top #(
.Features (FPU_FEATURES),
.Implementation(FPU_IMPLEMENTATION),
.TagType (logic [TRANS_ID_BITS-1:0])
.TagType (logic [CVA6Cfg.TRANS_ID_BITS-1:0])
) i_fpnew_bulk (
.clk_i,
.rst_ni,

View file

@ -36,15 +36,15 @@ module bht #(
// Update bht with resolved address - EXECUTE
input bht_update_t bht_update_i,
// Prediction from bht - FRONTEND
output ariane_pkg::bht_prediction_t [ariane_pkg::INSTR_PER_FETCH-1:0] bht_prediction_o
output ariane_pkg::bht_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_prediction_o
);
// the last bit is always zero, we don't need it for indexing
localparam OFFSET = CVA6Cfg.RVC == 1'b1 ? 1 : 2;
// re-shape the branch history table
localparam NR_ROWS = NR_ENTRIES / ariane_pkg::INSTR_PER_FETCH;
localparam NR_ROWS = NR_ENTRIES / CVA6Cfg.INSTR_PER_FETCH;
// number of bits needed to index the row
localparam ROW_ADDR_BITS = $clog2(ariane_pkg::INSTR_PER_FETCH);
localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(ariane_pkg::INSTR_PER_FETCH) : 1;
localparam ROW_ADDR_BITS = $clog2(CVA6Cfg.INSTR_PER_FETCH);
localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(CVA6Cfg.INSTR_PER_FETCH) : 1;
// number of bits we should use for prediction
localparam PREDICTION_BITS = $clog2(NR_ROWS) + OFFSET + ROW_ADDR_BITS;
// we are not interested in all bits of the address
@ -54,8 +54,8 @@ module bht #(
logic valid;
logic [1:0] saturation_counter;
}
bht_d[NR_ROWS-1:0][ariane_pkg::INSTR_PER_FETCH-1:0],
bht_q[NR_ROWS-1:0][ariane_pkg::INSTR_PER_FETCH-1:0];
bht_d[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0],
bht_q[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0];
logic [$clog2(NR_ROWS)-1:0] index, update_pc;
logic [ROW_INDEX_BITS-1:0] update_row_index;
@ -68,11 +68,11 @@ module bht #(
assign update_row_index = '0;
end
if (!ariane_pkg::FPGA_EN) begin : gen_asic_bht // ASIC TARGET
if (!CVA6Cfg.FPGA_EN) begin : gen_asic_bht // ASIC TARGET
logic [1:0] saturation_counter;
// prediction assignment
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_bht_output
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_bht_output
assign bht_prediction_o[i].valid = bht_q[index][i].valid;
assign bht_prediction_o[i].taken = bht_q[index][i].saturation_counter[1] == 1'b1;
end
@ -104,7 +104,7 @@ module bht #(
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
for (int unsigned i = 0; i < NR_ROWS; i++) begin
for (int j = 0; j < ariane_pkg::INSTR_PER_FETCH; j++) begin
for (int j = 0; j < CVA6Cfg.INSTR_PER_FETCH; j++) begin
bht_q[i][j] <= '0;
end
end
@ -112,7 +112,7 @@ module bht #(
// evict all entries
if (flush_bp_i) begin
for (int i = 0; i < NR_ROWS; i++) begin
for (int j = 0; j < ariane_pkg::INSTR_PER_FETCH; j++) begin
for (int j = 0; j < CVA6Cfg.INSTR_PER_FETCH; j++) begin
bht_q[i][j].valid <= 1'b0;
bht_q[i][j].saturation_counter <= 2'b10;
end
@ -127,17 +127,17 @@ module bht #(
// number of bits par word in the bram
localparam BRAM_WORD_BITS = $bits(ariane_pkg::bht_t);
logic [ ROW_INDEX_BITS-1:0] row_index;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] bht_ram_we;
logic [ariane_pkg::INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_0;
logic [ariane_pkg::INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_1;
logic [ariane_pkg::INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_write_address;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_wdata;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_0;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_1;
logic [ ROW_INDEX_BITS-1:0] row_index;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht_ram_we;
logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_0;
logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_read_address_1;
logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] bht_ram_write_address;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_wdata;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_0;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] bht_ram_rdata_1;
ariane_pkg::bht_t [ ariane_pkg::INSTR_PER_FETCH-1:0] bht;
ariane_pkg::bht_t [ ariane_pkg::INSTR_PER_FETCH-1:0] bht_updated;
ariane_pkg::bht_t [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht;
ariane_pkg::bht_t [ CVA6Cfg.INSTR_PER_FETCH-1:0] bht_updated;
if (CVA6Cfg.RVC) begin : gen_row_index
assign row_index = vpc_i[ROW_ADDR_BITS+OFFSET-1:OFFSET];
@ -157,7 +157,7 @@ module bht #(
bht_updated = '0;
bht = '0;
for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
if (row_index == i) begin
bht_ram_read_address_0[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = index;
bht_prediction_o[i].valid = bht_ram_rdata_0[i*BRAM_WORD_BITS+2];
@ -166,7 +166,7 @@ module bht #(
end
if (bht_update_i.valid && !debug_mode_i) begin
for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
if (update_row_index == i) begin
bht_ram_read_address_1[i*$clog2(NR_ROWS)+:$clog2(NR_ROWS)] = update_pc;
bht[i].saturation_counter = bht_ram_rdata_1[i*BRAM_WORD_BITS+:2];
@ -201,7 +201,7 @@ module bht #(
end
end
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_bht_ram
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_bht_ram
AsyncThreePortRam #(
.ADDR_WIDTH($clog2(NR_ROWS)),
.DATA_DEPTH(NR_ROWS),

View file

@ -44,15 +44,15 @@ module btb #(
// Update BTB with resolved address - EXECUTE
input btb_update_t btb_update_i,
// BTB Prediction - FRONTEND
output btb_prediction_t [ariane_pkg::INSTR_PER_FETCH-1:0] btb_prediction_o
output btb_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] btb_prediction_o
);
// the last bit is always zero, we don't need it for indexing
localparam OFFSET = CVA6Cfg.RVC == 1'b1 ? 1 : 2;
// re-shape the branch history table
localparam NR_ROWS = NR_ENTRIES / ariane_pkg::INSTR_PER_FETCH;
localparam NR_ROWS = NR_ENTRIES / CVA6Cfg.INSTR_PER_FETCH;
// number of bits needed to index the row
localparam ROW_ADDR_BITS = $clog2(ariane_pkg::INSTR_PER_FETCH);
localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(ariane_pkg::INSTR_PER_FETCH) : 1;
localparam ROW_ADDR_BITS = $clog2(CVA6Cfg.INSTR_PER_FETCH);
localparam ROW_INDEX_BITS = CVA6Cfg.RVC == 1'b1 ? $clog2(CVA6Cfg.INSTR_PER_FETCH) : 1;
// number of bits we should use for prediction
localparam PREDICTION_BITS = $clog2(NR_ROWS) + OFFSET + ROW_ADDR_BITS;
// prevent aliasing to degrade performance
@ -74,20 +74,20 @@ module btb #(
assign update_row_index = '0;
end
if (ariane_pkg::FPGA_EN) begin : gen_fpga_btb //FPGA TARGETS
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] btb_ram_csel_prediction;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] btb_ram_we_prediction;
logic [ariane_pkg::INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] btb_ram_addr_prediction;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_wdata_prediction;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_rdata_prediction;
if (CVA6Cfg.FPGA_EN) begin : gen_fpga_btb //FPGA TARGETS
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] btb_ram_csel_prediction;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] btb_ram_we_prediction;
logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] btb_ram_addr_prediction;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_wdata_prediction;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_rdata_prediction;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] btb_ram_csel_update;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] btb_ram_we_update;
logic [ariane_pkg::INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] btb_ram_addr_update;
logic [ ariane_pkg::INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_wdata_update;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] btb_ram_csel_update;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] btb_ram_we_update;
logic [CVA6Cfg.INSTR_PER_FETCH*$clog2(NR_ROWS)-1:0] btb_ram_addr_update;
logic [ CVA6Cfg.INSTR_PER_FETCH*BRAM_WORD_BITS-1:0] btb_ram_wdata_update;
// output matching prediction
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_btb_output
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_btb_output
assign btb_ram_csel_prediction[i] = 1'b1;
assign btb_ram_we_prediction[i] = 1'b0;
assign btb_ram_wdata_prediction = '0;
@ -106,7 +106,7 @@ module btb #(
btb_ram_wdata_update = '0;
if (btb_update_i.valid && !debug_mode_i) begin
for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
if (update_row_index == i) begin
btb_ram_csel_update[i] = 1'b1;
btb_ram_we_update[i] = 1'b1;
@ -119,7 +119,7 @@ module btb #(
end
end
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_btb_ram
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_btb_ram
SyncDpRam #(
.ADDR_WIDTH($clog2(NR_ROWS)),
.DATA_DEPTH(NR_ROWS),
@ -149,11 +149,11 @@ module btb #(
// typedef for all branch target entries
// we may want to try to put a tag field that fills the rest of the PC in-order to mitigate aliasing effects
btb_prediction_t
btb_d[NR_ROWS-1:0][ariane_pkg::INSTR_PER_FETCH-1:0],
btb_q[NR_ROWS-1:0][ariane_pkg::INSTR_PER_FETCH-1:0];
btb_d[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0],
btb_q[NR_ROWS-1:0][CVA6Cfg.INSTR_PER_FETCH-1:0];
// output matching prediction
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_btb_output
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_btb_output
assign btb_prediction_o[i] = btb_q[index][i]; // workaround
end
@ -180,7 +180,7 @@ module btb #(
// evict all entries
if (flush_bp_i) begin
for (int i = 0; i < NR_ROWS; i++) begin
for (int j = 0; j < ariane_pkg::INSTR_PER_FETCH; j++) begin
for (int j = 0; j < CVA6Cfg.INSTR_PER_FETCH; j++) begin
btb_q[i][j].valid <= 1'b0;
end
end

View file

@ -89,30 +89,30 @@ module frontend
};
// Instruction Cache Registers, from I$
logic [ FETCH_WIDTH-1:0] icache_data_q;
logic icache_valid_q;
ariane_pkg::frontend_exception_t icache_ex_valid_q;
logic [ riscv::VLEN-1:0] icache_vaddr_q;
logic instr_queue_ready;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_consumed;
logic [ CVA6Cfg.FETCH_WIDTH-1:0] icache_data_q;
logic icache_valid_q;
ariane_pkg::frontend_exception_t icache_ex_valid_q;
logic [ riscv::VLEN-1:0] icache_vaddr_q;
logic instr_queue_ready;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] instr_queue_consumed;
// upper-most branch-prediction from last cycle
btb_prediction_t btb_q;
bht_prediction_t bht_q;
btb_prediction_t btb_q;
bht_prediction_t bht_q;
// instruction fetch is ready
logic if_ready;
logic if_ready;
logic [riscv::VLEN-1:0] npc_d, npc_q; // next PC
// indicates whether we come out of reset (then we need to load boot_addr_i)
logic npc_rst_load_q;
logic npc_rst_load_q;
logic replay;
logic [ riscv::VLEN-1:0] replay_addr;
logic replay;
logic [ riscv::VLEN-1:0] replay_addr;
// shift amount
logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] shamt;
logic [$clog2(CVA6Cfg.INSTR_PER_FETCH)-1:0] shamt;
// address will always be 16 bit aligned, make this explicit here
if (CVA6Cfg.RVC) begin : gen_shamt
assign shamt = icache_dreq_i.vaddr[$clog2(ariane_pkg::INSTR_PER_FETCH):1];
assign shamt = icache_dreq_i.vaddr[$clog2(CVA6Cfg.INSTR_PER_FETCH):1];
end else begin
assign shamt = 1'b0;
end
@ -121,35 +121,35 @@ module frontend
// Ctrl Flow Speculation
// -----------------------
// RVI ctrl flow prediction
logic [INSTR_PER_FETCH-1:0] rvi_return, rvi_call, rvi_branch, rvi_jalr, rvi_jump;
logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvi_imm;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] rvi_return, rvi_call, rvi_branch, rvi_jalr, rvi_jump;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvi_imm;
// RVC branching
logic [INSTR_PER_FETCH-1:0] rvc_branch, rvc_jump, rvc_jr, rvc_return, rvc_jalr, rvc_call;
logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvc_imm;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] rvc_branch, rvc_jump, rvc_jr, rvc_return, rvc_jalr, rvc_call;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvc_imm;
// re-aligned instruction and address (coming from cache - combinationally)
logic [INSTR_PER_FETCH-1:0][ 31:0] instr;
logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr;
logic [INSTR_PER_FETCH-1:0] instruction_valid;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][ 31:0] instr;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] instruction_valid;
// BHT, BTB and RAS prediction
bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction;
btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction;
bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction_shifted;
btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction_shifted;
ras_t ras_predict;
logic [ riscv::VLEN-1:0] vpc_btb;
bht_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_prediction;
btb_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] btb_prediction;
bht_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] bht_prediction_shifted;
btb_prediction_t [CVA6Cfg.INSTR_PER_FETCH-1:0] btb_prediction_shifted;
ras_t ras_predict;
logic [ riscv::VLEN-1:0] vpc_btb;
// branch-predict update
logic is_mispredict;
logic is_mispredict;
logic ras_push, ras_pop;
logic [ riscv::VLEN-1:0] ras_update;
logic [ riscv::VLEN-1:0] ras_update;
// Instruction FIFO
logic [ riscv::VLEN-1:0] predict_address;
cf_t [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvi_cf;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvc_cf;
logic [ riscv::VLEN-1:0] predict_address;
cf_t [CVA6Cfg.INSTR_PER_FETCH-1:0] cf_type;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] taken_rvi_cf;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] taken_rvc_cf;
logic serving_unaligned;
logic serving_unaligned;
// Re-align instructions
instr_realign #(
.CVA6Cfg(CVA6Cfg)
@ -174,17 +174,17 @@ module frontend
// the prediction we saved from the previous fetch
if (CVA6Cfg.RVC) begin : gen_btb_prediction_shifted
assign bht_prediction_shifted[0] = (serving_unaligned) ? bht_q : bht_prediction[addr[0][$clog2(
INSTR_PER_FETCH
CVA6Cfg.INSTR_PER_FETCH
):1]];
assign btb_prediction_shifted[0] = (serving_unaligned) ? btb_q : btb_prediction[addr[0][$clog2(
INSTR_PER_FETCH
CVA6Cfg.INSTR_PER_FETCH
):1]];
// for all other predictions we can use the generated address to index
// into the branch prediction data structures
for (genvar i = 1; i < INSTR_PER_FETCH; i++) begin : gen_prediction_address
assign bht_prediction_shifted[i] = bht_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
assign btb_prediction_shifted[i] = btb_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
for (genvar i = 1; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_prediction_address
assign bht_prediction_shifted[i] = bht_prediction[addr[i][$clog2(CVA6Cfg.INSTR_PER_FETCH):1]];
assign btb_prediction_shifted[i] = btb_prediction[addr[i][$clog2(CVA6Cfg.INSTR_PER_FETCH):1]];
end
end else begin
assign bht_prediction_shifted[0] = (serving_unaligned) ? bht_q : bht_prediction[addr[0][1]];
@ -196,13 +196,13 @@ module frontend
// address of the call/return already
logic bp_valid;
logic [INSTR_PER_FETCH-1:0] is_branch;
logic [INSTR_PER_FETCH-1:0] is_call;
logic [INSTR_PER_FETCH-1:0] is_jump;
logic [INSTR_PER_FETCH-1:0] is_return;
logic [INSTR_PER_FETCH-1:0] is_jalr;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] is_branch;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] is_call;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] is_jump;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] is_return;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] is_jalr;
for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
// branch history table -> BHT
assign is_branch[i] = instruction_valid[i] & (rvi_branch[i] | rvc_branch[i]);
// function calls -> RAS
@ -221,14 +221,14 @@ module frontend
taken_rvc_cf = '0;
predict_address = '0;
for (int i = 0; i < INSTR_PER_FETCH; i++) cf_type[i] = ariane_pkg::NoCF;
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) cf_type[i] = ariane_pkg::NoCF;
ras_push = 1'b0;
ras_pop = 1'b0;
ras_update = '0;
// lower most prediction gets precedence
for (int i = INSTR_PER_FETCH - 1; i >= 0; i--) begin
for (int i = CVA6Cfg.INSTR_PER_FETCH - 1; i >= 0; i--) begin
unique case ({
is_branch[i], is_return[i], is_jump[i], is_jalr[i]
})
@ -297,7 +297,7 @@ module frontend
// BP cannot be valid if we have a return instruction and the RAS is not giving a valid address
// Check that we encountered a control flow and that for a return the RAS
// contains a valid prediction.
for (int i = 0; i < INSTR_PER_FETCH; i++)
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++)
bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid));
end
assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;
@ -406,7 +406,7 @@ module frontend
icache_dreq_o.vaddr = fetch_address;
end
logic [FETCH_WIDTH-1:0] icache_data;
logic [CVA6Cfg.FETCH_WIDTH-1:0] icache_data;
// re-align the cache line
assign icache_data = icache_dreq_i.data >> {shamt, 4'b0};
@ -438,8 +438,8 @@ module frontend
icache_ex_valid_q <= ariane_pkg::FE_NONE;
end
// save the uppermost prediction
btb_q <= btb_prediction[INSTR_PER_FETCH-1];
bht_q <= bht_prediction[INSTR_PER_FETCH-1];
btb_q <= btb_prediction[CVA6Cfg.INSTR_PER_FETCH-1];
bht_q <= bht_prediction[CVA6Cfg.INSTR_PER_FETCH-1];
end
end
end
@ -465,7 +465,7 @@ module frontend
//For FPGA, BTB is implemented in read synchronous BRAM
//while for ASIC, BTB is implemented in D flip-flop
//and can be read at the same cycle.
assign vpc_btb = (ariane_pkg::FPGA_EN) ? icache_dreq_i.vaddr : icache_vaddr_q;
assign vpc_btb = (CVA6Cfg.FPGA_EN) ? icache_dreq_i.vaddr : icache_vaddr_q;
if (CVA6Cfg.BTBEntries == 0) begin
assign btb_prediction = '0;
@ -504,9 +504,9 @@ module frontend
);
end
// we need to inspect up to INSTR_PER_FETCH instructions for branches
// we need to inspect up to CVA6Cfg.INSTR_PER_FETCH instructions for branches
// and jumps
for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin : gen_instr_scan
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_instr_scan
instr_scan #(
.CVA6Cfg(CVA6Cfg)
) i_instr_scan (
@ -553,7 +553,7 @@ module frontend
// pragma translate_off
`ifndef VERILATOR
initial begin
assert (FETCH_WIDTH == 32 || FETCH_WIDTH == 64)
assert (CVA6Cfg.FETCH_WIDTH == 32 || CVA6Cfg.FETCH_WIDTH == 64)
else $fatal(1, "[frontend] fetch width != not supported");
end
`endif

View file

@ -56,15 +56,15 @@ module instr_queue
// Fetch flush request - CONTROLLER
input logic flush_i,
// Instruction - instr_realign
input logic [ariane_pkg::INSTR_PER_FETCH-1:0][31:0] instr_i,
input logic [CVA6Cfg.INSTR_PER_FETCH-1:0][31:0] instr_i,
// Instruction address - instr_realign
input logic [ariane_pkg::INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i,
input logic [CVA6Cfg.INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i,
// Instruction is valid - instr_realign
input logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid_i,
input logic [CVA6Cfg.INSTR_PER_FETCH-1:0] valid_i,
// Handshakes ready with CACHE - CACHE
output logic ready_o,
// Indicates instructions consummed, or popped by ID_STAGE - FRONTEND
output logic [ariane_pkg::INSTR_PER_FETCH-1:0] consumed_o,
output logic [CVA6Cfg.INSTR_PER_FETCH-1:0] consumed_o,
// Exception (which is page-table fault) - CACHE
input ariane_pkg::frontend_exception_t exception_i,
// Exception address - CACHE
@ -72,7 +72,7 @@ module instr_queue
// Branch predict - FRONTEND
input logic [riscv::VLEN-1:0] predict_address_i,
// Instruction predict address - FRONTEND
input ariane_pkg::cf_t [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type_i,
input ariane_pkg::cf_t [CVA6Cfg.INSTR_PER_FETCH-1:0] cf_type_i,
// Replay instruction because one of the FIFO was full - FRONTEND
output logic replay_o,
// Address at which to replay the fetch - FRONTEND
@ -92,16 +92,16 @@ module instr_queue
logic [riscv::VLEN-1:0] ex_vaddr; // lower VLEN bits of tval for exception
} instr_data_t;
logic [ariane_pkg::LOG2_INSTR_PER_FETCH-1:0] branch_index;
logic [CVA6Cfg.LOG2_INSTR_PER_FETCH-1:0] branch_index;
// instruction queues
logic [ariane_pkg::INSTR_PER_FETCH-1:0][$clog2(
logic [CVA6Cfg.INSTR_PER_FETCH-1:0][$clog2(
ariane_pkg::FETCH_FIFO_DEPTH
)-1:0] instr_queue_usage;
instr_data_t [ariane_pkg::INSTR_PER_FETCH-1:0] instr_data_in, instr_data_out;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] push_instr, push_instr_fifo;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] pop_instr;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_full;
logic [ ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_empty;
instr_data_t [CVA6Cfg.INSTR_PER_FETCH-1:0] instr_data_in, instr_data_out;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] push_instr, push_instr_fifo;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] pop_instr;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] instr_queue_full;
logic [ CVA6Cfg.INSTR_PER_FETCH-1:0] instr_queue_empty;
logic instr_overflow;
// address queue
logic [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] address_queue_usage;
@ -112,42 +112,42 @@ ariane_pkg::FETCH_FIFO_DEPTH
logic empty_address;
logic address_overflow;
// input stream counter
logic [ariane_pkg::LOG2_INSTR_PER_FETCH-1:0] idx_is_d, idx_is_q;
logic [CVA6Cfg.LOG2_INSTR_PER_FETCH-1:0] idx_is_d, idx_is_q;
// Registers
// output FIFO select, one-hot
logic [ariane_pkg::INSTR_PER_FETCH-1:0] idx_ds_d, idx_ds_q;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] idx_ds_d, idx_ds_q;
logic [riscv::VLEN-1:0] pc_d, pc_q; // current PC
logic reset_address_d, reset_address_q; // we need to re-set the address because of a flush
logic [ariane_pkg::INSTR_PER_FETCH*2-2:0] branch_mask_extended;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] branch_mask;
logic [CVA6Cfg.INSTR_PER_FETCH*2-2:0] branch_mask_extended;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] branch_mask;
logic branch_empty;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] taken;
// shift amount, e.g.: instructions we want to retire
logic [ariane_pkg::LOG2_INSTR_PER_FETCH:0] popcount;
logic [ariane_pkg::LOG2_INSTR_PER_FETCH-1:0] shamt;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid;
logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] consumed_extended;
logic [CVA6Cfg.LOG2_INSTR_PER_FETCH:0] popcount;
logic [CVA6Cfg.LOG2_INSTR_PER_FETCH-1:0] shamt;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] valid;
logic [CVA6Cfg.INSTR_PER_FETCH*2-1:0] consumed_extended;
// FIFO mask
logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] fifo_pos_extended;
logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_pos;
logic [ariane_pkg::INSTR_PER_FETCH*2-1:0][31:0] instr;
ariane_pkg::cf_t [ariane_pkg::INSTR_PER_FETCH*2-1:0] cf;
logic [CVA6Cfg.INSTR_PER_FETCH*2-1:0] fifo_pos_extended;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] fifo_pos;
logic [CVA6Cfg.INSTR_PER_FETCH*2-1:0][31:0] instr;
ariane_pkg::cf_t [CVA6Cfg.INSTR_PER_FETCH*2-1:0] cf;
// replay interface
logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_overflow_fifo;
logic [CVA6Cfg.INSTR_PER_FETCH-1:0] instr_overflow_fifo;
assign ready_o = ~(|instr_queue_full) & ~full_address;
if (ariane_pkg::RVC) begin : gen_multiple_instr_per_fetch_with_C
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_unpack_taken
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_unpack_taken
assign taken[i] = cf_type_i[i] != ariane_pkg::NoCF;
end
// calculate a branch mask, e.g.: get the first taken branch
lzc #(
.WIDTH(ariane_pkg::INSTR_PER_FETCH),
.MODE (0) // count trailing zeros
.WIDTH(CVA6Cfg.INSTR_PER_FETCH),
.MODE (0) // count trailing zeros
) i_lzc_branch_index (
.in_i (taken), // we want to count trailing zeros
.cnt_o (branch_index), // first branch on branch_index
@ -161,17 +161,17 @@ ariane_pkg::FETCH_FIFO_DEPTH
// leading zero count = 1
// 0 0 0 1, 1 1 1 << 1 = 0 0 1 1, 1 1 0
// take the upper 4 bits: 0 0 1 1
assign branch_mask_extended = {{{ariane_pkg::INSTR_PER_FETCH-1}{1'b0}}, {{ariane_pkg::INSTR_PER_FETCH}{1'b1}}} << branch_index;
assign branch_mask = branch_mask_extended[ariane_pkg::INSTR_PER_FETCH * 2 - 2:ariane_pkg::INSTR_PER_FETCH - 1];
assign branch_mask_extended = {{{CVA6Cfg.INSTR_PER_FETCH-1}{1'b0}}, {{CVA6Cfg.INSTR_PER_FETCH}{1'b1}}} << branch_index;
assign branch_mask = branch_mask_extended[CVA6Cfg.INSTR_PER_FETCH * 2 - 2:CVA6Cfg.INSTR_PER_FETCH - 1];
// mask with taken branches to get the actual amount of instructions we want to push
assign valid = valid_i & branch_mask;
// rotate right again
assign consumed_extended = {push_instr_fifo, push_instr_fifo} >> idx_is_q;
assign consumed_o = consumed_extended[ariane_pkg::INSTR_PER_FETCH-1:0];
assign consumed_o = consumed_extended[CVA6Cfg.INSTR_PER_FETCH-1:0];
// count the numbers of valid instructions we've pushed from this package
popcount #(
.INPUT_WIDTH(ariane_pkg::INSTR_PER_FETCH)
.INPUT_WIDTH(CVA6Cfg.INSTR_PER_FETCH)
) i_popcount (
.data_i (push_instr_fifo),
.popcount_o(popcount)
@ -187,21 +187,21 @@ ariane_pkg::FETCH_FIFO_DEPTH
// rotate left by the current position
assign fifo_pos_extended = {valid, valid} << idx_is_q;
// we just care about the upper bits
assign fifo_pos = fifo_pos_extended[ariane_pkg::INSTR_PER_FETCH*2-1:ariane_pkg::INSTR_PER_FETCH];
assign fifo_pos = fifo_pos_extended[CVA6Cfg.INSTR_PER_FETCH*2-1:CVA6Cfg.INSTR_PER_FETCH];
// the fifo_position signal can directly be used to guide the push signal of each FIFO
// make sure it is not full
assign push_instr = fifo_pos & ~instr_queue_full;
// duplicate the entries for easier selection e.g.: 3 2 1 0 3 2 1 0
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input
assign instr[i] = instr_i[i];
assign instr[i+ariane_pkg::INSTR_PER_FETCH] = instr_i[i];
assign instr[i+CVA6Cfg.INSTR_PER_FETCH] = instr_i[i];
assign cf[i] = cf_type_i[i];
assign cf[i+ariane_pkg::INSTR_PER_FETCH] = cf_type_i[i];
assign cf[i+CVA6Cfg.INSTR_PER_FETCH] = cf_type_i[i];
end
// shift the inputs
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_fifo_input_select
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_fifo_input_select
/* verilator lint_off WIDTH */
assign instr_data_in[i].instr = instr[i+idx_is_q];
assign instr_data_in[i].cf = cf[i+idx_is_q];
@ -287,7 +287,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
fetch_entry_o.branch_predict.predict_address = address_out;
fetch_entry_o.branch_predict.cf = ariane_pkg::NoCF;
// output mux select
for (int unsigned i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
if (idx_ds_q[i]) begin
if (instr_data_out[i].ex == ariane_pkg::FE_INSTR_ACCESS_FAULT) begin
fetch_entry_o.ex.cause = riscv::INSTR_ACCESS_FAULT;
@ -306,9 +306,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
end
// rotate the pointer left
if (fetch_entry_ready_i) begin
idx_ds_d = {
idx_ds_q[ariane_pkg::INSTR_PER_FETCH-2:0], idx_ds_q[ariane_pkg::INSTR_PER_FETCH-1]
};
idx_ds_d = {idx_ds_q[CVA6Cfg.INSTR_PER_FETCH-2:0], idx_ds_q[CVA6Cfg.INSTR_PER_FETCH-1]};
end
end
end else begin : gen_downstream_itf_without_c
@ -366,12 +364,13 @@ ariane_pkg::FETCH_FIFO_DEPTH
end
// FIFOs
for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_instr_fifo
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_instr_fifo
// Make sure we don't save any instructions if we couldn't save the address
assign push_instr_fifo[i] = push_instr[i] & ~address_overflow;
fifo_v3 #(
.DEPTH(ariane_pkg::FETCH_FIFO_DEPTH),
.dtype(instr_data_t)
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH),
.dtype (instr_data_t),
.FPGA_EN(CVA6Cfg.FPGA_EN)
) i_fifo_instr_data (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -391,14 +390,15 @@ ariane_pkg::FETCH_FIFO_DEPTH
always_comb begin
push_address = 1'b0;
// check if we are pushing a ctrl flow change, if so save the address
for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
for (int i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
push_address |= push_instr[i] & (instr_data_in[i].cf != ariane_pkg::NoCF);
end
end
fifo_v3 #(
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH), // TODO(zarubaf): Fork out to separate param
.DATA_WIDTH(riscv::VLEN)
.DATA_WIDTH(riscv::VLEN),
.FPGA_EN (CVA6Cfg.FPGA_EN)
) i_fifo_address (
.clk_i (clk_i),
.rst_ni (rst_ni),

View file

@ -19,7 +19,9 @@ module id_stage #(
parameter type exception_t = logic,
parameter type fetch_entry_t = logic,
parameter type irq_ctrl_t = logic,
parameter type scoreboard_entry_t = logic
parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
@ -149,7 +151,9 @@ module id_stage #(
.branchpredict_sbe_t(branchpredict_sbe_t),
.exception_t(exception_t),
.irq_ctrl_t(irq_ctrl_t),
.scoreboard_entry_t(scoreboard_entry_t)
.scoreboard_entry_t(scoreboard_entry_t),
.interrupts_t(interrupts_t),
.INTERRUPTS(INTERRUPTS)
) decoder_i (
.debug_req_i,
.irq_ctrl_i,

View file

@ -29,11 +29,6 @@
package ariane_pkg;
// TODO: Slowly move those parameters to the new system.
localparam NR_SB_ENTRIES = cva6_config_pkg::CVA6ConfigNrScoreboardEntries; // number of scoreboard entries
localparam TRANS_ID_BITS = $clog2(
NR_SB_ENTRIES
); // depending on the number of scoreboard entries we need that many bits
// to uniquely identify the entry in the scoreboard
localparam ASID_WIDTH = (riscv::XLEN == 64) ? 16 : 1;
localparam BITS_SATURATION_COUNTER = 2;
@ -51,8 +46,6 @@ package ariane_pkg;
// allocate more space for the commit buffer to be on the save side, this needs to be a power of two
localparam logic [2:0] DEPTH_COMMIT = 'd4;
localparam bit FPGA_EN = cva6_config_pkg::CVA6ConfigFPGAEn; // Is FPGA optimization of CV32A6
localparam bit RVC = cva6_config_pkg::CVA6ConfigCExtEn; // Is C extension configuration
// Transprecision float unit
@ -120,19 +113,22 @@ package ariane_pkg;
`else
localparam bit ZERO_TVAL = 1'b0;
`endif
// read mask for SSTATUS over MMSTATUS
localparam logic [63:0] SMODE_STATUS_READ_MASK = riscv::SSTATUS_UIE
| riscv::SSTATUS_SIE
| riscv::SSTATUS_SPIE
| riscv::SSTATUS_SPP
| riscv::SSTATUS_FS
| riscv::SSTATUS_XS
| riscv::SSTATUS_SUM
| riscv::SSTATUS_MXR
| riscv::SSTATUS_UPIE
| riscv::SSTATUS_SPIE
| riscv::SSTATUS_UXL
| riscv::SSTATUS_SD;
function automatic logic [63:0] smode_status_read_mask(config_pkg::cva6_cfg_t Cfg);
return riscv::SSTATUS_UIE
| riscv::SSTATUS_SIE
| riscv::SSTATUS_SPIE
| riscv::SSTATUS_SPP
| riscv::SSTATUS_FS
| riscv::SSTATUS_XS
| riscv::SSTATUS_SUM
| riscv::SSTATUS_MXR
| riscv::SSTATUS_UPIE
| riscv::SSTATUS_SPIE
| riscv::SSTATUS_UXL
| riscv::sstatus_sd(riscv::IS_XLEN64);
endfunction
localparam logic [63:0] SMODE_STATUS_WRITE_MASK = riscv::SSTATUS_SIE
| riscv::SSTATUS_SPIE
@ -144,12 +140,8 @@ package ariane_pkg;
// AXI
// ---------------
localparam FETCH_USER_WIDTH = cva6_config_pkg::CVA6ConfigFetchUserWidth;
localparam DATA_USER_WIDTH = cva6_config_pkg::CVA6ConfigDataUserWidth;
localparam AXI_USER_EN = cva6_config_pkg::CVA6ConfigDataUserEn | cva6_config_pkg::CVA6ConfigFetchUserEn;
localparam AXI_USER_WIDTH = cva6_config_pkg::CVA6ConfigDataUserWidth;
localparam DATA_USER_EN = cva6_config_pkg::CVA6ConfigDataUserEn;
localparam FETCH_USER_EN = cva6_config_pkg::CVA6ConfigFetchUserEn;
typedef enum logic {
SINGLE_REQ,
@ -162,10 +154,6 @@ package ariane_pkg;
// leave as is (fails with >8 entries and wider fetch width)
localparam int unsigned FETCH_FIFO_DEPTH = 4;
localparam int unsigned FETCH_WIDTH = 32;
// maximum instructions we can fetch on one request (we support compressed instructions)
localparam int unsigned INSTR_PER_FETCH = RVC == 1'b1 ? (FETCH_WIDTH / 16) : 1;
localparam int unsigned LOG2_INSTR_PER_FETCH = RVC == 1'b1 ? $clog2(INSTR_PER_FETCH) : 1;
typedef enum logic [2:0] {
NoCF, // No control flow prediction
@ -251,29 +239,9 @@ package ariane_pkg;
localparam int unsigned DCACHE_INDEX_WIDTH = $clog2(`CONFIG_L1D_SIZE / DCACHE_SET_ASSOC);
localparam int unsigned DCACHE_TAG_WIDTH = riscv::PLEN - DCACHE_INDEX_WIDTH;
localparam int unsigned DCACHE_USER_LINE_WIDTH = (AXI_USER_WIDTH == 1) ? 4 : 128; // in bit
localparam int unsigned DCACHE_USER_WIDTH = DATA_USER_WIDTH;
localparam int unsigned DCACHE_USER_WIDTH = cva6_config_pkg::CVA6ConfigDataUserWidth;
localparam int unsigned MEM_TID_WIDTH = `L15_THREADID_WIDTH;
`else
// I$
localparam int unsigned CONFIG_L1I_SIZE = cva6_config_pkg::CVA6ConfigIcacheByteSize; // in byte
localparam int unsigned ICACHE_SET_ASSOC = cva6_config_pkg::CVA6ConfigIcacheSetAssoc; // number of ways
localparam int unsigned ICACHE_INDEX_WIDTH = $clog2(
CONFIG_L1I_SIZE / ICACHE_SET_ASSOC
); // in bit, contains also offset width
localparam int unsigned ICACHE_TAG_WIDTH = riscv::PLEN - ICACHE_INDEX_WIDTH; // in bit
localparam int unsigned ICACHE_LINE_WIDTH = cva6_config_pkg::CVA6ConfigIcacheLineWidth; // in bit
localparam int unsigned ICACHE_USER_LINE_WIDTH = (AXI_USER_WIDTH == 1) ? 4 : cva6_config_pkg::CVA6ConfigIcacheLineWidth; // in bit
// D$
localparam int unsigned CONFIG_L1D_SIZE = cva6_config_pkg::CVA6ConfigDcacheByteSize; // in byte
localparam int unsigned DCACHE_SET_ASSOC = cva6_config_pkg::CVA6ConfigDcacheSetAssoc; // number of ways
localparam int unsigned DCACHE_INDEX_WIDTH = $clog2(
CONFIG_L1D_SIZE / DCACHE_SET_ASSOC
); // in bit, contains also offset width
localparam int unsigned DCACHE_TAG_WIDTH = riscv::PLEN - DCACHE_INDEX_WIDTH; // in bit
localparam int unsigned DCACHE_LINE_WIDTH = cva6_config_pkg::CVA6ConfigDcacheLineWidth; // in bit
localparam int unsigned DCACHE_USER_LINE_WIDTH = (AXI_USER_WIDTH == 1) ? 4 : cva6_config_pkg::CVA6ConfigDcacheLineWidth; // in bit
localparam int unsigned DCACHE_USER_WIDTH = DATA_USER_WIDTH;
`endif
localparam int unsigned DCACHE_TID_WIDTH = cva6_config_pkg::CVA6ConfigDcacheIdWidth;

View file

@ -21,8 +21,15 @@ package build_config_pkg;
bit EnableAccelerator = CVA6Cfg.RVV; // Currently only used by V extension (Ara)
int unsigned NrWbPorts = (CVA6Cfg.CvxifEn || EnableAccelerator) ? 5 : 4;
int unsigned ICACHE_INDEX_WIDTH = $clog2(CVA6Cfg.IcacheByteSize / CVA6Cfg.IcacheSetAssoc);
int unsigned DCACHE_INDEX_WIDTH = $clog2(CVA6Cfg.DcacheByteSize / CVA6Cfg.DcacheSetAssoc);
int unsigned DCACHE_OFFSET_WIDTH = $clog2(CVA6Cfg.DcacheLineWidth / 8);
config_pkg::cva6_cfg_t cfg;
cfg.XLEN_ALIGN_BYTES = $clog2(riscv::XLEN / 8);
cfg.FPGA_EN = CVA6Cfg.FPGA_EN;
cfg.NrCommitPorts = CVA6Cfg.NrCommitPorts;
cfg.AxiAddrWidth = CVA6Cfg.AxiAddrWidth;
cfg.AxiDataWidth = CVA6Cfg.AxiDataWidth;
@ -43,6 +50,8 @@ package build_config_pkg;
cfg.XFVec = CVA6Cfg.XFVec;
cfg.CvxifEn = CVA6Cfg.CvxifEn;
cfg.ZiCondExtEn = CVA6Cfg.ZiCondExtEn;
cfg.NR_SB_ENTRIES = CVA6Cfg.NrScoreboardEntries;
cfg.TRANS_ID_BITS = $clog2(CVA6Cfg.NrScoreboardEntries);
cfg.RVF = bit'(RVF);
cfg.RVD = bit'(RVD);
@ -85,8 +94,38 @@ package build_config_pkg;
cfg.NonIdemPotenceEn = CVA6Cfg.NrNonIdempotentRules && CVA6Cfg.NonIdempotentLength;
cfg.AxiBurstWriteEn = CVA6Cfg.AxiBurstWriteEn;
cfg.ICACHE_SET_ASSOC = CVA6Cfg.IcacheSetAssoc;
cfg.ICACHE_SET_ASSOC_WIDTH = $clog2(CVA6Cfg.IcacheSetAssoc);
cfg.ICACHE_INDEX_WIDTH = ICACHE_INDEX_WIDTH;
cfg.ICACHE_TAG_WIDTH = riscv::PLEN - ICACHE_INDEX_WIDTH;
cfg.ICACHE_LINE_WIDTH = CVA6Cfg.IcacheLineWidth;
cfg.ICACHE_USER_LINE_WIDTH = (CVA6Cfg.AxiUserWidth == 1) ? 4 : CVA6Cfg.IcacheLineWidth;
cfg.DCACHE_SET_ASSOC = CVA6Cfg.DcacheSetAssoc;
cfg.DCACHE_SET_ASSOC_WIDTH = $clog2(CVA6Cfg.DcacheSetAssoc);
cfg.DCACHE_INDEX_WIDTH = DCACHE_INDEX_WIDTH;
cfg.DCACHE_TAG_WIDTH = riscv::PLEN - DCACHE_INDEX_WIDTH;
cfg.DCACHE_LINE_WIDTH = CVA6Cfg.DcacheLineWidth;
cfg.DCACHE_USER_LINE_WIDTH = (CVA6Cfg.AxiUserWidth == 1) ? 4 : CVA6Cfg.DcacheLineWidth;
cfg.DCACHE_USER_WIDTH = CVA6Cfg.AxiUserWidth;
cfg.DCACHE_OFFSET_WIDTH = DCACHE_OFFSET_WIDTH;
cfg.DCACHE_NUM_WORDS = 2 ** (DCACHE_INDEX_WIDTH - DCACHE_OFFSET_WIDTH);
cfg.DCACHE_MAX_TX = unsigned'(2 ** CVA6Cfg.MemTidWidth);
cfg.DATA_USER_EN = CVA6Cfg.DataUserEn;
cfg.FETCH_USER_WIDTH = CVA6Cfg.FetchUserWidth;
cfg.FETCH_USER_EN = CVA6Cfg.FetchUserEn;
cfg.FETCH_WIDTH = 32;
cfg.INSTR_PER_FETCH = CVA6Cfg.RVC == 1'b1 ? (cfg.FETCH_WIDTH / 16) : 1;
cfg.LOG2_INSTR_PER_FETCH = CVA6Cfg.RVC == 1'b1 ? $clog2(cfg.INSTR_PER_FETCH) : 1;
cfg.ModeW = (riscv::XLEN == 32) ? 1 : 4;
cfg.ASIDW = (riscv::XLEN == 32) ? 9 : 16;
cfg.PPNW = (riscv::XLEN == 32) ? 22 : 44;
cfg.MODE_SV = (riscv::XLEN == 32) ? config_pkg::ModeSv32 : config_pkg::ModeSv39;
cfg.SV = (cfg.MODE_SV == config_pkg::ModeSv32) ? 32 : 39;
return cfg;
endfunction

View file

@ -33,9 +33,21 @@ package config_pkg;
HPDCACHE = 2
} cache_type_t;
/// Data and Address length
typedef enum logic [3:0] {
ModeOff = 0,
ModeSv32 = 1,
ModeSv39 = 8,
ModeSv48 = 9,
ModeSv57 = 10,
ModeSv64 = 11
} vm_mode_t;
localparam NrMaxRules = 16;
typedef struct packed {
// Is FPGA optimization of CV32A6
bit FPGA_EN;
// Number of commit ports
int unsigned NrCommitPorts;
// AXI address width
@ -80,6 +92,8 @@ package config_pkg;
bit RVS;
// User mode
bit RVU;
// Scoreboard length
int unsigned NrScoreboardEntries;
// Address to jump when halt request
logic [63:0] HaltAddress;
// Address to jump when exception
@ -128,9 +142,30 @@ package config_pkg;
bit DebugEn;
// AXI burst in write
bit AxiBurstWriteEn;
// Instruction cache size (in bytes)
int unsigned IcacheByteSize;
// Instruction cache associativity (number of ways)
int unsigned IcacheSetAssoc;
// Instruction line width
int unsigned IcacheLineWidth;
// Data cache size (in bytes)
int unsigned DcacheByteSize;
// Data cache associativity (number of ways)
int unsigned DcacheSetAssoc;
// Data line width
int unsigned DcacheLineWidth;
// TODO
int unsigned DataUserEn;
// TODO
int unsigned FetchUserWidth;
// TODO
int unsigned FetchUserEn;
} cva6_user_cfg_t;
typedef struct packed {
int unsigned XLEN_ALIGN_BYTES;
bit FPGA_EN;
/// Number of commit ports, i.e., maximum number of instructions that the
/// core can retire per cycle. It can be beneficial to have more commit
/// ports than issue ports, for the scoreboard to empty out in case one
@ -156,7 +191,10 @@ package config_pkg;
bit XFVec;
bit CvxifEn;
bit ZiCondExtEn;
// Calculated
int unsigned NR_SB_ENTRIES;
int unsigned TRANS_ID_BITS;
bit RVF;
bit RVD;
bit FpPresent;
@ -198,7 +236,37 @@ package config_pkg;
bit NonIdemPotenceEn; // Currently only used by V extension (Ara)
bit AxiBurstWriteEn;
int unsigned ICACHE_SET_ASSOC;
int unsigned ICACHE_SET_ASSOC_WIDTH;
int unsigned ICACHE_INDEX_WIDTH;
int unsigned ICACHE_TAG_WIDTH;
int unsigned ICACHE_LINE_WIDTH;
int unsigned ICACHE_USER_LINE_WIDTH;
int unsigned DCACHE_SET_ASSOC;
int unsigned DCACHE_SET_ASSOC_WIDTH;
int unsigned DCACHE_INDEX_WIDTH;
int unsigned DCACHE_TAG_WIDTH;
int unsigned DCACHE_LINE_WIDTH;
int unsigned DCACHE_USER_LINE_WIDTH;
int unsigned DCACHE_USER_WIDTH;
int unsigned DCACHE_OFFSET_WIDTH;
int unsigned DCACHE_NUM_WORDS;
int unsigned DCACHE_MAX_TX;
int unsigned DATA_USER_EN;
int unsigned FETCH_USER_WIDTH;
int unsigned FETCH_USER_EN;
int unsigned FETCH_WIDTH;
int unsigned INSTR_PER_FETCH;
int unsigned LOG2_INSTR_PER_FETCH;
int unsigned ModeW;
int unsigned ASIDW;
int unsigned PPNW;
vm_mode_t MODE_SV;
int unsigned SV;
} cva6_cfg_t;
/// Empty configuration to sanity check proper parameter passing. Whenever

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -75,6 +75,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -95,6 +96,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(0),
RVU: bit'(0),
HaltAddress: 64'h800,
@ -120,7 +122,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(0),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -75,6 +75,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -95,6 +96,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(0),
RVU: bit'(0),
HaltAddress: 64'h800,
@ -132,7 +134,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(0),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -125,6 +127,15 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -83,6 +83,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -103,6 +104,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -140,7 +142,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,7 +135,16 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -76,6 +76,7 @@ package cva6_config_pkg;
localparam CVA6ConfigRvfiTrace = 1;
localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{
FPGA_EN: bit'(CVA6ConfigFPGAEn),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
@ -96,6 +97,7 @@ package cva6_config_pkg;
XFVec: bit'(CVA6ConfigFVecEn),
CvxifEn: bit'(CVA6ConfigCvxifEn),
ZiCondExtEn: bit'(CVA6ConfigZiCondExtEn),
NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries),
RVS: bit'(1),
RVU: bit'(1),
HaltAddress: 64'h800,
@ -133,6 +135,15 @@ package cva6_config_pkg;
CachedRegionLength: 1024'({64'h40000000}),
MaxOutstandingStores: unsigned'(7),
DebugEn: bit'(1),
AxiBurstWriteEn: bit'(0)
AxiBurstWriteEn: bit'(0),
IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize),
IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc),
IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth),
DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize),
DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc),
DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth),
DataUserEn: unsigned'(CVA6ConfigDataUserEn),
FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth),
FetchUserEn: unsigned'(CVA6ConfigFetchUserEn)
};
endpackage

View file

@ -13,7 +13,7 @@ package cvxif_pkg;
localparam X_DATAWIDTH = riscv::XLEN;
localparam X_NUM_RS = ariane_pkg::NR_RGPR_PORTS; //2 or 3
localparam X_ID_WIDTH = ariane_pkg::TRANS_ID_BITS;
localparam X_ID_WIDTH = $clog2(cva6_config_pkg::CVA6ConfigNrScoreboardEntries);
localparam X_MEM_WIDTH = 64;
localparam X_RFR_WIDTH = riscv::XLEN;
localparam X_RFW_WIDTH = riscv::XLEN;

View file

@ -22,18 +22,6 @@ package riscv;
// ----------------------
localparam XLEN = cva6_config_pkg::CVA6ConfigXlen;
// ----------------------
// Data and Address length
// ----------------------
typedef enum logic [3:0] {
ModeOff = 0,
ModeSv32 = 1,
ModeSv39 = 8,
ModeSv48 = 9,
ModeSv57 = 10,
ModeSv64 = 11
} vm_mode_t;
// Warning: When using STD_CACHE, configuration must be PLEN=56 and VLEN=64
// Warning: VLEN must be superior or equal to PLEN
localparam VLEN = (XLEN == 32) ? 32 : 64; // virtual address length
@ -41,13 +29,6 @@ package riscv;
localparam IS_XLEN32 = (XLEN == 32) ? 1'b1 : 1'b0;
localparam IS_XLEN64 = (XLEN == 32) ? 1'b0 : 1'b1;
localparam ModeW = (XLEN == 32) ? 1 : 4;
localparam ASIDW = (XLEN == 32) ? 9 : 16;
localparam PPNW = (XLEN == 32) ? 22 : 44;
localparam vm_mode_t MODE_SV = (XLEN == 32) ? ModeSv32 : ModeSv39;
localparam SV = (MODE_SV == ModeSv32) ? 32 : 39;
localparam VPN2 = (VLEN - 31 < 8) ? VLEN - 31 : 8;
localparam XLEN_ALIGN_BYTES = $clog2(XLEN / 8);
// --------------------
// Privilege Spec
@ -338,19 +319,12 @@ package riscv;
localparam int unsigned IRQ_S_EXT = 9;
localparam int unsigned IRQ_M_EXT = 11;
localparam logic [XLEN-1:0] MIP_SSIP = 1 << IRQ_S_SOFT;
localparam logic [XLEN-1:0] MIP_MSIP = 1 << IRQ_M_SOFT;
localparam logic [XLEN-1:0] MIP_STIP = 1 << IRQ_S_TIMER;
localparam logic [XLEN-1:0] MIP_MTIP = 1 << IRQ_M_TIMER;
localparam logic [XLEN-1:0] MIP_SEIP = 1 << IRQ_S_EXT;
localparam logic [XLEN-1:0] MIP_MEIP = 1 << IRQ_M_EXT;
localparam logic [XLEN-1:0] S_SW_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_S_SOFT);
localparam logic [XLEN-1:0] M_SW_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_M_SOFT);
localparam logic [XLEN-1:0] S_TIMER_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_S_TIMER);
localparam logic [XLEN-1:0] M_TIMER_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_M_TIMER);
localparam logic [XLEN-1:0] S_EXT_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_S_EXT);
localparam logic [XLEN-1:0] M_EXT_INTERRUPT = (1 << (XLEN - 1)) | XLEN'(IRQ_M_EXT);
localparam logic [31:0] MIP_SSIP = 1 << IRQ_S_SOFT;
localparam logic [31:0] MIP_MSIP = 1 << IRQ_M_SOFT;
localparam logic [31:0] MIP_STIP = 1 << IRQ_S_TIMER;
localparam logic [31:0] MIP_MTIP = 1 << IRQ_M_TIMER;
localparam logic [31:0] MIP_SEIP = 1 << IRQ_S_EXT;
localparam logic [31:0] MIP_MEIP = 1 << IRQ_M_EXT;
// -----
// CSRs
@ -608,7 +582,9 @@ package riscv;
localparam logic [63:0] SSTATUS_MXR = 'h00080000;
localparam logic [63:0] SSTATUS_UPIE = 'h00000010;
localparam logic [63:0] SSTATUS_UXL = 64'h0000000300000000;
localparam logic [63:0] SSTATUS_SD = {IS_XLEN64, 31'h00000000, ~IS_XLEN64, 31'h00000000};
function automatic logic [63:0] sstatus_sd(logic IS_XLEN64);
return {IS_XLEN64, 31'h00000000, ~IS_XLEN64, 31'h00000000};
endfunction
localparam logic [63:0] MSTATUS_UIE = 'h00000001;
localparam logic [63:0] MSTATUS_SIE = 'h00000002;

View file

@ -93,8 +93,8 @@
// RVFI PROBES
`define RVFI_PROBES_INSTR_T(Cfg) struct packed { \
logic [ariane_pkg::TRANS_ID_BITS-1:0] issue_pointer; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][ariane_pkg::TRANS_ID_BITS-1:0] commit_pointer; \
logic [Cfg.TRANS_ID_BITS-1:0] issue_pointer; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][Cfg.TRANS_ID_BITS-1:0] commit_pointer; \
logic flush_unissued_instr; \
logic decoded_instr_valid; \
logic decoded_instr_ack; \
@ -106,7 +106,7 @@
logic [riscv::XLEN-1:0] rs1_forwarding; \
logic [riscv::XLEN-1:0] rs2_forwarding; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][riscv::VLEN-1:0] commit_instr_pc; \
ariane_pkg::fu_op [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][ariane_pkg::TRANS_ID_BITS-1:0] commit_instr_op; \
ariane_pkg::fu_op [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][Cfg.TRANS_ID_BITS-1:0] commit_instr_op; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] commit_instr_rs1; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] commit_instr_rs2; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0][ariane_pkg::REG_ADDR_SIZE-1:0] commit_instr_rd; \
@ -118,7 +118,7 @@
logic [riscv::VLEN-1:0] lsu_ctrl_vaddr; \
ariane_pkg::fu_t lsu_ctrl_fu; \
logic [(riscv::XLEN/8)-1:0] lsu_ctrl_be; \
logic [ariane_pkg::TRANS_ID_BITS-1:0] lsu_ctrl_trans_id; \
logic [Cfg.TRANS_ID_BITS-1:0] lsu_ctrl_trans_id; \
logic [((cva6_config_pkg::CVA6ConfigCvxifEn || cva6_config_pkg::CVA6ConfigVExtEn) ? 5 : 4)-1:0][riscv::XLEN-1:0] wbdata; \
logic [cva6_config_pkg::CVA6ConfigNrCommitPorts-1:0] commit_ack; \
logic [riscv::PLEN-1:0] mem_paddr; \

View file

@ -17,11 +17,6 @@
package std_cache_pkg;
// Calculated parameter
localparam DCACHE_BYTE_OFFSET = $clog2(ariane_pkg::DCACHE_LINE_WIDTH / 8);
localparam DCACHE_NUM_WORDS = 2 ** (ariane_pkg::DCACHE_INDEX_WIDTH - DCACHE_BYTE_OFFSET);
localparam DCACHE_DIRTY_WIDTH = ariane_pkg::DCACHE_SET_ASSOC * 2;
localparam DCACHE_SET_ASSOC_WIDTH = $clog2(ariane_pkg::DCACHE_SET_ASSOC);
// localparam DECISION_BIT = 30; // bit on which to decide whether the request is cache-able or not
typedef struct packed {

View file

@ -37,23 +37,14 @@ package wt_cache_pkg;
localparam L15_SET_ASSOC = `CONFIG_L15_ASSOCIATIVITY;
localparam L15_TLB_CSM_WIDTH = `TLB_CSM_WIDTH;
`else
localparam L15_SET_ASSOC = ariane_pkg::DCACHE_SET_ASSOC;// align with dcache for compatibility with the standard Ariane setup
localparam L15_TLB_CSM_WIDTH = 33;
`endif
localparam L15_WAY_WIDTH = $clog2(L15_SET_ASSOC);
localparam L1I_WAY_WIDTH = $clog2(ariane_pkg::ICACHE_SET_ASSOC);
localparam L1D_WAY_WIDTH = $clog2(ariane_pkg::DCACHE_SET_ASSOC);
// FIFO depths of L15 adapter
localparam ADAPTER_REQ_FIFO_DEPTH = 2;
localparam ADAPTER_RTRN_FIFO_DEPTH = 2;
// Calculated parameter
localparam DCACHE_OFFSET_WIDTH = $clog2(ariane_pkg::DCACHE_LINE_WIDTH / 8);
localparam DCACHE_NUM_WORDS = 2 ** (ariane_pkg::DCACHE_INDEX_WIDTH - DCACHE_OFFSET_WIDTH);
localparam DCACHE_CL_IDX_WIDTH = $clog2(DCACHE_NUM_WORDS); // excluding byte offset
// write buffer parameterization
localparam DCACHE_WBUF_DEPTH = ariane_pkg::WT_DCACHE_WBUF_DEPTH;

View file

@ -38,18 +38,18 @@ module instr_realign
// 32-bit block address - CACHE
input logic [riscv::VLEN-1:0] address_i,
// 32-bit block - CACHE
input logic [FETCH_WIDTH-1:0] data_i,
input logic [CVA6Cfg.FETCH_WIDTH-1:0] data_i,
// instruction is valid - FRONTEND
output logic [INSTR_PER_FETCH-1:0] valid_o,
output logic [CVA6Cfg.INSTR_PER_FETCH-1:0] valid_o,
// Instruction address - FRONTEND
output logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_o,
output logic [CVA6Cfg.INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_o,
// Instruction - instr_scan&instr_queue
output logic [INSTR_PER_FETCH-1:0][31:0] instr_o
output logic [CVA6Cfg.INSTR_PER_FETCH-1:0][31:0] instr_o
);
// as a maximum we support a fetch width of 64-bit, hence there can be 4 compressed instructions
logic [3:0] instr_is_compressed;
for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin
// LSB != 2'b11
assign instr_is_compressed[i] = ~&data_i[i*16+:2];
end
@ -64,7 +64,7 @@ module instr_realign
assign serving_unaligned_o = unaligned_q;
// Instruction re-alignment
if (FETCH_WIDTH == 32) begin : realign_bp_32
if (CVA6Cfg.FETCH_WIDTH == 32) begin : realign_bp_32
always_comb begin : re_align
unaligned_d = unaligned_q;
unaligned_address_d = {address_i[riscv::VLEN-1:2], 2'b10};
@ -109,12 +109,12 @@ module instr_realign
unaligned_instr_d = data_i[15:0];
// the instruction isn't compressed but only the lower is ready
end else begin
valid_o = {{INSTR_PER_FETCH - 1{1'b0}}, 1'b1};
valid_o = {{CVA6Cfg.INSTR_PER_FETCH - 1{1'b0}}, 1'b1};
end
end
end
// TODO(zarubaf): Fix 64 bit FETCH_WIDTH, maybe generalize to arbitrary fetch width
end else if (FETCH_WIDTH == 64) begin : realign_bp_64
// TODO(zarubaf): Fix 64 bit CVA6Cfg.FETCH_WIDTH, maybe generalize to arbitrary fetch width
end else if (CVA6Cfg.FETCH_WIDTH == 64) begin : realign_bp_64
initial begin
$error("Not propperly implemented");
end

View file

@ -136,7 +136,7 @@ module issue_read_operands
logic cvxif_valid_q;
logic [31:0] cvxif_off_instr_q;
logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_n, trans_id_q;
fu_op operator_n, operator_q; // operation to perform
fu_t fu_n, fu_q; // functional unit to use
@ -483,7 +483,7 @@ module issue_read_operands
assign wdata_pack[i] = wdata_i[i];
assign we_pack[i] = we_gpr_i[i];
end
if (ariane_pkg::FPGA_EN) begin : gen_fpga_regfile
if (CVA6Cfg.FPGA_EN) begin : gen_fpga_regfile
ariane_regfile_fpga #(
.CVA6Cfg (CVA6Cfg),
.DATA_WIDTH (riscv::XLEN),
@ -532,7 +532,7 @@ module issue_read_operands
for (genvar i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin : gen_fp_wdata_pack
assign fp_wdata_pack[i] = {wdata_i[i][CVA6Cfg.FLen-1:0]};
end
if (ariane_pkg::FPGA_EN) begin : gen_fpga_fp_regfile
if (CVA6Cfg.FPGA_EN) begin : gen_fpga_fp_regfile
ariane_regfile_fpga #(
.CVA6Cfg (CVA6Cfg),
.DATA_WIDTH (CVA6Cfg.FLen),

View file

@ -93,7 +93,7 @@ module issue_stage
// TO_BE_COMPLETED - ACC_DISPATCHER
output logic issue_instr_hs_o,
// Transaction ID - EX_STAGE
input logic [CVA6Cfg.NrWbPorts-1:0][TRANS_ID_BITS-1:0] trans_id_i,
input logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_i,
// The branch engine uses the write back from the ALU - EX_STAGE
input bp_resolve_t resolved_branch_i,
// TO_BE_COMPLETED - EX_STAGE
@ -119,9 +119,9 @@ module issue_stage
// Issue stall - PERF_COUNTERS
output logic stall_issue_o,
// Information dedicated to RVFI - RVFI
output logic [TRANS_ID_BITS-1:0] rvfi_issue_pointer_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_issue_pointer_o,
// Information dedicated to RVFI - RVFI
output logic [CVA6Cfg.NrCommitPorts-1:0][TRANS_ID_BITS-1:0] rvfi_commit_pointer_o
output logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_commit_pointer_o
);
// ---------------------------------------------------
// Scoreboard (SB) <-> Issue and Read Operands (IRO)

View file

@ -48,7 +48,7 @@ module load_store_unit
input logic lsu_valid_i,
// Load transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] load_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] load_trans_id_o,
// Load result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] load_result_o,
// Load result is valid - ISSUE_STAGE
@ -57,7 +57,7 @@ module load_store_unit
output exception_t load_exception_o,
// Store transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] store_trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] store_trans_id_o,
// Store result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] store_result_o,
// Store result is valid - ISSUE_STAGE
@ -70,7 +70,7 @@ module load_store_unit
// Commit queue is ready to accept another commit request - TO_BE_COMPLETED
output logic commit_ready_o,
// Commit transaction ID - TO_BE_COMPLETED
input logic [TRANS_ID_BITS-1:0] commit_tran_id_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] commit_tran_id_i,
// Enable virtual memory translation - TO_BE_COMPLETED
input logic enable_translation_i,
@ -83,27 +83,27 @@ module load_store_unit
output icache_areq_t icache_areq_o,
// Current privilege mode - CSR_REGFILE
input riscv::priv_lvl_t priv_lvl_i,
input riscv::priv_lvl_t priv_lvl_i,
// Privilege level at which load and stores should happen - CSR_REGFILE
input riscv::priv_lvl_t ld_st_priv_lvl_i,
input riscv::priv_lvl_t ld_st_priv_lvl_i,
// Supervisor User Memory - CSR_REGFILE
input logic sum_i,
input logic sum_i,
// Make Executable Readable - CSR_REGFILE
input logic mxr_i,
input logic mxr_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [riscv::PPNW-1:0] satp_ppn_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [ ASID_WIDTH-1:0] asid_i,
input logic [ ASID_WIDTH-1:0] asid_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [ ASID_WIDTH-1:0] asid_to_be_flushed_i,
input logic [ ASID_WIDTH-1:0] asid_to_be_flushed_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [riscv::VLEN-1:0] vaddr_to_be_flushed_i,
input logic [ riscv::VLEN-1:0] vaddr_to_be_flushed_i,
// TLB flush - CONTROLLER
input logic flush_tlb_i,
input logic flush_tlb_i,
// Instruction TLB miss - PERF_COUNTERS
output logic itlb_miss_o,
output logic itlb_miss_o,
// Data TLB miss - PERF_COUNTERS
output logic dtlb_miss_o,
output logic dtlb_miss_o,
// Data cache request output - CACHES
input dcache_req_o_t [ 2:0] dcache_req_ports_i,
@ -152,7 +152,7 @@ module load_store_unit
assign vaddr_xlen = $unsigned($signed(fu_data_i.imm) + $signed(fu_data_i.operand_a));
assign vaddr_i = vaddr_xlen[riscv::VLEN-1:0];
// we work with SV39 or SV32, so if VM is enabled, check that all bits [XLEN-1:38] or [XLEN-1:31] are equal
assign overflow = (riscv::IS_XLEN64 && (!((&vaddr_xlen[riscv::XLEN-1:riscv::SV-1]) == 1'b1 || (|vaddr_xlen[riscv::XLEN-1:riscv::SV-1]) == 1'b0)));
assign overflow = (riscv::IS_XLEN64 && (!((&vaddr_xlen[riscv::XLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|vaddr_xlen[riscv::XLEN-1:CVA6Cfg.SV-1]) == 1'b0)));
logic st_valid_i;
logic ld_valid_i;
@ -164,23 +164,23 @@ module load_store_unit
logic translation_valid;
logic [riscv::VLEN-1:0] mmu_vaddr;
logic [riscv::PLEN-1:0] mmu_paddr, mmu_vaddr_plen, fetch_vaddr_plen;
exception_t mmu_exception;
logic dtlb_hit;
logic [ riscv::PPNW-1:0] dtlb_ppn;
exception_t mmu_exception;
logic dtlb_hit;
logic [ CVA6Cfg.PPNW-1:0] dtlb_ppn;
logic ld_valid;
logic [TRANS_ID_BITS-1:0] ld_trans_id;
logic [ riscv::XLEN-1:0] ld_result;
logic st_valid;
logic [TRANS_ID_BITS-1:0] st_trans_id;
logic [ riscv::XLEN-1:0] st_result;
logic ld_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
logic [ riscv::XLEN-1:0] ld_result;
logic st_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
logic [ riscv::XLEN-1:0] st_result;
logic [ 11:0] page_offset;
logic page_offset_matches;
logic [ 11:0] page_offset;
logic page_offset_matches;
exception_t misaligned_exception;
exception_t ld_ex;
exception_t st_ex;
exception_t misaligned_exception;
exception_t ld_ex;
exception_t st_ex;
// -------------------
// MMU e.g.: TLBs/PTW

View file

@ -42,7 +42,7 @@ module load_unit
// Load unit result is valid - TO_BE_COMPLETED
output logic valid_o,
// Load transaction ID - TO_BE_COMPLETED
output logic [TRANS_ID_BITS-1:0] trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_o,
// Load result - TO_BE_COMPLETED
output logic [riscv::XLEN-1:0] result_o,
// Load exception - TO_BE_COMPLETED
@ -58,7 +58,7 @@ module load_unit
// Data TLB hit - lsu
input logic dtlb_hit_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [riscv::PPNW-1:0] dtlb_ppn_i,
input logic [CVA6Cfg.PPNW-1:0] dtlb_ppn_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
output logic [11:0] page_offset_o,
// TO_BE_COMPLETED - TO_BE_COMPLETED
@ -66,7 +66,7 @@ module load_unit
// Store buffer is empty - TO_BE_COMPLETED
input logic store_buffer_empty_i,
// TO_BE_COMPLETED - TO_BE_COMPLETED
input logic [TRANS_ID_BITS-1:0] commit_tran_id_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] commit_tran_id_i,
// Data cache request out - CACHES
input dcache_req_o_t req_port_i,
// Data cache request in - CACHES
@ -90,9 +90,9 @@ module load_unit
// in order to decouple the response interface from the request interface,
// we need a a buffer which can hold all inflight memory load requests
typedef struct packed {
logic [TRANS_ID_BITS-1:0] trans_id; // scoreboard identifier
logic [riscv::XLEN_ALIGN_BYTES-1:0] address_offset; // least significant bits of the address
fu_op operation; // type of load
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id; // scoreboard identifier
logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] address_offset; // least significant bits of the address
fu_op operation; // type of load
} ldbuf_t;
@ -188,15 +188,15 @@ module load_unit
assign req_port_o.data_wdata = '0;
// compose the load buffer write data, control is handled in the FSM
assign ldbuf_wdata = {
lsu_ctrl_i.trans_id, lsu_ctrl_i.vaddr[riscv::XLEN_ALIGN_BYTES-1:0], lsu_ctrl_i.operation
lsu_ctrl_i.trans_id, lsu_ctrl_i.vaddr[CVA6Cfg.XLEN_ALIGN_BYTES-1:0], lsu_ctrl_i.operation
};
// output address
// we can now output the lower 12 bit as the index to the cache
assign req_port_o.address_index = lsu_ctrl_i.vaddr[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_index = lsu_ctrl_i.vaddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
// translation from last cycle, again: control is handled in the FSM
assign req_port_o.address_tag = paddr_i[ariane_pkg::DCACHE_TAG_WIDTH +
ariane_pkg::DCACHE_INDEX_WIDTH-1 :
ariane_pkg::DCACHE_INDEX_WIDTH];
assign req_port_o.address_tag = paddr_i[CVA6Cfg.DCACHE_TAG_WIDTH +
CVA6Cfg.DCACHE_INDEX_WIDTH-1 :
CVA6Cfg.DCACHE_INDEX_WIDTH];
// request id = index of the load buffer's entry
assign req_port_o.data_id = ldbuf_windex;
// directly forward exception fields (valid bit is set below)
@ -209,7 +209,7 @@ module load_unit
logic inflight_stores;
logic stall_ni;
assign paddr_ni = config_pkg::is_inside_nonidempotent_regions(
CVA6Cfg, {{52 - riscv::PPNW{1'b0}}, dtlb_ppn_i, 12'd0}
CVA6Cfg, {{52 - CVA6Cfg.PPNW{1'b0}}, dtlb_ppn_i, 12'd0}
);
assign not_commit_time = commit_tran_id_i != lsu_ctrl_i.trans_id;
assign inflight_stores = (!dcache_wbuffer_not_ni_i || !store_buffer_empty_i);
@ -473,8 +473,8 @@ module load_unit
end */
// result mux fast
logic [ (riscv::XLEN/8)-1:0] rdata_sign_bits;
logic [riscv::XLEN_ALIGN_BYTES-1:0] rdata_offset;
logic [ (riscv::XLEN/8)-1:0] rdata_sign_bits;
logic [CVA6Cfg.XLEN_ALIGN_BYTES-1:0] rdata_offset;
logic rdata_sign_bit, rdata_is_signed, rdata_is_fp_signed;

View file

@ -59,7 +59,7 @@ module cva6_mmu_sv32
// if we need to walk the page table we can't grant in the same cycle
// Cycle 0
output logic lsu_dtlb_hit_o, // sent in the same cycle as the request if translation hits in the DTLB
output logic [riscv::PPNW-1:0] lsu_dtlb_ppn_o, // ppn (send same cycle as hit)
output logic [CVA6Cfg.PPNW-1:0] lsu_dtlb_ppn_o, // ppn (send same cycle as hit)
// Cycle 1
output logic lsu_valid_o, // translation is valid
output logic [riscv::PLEN-1:0] lsu_paddr_o, // translated address
@ -70,7 +70,7 @@ module cva6_mmu_sv32
input logic sum_i,
input logic mxr_i,
// input logic flag_mprv_i,
input logic [riscv::PPNW-1:0] satp_ppn_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic [ASID_WIDTH-1:0] asid_to_be_flushed_i,
input logic [riscv::VLEN-1:0] vaddr_to_be_flushed_i,
@ -303,8 +303,8 @@ module cva6_mmu_sv32
// AXI decode error), or when PTW performs walk due to ITLB miss and raises
// an error.
if (enable_translation_i) begin
// we work with SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:riscv::SV-1] are equal
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin
// we work with SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:CVA6Cfg.SV-1] are equal
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:CVA6Cfg.SV-1]) == 1'b0)) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
@ -415,7 +415,7 @@ module cva6_mmu_sv32
// Wires to PMP checks
riscv::pmp_access_t pmp_access_type;
logic pmp_data_allow;
localparam PPNWMin = (riscv::PPNW - 1 > 29) ? 29 : riscv::PPNW - 1;
localparam PPNWMin = (CVA6Cfg.PPNW - 1 > 29) ? 29 : CVA6Cfg.PPNW - 1;
// The data interface is simpler and only consists of a request/response interface
always_comb begin : data_interface
// save request and DTLB response
@ -432,7 +432,7 @@ module cva6_mmu_sv32
lsu_dtlb_ppn_o = {{riscv::PLEN - riscv::VLEN{1'b0}}, lsu_vaddr_n[riscv::VLEN-1:12]};
end else begin
lsu_paddr_o = {2'b00, lsu_vaddr_q[riscv::VLEN-1:0]};
lsu_dtlb_ppn_o = lsu_vaddr_n[riscv::PPNW-1:0];
lsu_dtlb_ppn_o = lsu_vaddr_n[CVA6Cfg.PPNW-1:0];
end
lsu_valid_o = lsu_req_q;
lsu_exception_o = misaligned_ex_q;

View file

@ -64,8 +64,8 @@ module cva6_ptw_sv32
input logic itlb_req_i,
// from CSR file
input logic [riscv::PPNW-1:0] satp_ppn_i, // ppn from satp
input logic mxr_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i, // ppn from satp
input logic mxr_i,
// Performance counters
output logic shared_tlb_miss_o,
@ -122,8 +122,8 @@ module cva6_ptw_sv32
//assign walking_instr_o = is_instr_ptw_q;
assign walking_instr_o = is_instr_ptw_q;
// directly output the correct physical address
assign req_port_o.address_index = ptw_pptr_q[DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_tag = ptw_pptr_q[DCACHE_INDEX_WIDTH+DCACHE_TAG_WIDTH-1:DCACHE_INDEX_WIDTH];
assign req_port_o.address_index = ptw_pptr_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_tag = ptw_pptr_q[CVA6Cfg.DCACHE_INDEX_WIDTH+CVA6Cfg.DCACHE_TAG_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
// we are never going to kill this request
assign req_port_o.kill_req = '0;
// we are never going to write with the HPTW
@ -134,7 +134,7 @@ module cva6_ptw_sv32
// -----------
// Shared TLB Update
// -----------
assign shared_tlb_update_o.vpn = vaddr_q[riscv::SV-1:12];
assign shared_tlb_update_o.vpn = vaddr_q[CVA6Cfg.SV-1:12];
// update the correct page table level
assign shared_tlb_update_o.is_4M = (ptw_lvl_q == LVL1);
// output the correct ASID
@ -223,7 +223,7 @@ module cva6_ptw_sv32
// if we got a Shared TLB miss
if (shared_tlb_access_i & ~shared_tlb_hit_i) begin
ptw_pptr_n = {
satp_ppn_i, shared_tlb_vaddr_i[riscv::SV-1:22], 2'b0
satp_ppn_i, shared_tlb_vaddr_i[CVA6Cfg.SV-1:22], 2'b0
}; // SATP.PPN * PAGESIZE + VPN*PTESIZE = SATP.PPN * 2^(12) + VPN*4
is_instr_ptw_n = itlb_req_i;
tlb_update_asid_n = asid_i;

View file

@ -243,8 +243,8 @@ module cva6_shared_tlb_sv32
dtlb_req_q <= '0;
shared_tag_valid <= '0;
end else begin
itlb_vpn_q <= itlb_vaddr_i[riscv::SV-1:12];
dtlb_vpn_q <= dtlb_vaddr_i[riscv::SV-1:12];
itlb_vpn_q <= itlb_vaddr_i[CVA6Cfg.SV-1:12];
dtlb_vpn_q <= dtlb_vaddr_i[CVA6Cfg.SV-1:12];
tlb_update_asid_q <= tlb_update_asid_d;
shared_tlb_access_q <= shared_tlb_access_d;
shared_tlb_vaddr_q <= shared_tlb_vaddr_d;

View file

@ -48,7 +48,7 @@ module mmu
// if we need to walk the page table we can't grant in the same cycle
// Cycle 0
output logic lsu_dtlb_hit_o, // sent in the same cycle as the request if translation hits in the DTLB
output logic [riscv::PPNW-1:0] lsu_dtlb_ppn_o, // ppn (send same cycle as hit)
output logic [CVA6Cfg.PPNW-1:0] lsu_dtlb_ppn_o, // ppn (send same cycle as hit)
// Cycle 1
output logic lsu_valid_o, // translation is valid
output logic [riscv::PLEN-1:0] lsu_paddr_o, // translated address
@ -59,7 +59,7 @@ module mmu
input logic sum_i,
input logic mxr_i,
// input logic flag_mprv_i,
input logic [riscv::PPNW-1:0] satp_ppn_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i,
input logic [ASID_WIDTH-1:0] asid_i,
input logic [ASID_WIDTH-1:0] asid_to_be_flushed_i,
input logic [riscv::VLEN-1:0] vaddr_to_be_flushed_i,
@ -241,8 +241,8 @@ module mmu
// AXI decode error), or when PTW performs walk due to ITLB miss and raises
// an error.
if (enable_translation_i) begin
// we work with SV39 or SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:riscv::SV-1] are equal
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin
// we work with SV39 or SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:CVA6Cfg.SV-1] are equal
if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:CVA6Cfg.SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:CVA6Cfg.SV-1]) == 1'b0)) begin
icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT;
icache_areq_o.fetch_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
@ -359,7 +359,7 @@ module mmu
// Wires to PMP checks
riscv::pmp_access_t pmp_access_type;
logic pmp_data_allow;
localparam PPNWMin = (riscv::PPNW - 1 > 29) ? 29 : riscv::PPNW - 1;
localparam PPNWMin = (CVA6Cfg.PPNW - 1 > 29) ? 29 : CVA6Cfg.PPNW - 1;
// The data interface is simpler and only consists of a request/response interface
always_comb begin : data_interface
// save request and DTLB response

View file

@ -55,15 +55,15 @@ module ptw
input logic itlb_hit_i,
input logic [riscv::VLEN-1:0] itlb_vaddr_i,
input logic dtlb_access_i,
input logic dtlb_hit_i,
input logic [riscv::VLEN-1:0] dtlb_vaddr_i,
input logic dtlb_access_i,
input logic dtlb_hit_i,
input logic [ riscv::VLEN-1:0] dtlb_vaddr_i,
// from CSR file
input logic [riscv::PPNW-1:0] satp_ppn_i, // ppn from satp
input logic mxr_i,
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i, // ppn from satp
input logic mxr_i,
// Performance counters
output logic itlb_miss_o,
output logic dtlb_miss_o,
output logic itlb_miss_o,
output logic dtlb_miss_o,
// PMP
input riscv::pmpcfg_t [15:0] pmpcfg_i,
@ -115,8 +115,8 @@ module ptw
assign ptw_active_o = (state_q != IDLE);
assign walking_instr_o = is_instr_ptw_q;
// directly output the correct physical address
assign req_port_o.address_index = ptw_pptr_q[DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_tag = ptw_pptr_q[DCACHE_INDEX_WIDTH+DCACHE_TAG_WIDTH-1:DCACHE_INDEX_WIDTH];
assign req_port_o.address_index = ptw_pptr_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_tag = ptw_pptr_q[CVA6Cfg.DCACHE_INDEX_WIDTH+CVA6Cfg.DCACHE_TAG_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
// we are never going to kill this request
assign req_port_o.kill_req = '0;
// we are never going to write with the HPTW
@ -126,8 +126,8 @@ module ptw
// -----------
// TLB Update
// -----------
assign itlb_update_o.vpn = {{39 - riscv::SV{1'b0}}, vaddr_q[riscv::SV-1:12]};
assign dtlb_update_o.vpn = {{39 - riscv::SV{1'b0}}, vaddr_q[riscv::SV-1:12]};
assign itlb_update_o.vpn = {{39 - CVA6Cfg.SV{1'b0}}, vaddr_q[CVA6Cfg.SV-1:12]};
assign dtlb_update_o.vpn = {{39 - CVA6Cfg.SV{1'b0}}, vaddr_q[CVA6Cfg.SV-1:12]};
// update the correct page table level
assign itlb_update_o.is_2M = (ptw_lvl_q == LVL2);
assign itlb_update_o.is_1G = (ptw_lvl_q == LVL1);
@ -219,7 +219,7 @@ module ptw
is_instr_ptw_n = 1'b0;
// if we got an ITLB miss
if (enable_translation_i & itlb_access_i & ~itlb_hit_i & ~dtlb_access_i) begin
ptw_pptr_n = {satp_ppn_i, itlb_vaddr_i[riscv::SV-1:30], 3'b0};
ptw_pptr_n = {satp_ppn_i, itlb_vaddr_i[CVA6Cfg.SV-1:30], 3'b0};
is_instr_ptw_n = 1'b1;
tlb_update_asid_n = asid_i;
vaddr_n = itlb_vaddr_i;
@ -227,7 +227,7 @@ module ptw
itlb_miss_o = 1'b1;
// we got an DTLB miss
end else if (en_ld_st_translation_i & dtlb_access_i & ~dtlb_hit_i) begin
ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[riscv::SV-1:30], 3'b0};
ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[CVA6Cfg.SV-1:30], 3'b0};
tlb_update_asid_n = asid_i;
vaddr_n = dtlb_vaddr_i;
state_d = WAIT_GRANT;

View file

@ -40,10 +40,12 @@ module tlb
output logic lu_hit_o
);
localparam VPN2 = (riscv::VLEN - 31 < 8) ? riscv::VLEN - 31 : 8;
// SV39 defines three levels of page tables
struct packed {
logic [ASID_WIDTH-1:0] asid;
logic [riscv::VPN2:0] vpn2;
logic [VPN2:0] vpn2;
logic [8:0] vpn1;
logic [8:0] vpn0;
logic is_2M;
@ -54,7 +56,7 @@ module tlb
riscv::pte_t [TLB_ENTRIES-1:0] content_q, content_n;
logic [8:0] vpn0, vpn1;
logic [ riscv::VPN2:0] vpn2;
logic [VPN2:0] vpn2;
logic [TLB_ENTRIES-1:0] lu_hit; // to replacement logic
logic [TLB_ENTRIES-1:0] replace_en; // replace the following entry, set by replacement strategy
//-------------
@ -63,7 +65,7 @@ module tlb
always_comb begin : translation
vpn0 = lu_vaddr_i[20:12];
vpn1 = lu_vaddr_i[29:21];
vpn2 = lu_vaddr_i[30+riscv::VPN2:30];
vpn2 = lu_vaddr_i[30+VPN2:30];
// default assignment
lu_hit = '{default: 0};
@ -119,7 +121,7 @@ module tlb
vaddr_vpn0_match[i] = (vaddr_to_be_flushed_i[20:12] == tags_q[i].vpn0);
vaddr_vpn1_match[i] = (vaddr_to_be_flushed_i[29:21] == tags_q[i].vpn1);
vaddr_vpn2_match[i] = (vaddr_to_be_flushed_i[30+riscv::VPN2:30] == tags_q[i].vpn2);
vaddr_vpn2_match[i] = (vaddr_to_be_flushed_i[30+VPN2:30] == tags_q[i].vpn2);
if (flush_i) begin
// invalidate logic
@ -139,7 +141,7 @@ module tlb
// update tag array
tags_n[i] = '{
asid: update_i.asid,
vpn2: update_i.vpn[18+riscv::VPN2:18],
vpn2: update_i.vpn[18+VPN2:18],
vpn1: update_i.vpn[17:9],
vpn0: update_i.vpn[8:0],
is_1G: update_i.is_1G,

View file

@ -7,29 +7,29 @@ module mult
parameter type fu_data_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
input logic rst_ni,
// Flush - CONTROLLER
input logic flush_i,
input logic flush_i,
// FU data needed to execute instruction - ISSUE_STAGE
input fu_data_t fu_data_i,
input fu_data_t fu_data_i,
// Mult instruction is valid - ISSUE_STAGE
input logic mult_valid_i,
input logic mult_valid_i,
// Mult result - ISSUE_STAGE
output logic [ riscv::XLEN-1:0] result_o,
output logic [ riscv::XLEN-1:0] result_o,
// Mult result is valid - ISSUE_STAGE
output logic mult_valid_o,
output logic mult_valid_o,
// Mutl is ready - ISSUE_STAGE
output logic mult_ready_o,
output logic mult_ready_o,
// Mult transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] mult_trans_id_o
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] mult_trans_id_o
);
logic mul_valid;
logic div_valid;
logic div_ready_i; // receiver of division result is able to accept the result
logic [TRANS_ID_BITS-1:0] mul_trans_id;
logic [TRANS_ID_BITS-1:0] div_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] mul_trans_id;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] div_trans_id;
logic [riscv::XLEN-1:0] mul_result;
logic [riscv::XLEN-1:0] div_result;

View file

@ -21,27 +21,27 @@ module multiplier
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
input logic rst_ni,
// Multiplier transaction ID - Mult
input logic [TRANS_ID_BITS-1:0] trans_id_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_i,
// Multiplier instruction is valid - Mult
input logic mult_valid_i,
input logic mult_valid_i,
// Multiplier operation - Mult
input fu_op operation_i,
input fu_op operation_i,
// A operand - Mult
input logic [ riscv::XLEN-1:0] operand_a_i,
input logic [ riscv::XLEN-1:0] operand_a_i,
// B operand - Mult
input logic [ riscv::XLEN-1:0] operand_b_i,
input logic [ riscv::XLEN-1:0] operand_b_i,
// Multiplier result - Mult
output logic [ riscv::XLEN-1:0] result_o,
output logic [ riscv::XLEN-1:0] result_o,
// Mutliplier result is valid - Mult
output logic mult_valid_o,
output logic mult_valid_o,
// Multiplier FU is ready - Mult
output logic mult_ready_o,
output logic mult_ready_o,
// Multiplier transaction ID - Mult
output logic [TRANS_ID_BITS-1:0] mult_trans_id_o
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] mult_trans_id_o
);
// Carry-less multiplication
logic [riscv::XLEN-1:0]
@ -78,8 +78,8 @@ module multiplier
end
// Pipeline register
logic [TRANS_ID_BITS-1:0] trans_id_q;
logic mult_valid_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_q;
logic mult_valid_q;
fu_op operator_d, operator_q;
logic [riscv::XLEN*2-1:0] mult_result_d, mult_result_q;

View file

@ -54,7 +54,7 @@ module perf_counters
input exception_t branch_exceptions_i, //Branch exceptions->execute unit-> branch_exception_o
input icache_dreq_t l1_icache_access_i,
input dcache_req_i_t [2:0] l1_dcache_access_i,
input logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0]miss_vld_bits_i, //For Cache eviction (3ports-LOAD,STORE,PTW)
input logic [NumPorts-1:0][CVA6Cfg.DCACHE_SET_ASSOC-1:0]miss_vld_bits_i, //For Cache eviction (3ports-LOAD,STORE,PTW)
input logic i_tlb_flush_i,
input logic stall_issue_i, //stall-read operands
input logic [31:0] mcountinhibit_i

View file

@ -87,7 +87,7 @@ module scoreboard #(
// TO_BE_COMPLETED - TO_BE_COMPLETED
input bp_resolve_t resolved_branch_i,
// Transaction ID at which to write the result back - TO_BE_COMPLETED
input logic [CVA6Cfg.NrWbPorts-1:0][ariane_pkg::TRANS_ID_BITS-1:0] trans_id_i,
input logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_i,
// Results to write back - TO_BE_COMPLETED
input logic [CVA6Cfg.NrWbPorts-1:0][riscv::XLEN-1:0] wbdata_i,
// Exception from a functional unit (e.g.: ld/st exception) - TO_BE_COMPLETED
@ -98,9 +98,9 @@ module scoreboard #(
input logic x_we_i,
// TO_BE_COMPLETED - RVFI
output logic [ariane_pkg::TRANS_ID_BITS-1:0] rvfi_issue_pointer_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_issue_pointer_o,
// TO_BE_COMPLETED - RVFI
output logic [CVA6Cfg.NrCommitPorts-1:0][ariane_pkg::TRANS_ID_BITS-1:0] rvfi_commit_pointer_o
output logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] rvfi_commit_pointer_o
);
// this is the FIFO struct of the issue queue
@ -109,18 +109,17 @@ module scoreboard #(
logic is_rd_fpr_flag; // redundant meta info, added for speed
scoreboard_entry_t sbe; // this is the score board entry we will send to ex
} sb_mem_t;
sb_mem_t [ariane_pkg::NR_SB_ENTRIES-1:0] mem_q, mem_n;
sb_mem_t [CVA6Cfg.NR_SB_ENTRIES-1:0] mem_q, mem_n;
logic issue_full, issue_en;
logic [ariane_pkg::TRANS_ID_BITS:0] issue_cnt_n, issue_cnt_q;
logic [ariane_pkg::TRANS_ID_BITS-1:0] issue_pointer_n, issue_pointer_q;
logic [CVA6Cfg.NrCommitPorts-1:0][ariane_pkg::TRANS_ID_BITS-1:0]
commit_pointer_n, commit_pointer_q;
logic [CVA6Cfg.TRANS_ID_BITS:0] issue_cnt_n, issue_cnt_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] issue_pointer_n, issue_pointer_q;
logic [CVA6Cfg.NrCommitPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] commit_pointer_n, commit_pointer_q;
logic [$clog2(CVA6Cfg.NrCommitPorts):0] num_commit;
// the issue queue is full don't issue any new instructions
// works since aligned to power of 2
assign issue_full = (issue_cnt_q[ariane_pkg::TRANS_ID_BITS] == 1'b1);
assign issue_full = (issue_cnt_q[CVA6Cfg.TRANS_ID_BITS] == 1'b1);
assign sb_full_o = issue_full;
@ -173,7 +172,7 @@ module scoreboard #(
// ------------
// FU NONE
// ------------
for (int unsigned i = 0; i < ariane_pkg::NR_SB_ENTRIES; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
// The FU is NONE -> this instruction is valid immediately
if (mem_q[i].sbe.fu == ariane_pkg::NONE && mem_q[i].issued) mem_n[i].sbe.valid = 1'b1;
end
@ -228,7 +227,7 @@ module scoreboard #(
// Flush
// ------
if (flush_i) begin
for (int unsigned i = 0; i < ariane_pkg::NR_SB_ENTRIES; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
// set all valid flags for all entries to zero
mem_n[i].issued = 1'b0;
mem_n[i].sbe.valid = 1'b0;
@ -244,9 +243,9 @@ module scoreboard #(
assign num_commit = commit_ack_i[0];
end
assign issue_cnt_n = (flush_i) ? '0 : issue_cnt_q - {{ariane_pkg::TRANS_ID_BITS - $clog2(
assign issue_cnt_n = (flush_i) ? '0 : issue_cnt_q - {{CVA6Cfg.TRANS_ID_BITS - $clog2(
CVA6Cfg.NrCommitPorts
) {1'b0}}, num_commit} + {{ariane_pkg::TRANS_ID_BITS - 1{1'b0}}, issue_en};
) {1'b0}}, num_commit} + {{CVA6Cfg.TRANS_ID_BITS - 1{1'b0}}, issue_en};
assign commit_pointer_n[0] = (flush_i) ? '0 : commit_pointer_q[0] + num_commit;
assign issue_pointer_n = (flush_i) ? '0 : issue_pointer_q + issue_en;
@ -259,23 +258,23 @@ module scoreboard #(
// RD clobber process
// -------------------
// rd_clobber output: output currently clobbered destination registers
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][ariane_pkg::NR_SB_ENTRIES:0] gpr_clobber_vld;
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][ariane_pkg::NR_SB_ENTRIES:0] fpr_clobber_vld;
ariane_pkg::fu_t [ ariane_pkg::NR_SB_ENTRIES:0] clobber_fu;
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] gpr_clobber_vld;
logic [2**ariane_pkg::REG_ADDR_SIZE-1:0][CVA6Cfg.NR_SB_ENTRIES:0] fpr_clobber_vld;
ariane_pkg::fu_t [ CVA6Cfg.NR_SB_ENTRIES:0] clobber_fu;
always_comb begin : clobber_assign
gpr_clobber_vld = '0;
fpr_clobber_vld = '0;
// default (highest entry hast lowest prio in arbiter tree below)
clobber_fu[ariane_pkg::NR_SB_ENTRIES] = ariane_pkg::NONE;
clobber_fu[CVA6Cfg.NR_SB_ENTRIES] = ariane_pkg::NONE;
for (int unsigned i = 0; i < 2 ** ariane_pkg::REG_ADDR_SIZE; i++) begin
gpr_clobber_vld[i][ariane_pkg::NR_SB_ENTRIES] = 1'b1;
fpr_clobber_vld[i][ariane_pkg::NR_SB_ENTRIES] = 1'b1;
gpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1;
fpr_clobber_vld[i][CVA6Cfg.NR_SB_ENTRIES] = 1'b1;
end
// check for all valid entries and set the clobber accordingly
for (int unsigned i = 0; i < ariane_pkg::NR_SB_ENTRIES; i++) begin
for (int unsigned i = 0; i < CVA6Cfg.NR_SB_ENTRIES; i++) begin
gpr_clobber_vld[mem_q[i].sbe.rd][i] = mem_q[i].issued & ~mem_q[i].is_rd_fpr_flag;
fpr_clobber_vld[mem_q[i].sbe.rd][i] = mem_q[i].issued & mem_q[i].is_rd_fpr_flag;
clobber_fu[i] = mem_q[i].sbe.fu;
@ -288,7 +287,7 @@ module scoreboard #(
for (genvar k = 0; k < 2 ** ariane_pkg::REG_ADDR_SIZE; k++) begin : gen_sel_clobbers
// get fu that is going to clobber this register (there should be only one)
rr_arb_tree #(
.NumIn(ariane_pkg::NR_SB_ENTRIES + 1),
.NumIn(CVA6Cfg.NR_SB_ENTRIES + 1),
.DataType(ariane_pkg::fu_t),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
@ -307,7 +306,7 @@ module scoreboard #(
);
if (CVA6Cfg.FpPresent) begin
rr_arb_tree #(
.NumIn(ariane_pkg::NR_SB_ENTRIES + 1),
.NumIn(CVA6Cfg.NR_SB_ENTRIES + 1),
.DataType(ariane_pkg::fu_t),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
@ -331,8 +330,8 @@ module scoreboard #(
// Read Operands (a.k.a forwarding)
// ----------------------------------
// read operand interface: same logic as register file
logic [ariane_pkg::NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0] rs1_fwd_req, rs2_fwd_req, rs3_fwd_req;
logic [ariane_pkg::NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0][riscv::XLEN-1:0] rs_data;
logic [CVA6Cfg.NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0] rs1_fwd_req, rs2_fwd_req, rs3_fwd_req;
logic [CVA6Cfg.NR_SB_ENTRIES+CVA6Cfg.NrWbPorts-1:0][riscv::XLEN-1:0] rs_data;
logic rs1_valid, rs2_valid, rs3_valid;
// WB ports have higher prio than entries
@ -348,7 +347,7 @@ module scoreboard #(
)));
assign rs_data[k] = wbdata_i[k];
end
for (genvar k = 0; unsigned'(k) < ariane_pkg::NR_SB_ENTRIES; k++) begin : gen_rs_entries
for (genvar k = 0; unsigned'(k) < CVA6Cfg.NR_SB_ENTRIES; k++) begin : gen_rs_entries
assign rs1_fwd_req[k+CVA6Cfg.NrWbPorts] = (mem_q[k].sbe.rd == rs1_i) & mem_q[k].issued & mem_q[k].sbe.valid & (mem_q[k].is_rd_fpr_flag == (CVA6Cfg.FpPresent && ariane_pkg::is_rs1_fpr(
issue_instr_o.op
)));
@ -375,7 +374,7 @@ module scoreboard #(
// use fixed prio here
// this implicitly gives higher prio to WB ports
rr_arb_tree #(
.NumIn(ariane_pkg::NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(riscv::XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
@ -394,7 +393,7 @@ module scoreboard #(
);
rr_arb_tree #(
.NumIn(ariane_pkg::NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(riscv::XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
@ -415,7 +414,7 @@ module scoreboard #(
logic [riscv::XLEN-1:0] rs3;
rr_arb_tree #(
.NumIn(ariane_pkg::NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.NumIn(CVA6Cfg.NR_SB_ENTRIES + CVA6Cfg.NrWbPorts),
.DataWidth(riscv::XLEN),
.ExtPrio(1'b1),
.AxiVldRdy(1'b1)
@ -461,7 +460,7 @@ module scoreboard #(
//pragma translate_off
initial begin
assert (ariane_pkg::NR_SB_ENTRIES == 2 ** ariane_pkg::TRANS_ID_BITS)
assert (CVA6Cfg.NR_SB_ENTRIES == 2 ** CVA6Cfg.TRANS_ID_BITS)
else $fatal(1, "Scoreboard size needs to be a power of two.");
end

View file

@ -27,7 +27,7 @@ module serdiv
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
// Serdiv translation ID - Mult
input logic [TRANS_ID_BITS-1:0] id_i,
input logic [CVA6Cfg.TRANS_ID_BITS-1:0] id_i,
// A operand - Mult
input logic [WIDTH-1:0] op_a_i,
// B operand - Mult
@ -45,7 +45,7 @@ module serdiv
// Serdiv is ready - Mult
input logic out_rdy_i,
// Serdiv transaction ID - Mult
output logic [TRANS_ID_BITS-1:0] id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] id_o,
// Serdiv result - Mult
output logic [WIDTH-1:0] res_o
);
@ -68,7 +68,7 @@ module serdiv
logic op_b_zero, op_b_zero_q, op_b_zero_d;
logic op_b_neg_one, op_b_neg_one_q, op_b_neg_one_d;
logic [TRANS_ID_BITS-1:0] id_q, id_d;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] id_q, id_d;
logic rem_sel_d, rem_sel_q;
logic comp_inv_d, comp_inv_q;

View file

@ -141,11 +141,11 @@ module store_buffer
// we do not require an acknowledgement for writes, thus we do not need to identify uniquely the responses
assign req_port_o.data_id = '0;
// those signals can directly be output to the memory
assign req_port_o.address_index = commit_queue_q[commit_read_pointer_q].address[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
assign req_port_o.address_index = commit_queue_q[commit_read_pointer_q].address[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
// if we got a new request we already saved the tag from the previous cycle
assign req_port_o.address_tag = commit_queue_q[commit_read_pointer_q].address[ariane_pkg::DCACHE_TAG_WIDTH +
ariane_pkg::DCACHE_INDEX_WIDTH-1 :
ariane_pkg::DCACHE_INDEX_WIDTH];
assign req_port_o.address_tag = commit_queue_q[commit_read_pointer_q].address[CVA6Cfg.DCACHE_TAG_WIDTH +
CVA6Cfg.DCACHE_INDEX_WIDTH-1 :
CVA6Cfg.DCACHE_INDEX_WIDTH];
assign req_port_o.data_wdata = commit_queue_q[commit_read_pointer_q].data;
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;

View file

@ -49,7 +49,7 @@ module store_unit
// Store result is valid - ISSUE_STAGE
output logic valid_o,
// Transaction ID - ISSUE_STAGE
output logic [TRANS_ID_BITS-1:0] trans_id_o,
output logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_o,
// Store result - ISSUE_STAGE
output logic [riscv::XLEN-1:0] result_o,
// Store exception output - TO_BE_COMPLETED
@ -124,7 +124,7 @@ module store_unit
logic [1:0] st_data_size_n, st_data_size_q;
amo_t amo_op_d, amo_op_q;
logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_n, trans_id_q;
// output assignments
assign vaddr_o = lsu_ctrl_i.vaddr; // virtual address

View file

@ -80,7 +80,9 @@ module ariane import ariane_pkg::*; #(
);
if (CVA6Cfg.CvxifEn) begin : gen_example_coprocessor
cvxif_example_coprocessor i_cvxif_coprocessor (
cvxif_example_coprocessor #(
.CVA6Cfg ( CVA6Cfg )
) i_cvxif_coprocessor (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.cvxif_req_i ( cvxif_req ),

View file

@ -19,31 +19,7 @@ import uvma_cva6pkg_utils_pkg::*;
module spike #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = cva6_config_pkg::cva6_cfg,
parameter type rvfi_instr_t = struct packed {
logic [config_pkg::NRET-1:0] valid;
logic [config_pkg::NRET*64-1:0] order;
logic [config_pkg::NRET*config_pkg::ILEN-1:0] insn;
logic [config_pkg::NRET-1:0] trap;
logic [config_pkg::NRET*riscv::XLEN-1:0] cause;
logic [config_pkg::NRET-1:0] halt;
logic [config_pkg::NRET-1:0] intr;
logic [config_pkg::NRET*2-1:0] mode;
logic [config_pkg::NRET*2-1:0] ixl;
logic [config_pkg::NRET*5-1:0] rs1_addr;
logic [config_pkg::NRET*5-1:0] rs2_addr;
logic [config_pkg::NRET*riscv::XLEN-1:0] rs1_rdata;
logic [config_pkg::NRET*riscv::XLEN-1:0] rs2_rdata;
logic [config_pkg::NRET*5-1:0] rd_addr;
logic [config_pkg::NRET*riscv::XLEN-1:0] rd_wdata;
logic [config_pkg::NRET*riscv::XLEN-1:0] pc_rdata;
logic [config_pkg::NRET*riscv::XLEN-1:0] pc_wdata;
logic [config_pkg::NRET*riscv::VLEN-1:0] mem_addr;
logic [config_pkg::NRET*riscv::PLEN-1:0] mem_paddr;
logic [config_pkg::NRET*(riscv::XLEN/8)-1:0] mem_rmask;
logic [config_pkg::NRET*(riscv::XLEN/8)-1:0] mem_wmask;
logic [config_pkg::NRET*riscv::XLEN-1:0] mem_rdata;
logic [config_pkg::NRET*riscv::XLEN-1:0] mem_wdata;
},
parameter type rvfi_instr_t = logic,
parameter longint unsigned DramBase = 'h8000_0000,
parameter int unsigned Size = 64 * 1024 * 1024 // 64 Mega Byte
)(

View file

@ -64,8 +64,8 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
logic [63:0] paddr;
logic seq_end_req, seq_end_ack, prog_end;
logic [DCACHE_TAG_WIDTH-1:0] tag_q;
logic [DCACHE_TAG_WIDTH-1:0] tag_vld_q;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_q;
logic [CVA6Cfg.DCACHE_TAG_WIDTH-1:0] tag_vld_q;
///////////////////////////////////////////////////////////////////////////////
@ -93,7 +93,7 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
if(cnt==0) begin
if(tmp_vld) begin
tmp_vld = 0;
tag_q <= tmp_paddr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
tag_q <= tmp_paddr[CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
tag_vld_q <= 1'b1;
end else begin
tag_vld_q <= 1'b0;
@ -126,7 +126,7 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
assign dut_req_port_o.address_tag = tag_q;
assign dut_req_port_o.tag_valid = tag_vld_q;
assign dut_req_port_o.address_index = paddr[DCACHE_INDEX_WIDTH-1:0];
assign dut_req_port_o.address_index = paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
assign exp_paddr_o = paddr;
///////////////////////////////////////////////////////////////////////////////
@ -221,11 +221,11 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
// Generate a sequence of reads to the same set (constant index)
task automatic genSetSeqRead();
automatic logic [63:0] val, rnd;
paddr = CachedAddrBeg + 2 ** DCACHE_INDEX_WIDTH;
paddr = CachedAddrBeg + 2 ** CVA6Cfg.DCACHE_INDEX_WIDTH;
dut_req_port_o.data_req = '0;
dut_req_port_o.data_size = '0;
dut_req_port_o.kill_req = '0;
val = CachedAddrBeg + 2 ** DCACHE_INDEX_WIDTH;
val = CachedAddrBeg + 2 ** CVA6Cfg.DCACHE_INDEX_WIDTH;
while(~seq_end_req) begin
void'(randomize(rnd) with {rnd > 0; rnd <= 100;});
if(rnd < req_rate_i) begin
@ -235,7 +235,7 @@ program tb_readport import tb_pkg::*; import ariane_pkg::*; #(
// generate linear read
`APPL_WAIT_COMB_SIG(clk_i, dut_req_port_i.data_gnt)
// increment by set size
val = (val + 2 ** DCACHE_INDEX_WIDTH) % (MemWords<<3);
val = (val + 2 ** CVA6Cfg.DCACHE_INDEX_WIDTH) % (MemWords<<3);
end
`APPL_WAIT_CYC(clk_i,1)
dut_req_port_o.data_req = '0;

View file

@ -49,8 +49,8 @@ program tb_writeport import tb_pkg::*; import ariane_pkg::*; #(
logic [63:0] paddr;
assign dut_req_port_o.address_tag = paddr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
assign dut_req_port_o.address_index = paddr[DCACHE_INDEX_WIDTH-1:0];
assign dut_req_port_o.address_tag = paddr[CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
assign dut_req_port_o.address_index = paddr[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
assign dut_req_port_o.data_we = dut_req_port_o.data_req;
///////////////////////////////////////////////////////////////////////////////

View file

@ -154,7 +154,7 @@ module mem_emul import ariane_pkg::*; import wt_cache_pkg::*; #(
// we allways invalidate all ways of the aliased index.
// this is not entirely correct and will produce
// too many invalidations
infifo_data.inv.idx = rand_addr_q[ICACHE_INDEX_WIDTH-1:0];
infifo_data.inv.idx = rand_addr_q[CVA6Cfg.ICACHE_INDEX_WIDTH-1:0];
infifo_data.inv.all = '1;
infifo_push = 1'b1;

View file

@ -32,7 +32,7 @@ module tb import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*; #()();
timeprecision 1ps;
// number of 32bit words
parameter MemBytes = 2**ICACHE_INDEX_WIDTH * 4 * 32;
parameter MemBytes = 2**CVA6Cfg.ICACHE_INDEX_WIDTH * 4 * 32;
parameter MemWords = MemBytes>>2;
parameter logic [63:0] CachedAddrBeg = MemBytes/4;
parameter logic [63:0] CachedAddrEnd = MemBytes;

View file

@ -24,7 +24,7 @@ module tb import ariane_pkg::*; import std_cache_pkg::*; import tb_pkg::*; #()()
timeprecision 1ps;
// memory configuration (64bit words)
parameter MemBytes = 2**DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemBytes = 2**CVA6Cfg.DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemWords = MemBytes>>3;
// noncacheable portion
@ -849,9 +849,9 @@ axi_riscv_atomics_wrap #(
seq_type = '{IDLE_SEQ, IDLE_SEQ, LINEAR_SEQ};
req_rate = '{default:100};
runSeq((CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
runSeq((CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
runSeq(0,(CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
runSeq(0,(CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
flushCache();
tb_mem_port_t::check_mem();

View file

@ -24,7 +24,7 @@ module tb import ariane_pkg::*; import wt_cache_pkg::*; import tb_pkg::*; #()();
timeprecision 1ps;
// memory configuration (64bit words)
parameter MemBytes = 2**DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemBytes = 2**CVA6Cfg.DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemWords = MemBytes>>3;
// noncacheable portion
@ -809,9 +809,9 @@ axi_riscv_atomics_wrap #(
seq_type = '{IDLE_SEQ, IDLE_SEQ, LINEAR_SEQ};
req_rate = '{default:100};
runSeq((CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
runSeq((CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
runSeq(0,(CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
runSeq(0,(CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
flushCache();
tb_mem_port_t::check_mem();

View file

@ -32,7 +32,7 @@ module tb import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*; #()();
timeprecision 1ps;
// memory configuration (64bit words)
parameter MemBytes = 2**DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemBytes = 2**CVA6Cfg.DCACHE_INDEX_WIDTH * 4 * 32;
parameter MemWords = MemBytes>>3;
// noncacheable portion
parameter logic [63:0] CachedAddrBeg = MemBytes>>3;//1/8th of the memory is NC
@ -546,9 +546,9 @@ module tb import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*; #()();
inv_rand_en = 0;
seq_type = '{IDLE_SEQ, IDLE_SEQ, LINEAR_SEQ};
req_rate = '{default:100};
runSeq((CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,0);
runSeq((CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC,0);
seq_type = '{LINEAR_SEQ, IDLE_SEQ, IDLE_SEQ};
runSeq(0,(CachedAddrBeg>>3)+(2**(DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
runSeq(0,(CachedAddrBeg>>3)+(2**(CVA6Cfg.DCACHE_INDEX_WIDTH-3))*DCACHE_SET_ASSOC);
flushCache();
memCheck();
///////////////////////////////////////////////

View file

@ -208,7 +208,7 @@ module tb_mem import tb_pkg::*; import ariane_pkg::*; import wt_cache_pkg::*;#(
// we allways invalidate all ways of the aliased index.
// this is not entirely correct and will produce
// too many invalidations
infifo_data.inv.idx = rand_addr_q[DCACHE_INDEX_WIDTH-1:0];
infifo_data.inv.idx = rand_addr_q[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
infifo_data.inv.all = '1;
infifo_push = 1'b1;

View file

@ -15,6 +15,7 @@ module fifo_v3 #(
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
parameter type dtype = logic [DATA_WIDTH-1:0],
parameter bit FPGA_EN = 1'b0,
// DO NOT OVERWRITE THIS PARAMETER
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
)(
@ -70,7 +71,7 @@ module fifo_v3 #(
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
status_cnt_n = status_cnt_q;
if (ariane_pkg::FPGA_EN) begin
if (FPGA_EN) begin
fifo_ram_we = '0;
fifo_ram_read_address = read_pointer_q;
fifo_ram_write_address = '0;
@ -84,7 +85,7 @@ module fifo_v3 #(
// push a new element to the queue
if (push_i && ~full_o) begin
if (ariane_pkg::FPGA_EN) begin
if (FPGA_EN) begin
fifo_ram_we = 1'b1;
fifo_ram_write_address = write_pointer_q;
fifo_ram_wdata = data_i;
@ -149,7 +150,7 @@ module fifo_v3 #(
end
end
if (ariane_pkg::FPGA_EN) begin : gen_fpga_queue
if (FPGA_EN) begin : gen_fpga_queue
AsyncDpRam #(
.ADDR_WIDTH (ADDR_DEPTH),
.DATA_DEPTH (DEPTH),