mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-19 03:44:46 -04:00
[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:
parent
2ef1c1b1fc
commit
1bc415391a
14 changed files with 393 additions and 241 deletions
10
Bender.yml
10
Bender.yml
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
57
core/cva6.sv
57
core/cva6.sv
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue