[RVV] CVA6 re-parametrization and MMU interface (#2652)

Follow-up to the discussion on extending Linux support to the Ara vector processor.

* Main changes:
Add:
Add external MMU interface to share the MMU with the external accelerator.
Add avoid_neg() function used to clip negative numbers to zero. Useful for parametric array sizes and vector multipliers.

Modifications:
2 commit ports by default in cv64a6_imafdcv_config_pkg.
Change exception_t from localparam to param in cva6.sv.
Add parameters accelerator_req_t, accelerator_resp_t, acc_mmu_req_t, and acc_mmu_resp_t to cva6.sv.
Replace the fall-through register with a spill register in acc_dispatcher to decouple timing with the accelerator.
Decrease cache sizes in cv64a6_imafdcv_sv39_config_pkg.
Modify Bender.yml package name from ariane to cva6.
Add harmless code to prevent synthesizer tool from crashing when compiling csr_regfile.

* Collateral changes:
Fixes:
Guard some X-IF code lines with correct parameter in cva6.sv.
Parametrize the tracer interface with NrCommitPorts.
Add missing local dependencies to Bender.yml.

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
This commit is contained in:
Matteo Perotti 2025-02-11 07:22:31 +01:00 committed by GitHub
parent 2ef1c1b1fc
commit 1bc415391a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 393 additions and 241 deletions

View file

@ -1,5 +1,5 @@
package:
name: ariane
name: cva6
authors:
- "Florian Zaruba <zarubaf@iis.ee.ethz.ch>"
- "Michael Schaffner <schaffner@iis.ee.ethz.ch>"
@ -68,6 +68,7 @@ sources:
- target: any(cv64a6_imafdcv_sv39, cv64a6_imafdc_sv39, cv64a6_imafdc_sv39_wb, cv64a6_imafdch_sv39, cv64a6_imafdch_sv39_wb, cv32a6_imac_sv0, cv32a6_imac_sv32, cv32a6_imafc_sv32)
files:
- core/cva6_mmu/cva6_tlb.sv
- core/cva6_mmu/cva6_shared_tlb.sv
- core/cva6_mmu/cva6_mmu.sv
- core/cva6_mmu/cva6_ptw.sv
@ -78,6 +79,8 @@ sources:
# Extension Interface
- core/cvxif_example/include/cvxif_instr_pkg.sv
- core/cvxif_fu.sv
- core/cvxif_issue_register_commit_if_driver.sv
- core/cvxif_compressed_if_driver.sv
- core/cvxif_example/cvxif_example_coprocessor.sv
- core/cvxif_example/instr_decoder.sv
@ -95,6 +98,7 @@ sources:
- core/csr_regfile.sv
- core/decoder.sv
- core/ex_stage.sv
- core/acc_dispatcher.sv
- core/instr_realign.sv
- core/id_stage.sv
- core/issue_read_operands.sv
@ -142,6 +146,7 @@ sources:
# Physical Memory Protection
- core/pmp/src/pmp.sv
- core/pmp/src/pmp_entry.sv
- core/pmp/src/pmp_data_if.sv
- include_dirs:
- common/local/util
@ -153,12 +158,15 @@ sources:
- common/local/util
files:
- common/local/util/tc_sram_wrapper.sv
- common/local/util/sram_cache.sv
- target: all(fpga, xilinx)
include_dirs:
- common/local/util
files:
- common/local/util/sram_cache.sv
- common/local/util/tc_sram_fpga_wrapper.sv
- vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx64.sv
- target: not(synthesis)
include_dirs:

View file

@ -25,32 +25,32 @@ module instr_tracer #(
parameter type exception_t = logic,
parameter interrupts_t INTERRUPTS = '0
)(
input logic pck,
input logic rstn,
input logic flush_unissued,
input logic flush_all,
input logic [31:0] instruction,
input logic fetch_valid,
input logic fetch_ack,
input logic issue_ack, // issue acknowledged
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
input logic [1:0][4:0] waddr, // WB stage
input logic [1:0][63:0] wdata,
input logic [1:0] we_gpr,
input logic [1:0] we_fpr,
input scoreboard_entry_t [1:0] commit_instr, // commit instruction
input logic [1:0] commit_ack,
input logic st_valid, // stores - address translation
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
input logic ld_valid, // loads
input logic ld_kill,
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
input bp_resolve_t resolve_branch, // misprediction
input exception_t commit_exception,
input riscv::priv_lvl_t priv_lvl, // current privilege level
input logic debug_mode,
input logic pck,
input logic rstn,
input logic flush_unissued,
input logic flush_all,
input logic [31:0] instruction,
input logic fetch_valid,
input logic fetch_ack,
input logic issue_ack, // issue acknowledged
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr, // WB stage
input logic [CVA6Cfg.NrCommitPorts-1:0][63:0] wdata,
input logic [CVA6Cfg.NrCommitPorts-1:0] we_gpr,
input logic [CVA6Cfg.NrCommitPorts-1:0] we_fpr,
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr, // commit instruction
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack,
input logic st_valid, // stores - address translation
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
input logic ld_valid, // loads
input logic ld_kill,
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
input bp_resolve_t resolve_branch, // misprediction
input exception_t commit_exception,
input riscv::priv_lvl_t priv_lvl, // current privilege level
input logic debug_mode,
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
);
// keep the decoded instructions in a queue

View file

@ -23,36 +23,12 @@ module acc_dispatcher
parameter type exception_t = logic,
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 [CVA6Cfg.XLEN-1:0] rs1;
logic [CVA6Cfg.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;
},
parameter type acc_req_t = accelerator_req_t,
parameter type acc_resp_t = struct packed {
logic req_ready;
logic resp_valid;
logic [CVA6Cfg.XLEN-1:0] result;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] trans_id;
exception_t exception;
// Metadata
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;
},
parameter type acc_req_t = logic,
parameter type acc_resp_t = logic,
parameter type accelerator_req_t = logic,
parameter type accelerator_resp_t = logic,
parameter type acc_mmu_req_t = logic,
parameter type acc_mmu_resp_t = logic,
parameter type acc_cfg_t = logic,
parameter acc_cfg_t AccCfg = '0
) (
@ -65,10 +41,11 @@ module acc_dispatcher
// Interface with the CSRs
input priv_lvl_t ld_st_priv_lvl_i,
input logic sum_i,
input pmpcfg_t [CVA6Cfg.NrPMPEntries-1:0] pmpcfg_i,
input logic [CVA6Cfg.NrPMPEntries-1:0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input logic [2:0] fcsr_frm_i,
output logic dirty_v_state_o,
input logic acc_mmu_en_i,
// Interface with the issue stage
input scoreboard_entry_t issue_instr_i,
input logic issue_instr_hs_i,
@ -88,6 +65,9 @@ module acc_dispatcher
output logic acc_stall_st_pending_o,
input logic acc_no_st_pending_i,
input dcache_req_i_t [2:0] dcache_req_ports_i,
// Interface with the MMU
output acc_mmu_req_t acc_mmu_req_o,
input acc_mmu_resp_t acc_mmu_resp_i,
// Interface with the controller
output logic ctrl_halt_o,
input logic [11:0] csr_addr_i,
@ -219,7 +199,7 @@ module acc_dispatcher
end
// An accelerator instruction was issued.
if (acc_req_o.req_valid) insn_ready_d[acc_req_o.trans_id] = 1'b0;
if (acc_req_o.acc_req.req_valid) insn_ready_d[acc_req_o.acc_req.trans_id] = 1'b0;
end : p_non_speculative_ff
/*************************
@ -231,29 +211,31 @@ module acc_dispatcher
logic acc_req_ready;
accelerator_req_t acc_req_int;
fall_through_register #(
spill_register #(
.T(accelerator_req_t)
) i_accelerator_req_register (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (1'b0),
.testmode_i(1'b0),
.data_i (acc_req),
.valid_i (acc_req_valid),
.ready_o (acc_req_ready),
.data_o (acc_req_int),
.valid_o (acc_req_o.req_valid),
.ready_i (acc_resp_i.req_ready)
.clk_i (clk_i),
.rst_ni (rst_ni),
.data_i (acc_req),
.valid_i(acc_req_valid),
.ready_o(acc_req_ready),
.data_o (acc_req_int),
.valid_o(acc_req_o.acc_req.req_valid),
.ready_i(acc_resp_i.acc_resp.req_ready)
);
assign acc_req_o.insn = acc_req_int.insn;
assign acc_req_o.rs1 = acc_req_int.rs1;
assign acc_req_o.rs2 = acc_req_int.rs2;
assign acc_req_o.frm = acc_req_int.frm;
assign acc_req_o.trans_id = acc_req_int.trans_id;
assign acc_req_o.store_pending = !acc_no_st_pending_i && acc_cons_en_i;
assign acc_req_o.acc_cons_en = acc_cons_en_i;
assign acc_req_o.inval_ready = inval_ready_i;
assign acc_req_o.acc_req.insn = acc_req_int.insn;
assign acc_req_o.acc_req.rs1 = acc_req_int.rs1;
assign acc_req_o.acc_req.rs2 = acc_req_int.rs2;
assign acc_req_o.acc_req.frm = acc_req_int.frm;
assign acc_req_o.acc_req.trans_id = acc_req_int.trans_id;
assign acc_req_o.acc_req.store_pending = !acc_no_st_pending_i && acc_cons_en_i;
assign acc_req_o.acc_req.acc_cons_en = acc_cons_en_i;
assign acc_req_o.acc_req.inval_ready = inval_ready_i;
// MMU interface
assign acc_req_o.acc_mmu_resp = acc_mmu_resp_i;
assign acc_req_o.acc_mmu_en = acc_mmu_en_i;
always_comb begin : accelerator_req_dispatcher
// Do not fetch from the instruction queue
@ -263,7 +245,7 @@ module acc_dispatcher
acc_req = '0;
acc_req_valid = 1'b0;
// Unpack fu_data_t into accelerator_req_t
// Unpack fu_data_t into acc_req_t
if (!acc_insn_queue_empty) begin
acc_req = '{
// Instruction is forwarded from the decoder as an immediate
@ -297,23 +279,27 @@ module acc_dispatcher
logic acc_ld_disp;
logic acc_st_disp;
assign acc_trans_id_o = acc_resp_i.trans_id;
assign acc_result_o = acc_resp_i.result;
assign acc_valid_o = acc_resp_i.resp_valid;
assign acc_exception_o = acc_resp_i.exception;
assign acc_trans_id_o = acc_resp_i.acc_resp.trans_id;
assign acc_result_o = acc_resp_i.acc_resp.result;
assign acc_valid_o = acc_resp_i.acc_resp.resp_valid;
assign acc_exception_o = acc_resp_i.acc_resp.exception;
// Unpack the accelerator response
assign acc_fflags_valid_o = acc_resp_i.fflags_valid;
assign acc_fflags_o = acc_resp_i.fflags;
assign acc_fflags_valid_o = acc_resp_i.acc_resp.fflags_valid;
assign acc_fflags_o = acc_resp_i.acc_resp.fflags;
// MMU interface
assign acc_mmu_req_o = acc_resp_i.acc_mmu_req;
// Always ready to receive responses
assign acc_req_o.resp_ready = 1'b1;
assign acc_req_o.acc_req.resp_ready = 1'b1;
// Signal dispatched load/store to issue stage
assign acc_ld_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
assign acc_st_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);
assign acc_ld_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
assign acc_st_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);
// Cache invalidation
assign inval_valid_o = acc_resp_i.inval_valid;
assign inval_addr_o = acc_resp_i.inval_addr;
assign inval_valid_o = acc_resp_i.acc_resp.inval_valid;
assign inval_addr_o = acc_resp_i.acc_resp.inval_addr;
/**************************
* Accelerator commit *
@ -351,8 +337,8 @@ module acc_dispatcher
`FF(wait_acc_store_q, wait_acc_store_d, '0)
// Set on store barrier. Clear when no store is pending.
assign wait_acc_store_d = (wait_acc_store_q | commit_st_barrier_i) & acc_resp_i.store_pending;
assign ctrl_halt_o = wait_acc_store_q;
assign wait_acc_store_d = (wait_acc_store_q | commit_st_barrier_i) & acc_resp_i.acc_resp.store_pending;
assign ctrl_halt_o = wait_acc_store_q;
/**************************
* Load/Store tracking *
@ -390,9 +376,9 @@ module acc_dispatcher
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (1'b0),
.en_i (acc_ld_disp ^ acc_resp_i.load_complete),
.en_i (acc_ld_disp ^ acc_resp_i.acc_resp.load_complete),
.load_i (1'b0),
.down_i (acc_resp_i.load_complete),
.down_i (acc_resp_i.acc_resp.load_complete),
.d_i ('0),
.q_o (acc_disp_loads_pending),
.overflow_o(acc_disp_loads_overflow)
@ -435,9 +421,9 @@ module acc_dispatcher
.clk_i (clk_i),
.rst_ni (rst_ni),
.clear_i (1'b0),
.en_i (acc_st_disp ^ acc_resp_i.store_complete),
.en_i (acc_st_disp ^ acc_resp_i.acc_resp.store_complete),
.load_i (1'b0),
.down_i (acc_resp_i.store_complete),
.down_i (acc_resp_i.acc_resp.store_complete),
.d_i ('0),
.q_o (acc_disp_stores_pending),
.overflow_o(acc_disp_stores_overflow)

View file

@ -426,7 +426,7 @@ module cva6_icache
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}+:CVA6Cfg.FETCH_WIDTH];
assign cl_user[i] = cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH];
assign cl_user[i] = CVA6Cfg.FETCH_USER_EN ? cl_ruser[i][{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH] : '0;
end
@ -441,10 +441,10 @@ module cva6_icache
always_comb begin
if (cmp_en_q) begin
dreq_o.data = cl_sel[hit_idx];
dreq_o.user = cl_user[hit_idx];
dreq_o.user = CVA6Cfg.FETCH_USER_EN ? cl_user[hit_idx] : '0;
end else begin
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];
dreq_o.user = CVA6Cfg.FETCH_USER_EN ? mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH] : '0;
end
end

View file

@ -162,9 +162,9 @@ module csr_regfile
// TO_BE_COMPLETED - PERF_COUNTERS
output logic perf_we_o,
// PMP configuration containing pmpcfg for max 64 PMPs - ACC_DISPATCHER
output riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_o,
output riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_o,
// PMP addresses - ACC_DISPATCHER
output logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_o,
output logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_o,
// TO_BE_COMPLETED - PERF_COUNTERS
output logic [31:0] mcountinhibit_o,
// RVFI
@ -784,11 +784,13 @@ module csr_regfile
riscv::CSR_PMPCFG14,
riscv::CSR_PMPCFG15: begin
// index is calculated using PMPCFG0 as the offset
automatic logic [11:0] index = csr_addr.address[11:0] - riscv::CSR_PMPCFG0;
automatic logic [3:0] index = csr_addr.address[11:0] - riscv::CSR_PMPCFG0;
// if index is not even and XLEN==64, raise exception
if (CVA6Cfg.XLEN == 64 && index[0] == 1'b1) read_access_exception = 1'b1;
else begin
// The following line has no effect. It's here just to prevent the synthesizer from crashing
if (CVA6Cfg.XLEN == 64) index = (index >> 1) << 1;
csr_rdata = pmpcfg_q[index*4+:CVA6Cfg.XLEN/8];
end
end

View file

@ -39,7 +39,7 @@ module cva6
logic [CVA6Cfg.VLEN-1:0] predict_address; // target address at which to jump, or not
},
localparam type exception_t = struct packed {
parameter type exception_t = struct packed {
logic [CVA6Cfg.XLEN-1:0] cause; // cause of exception
logic [CVA6Cfg.XLEN-1:0] tval; // additional information of causing exception (e.g.: instruction causing it),
// address of LD/ST fault
@ -217,6 +217,14 @@ module cva6
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] data_ruser;
},
// Accelerator - CVA6
parameter type accelerator_req_t = logic,
parameter type accelerator_resp_t = logic,
// Accelerator - CVA6's MMU
parameter type acc_mmu_req_t = logic,
parameter type acc_mmu_resp_t = logic,
// AXI types
parameter type axi_ar_chan_t = struct packed {
logic [CVA6Cfg.AxiIdWidth-1:0] id;
@ -509,6 +517,11 @@ module cva6
// ACCEL Commit
logic acc_valid_acc_ex;
// --------------
// EX <-> ACC_DISP
// --------------
acc_mmu_req_t acc_mmu_req;
acc_mmu_resp_t acc_mmu_resp;
// --------------
// ID <-> COMMIT
// --------------
scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_id_commit;
@ -569,8 +582,8 @@ module cva6
logic acc_cons_en_csr;
logic debug_mode;
logic single_step_csr_commit;
riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg;
logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr;
riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg;
logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr;
logic [31:0] mcountinhibit_csr_perf;
//jvt
jvt_t jvt;
@ -764,16 +777,17 @@ module cva6
assign ex_ex_ex_id[FPU_WB] = fpu_exception_ex_id;
assign wt_valid_ex_id[FPU_WB] = fpu_valid_ex_id;
always_comb begin : gen_cvxif_input_assignement
x_compressed_ready = cvxif_resp_i.compressed_ready;
x_compressed_resp = cvxif_resp_i.compressed_resp;
x_issue_ready = cvxif_resp_i.issue_ready;
x_issue_resp = cvxif_resp_i.issue_resp;
x_register_ready = cvxif_resp_i.register_ready;
x_result_valid = cvxif_resp_i.result_valid;
x_result = cvxif_resp_i.result;
end
if (CVA6Cfg.CvxifEn) begin
always_comb begin : gen_cvxif_input_assignement
x_compressed_ready = cvxif_resp_i.compressed_ready;
x_compressed_resp = cvxif_resp_i.compressed_resp;
x_issue_ready = cvxif_resp_i.issue_ready;
x_issue_resp = cvxif_resp_i.issue_resp;
x_register_ready = cvxif_resp_i.register_ready;
x_result_valid = cvxif_resp_i.result_valid;
x_result = cvxif_resp_i.result;
end
always_comb begin : gen_cvxif_output_assignement
cvxif_req.compressed_valid = x_compressed_valid;
cvxif_req.compressed_req = x_compressed_req;
@ -921,7 +935,9 @@ module cva6
.icache_dreq_t(icache_dreq_t),
.icache_drsp_t(icache_drsp_t),
.lsu_ctrl_t(lsu_ctrl_t),
.x_result_t(x_result_t)
.x_result_t(x_result_t),
.acc_mmu_req_t(acc_mmu_req_t),
.acc_mmu_resp_t(acc_mmu_resp_t)
) ex_stage_i (
.clk_i(clk_i),
.rst_ni(rst_ni),
@ -1005,6 +1021,9 @@ module cva6
.x_result_ready_o (x_result_ready),
// Accelerator
.acc_valid_i (acc_valid_acc_ex),
// Accelerator MMU access
.acc_mmu_req_i (acc_mmu_req),
.acc_mmu_resp_o (acc_mmu_resp),
// Performance counters
.itlb_miss_o (itlb_miss_ex_perf),
.dtlb_miss_o (dtlb_miss_ex_perf),
@ -1504,7 +1523,11 @@ module cva6
.acc_cfg_t (acc_cfg_t),
.AccCfg (AccCfg),
.acc_req_t (cvxif_req_t),
.acc_resp_t (cvxif_resp_t)
.acc_resp_t (cvxif_resp_t),
.accelerator_req_t (accelerator_req_t),
.accelerator_resp_t(accelerator_resp_t),
.acc_mmu_req_t (acc_mmu_req_t),
.acc_mmu_resp_t (acc_mmu_resp_t)
) i_acc_dispatcher (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -1520,6 +1543,7 @@ module cva6
.pmpcfg_i (pmpcfg),
.pmpaddr_i (pmpaddr),
.fcsr_frm_i (frm_csr_id_issue_ex),
.acc_mmu_en_i (enable_translation_csr_ex),
.dirty_v_state_o (dirty_v_state),
.issue_instr_i (issue_instr_id_acc),
.issue_instr_hs_i (issue_instr_hs_id_acc),
@ -1536,6 +1560,8 @@ module cva6
.acc_stall_st_pending_o(stall_st_pending_ex),
.acc_no_st_pending_i (no_st_pending_commit),
.dcache_req_ports_i (dcache_req_ports_ex_cache),
.acc_mmu_req_o (acc_mmu_req),
.acc_mmu_resp_i (acc_mmu_resp),
.ctrl_halt_o (halt_acc_ctrl),
.csr_addr_i (csr_addr_ex_csr),
.acc_dcache_req_ports_o(dcache_req_ports_acc_cache),
@ -1565,6 +1591,9 @@ module cva6
// D$ connection is unused
assign dcache_req_ports_acc_cache = '0;
// MMU access is unused
assign acc_mmu_req = '0;
// No invalidation interface
assign inval_valid = '0;
assign inval_addr = '0;

View file

@ -100,8 +100,8 @@ module cva6_mmu
// PMP
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_i,
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_i
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i
);
// memory management, pte for cva6

View file

@ -16,7 +16,7 @@
// Date: 26/02/2024
// Description: Hardware-PTW (Page-Table-Walker) for CVA6 supporting sv32, sv39 and sv39x4.
// This module is an merge of the PTW Sv39 developed by Florian Zaruba,
// the PTW Sv32 developed by Sebastien Jacq and the PTW Sv39x4 by Bruno Sá.
// the PTW Sv32 developed by Sebastien Jacq and the PTW Sv39x4 by Bruno Sá.
/* verilator lint_off WIDTH */
@ -83,8 +83,8 @@ module cva6_ptw
output logic shared_tlb_miss_o,
// PMP
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_i,
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
output logic [CVA6Cfg.PLEN-1:0] bad_paddr_o,
output logic [CVA6Cfg.GPLEN-1:0] bad_gpaddr_o
);
@ -258,8 +258,8 @@ module cva6_ptw
// PAGESIZE=2^12 and LEVELS=3.)
// 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For
// Sv32, PTESIZE=4.)
// 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if any bits or encodings
// that are reserved for future standard use are set within pte, stop and raise
// 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if any bits or encodings
// that are reserved for future standard use are set within pte, stop and raise
// a page-fault exception corresponding to the original access type.
// 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5.
// Otherwise, this PTE is a pointer to the next level of the page table.

View file

@ -29,7 +29,9 @@ module ex_stage
parameter type icache_dreq_t = logic,
parameter type icache_drsp_t = logic,
parameter type lsu_ctrl_t = logic,
parameter type x_result_t = logic
parameter type x_result_t = logic,
parameter type acc_mmu_req_t = logic,
parameter type acc_mmu_resp_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
@ -161,6 +163,9 @@ module ex_stage
input logic x_transaction_rejected_i,
// accelerate port result is valid - ACC_DISPATCHER
input logic acc_valid_i,
// Accelerator MMU access
input acc_mmu_req_t acc_mmu_req_i,
output acc_mmu_resp_t acc_mmu_resp_o,
// Enable virtual memory translation - CSR_REGFILE
input logic enable_translation_i,
// Enable G-Stage memory translation - CSR_REGFILE
@ -224,9 +229,9 @@ module ex_stage
// To count the data TLB misses - PERF_COUNTERS
output logic dtlb_miss_o,
// Report the PMP configuration - CSR_REGFILE
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_i,
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
// Report the PMP addresses - CSR_REGFILE
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
// Information dedicated to RVFI - RVFI
output lsu_ctrl_t rvfi_lsu_ctrl_o,
// Information dedicated to RVFI - RVFI
@ -529,7 +534,9 @@ module ex_stage
.icache_arsp_t(icache_arsp_t),
.icache_dreq_t(icache_dreq_t),
.icache_drsp_t(icache_drsp_t),
.lsu_ctrl_t(lsu_ctrl_t)
.lsu_ctrl_t(lsu_ctrl_t),
.acc_mmu_req_t(acc_mmu_req_t),
.acc_mmu_resp_t(acc_mmu_resp_t)
) lsu_i (
.clk_i,
.rst_ni,
@ -554,6 +561,8 @@ module ex_stage
.enable_g_translation_i,
.en_ld_st_translation_i,
.en_ld_st_g_translation_i,
.acc_mmu_req_i,
.acc_mmu_resp_o,
.icache_areq_i,
.icache_areq_o,
.priv_lvl_i,

View file

@ -807,4 +807,12 @@ package ariane_pkg;
return gppn;
endfunction : make_gppn
// ----------------------
// Helper functions
// ----------------------
// Avoid negative array slices when defining parametrized sizes
function automatic int unsigned avoid_neg(int n);
return (n < 0) ? 0 : n;
endfunction : avoid_neg
endpackage

View file

@ -12,6 +12,8 @@ package cva6_config_pkg;
localparam CVA6ConfigXlen = 64;
localparam CVA6ConfigNrCommitPorts = 2;
localparam CVA6ConfigRVF = 1;
localparam CVA6ConfigF16En = 0;
localparam CVA6ConfigF16AltEn = 0;
@ -32,16 +34,16 @@ package cva6_config_pkg;
localparam CVA6ConfigAxiAddrWidth = 64;
localparam CVA6ConfigAxiDataWidth = 64;
localparam CVA6ConfigFetchUserEn = 0;
localparam CVA6ConfigFetchUserWidth = CVA6ConfigXlen;
localparam CVA6ConfigFetchUserWidth = 1; // Just not to raise warnings
localparam CVA6ConfigDataUserEn = 0;
localparam CVA6ConfigDataUserWidth = CVA6ConfigXlen;
localparam CVA6ConfigIcacheByteSize = 16384;
localparam CVA6ConfigIcacheByteSize = 4096;
localparam CVA6ConfigIcacheSetAssoc = 4;
localparam CVA6ConfigIcacheLineWidth = 128;
localparam CVA6ConfigDcacheByteSize = 16384;
localparam CVA6ConfigDcacheByteSize = 8192;
localparam CVA6ConfigDcacheSetAssoc = 4;
localparam CVA6ConfigDcacheLineWidth = 128;
localparam CVA6ConfigDcacheLineWidth = 256;
localparam CVA6ConfigDcacheFlushOnFence = 1'b0;
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
@ -80,7 +82,7 @@ package cva6_config_pkg;
FpgaAlteraEn: bit'(0), // for Altera (only)
TechnoCut: bit'(0),
SuperscalarEn: bit'(0),
NrCommitPorts: unsigned'(1),
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth),

View file

@ -25,7 +25,9 @@ module load_store_unit
parameter type icache_arsp_t = logic,
parameter type icache_dreq_t = logic,
parameter type icache_drsp_t = logic,
parameter type lsu_ctrl_t = logic
parameter type lsu_ctrl_t = logic,
parameter type acc_mmu_req_t = logic,
parameter type acc_mmu_resp_t = logic
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
@ -82,6 +84,10 @@ module load_store_unit
// Enable G-Stage memory translation for load/stores - TO_BE_COMPLETED
input logic en_ld_st_g_translation_i,
// Accelerator request for CVA6's MMU
input acc_mmu_req_t acc_mmu_req_i,
output acc_mmu_resp_t acc_mmu_resp_o,
// Instruction cache input request - CACHES
input icache_arsp_t icache_areq_i,
// Instruction cache output request - CACHES
@ -148,9 +154,9 @@ module load_store_unit
input amo_resp_t amo_resp_i,
// PMP configuration - CSR_REGFILE
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_i,
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
// PMP address - CSR_REGFILE
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
// RVFI inforamtion - RVFI
output lsu_ctrl_t rvfi_lsu_ctrl_o,
@ -159,26 +165,26 @@ module load_store_unit
);
// data is misaligned
logic data_misaligned;
logic data_misaligned;
// --------------------------------------
// 1st register stage - (stall registers)
// --------------------------------------
// those are the signals which are always correct
// e.g.: they keep the value in the stall case
lsu_ctrl_t lsu_ctrl;
lsu_ctrl_t lsu_ctrl, lsu_ctrl_byp;
logic pop_st;
logic pop_ld;
logic pop_st;
logic pop_ld;
// ------------------------------
// Address Generation Unit (AGU)
// ------------------------------
// virtual address as calculated by the AGU in the first cycle
logic [ CVA6Cfg.VLEN-1:0] vaddr_i;
logic [ CVA6Cfg.XLEN-1:0] vaddr_xlen;
logic overflow;
logic g_overflow;
logic [(CVA6Cfg.XLEN/8)-1:0] be_i;
logic [ CVA6Cfg.VLEN-1:0] vaddr_i;
logic [ CVA6Cfg.XLEN-1:0] vaddr_xlen;
logic overflow;
logic g_overflow;
logic [(CVA6Cfg.XLEN/8)-1:0] be_i;
assign vaddr_xlen = $unsigned($signed(fu_data_i.imm) + $signed(fu_data_i.operand_a));
assign vaddr_i = vaddr_xlen[CVA6Cfg.VLEN-1:0];
@ -190,10 +196,10 @@ module load_store_unit
assign g_overflow = 1'b0;
end
logic st_valid_i;
logic ld_valid_i;
logic ld_translation_req;
logic st_translation_req;
logic st_valid_i;
logic ld_valid_i;
logic ld_translation_req;
logic st_translation_req, cva6_st_translation_req, acc_st_translation_req;
logic [CVA6Cfg.VLEN-1:0] ld_vaddr;
logic [ 31:0] ld_tinst;
logic ld_hs_ld_st_inst;
@ -202,41 +208,41 @@ module load_store_unit
logic [ 31:0] st_tinst;
logic st_hs_ld_st_inst;
logic st_hlvx_inst;
logic translation_req;
logic translation_valid;
logic [CVA6Cfg.VLEN-1:0] mmu_vaddr;
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, lsu_paddr;
logic [ 31:0] mmu_tinst;
logic mmu_hs_ld_st_inst;
logic mmu_hlvx_inst;
exception_t mmu_exception;
exception_t pmp_exception;
icache_areq_t pmp_icache_areq_i;
logic pmp_translation_valid;
logic dtlb_hit;
logic [ CVA6Cfg.PPNW-1:0] dtlb_ppn;
logic translation_req, cva6_translation_req, acc_translation_req;
logic translation_valid, cva6_translation_valid, acc_translataion_valid;
logic [CVA6Cfg.VLEN-1:0] mmu_vaddr, cva6_mmu_vaddr, acc_mmu_vaddr;
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, cva6_mmu_paddr, acc_mmu_paddr, lsu_paddr;
logic [31:0] mmu_tinst;
logic mmu_hs_ld_st_inst;
logic mmu_hlvx_inst;
exception_t mmu_exception, cva6_mmu_exception, acc_mmu_exception;
exception_t pmp_exception;
icache_areq_t pmp_icache_areq_i;
logic pmp_translation_valid;
logic dtlb_hit, cva6_dtlb_hit, acc_dtlb_hit;
logic [CVA6Cfg.PPNW-1:0] dtlb_ppn, cva6_dtlb_ppn, acc_dtlb_ppn;
logic ld_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
logic [ CVA6Cfg.XLEN-1:0] ld_result;
logic st_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
logic [ CVA6Cfg.XLEN-1:0] st_result;
logic ld_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
logic [ CVA6Cfg.XLEN-1:0] ld_result;
logic st_valid;
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
logic [ CVA6Cfg.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;
logic hs_ld_st_inst;
logic hlvx_inst;
exception_t misaligned_exception, cva6_misaligned_exception, acc_misaligned_exception;
exception_t ld_ex;
exception_t st_ex;
logic hs_ld_st_inst;
logic hlvx_inst;
logic [1:0] sum, mxr;
logic [CVA6Cfg.PPNW-1:0] satp_ppn[2:0];
logic [CVA6Cfg.ASID_WIDTH-1:0] asid[2:0], asid_to_be_flushed[1:0];
logic [CVA6Cfg.VLEN-1:0] vaddr_to_be_flushed[1:0];
// -------------------
// MMU e.g.: TLBs/PTW
// -------------------
@ -387,6 +393,108 @@ module load_store_unit
.pmpaddr_i (pmpaddr_i)
);
// ------------------
// External MMU port
// ------------------
if (CVA6Cfg.EnableAccelerator) begin
// The MMU can be connected to CVA6 or the ACCELERATOR
enum logic {
CVA6,
ACC
}
mmu_state_d, mmu_state_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
mmu_state_q <= CVA6;
end else begin
mmu_state_q <= mmu_state_d;
end
end
// Straightforward and slow-reactive MMU arbitration logic
// This logic can be optimized to reduce answer latency and contention
always_comb begin
// Maintain state
mmu_state_d = mmu_state_q;
// Serve CVA6 and gate the accelerator by default
// MMU input
misaligned_exception = cva6_misaligned_exception;
st_translation_req = cva6_st_translation_req;
translation_req = cva6_translation_req;
mmu_vaddr = cva6_mmu_vaddr;
// MMU output
cva6_translation_valid = translation_valid;
cva6_mmu_paddr = mmu_paddr;
cva6_mmu_exception = mmu_exception;
cva6_dtlb_hit = dtlb_hit;
cva6_dtlb_ppn = dtlb_ppn;
acc_mmu_resp_o.acc_mmu_valid = '0;
acc_mmu_resp_o.acc_mmu_paddr = '0;
acc_mmu_resp_o.acc_mmu_exception = '0;
acc_mmu_resp_o.acc_mmu_dtlb_hit = '0;
acc_mmu_resp_o.acc_mmu_dtlb_ppn = '0;
unique case (mmu_state_q)
CVA6: begin
// Only the accelerator is requesting, and the lsu bypass queue is empty.
if (acc_mmu_req_i.acc_mmu_req && !lsu_valid_i && lsu_ready_o) begin
// Lock the MMU to the accelerator.
// If the issue stage is firing a mem op in this cycle,
// the bypass queue will buffer it.
mmu_state_d = ACC;
end
// Make this a mealy FSM to cut some latency.
// It should be okay timing-wise since cva6's requests already
// depend on lsu_valid_i. Moreover, lsu_ready_o is sequentially
// generated by the bypass and, in this first implementation,
// the acc request already depends combinatorially upon acc_mmu_req_i.acc_mmu_req.
end
ACC: begin
// MMU input
misaligned_exception = acc_mmu_req_i.acc_mmu_misaligned_ex;
st_translation_req = acc_mmu_req_i.acc_mmu_is_store;
translation_req = acc_mmu_req_i.acc_mmu_req;
mmu_vaddr = acc_mmu_req_i.acc_mmu_vaddr;
// MMU output
acc_mmu_resp_o.acc_mmu_valid = translation_valid;
acc_mmu_resp_o.acc_mmu_paddr = mmu_paddr;
acc_mmu_resp_o.acc_mmu_exception = mmu_exception;
acc_mmu_resp_o.acc_mmu_dtlb_hit = dtlb_hit;
acc_mmu_resp_o.acc_mmu_dtlb_ppn = dtlb_ppn;
cva6_translation_valid = '0;
cva6_mmu_paddr = '0;
cva6_mmu_exception = '0;
cva6_dtlb_hit = '0;
cva6_dtlb_ppn = '0;
// Get back to CVA6 after the translation
if (translation_valid) mmu_state_d = CVA6;
end
default: mmu_state_d = CVA6;
endcase
end
always_comb begin
// Feed forward
lsu_ctrl = lsu_ctrl_byp;
// Mask the lsu valid so that cva6's req gets buffered in the
// bypass queue when the MMU is being used by the accelerator.
lsu_ctrl.valid = (mmu_state_q == ACC) ? 1'b0 : lsu_ctrl_byp.valid;
end
end else begin
// MMU input
assign misaligned_exception = cva6_misaligned_exception;
assign st_translation_req = cva6_st_translation_req;
assign translation_req = cva6_translation_req;
assign mmu_vaddr = cva6_mmu_vaddr;
// MMU output
assign cva6_translation_valid = translation_valid;
assign cva6_mmu_paddr = mmu_paddr;
assign cva6_mmu_exception = mmu_exception;
assign cva6_dtlb_hit = dtlb_hit;
assign cva6_dtlb_ppn = dtlb_ppn;
// No accelerator
assign acc_mmu_resp_o = '0;
// Feed forward the lsu_ctrl bypass
assign lsu_ctrl = lsu_ctrl_byp;
end
logic store_buffer_empty;
// ------------------
@ -418,15 +526,15 @@ module load_store_unit
.result_o (st_result),
.ex_o (st_ex),
// MMU port
.translation_req_o (st_translation_req),
.translation_req_o (cva6_st_translation_req),
.vaddr_o (st_vaddr),
.rvfi_mem_paddr_o (rvfi_mem_paddr_o),
.tinst_o (st_tinst),
.hs_ld_st_inst_o (st_hs_ld_st_inst),
.hlvx_inst_o (st_hlvx_inst),
.paddr_i (mmu_paddr),
.ex_i (mmu_exception),
.dtlb_hit_i (dtlb_hit),
.paddr_i (cva6_mmu_paddr),
.ex_i (cva6_mmu_exception),
.dtlb_hit_i (cva6_dtlb_hit),
// Load Unit
.page_offset_i (page_offset),
.page_offset_matches_o(page_offset_matches),
@ -465,10 +573,10 @@ module load_store_unit
.tinst_o (ld_tinst),
.hs_ld_st_inst_o (ld_hs_ld_st_inst),
.hlvx_inst_o (ld_hlvx_inst),
.paddr_i (mmu_paddr),
.ex_i (mmu_exception),
.dtlb_hit_i (dtlb_hit),
.dtlb_ppn_i (dtlb_ppn),
.paddr_i (cva6_mmu_paddr),
.ex_i (cva6_mmu_exception),
.dtlb_hit_i (cva6_dtlb_hit),
.dtlb_ppn_i (cva6_dtlb_ppn),
// to store unit
.page_offset_o (page_offset),
.page_offset_matches_i(page_offset_matches),
@ -510,22 +618,22 @@ module load_store_unit
// determine whether this is a load or store
always_comb begin : which_op
ld_valid_i = 1'b0;
st_valid_i = 1'b0;
ld_valid_i = 1'b0;
st_valid_i = 1'b0;
translation_req = 1'b0;
mmu_vaddr = {CVA6Cfg.VLEN{1'b0}};
mmu_tinst = {32{1'b0}};
mmu_hs_ld_st_inst = 1'b0;
mmu_hlvx_inst = 1'b0;
cva6_translation_req = 1'b0;
cva6_mmu_vaddr = {CVA6Cfg.VLEN{1'b0}};
mmu_tinst = {32{1'b0}};
mmu_hs_ld_st_inst = 1'b0;
mmu_hlvx_inst = 1'b0;
// check the operation to activate the right functional unit accordingly
unique case (lsu_ctrl.fu)
// all loads go here
LOAD: begin
ld_valid_i = lsu_ctrl.valid;
translation_req = ld_translation_req;
mmu_vaddr = ld_vaddr;
ld_valid_i = lsu_ctrl.valid;
cva6_translation_req = ld_translation_req;
cva6_mmu_vaddr = ld_vaddr;
if (CVA6Cfg.RVH) begin
mmu_tinst = ld_tinst;
mmu_hs_ld_st_inst = ld_hs_ld_st_inst;
@ -534,9 +642,9 @@ module load_store_unit
end
// all stores go here
STORE: begin
st_valid_i = lsu_ctrl.valid;
translation_req = st_translation_req;
mmu_vaddr = st_vaddr;
st_valid_i = lsu_ctrl.valid;
cva6_translation_req = st_translation_req;
cva6_mmu_vaddr = st_vaddr;
if (CVA6Cfg.RVH) begin
mmu_tinst = st_tinst;
mmu_hs_ld_st_inst = st_hs_ld_st_inst;
@ -594,7 +702,7 @@ module load_store_unit
// the misaligned exception is passed to the functional unit via the MMU, which in case
// can augment the exception if other memory related exceptions like a page fault or access errors
always_comb begin : data_misaligned_detection
misaligned_exception = {
cva6_misaligned_exception = {
{CVA6Cfg.XLEN{1'b0}}, {CVA6Cfg.XLEN{1'b0}}, {CVA6Cfg.GPLEN{1'b0}}, {32{1'b0}}, 1'b0, 1'b0
};
data_misaligned = 1'b0;
@ -640,26 +748,26 @@ module load_store_unit
if (data_misaligned) begin
case (lsu_ctrl.fu)
LOAD: begin
misaligned_exception.cause = riscv::LD_ADDR_MISALIGNED;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::LD_ADDR_MISALIGNED;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
STORE: begin
misaligned_exception.cause = riscv::ST_ADDR_MISALIGNED;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::ST_ADDR_MISALIGNED;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
default: ;
@ -670,25 +778,25 @@ module load_store_unit
case (lsu_ctrl.fu)
LOAD: begin
misaligned_exception.cause = riscv::LOAD_PAGE_FAULT;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::LOAD_PAGE_FAULT;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
STORE: begin
misaligned_exception.cause = riscv::STORE_PAGE_FAULT;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::STORE_PAGE_FAULT;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
default: ;
@ -699,25 +807,25 @@ module load_store_unit
case (lsu_ctrl.fu)
LOAD: begin
misaligned_exception.cause = riscv::LOAD_GUEST_PAGE_FAULT;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::LOAD_GUEST_PAGE_FAULT;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
STORE: begin
misaligned_exception.cause = riscv::STORE_GUEST_PAGE_FAULT;
misaligned_exception.valid = 1'b1;
cva6_misaligned_exception.cause = riscv::STORE_GUEST_PAGE_FAULT;
cva6_misaligned_exception.valid = 1'b1;
if (CVA6Cfg.TvalEn)
misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
cva6_misaligned_exception.tval = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, lsu_ctrl.vaddr};
if (CVA6Cfg.RVH) begin
misaligned_exception.tval2 = '0;
misaligned_exception.tinst = lsu_ctrl.tinst;
misaligned_exception.gva = ld_st_v_i;
cva6_misaligned_exception.tval2 = '0;
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
cva6_misaligned_exception.gva = ld_st_v_i;
end
end
default: ;
@ -759,12 +867,10 @@ module load_store_unit
.pop_ld_i (pop_ld),
.pop_st_i (pop_st),
.lsu_ctrl_o(lsu_ctrl),
.lsu_ctrl_o(lsu_ctrl_byp),
.ready_o (lsu_ready_o)
);
assign rvfi_lsu_ctrl_o = lsu_ctrl;
endmodule

View file

@ -12,7 +12,9 @@
// Date: 2.10.2019
// Description: purely combinatorial PMP unit (with extraction for more complex configs such as NAPOT)
module pmp #(
module pmp
import ariane_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
) (
// Input
@ -20,8 +22,8 @@ module pmp #(
input riscv::pmp_access_t access_type_i,
input riscv::priv_lvl_t priv_lvl_i,
// Configuration
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] conf_addr_i,
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] conf_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] conf_addr_i,
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] conf_i,
// Output
output logic allow_o
);

View file

@ -36,8 +36,8 @@ module pmp_data_if
input riscv::priv_lvl_t ld_st_priv_lvl_i,
input logic ld_st_v_i,
// PMP
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_i,
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_i
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i
);
// virtual address causing the exception
logic [CVA6Cfg.XLEN-1:0] fetch_vaddr_xlen, lsu_vaddr_xlen;