mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 21:27:10 -04:00
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:
parent
f0887e4ec5
commit
987c645bb7
87 changed files with 1419 additions and 1192 deletions
|
@ -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;
|
||||
|
|
|
@ -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"});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
// }}}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
229
core/cva6.sv
229
core/cva6.sv
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
// Handshake’s 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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
22
core/mult.sv
22
core/mult.sv
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ),
|
||||
|
|
|
@ -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
|
||||
)(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
///////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue