mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-06-27 17:00:57 -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:
|
package:
|
||||||
name: ariane
|
name: cva6
|
||||||
authors:
|
authors:
|
||||||
- "Florian Zaruba <zarubaf@iis.ee.ethz.ch>"
|
- "Florian Zaruba <zarubaf@iis.ee.ethz.ch>"
|
||||||
- "Michael Schaffner <schaffner@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)
|
- 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:
|
files:
|
||||||
- core/cva6_mmu/cva6_tlb.sv
|
- core/cva6_mmu/cva6_tlb.sv
|
||||||
|
- core/cva6_mmu/cva6_shared_tlb.sv
|
||||||
- core/cva6_mmu/cva6_mmu.sv
|
- core/cva6_mmu/cva6_mmu.sv
|
||||||
- core/cva6_mmu/cva6_ptw.sv
|
- core/cva6_mmu/cva6_ptw.sv
|
||||||
|
|
||||||
|
@ -78,6 +79,8 @@ sources:
|
||||||
# Extension Interface
|
# Extension Interface
|
||||||
- core/cvxif_example/include/cvxif_instr_pkg.sv
|
- core/cvxif_example/include/cvxif_instr_pkg.sv
|
||||||
- core/cvxif_fu.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/cvxif_example_coprocessor.sv
|
||||||
- core/cvxif_example/instr_decoder.sv
|
- core/cvxif_example/instr_decoder.sv
|
||||||
|
|
||||||
|
@ -95,6 +98,7 @@ sources:
|
||||||
- core/csr_regfile.sv
|
- core/csr_regfile.sv
|
||||||
- core/decoder.sv
|
- core/decoder.sv
|
||||||
- core/ex_stage.sv
|
- core/ex_stage.sv
|
||||||
|
- core/acc_dispatcher.sv
|
||||||
- core/instr_realign.sv
|
- core/instr_realign.sv
|
||||||
- core/id_stage.sv
|
- core/id_stage.sv
|
||||||
- core/issue_read_operands.sv
|
- core/issue_read_operands.sv
|
||||||
|
@ -142,6 +146,7 @@ sources:
|
||||||
# Physical Memory Protection
|
# Physical Memory Protection
|
||||||
- core/pmp/src/pmp.sv
|
- core/pmp/src/pmp.sv
|
||||||
- core/pmp/src/pmp_entry.sv
|
- core/pmp/src/pmp_entry.sv
|
||||||
|
- core/pmp/src/pmp_data_if.sv
|
||||||
|
|
||||||
- include_dirs:
|
- include_dirs:
|
||||||
- common/local/util
|
- common/local/util
|
||||||
|
@ -153,12 +158,15 @@ sources:
|
||||||
- common/local/util
|
- common/local/util
|
||||||
files:
|
files:
|
||||||
- common/local/util/tc_sram_wrapper.sv
|
- common/local/util/tc_sram_wrapper.sv
|
||||||
|
- common/local/util/sram_cache.sv
|
||||||
|
|
||||||
- target: all(fpga, xilinx)
|
- target: all(fpga, xilinx)
|
||||||
include_dirs:
|
include_dirs:
|
||||||
- common/local/util
|
- common/local/util
|
||||||
files:
|
files:
|
||||||
|
- common/local/util/sram_cache.sv
|
||||||
- common/local/util/tc_sram_fpga_wrapper.sv
|
- common/local/util/tc_sram_fpga_wrapper.sv
|
||||||
|
- vendor/pulp-platform/fpga-support/rtl/SyncSpRamBeNx64.sv
|
||||||
|
|
||||||
- target: not(synthesis)
|
- target: not(synthesis)
|
||||||
include_dirs:
|
include_dirs:
|
||||||
|
|
|
@ -25,32 +25,32 @@ module instr_tracer #(
|
||||||
parameter type exception_t = logic,
|
parameter type exception_t = logic,
|
||||||
parameter interrupts_t INTERRUPTS = '0
|
parameter interrupts_t INTERRUPTS = '0
|
||||||
)(
|
)(
|
||||||
input logic pck,
|
input logic pck,
|
||||||
input logic rstn,
|
input logic rstn,
|
||||||
input logic flush_unissued,
|
input logic flush_unissued,
|
||||||
input logic flush_all,
|
input logic flush_all,
|
||||||
input logic [31:0] instruction,
|
input logic [31:0] instruction,
|
||||||
input logic fetch_valid,
|
input logic fetch_valid,
|
||||||
input logic fetch_ack,
|
input logic fetch_ack,
|
||||||
input logic issue_ack, // issue acknowledged
|
input logic issue_ack, // issue acknowledged
|
||||||
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
|
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
|
||||||
input logic [1:0][4:0] waddr, // WB stage
|
input logic [CVA6Cfg.NrCommitPorts-1:0][4:0] waddr, // WB stage
|
||||||
input logic [1:0][63:0] wdata,
|
input logic [CVA6Cfg.NrCommitPorts-1:0][63:0] wdata,
|
||||||
input logic [1:0] we_gpr,
|
input logic [CVA6Cfg.NrCommitPorts-1:0] we_gpr,
|
||||||
input logic [1:0] we_fpr,
|
input logic [CVA6Cfg.NrCommitPorts-1:0] we_fpr,
|
||||||
input scoreboard_entry_t [1:0] commit_instr, // commit instruction
|
input scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr, // commit instruction
|
||||||
input logic [1:0] commit_ack,
|
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack,
|
||||||
input logic st_valid, // stores - address translation
|
input logic st_valid, // stores - address translation
|
||||||
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
|
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
|
||||||
input logic ld_valid, // loads
|
input logic ld_valid, // loads
|
||||||
input logic ld_kill,
|
input logic ld_kill,
|
||||||
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
|
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
|
||||||
input bp_resolve_t resolve_branch, // misprediction
|
input bp_resolve_t resolve_branch, // misprediction
|
||||||
input exception_t commit_exception,
|
input exception_t commit_exception,
|
||||||
input riscv::priv_lvl_t priv_lvl, // current privilege level
|
input riscv::priv_lvl_t priv_lvl, // current privilege level
|
||||||
input logic debug_mode,
|
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
|
// keep the decoded instructions in a queue
|
||||||
|
|
|
@ -23,36 +23,12 @@ module acc_dispatcher
|
||||||
parameter type exception_t = logic,
|
parameter type exception_t = logic,
|
||||||
parameter type fu_data_t = logic,
|
parameter type fu_data_t = logic,
|
||||||
parameter type scoreboard_entry_t = logic,
|
parameter type scoreboard_entry_t = logic,
|
||||||
localparam type accelerator_req_t = struct packed {
|
parameter type acc_req_t = logic,
|
||||||
logic req_valid;
|
parameter type acc_resp_t = logic,
|
||||||
logic resp_ready;
|
parameter type accelerator_req_t = logic,
|
||||||
riscv::instruction_t insn;
|
parameter type accelerator_resp_t = logic,
|
||||||
logic [CVA6Cfg.XLEN-1:0] rs1;
|
parameter type acc_mmu_req_t = logic,
|
||||||
logic [CVA6Cfg.XLEN-1:0] rs2;
|
parameter type acc_mmu_resp_t = logic,
|
||||||
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_cfg_t = logic,
|
parameter type acc_cfg_t = logic,
|
||||||
parameter acc_cfg_t AccCfg = '0
|
parameter acc_cfg_t AccCfg = '0
|
||||||
) (
|
) (
|
||||||
|
@ -65,10 +41,11 @@ module acc_dispatcher
|
||||||
// Interface with the CSRs
|
// Interface with the CSRs
|
||||||
input priv_lvl_t ld_st_priv_lvl_i,
|
input priv_lvl_t ld_st_priv_lvl_i,
|
||||||
input logic sum_i,
|
input logic sum_i,
|
||||||
input pmpcfg_t [CVA6Cfg.NrPMPEntries-1:0] pmpcfg_i,
|
input pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i,
|
||||||
input logic [CVA6Cfg.NrPMPEntries-1:0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
|
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i,
|
||||||
input logic [2:0] fcsr_frm_i,
|
input logic [2:0] fcsr_frm_i,
|
||||||
output logic dirty_v_state_o,
|
output logic dirty_v_state_o,
|
||||||
|
input logic acc_mmu_en_i,
|
||||||
// Interface with the issue stage
|
// Interface with the issue stage
|
||||||
input scoreboard_entry_t issue_instr_i,
|
input scoreboard_entry_t issue_instr_i,
|
||||||
input logic issue_instr_hs_i,
|
input logic issue_instr_hs_i,
|
||||||
|
@ -88,6 +65,9 @@ module acc_dispatcher
|
||||||
output logic acc_stall_st_pending_o,
|
output logic acc_stall_st_pending_o,
|
||||||
input logic acc_no_st_pending_i,
|
input logic acc_no_st_pending_i,
|
||||||
input dcache_req_i_t [2:0] dcache_req_ports_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
|
// Interface with the controller
|
||||||
output logic ctrl_halt_o,
|
output logic ctrl_halt_o,
|
||||||
input logic [11:0] csr_addr_i,
|
input logic [11:0] csr_addr_i,
|
||||||
|
@ -219,7 +199,7 @@ module acc_dispatcher
|
||||||
end
|
end
|
||||||
|
|
||||||
// An accelerator instruction was issued.
|
// 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
|
end : p_non_speculative_ff
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
|
@ -231,29 +211,31 @@ module acc_dispatcher
|
||||||
logic acc_req_ready;
|
logic acc_req_ready;
|
||||||
|
|
||||||
accelerator_req_t acc_req_int;
|
accelerator_req_t acc_req_int;
|
||||||
fall_through_register #(
|
spill_register #(
|
||||||
.T(accelerator_req_t)
|
.T(accelerator_req_t)
|
||||||
) i_accelerator_req_register (
|
) i_accelerator_req_register (
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_ni (rst_ni),
|
.rst_ni (rst_ni),
|
||||||
.clr_i (1'b0),
|
.data_i (acc_req),
|
||||||
.testmode_i(1'b0),
|
.valid_i(acc_req_valid),
|
||||||
.data_i (acc_req),
|
.ready_o(acc_req_ready),
|
||||||
.valid_i (acc_req_valid),
|
.data_o (acc_req_int),
|
||||||
.ready_o (acc_req_ready),
|
.valid_o(acc_req_o.acc_req.req_valid),
|
||||||
.data_o (acc_req_int),
|
.ready_i(acc_resp_i.acc_resp.req_ready)
|
||||||
.valid_o (acc_req_o.req_valid),
|
|
||||||
.ready_i (acc_resp_i.req_ready)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assign acc_req_o.insn = acc_req_int.insn;
|
assign acc_req_o.acc_req.insn = acc_req_int.insn;
|
||||||
assign acc_req_o.rs1 = acc_req_int.rs1;
|
assign acc_req_o.acc_req.rs1 = acc_req_int.rs1;
|
||||||
assign acc_req_o.rs2 = acc_req_int.rs2;
|
assign acc_req_o.acc_req.rs2 = acc_req_int.rs2;
|
||||||
assign acc_req_o.frm = acc_req_int.frm;
|
assign acc_req_o.acc_req.frm = acc_req_int.frm;
|
||||||
assign acc_req_o.trans_id = acc_req_int.trans_id;
|
assign acc_req_o.acc_req.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_req.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.acc_req.acc_cons_en = acc_cons_en_i;
|
||||||
assign acc_req_o.inval_ready = inval_ready_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
|
always_comb begin : accelerator_req_dispatcher
|
||||||
// Do not fetch from the instruction queue
|
// Do not fetch from the instruction queue
|
||||||
|
@ -263,7 +245,7 @@ module acc_dispatcher
|
||||||
acc_req = '0;
|
acc_req = '0;
|
||||||
acc_req_valid = 1'b0;
|
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
|
if (!acc_insn_queue_empty) begin
|
||||||
acc_req = '{
|
acc_req = '{
|
||||||
// Instruction is forwarded from the decoder as an immediate
|
// Instruction is forwarded from the decoder as an immediate
|
||||||
|
@ -297,23 +279,27 @@ module acc_dispatcher
|
||||||
logic acc_ld_disp;
|
logic acc_ld_disp;
|
||||||
logic acc_st_disp;
|
logic acc_st_disp;
|
||||||
|
|
||||||
assign acc_trans_id_o = acc_resp_i.trans_id;
|
assign acc_trans_id_o = acc_resp_i.acc_resp.trans_id;
|
||||||
assign acc_result_o = acc_resp_i.result;
|
assign acc_result_o = acc_resp_i.acc_resp.result;
|
||||||
assign acc_valid_o = acc_resp_i.resp_valid;
|
assign acc_valid_o = acc_resp_i.acc_resp.resp_valid;
|
||||||
assign acc_exception_o = acc_resp_i.exception;
|
assign acc_exception_o = acc_resp_i.acc_resp.exception;
|
||||||
// Unpack the accelerator response
|
// Unpack the accelerator response
|
||||||
assign acc_fflags_valid_o = acc_resp_i.fflags_valid;
|
assign acc_fflags_valid_o = acc_resp_i.acc_resp.fflags_valid;
|
||||||
assign acc_fflags_o = acc_resp_i.fflags;
|
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
|
// 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
|
// Signal dispatched load/store to issue stage
|
||||||
assign acc_ld_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_LOAD);
|
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_st_disp = acc_req_valid && (acc_insn_queue_o.operation == ACCEL_OP_STORE);
|
||||||
|
|
||||||
// Cache invalidation
|
// Cache invalidation
|
||||||
assign inval_valid_o = acc_resp_i.inval_valid;
|
assign inval_valid_o = acc_resp_i.acc_resp.inval_valid;
|
||||||
assign inval_addr_o = acc_resp_i.inval_addr;
|
assign inval_addr_o = acc_resp_i.acc_resp.inval_addr;
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
* Accelerator commit *
|
* Accelerator commit *
|
||||||
|
@ -351,8 +337,8 @@ module acc_dispatcher
|
||||||
`FF(wait_acc_store_q, wait_acc_store_d, '0)
|
`FF(wait_acc_store_q, wait_acc_store_d, '0)
|
||||||
|
|
||||||
// Set on store barrier. Clear when no store is pending.
|
// 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 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;
|
assign ctrl_halt_o = wait_acc_store_q;
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
* Load/Store tracking *
|
* Load/Store tracking *
|
||||||
|
@ -390,9 +376,9 @@ module acc_dispatcher
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_ni (rst_ni),
|
.rst_ni (rst_ni),
|
||||||
.clear_i (1'b0),
|
.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),
|
.load_i (1'b0),
|
||||||
.down_i (acc_resp_i.load_complete),
|
.down_i (acc_resp_i.acc_resp.load_complete),
|
||||||
.d_i ('0),
|
.d_i ('0),
|
||||||
.q_o (acc_disp_loads_pending),
|
.q_o (acc_disp_loads_pending),
|
||||||
.overflow_o(acc_disp_loads_overflow)
|
.overflow_o(acc_disp_loads_overflow)
|
||||||
|
@ -435,9 +421,9 @@ module acc_dispatcher
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_ni (rst_ni),
|
.rst_ni (rst_ni),
|
||||||
.clear_i (1'b0),
|
.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),
|
.load_i (1'b0),
|
||||||
.down_i (acc_resp_i.store_complete),
|
.down_i (acc_resp_i.acc_resp.store_complete),
|
||||||
.d_i ('0),
|
.d_i ('0),
|
||||||
.q_o (acc_disp_stores_pending),
|
.q_o (acc_disp_stores_pending),
|
||||||
.overflow_o(acc_disp_stores_overflow)
|
.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
|
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_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_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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -441,10 +441,10 @@ module cva6_icache
|
||||||
always_comb begin
|
always_comb begin
|
||||||
if (cmp_en_q) begin
|
if (cmp_en_q) begin
|
||||||
dreq_o.data = cl_sel[hit_idx];
|
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
|
end else begin
|
||||||
dreq_o.data = mem_rtrn_i.data[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_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];
|
dreq_o.user = CVA6Cfg.FETCH_USER_EN ? mem_rtrn_i.user[{cl_offset_q, 3'b0}+:CVA6Cfg.FETCH_USER_WIDTH] : '0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -162,9 +162,9 @@ module csr_regfile
|
||||||
// TO_BE_COMPLETED - PERF_COUNTERS
|
// TO_BE_COMPLETED - PERF_COUNTERS
|
||||||
output logic perf_we_o,
|
output logic perf_we_o,
|
||||||
// PMP configuration containing pmpcfg for max 64 PMPs - ACC_DISPATCHER
|
// 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
|
// 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
|
// TO_BE_COMPLETED - PERF_COUNTERS
|
||||||
output logic [31:0] mcountinhibit_o,
|
output logic [31:0] mcountinhibit_o,
|
||||||
// RVFI
|
// RVFI
|
||||||
|
@ -784,11 +784,13 @@ module csr_regfile
|
||||||
riscv::CSR_PMPCFG14,
|
riscv::CSR_PMPCFG14,
|
||||||
riscv::CSR_PMPCFG15: begin
|
riscv::CSR_PMPCFG15: begin
|
||||||
// index is calculated using PMPCFG0 as the offset
|
// 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 index is not even and XLEN==64, raise exception
|
||||||
if (CVA6Cfg.XLEN == 64 && index[0] == 1'b1) read_access_exception = 1'b1;
|
if (CVA6Cfg.XLEN == 64 && index[0] == 1'b1) read_access_exception = 1'b1;
|
||||||
else begin
|
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];
|
csr_rdata = pmpcfg_q[index*4+:CVA6Cfg.XLEN/8];
|
||||||
end
|
end
|
||||||
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
|
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] cause; // cause of exception
|
||||||
logic [CVA6Cfg.XLEN-1:0] tval; // additional information of causing exception (e.g.: instruction causing it),
|
logic [CVA6Cfg.XLEN-1:0] tval; // additional information of causing exception (e.g.: instruction causing it),
|
||||||
// address of LD/ST fault
|
// address of LD/ST fault
|
||||||
|
@ -217,6 +217,14 @@ module cva6
|
||||||
logic [CVA6Cfg.DCACHE_USER_WIDTH-1:0] data_ruser;
|
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
|
// AXI types
|
||||||
parameter type axi_ar_chan_t = struct packed {
|
parameter type axi_ar_chan_t = struct packed {
|
||||||
logic [CVA6Cfg.AxiIdWidth-1:0] id;
|
logic [CVA6Cfg.AxiIdWidth-1:0] id;
|
||||||
|
@ -509,6 +517,11 @@ module cva6
|
||||||
// ACCEL Commit
|
// ACCEL Commit
|
||||||
logic acc_valid_acc_ex;
|
logic acc_valid_acc_ex;
|
||||||
// --------------
|
// --------------
|
||||||
|
// EX <-> ACC_DISP
|
||||||
|
// --------------
|
||||||
|
acc_mmu_req_t acc_mmu_req;
|
||||||
|
acc_mmu_resp_t acc_mmu_resp;
|
||||||
|
// --------------
|
||||||
// ID <-> COMMIT
|
// ID <-> COMMIT
|
||||||
// --------------
|
// --------------
|
||||||
scoreboard_entry_t [CVA6Cfg.NrCommitPorts-1:0] commit_instr_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 acc_cons_en_csr;
|
||||||
logic debug_mode;
|
logic debug_mode;
|
||||||
logic single_step_csr_commit;
|
logic single_step_csr_commit;
|
||||||
riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg;
|
riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg;
|
||||||
logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr;
|
logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr;
|
||||||
logic [31:0] mcountinhibit_csr_perf;
|
logic [31:0] mcountinhibit_csr_perf;
|
||||||
//jvt
|
//jvt
|
||||||
jvt_t jvt;
|
jvt_t jvt;
|
||||||
|
@ -764,16 +777,17 @@ module cva6
|
||||||
assign ex_ex_ex_id[FPU_WB] = fpu_exception_ex_id;
|
assign ex_ex_ex_id[FPU_WB] = fpu_exception_ex_id;
|
||||||
assign wt_valid_ex_id[FPU_WB] = fpu_valid_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
|
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
|
always_comb begin : gen_cvxif_output_assignement
|
||||||
cvxif_req.compressed_valid = x_compressed_valid;
|
cvxif_req.compressed_valid = x_compressed_valid;
|
||||||
cvxif_req.compressed_req = x_compressed_req;
|
cvxif_req.compressed_req = x_compressed_req;
|
||||||
|
@ -921,7 +935,9 @@ module cva6
|
||||||
.icache_dreq_t(icache_dreq_t),
|
.icache_dreq_t(icache_dreq_t),
|
||||||
.icache_drsp_t(icache_drsp_t),
|
.icache_drsp_t(icache_drsp_t),
|
||||||
.lsu_ctrl_t(lsu_ctrl_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 (
|
) ex_stage_i (
|
||||||
.clk_i(clk_i),
|
.clk_i(clk_i),
|
||||||
.rst_ni(rst_ni),
|
.rst_ni(rst_ni),
|
||||||
|
@ -1005,6 +1021,9 @@ module cva6
|
||||||
.x_result_ready_o (x_result_ready),
|
.x_result_ready_o (x_result_ready),
|
||||||
// Accelerator
|
// Accelerator
|
||||||
.acc_valid_i (acc_valid_acc_ex),
|
.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
|
// Performance counters
|
||||||
.itlb_miss_o (itlb_miss_ex_perf),
|
.itlb_miss_o (itlb_miss_ex_perf),
|
||||||
.dtlb_miss_o (dtlb_miss_ex_perf),
|
.dtlb_miss_o (dtlb_miss_ex_perf),
|
||||||
|
@ -1504,7 +1523,11 @@ module cva6
|
||||||
.acc_cfg_t (acc_cfg_t),
|
.acc_cfg_t (acc_cfg_t),
|
||||||
.AccCfg (AccCfg),
|
.AccCfg (AccCfg),
|
||||||
.acc_req_t (cvxif_req_t),
|
.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 (
|
) i_acc_dispatcher (
|
||||||
.clk_i (clk_i),
|
.clk_i (clk_i),
|
||||||
.rst_ni (rst_ni),
|
.rst_ni (rst_ni),
|
||||||
|
@ -1520,6 +1543,7 @@ module cva6
|
||||||
.pmpcfg_i (pmpcfg),
|
.pmpcfg_i (pmpcfg),
|
||||||
.pmpaddr_i (pmpaddr),
|
.pmpaddr_i (pmpaddr),
|
||||||
.fcsr_frm_i (frm_csr_id_issue_ex),
|
.fcsr_frm_i (frm_csr_id_issue_ex),
|
||||||
|
.acc_mmu_en_i (enable_translation_csr_ex),
|
||||||
.dirty_v_state_o (dirty_v_state),
|
.dirty_v_state_o (dirty_v_state),
|
||||||
.issue_instr_i (issue_instr_id_acc),
|
.issue_instr_i (issue_instr_id_acc),
|
||||||
.issue_instr_hs_i (issue_instr_hs_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_stall_st_pending_o(stall_st_pending_ex),
|
||||||
.acc_no_st_pending_i (no_st_pending_commit),
|
.acc_no_st_pending_i (no_st_pending_commit),
|
||||||
.dcache_req_ports_i (dcache_req_ports_ex_cache),
|
.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),
|
.ctrl_halt_o (halt_acc_ctrl),
|
||||||
.csr_addr_i (csr_addr_ex_csr),
|
.csr_addr_i (csr_addr_ex_csr),
|
||||||
.acc_dcache_req_ports_o(dcache_req_ports_acc_cache),
|
.acc_dcache_req_ports_o(dcache_req_ports_acc_cache),
|
||||||
|
@ -1565,6 +1591,9 @@ module cva6
|
||||||
// D$ connection is unused
|
// D$ connection is unused
|
||||||
assign dcache_req_ports_acc_cache = '0;
|
assign dcache_req_ports_acc_cache = '0;
|
||||||
|
|
||||||
|
// MMU access is unused
|
||||||
|
assign acc_mmu_req = '0;
|
||||||
|
|
||||||
// No invalidation interface
|
// No invalidation interface
|
||||||
assign inval_valid = '0;
|
assign inval_valid = '0;
|
||||||
assign inval_addr = '0;
|
assign inval_addr = '0;
|
||||||
|
|
|
@ -100,8 +100,8 @@ module cva6_mmu
|
||||||
|
|
||||||
// PMP
|
// PMP
|
||||||
|
|
||||||
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,
|
||||||
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
|
||||||
);
|
);
|
||||||
|
|
||||||
// memory management, pte for cva6
|
// memory management, pte for cva6
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// Date: 26/02/2024
|
// Date: 26/02/2024
|
||||||
// Description: Hardware-PTW (Page-Table-Walker) for CVA6 supporting sv32, sv39 and sv39x4.
|
// 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,
|
// 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 */
|
/* verilator lint_off WIDTH */
|
||||||
|
|
||||||
|
@ -83,8 +83,8 @@ module cva6_ptw
|
||||||
output logic shared_tlb_miss_o,
|
output logic shared_tlb_miss_o,
|
||||||
|
|
||||||
// PMP
|
// PMP
|
||||||
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,
|
||||||
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,
|
||||||
output logic [CVA6Cfg.PLEN-1:0] bad_paddr_o,
|
output logic [CVA6Cfg.PLEN-1:0] bad_paddr_o,
|
||||||
output logic [CVA6Cfg.GPLEN-1:0] bad_gpaddr_o
|
output logic [CVA6Cfg.GPLEN-1:0] bad_gpaddr_o
|
||||||
);
|
);
|
||||||
|
@ -258,8 +258,8 @@ module cva6_ptw
|
||||||
// PAGESIZE=2^12 and LEVELS=3.)
|
// PAGESIZE=2^12 and LEVELS=3.)
|
||||||
// 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For
|
// 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For
|
||||||
// Sv32, PTESIZE=4.)
|
// Sv32, PTESIZE=4.)
|
||||||
// 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if any bits or encodings
|
// 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
|
// that are reserved for future standard use are set within pte, stop and raise
|
||||||
// a page-fault exception corresponding to the original access type.
|
// 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.
|
// 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.
|
// 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_dreq_t = logic,
|
||||||
parameter type icache_drsp_t = logic,
|
parameter type icache_drsp_t = logic,
|
||||||
parameter type lsu_ctrl_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
|
// Subsystem Clock - SUBSYSTEM
|
||||||
input logic clk_i,
|
input logic clk_i,
|
||||||
|
@ -161,6 +163,9 @@ module ex_stage
|
||||||
input logic x_transaction_rejected_i,
|
input logic x_transaction_rejected_i,
|
||||||
// accelerate port result is valid - ACC_DISPATCHER
|
// accelerate port result is valid - ACC_DISPATCHER
|
||||||
input logic acc_valid_i,
|
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
|
// Enable virtual memory translation - CSR_REGFILE
|
||||||
input logic enable_translation_i,
|
input logic enable_translation_i,
|
||||||
// Enable G-Stage memory translation - CSR_REGFILE
|
// Enable G-Stage memory translation - CSR_REGFILE
|
||||||
|
@ -224,9 +229,9 @@ module ex_stage
|
||||||
// To count the data TLB misses - PERF_COUNTERS
|
// To count the data TLB misses - PERF_COUNTERS
|
||||||
output logic dtlb_miss_o,
|
output logic dtlb_miss_o,
|
||||||
// Report the PMP configuration - CSR_REGFILE
|
// 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
|
// 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
|
// Information dedicated to RVFI - RVFI
|
||||||
output lsu_ctrl_t rvfi_lsu_ctrl_o,
|
output lsu_ctrl_t rvfi_lsu_ctrl_o,
|
||||||
// Information dedicated to RVFI - RVFI
|
// Information dedicated to RVFI - RVFI
|
||||||
|
@ -529,7 +534,9 @@ module ex_stage
|
||||||
.icache_arsp_t(icache_arsp_t),
|
.icache_arsp_t(icache_arsp_t),
|
||||||
.icache_dreq_t(icache_dreq_t),
|
.icache_dreq_t(icache_dreq_t),
|
||||||
.icache_drsp_t(icache_drsp_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 (
|
) lsu_i (
|
||||||
.clk_i,
|
.clk_i,
|
||||||
.rst_ni,
|
.rst_ni,
|
||||||
|
@ -554,6 +561,8 @@ module ex_stage
|
||||||
.enable_g_translation_i,
|
.enable_g_translation_i,
|
||||||
.en_ld_st_translation_i,
|
.en_ld_st_translation_i,
|
||||||
.en_ld_st_g_translation_i,
|
.en_ld_st_g_translation_i,
|
||||||
|
.acc_mmu_req_i,
|
||||||
|
.acc_mmu_resp_o,
|
||||||
.icache_areq_i,
|
.icache_areq_i,
|
||||||
.icache_areq_o,
|
.icache_areq_o,
|
||||||
.priv_lvl_i,
|
.priv_lvl_i,
|
||||||
|
|
|
@ -807,4 +807,12 @@ package ariane_pkg;
|
||||||
return gppn;
|
return gppn;
|
||||||
endfunction : make_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
|
endpackage
|
||||||
|
|
|
@ -12,6 +12,8 @@ package cva6_config_pkg;
|
||||||
|
|
||||||
localparam CVA6ConfigXlen = 64;
|
localparam CVA6ConfigXlen = 64;
|
||||||
|
|
||||||
|
localparam CVA6ConfigNrCommitPorts = 2;
|
||||||
|
|
||||||
localparam CVA6ConfigRVF = 1;
|
localparam CVA6ConfigRVF = 1;
|
||||||
localparam CVA6ConfigF16En = 0;
|
localparam CVA6ConfigF16En = 0;
|
||||||
localparam CVA6ConfigF16AltEn = 0;
|
localparam CVA6ConfigF16AltEn = 0;
|
||||||
|
@ -32,16 +34,16 @@ package cva6_config_pkg;
|
||||||
localparam CVA6ConfigAxiAddrWidth = 64;
|
localparam CVA6ConfigAxiAddrWidth = 64;
|
||||||
localparam CVA6ConfigAxiDataWidth = 64;
|
localparam CVA6ConfigAxiDataWidth = 64;
|
||||||
localparam CVA6ConfigFetchUserEn = 0;
|
localparam CVA6ConfigFetchUserEn = 0;
|
||||||
localparam CVA6ConfigFetchUserWidth = CVA6ConfigXlen;
|
localparam CVA6ConfigFetchUserWidth = 1; // Just not to raise warnings
|
||||||
localparam CVA6ConfigDataUserEn = 0;
|
localparam CVA6ConfigDataUserEn = 0;
|
||||||
localparam CVA6ConfigDataUserWidth = CVA6ConfigXlen;
|
localparam CVA6ConfigDataUserWidth = CVA6ConfigXlen;
|
||||||
|
|
||||||
localparam CVA6ConfigIcacheByteSize = 16384;
|
localparam CVA6ConfigIcacheByteSize = 4096;
|
||||||
localparam CVA6ConfigIcacheSetAssoc = 4;
|
localparam CVA6ConfigIcacheSetAssoc = 4;
|
||||||
localparam CVA6ConfigIcacheLineWidth = 128;
|
localparam CVA6ConfigIcacheLineWidth = 128;
|
||||||
localparam CVA6ConfigDcacheByteSize = 16384;
|
localparam CVA6ConfigDcacheByteSize = 8192;
|
||||||
localparam CVA6ConfigDcacheSetAssoc = 4;
|
localparam CVA6ConfigDcacheSetAssoc = 4;
|
||||||
localparam CVA6ConfigDcacheLineWidth = 128;
|
localparam CVA6ConfigDcacheLineWidth = 256;
|
||||||
|
|
||||||
localparam CVA6ConfigDcacheFlushOnFence = 1'b0;
|
localparam CVA6ConfigDcacheFlushOnFence = 1'b0;
|
||||||
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
|
localparam CVA6ConfigDcacheInvalidateOnFlush = 1'b0;
|
||||||
|
@ -80,7 +82,7 @@ package cva6_config_pkg;
|
||||||
FpgaAlteraEn: bit'(0), // for Altera (only)
|
FpgaAlteraEn: bit'(0), // for Altera (only)
|
||||||
TechnoCut: bit'(0),
|
TechnoCut: bit'(0),
|
||||||
SuperscalarEn: bit'(0),
|
SuperscalarEn: bit'(0),
|
||||||
NrCommitPorts: unsigned'(1),
|
NrCommitPorts: unsigned'(CVA6ConfigNrCommitPorts),
|
||||||
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
|
AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth),
|
||||||
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
|
AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth),
|
||||||
AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth),
|
AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth),
|
||||||
|
|
|
@ -25,7 +25,9 @@ module load_store_unit
|
||||||
parameter type icache_arsp_t = logic,
|
parameter type icache_arsp_t = logic,
|
||||||
parameter type icache_dreq_t = logic,
|
parameter type icache_dreq_t = logic,
|
||||||
parameter type icache_drsp_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
|
// Subsystem Clock - SUBSYSTEM
|
||||||
input logic clk_i,
|
input logic clk_i,
|
||||||
|
@ -82,6 +84,10 @@ module load_store_unit
|
||||||
// Enable G-Stage memory translation for load/stores - TO_BE_COMPLETED
|
// Enable G-Stage memory translation for load/stores - TO_BE_COMPLETED
|
||||||
input logic en_ld_st_g_translation_i,
|
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
|
// Instruction cache input request - CACHES
|
||||||
input icache_arsp_t icache_areq_i,
|
input icache_arsp_t icache_areq_i,
|
||||||
// Instruction cache output request - CACHES
|
// Instruction cache output request - CACHES
|
||||||
|
@ -148,9 +154,9 @@ module load_store_unit
|
||||||
input amo_resp_t amo_resp_i,
|
input amo_resp_t amo_resp_i,
|
||||||
|
|
||||||
// PMP configuration - CSR_REGFILE
|
// 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
|
// 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
|
// RVFI inforamtion - RVFI
|
||||||
output lsu_ctrl_t rvfi_lsu_ctrl_o,
|
output lsu_ctrl_t rvfi_lsu_ctrl_o,
|
||||||
|
@ -159,26 +165,26 @@ module load_store_unit
|
||||||
);
|
);
|
||||||
|
|
||||||
// data is misaligned
|
// data is misaligned
|
||||||
logic data_misaligned;
|
logic data_misaligned;
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// 1st register stage - (stall registers)
|
// 1st register stage - (stall registers)
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// those are the signals which are always correct
|
// those are the signals which are always correct
|
||||||
// e.g.: they keep the value in the stall case
|
// 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_st;
|
||||||
logic pop_ld;
|
logic pop_ld;
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// Address Generation Unit (AGU)
|
// Address Generation Unit (AGU)
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// virtual address as calculated by the AGU in the first cycle
|
// virtual address as calculated by the AGU in the first cycle
|
||||||
logic [ CVA6Cfg.VLEN-1:0] vaddr_i;
|
logic [ CVA6Cfg.VLEN-1:0] vaddr_i;
|
||||||
logic [ CVA6Cfg.XLEN-1:0] vaddr_xlen;
|
logic [ CVA6Cfg.XLEN-1:0] vaddr_xlen;
|
||||||
logic overflow;
|
logic overflow;
|
||||||
logic g_overflow;
|
logic g_overflow;
|
||||||
logic [(CVA6Cfg.XLEN/8)-1:0] be_i;
|
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_xlen = $unsigned($signed(fu_data_i.imm) + $signed(fu_data_i.operand_a));
|
||||||
assign vaddr_i = vaddr_xlen[CVA6Cfg.VLEN-1:0];
|
assign vaddr_i = vaddr_xlen[CVA6Cfg.VLEN-1:0];
|
||||||
|
@ -190,10 +196,10 @@ module load_store_unit
|
||||||
assign g_overflow = 1'b0;
|
assign g_overflow = 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
logic st_valid_i;
|
logic st_valid_i;
|
||||||
logic ld_valid_i;
|
logic ld_valid_i;
|
||||||
logic ld_translation_req;
|
logic ld_translation_req;
|
||||||
logic st_translation_req;
|
logic st_translation_req, cva6_st_translation_req, acc_st_translation_req;
|
||||||
logic [CVA6Cfg.VLEN-1:0] ld_vaddr;
|
logic [CVA6Cfg.VLEN-1:0] ld_vaddr;
|
||||||
logic [ 31:0] ld_tinst;
|
logic [ 31:0] ld_tinst;
|
||||||
logic ld_hs_ld_st_inst;
|
logic ld_hs_ld_st_inst;
|
||||||
|
@ -202,41 +208,41 @@ module load_store_unit
|
||||||
logic [ 31:0] st_tinst;
|
logic [ 31:0] st_tinst;
|
||||||
logic st_hs_ld_st_inst;
|
logic st_hs_ld_st_inst;
|
||||||
logic st_hlvx_inst;
|
logic st_hlvx_inst;
|
||||||
logic translation_req;
|
logic translation_req, cva6_translation_req, acc_translation_req;
|
||||||
logic translation_valid;
|
logic translation_valid, cva6_translation_valid, acc_translataion_valid;
|
||||||
logic [CVA6Cfg.VLEN-1:0] mmu_vaddr;
|
logic [CVA6Cfg.VLEN-1:0] mmu_vaddr, cva6_mmu_vaddr, acc_mmu_vaddr;
|
||||||
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, lsu_paddr;
|
logic [CVA6Cfg.PLEN-1:0] mmu_paddr, cva6_mmu_paddr, acc_mmu_paddr, lsu_paddr;
|
||||||
logic [ 31:0] mmu_tinst;
|
logic [31:0] mmu_tinst;
|
||||||
logic mmu_hs_ld_st_inst;
|
logic mmu_hs_ld_st_inst;
|
||||||
logic mmu_hlvx_inst;
|
logic mmu_hlvx_inst;
|
||||||
exception_t mmu_exception;
|
exception_t mmu_exception, cva6_mmu_exception, acc_mmu_exception;
|
||||||
exception_t pmp_exception;
|
exception_t pmp_exception;
|
||||||
icache_areq_t pmp_icache_areq_i;
|
icache_areq_t pmp_icache_areq_i;
|
||||||
logic pmp_translation_valid;
|
logic pmp_translation_valid;
|
||||||
logic dtlb_hit;
|
logic dtlb_hit, cva6_dtlb_hit, acc_dtlb_hit;
|
||||||
logic [ CVA6Cfg.PPNW-1:0] dtlb_ppn;
|
logic [CVA6Cfg.PPNW-1:0] dtlb_ppn, cva6_dtlb_ppn, acc_dtlb_ppn;
|
||||||
|
|
||||||
logic ld_valid;
|
logic ld_valid;
|
||||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
|
logic [CVA6Cfg.TRANS_ID_BITS-1:0] ld_trans_id;
|
||||||
logic [ CVA6Cfg.XLEN-1:0] ld_result;
|
logic [ CVA6Cfg.XLEN-1:0] ld_result;
|
||||||
logic st_valid;
|
logic st_valid;
|
||||||
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
|
logic [CVA6Cfg.TRANS_ID_BITS-1:0] st_trans_id;
|
||||||
logic [ CVA6Cfg.XLEN-1:0] st_result;
|
logic [ CVA6Cfg.XLEN-1:0] st_result;
|
||||||
|
|
||||||
logic [ 11:0] page_offset;
|
logic [ 11:0] page_offset;
|
||||||
logic page_offset_matches;
|
logic page_offset_matches;
|
||||||
|
|
||||||
exception_t misaligned_exception;
|
exception_t misaligned_exception, cva6_misaligned_exception, acc_misaligned_exception;
|
||||||
exception_t ld_ex;
|
exception_t ld_ex;
|
||||||
exception_t st_ex;
|
exception_t st_ex;
|
||||||
|
|
||||||
logic hs_ld_st_inst;
|
|
||||||
logic hlvx_inst;
|
|
||||||
|
|
||||||
|
logic hs_ld_st_inst;
|
||||||
|
logic hlvx_inst;
|
||||||
logic [1:0] sum, mxr;
|
logic [1:0] sum, mxr;
|
||||||
logic [CVA6Cfg.PPNW-1:0] satp_ppn[2:0];
|
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.ASID_WIDTH-1:0] asid[2:0], asid_to_be_flushed[1:0];
|
||||||
logic [CVA6Cfg.VLEN-1:0] vaddr_to_be_flushed[1:0];
|
logic [CVA6Cfg.VLEN-1:0] vaddr_to_be_flushed[1:0];
|
||||||
|
|
||||||
// -------------------
|
// -------------------
|
||||||
// MMU e.g.: TLBs/PTW
|
// MMU e.g.: TLBs/PTW
|
||||||
// -------------------
|
// -------------------
|
||||||
|
@ -387,6 +393,108 @@ module load_store_unit
|
||||||
.pmpaddr_i (pmpaddr_i)
|
.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;
|
logic store_buffer_empty;
|
||||||
// ------------------
|
// ------------------
|
||||||
|
@ -418,15 +526,15 @@ module load_store_unit
|
||||||
.result_o (st_result),
|
.result_o (st_result),
|
||||||
.ex_o (st_ex),
|
.ex_o (st_ex),
|
||||||
// MMU port
|
// MMU port
|
||||||
.translation_req_o (st_translation_req),
|
.translation_req_o (cva6_st_translation_req),
|
||||||
.vaddr_o (st_vaddr),
|
.vaddr_o (st_vaddr),
|
||||||
.rvfi_mem_paddr_o (rvfi_mem_paddr_o),
|
.rvfi_mem_paddr_o (rvfi_mem_paddr_o),
|
||||||
.tinst_o (st_tinst),
|
.tinst_o (st_tinst),
|
||||||
.hs_ld_st_inst_o (st_hs_ld_st_inst),
|
.hs_ld_st_inst_o (st_hs_ld_st_inst),
|
||||||
.hlvx_inst_o (st_hlvx_inst),
|
.hlvx_inst_o (st_hlvx_inst),
|
||||||
.paddr_i (mmu_paddr),
|
.paddr_i (cva6_mmu_paddr),
|
||||||
.ex_i (mmu_exception),
|
.ex_i (cva6_mmu_exception),
|
||||||
.dtlb_hit_i (dtlb_hit),
|
.dtlb_hit_i (cva6_dtlb_hit),
|
||||||
// Load Unit
|
// Load Unit
|
||||||
.page_offset_i (page_offset),
|
.page_offset_i (page_offset),
|
||||||
.page_offset_matches_o(page_offset_matches),
|
.page_offset_matches_o(page_offset_matches),
|
||||||
|
@ -465,10 +573,10 @@ module load_store_unit
|
||||||
.tinst_o (ld_tinst),
|
.tinst_o (ld_tinst),
|
||||||
.hs_ld_st_inst_o (ld_hs_ld_st_inst),
|
.hs_ld_st_inst_o (ld_hs_ld_st_inst),
|
||||||
.hlvx_inst_o (ld_hlvx_inst),
|
.hlvx_inst_o (ld_hlvx_inst),
|
||||||
.paddr_i (mmu_paddr),
|
.paddr_i (cva6_mmu_paddr),
|
||||||
.ex_i (mmu_exception),
|
.ex_i (cva6_mmu_exception),
|
||||||
.dtlb_hit_i (dtlb_hit),
|
.dtlb_hit_i (cva6_dtlb_hit),
|
||||||
.dtlb_ppn_i (dtlb_ppn),
|
.dtlb_ppn_i (cva6_dtlb_ppn),
|
||||||
// to store unit
|
// to store unit
|
||||||
.page_offset_o (page_offset),
|
.page_offset_o (page_offset),
|
||||||
.page_offset_matches_i(page_offset_matches),
|
.page_offset_matches_i(page_offset_matches),
|
||||||
|
@ -510,22 +618,22 @@ module load_store_unit
|
||||||
// determine whether this is a load or store
|
// determine whether this is a load or store
|
||||||
always_comb begin : which_op
|
always_comb begin : which_op
|
||||||
|
|
||||||
ld_valid_i = 1'b0;
|
ld_valid_i = 1'b0;
|
||||||
st_valid_i = 1'b0;
|
st_valid_i = 1'b0;
|
||||||
|
|
||||||
translation_req = 1'b0;
|
cva6_translation_req = 1'b0;
|
||||||
mmu_vaddr = {CVA6Cfg.VLEN{1'b0}};
|
cva6_mmu_vaddr = {CVA6Cfg.VLEN{1'b0}};
|
||||||
mmu_tinst = {32{1'b0}};
|
mmu_tinst = {32{1'b0}};
|
||||||
mmu_hs_ld_st_inst = 1'b0;
|
mmu_hs_ld_st_inst = 1'b0;
|
||||||
mmu_hlvx_inst = 1'b0;
|
mmu_hlvx_inst = 1'b0;
|
||||||
|
|
||||||
// check the operation to activate the right functional unit accordingly
|
// check the operation to activate the right functional unit accordingly
|
||||||
unique case (lsu_ctrl.fu)
|
unique case (lsu_ctrl.fu)
|
||||||
// all loads go here
|
// all loads go here
|
||||||
LOAD: begin
|
LOAD: begin
|
||||||
ld_valid_i = lsu_ctrl.valid;
|
ld_valid_i = lsu_ctrl.valid;
|
||||||
translation_req = ld_translation_req;
|
cva6_translation_req = ld_translation_req;
|
||||||
mmu_vaddr = ld_vaddr;
|
cva6_mmu_vaddr = ld_vaddr;
|
||||||
if (CVA6Cfg.RVH) begin
|
if (CVA6Cfg.RVH) begin
|
||||||
mmu_tinst = ld_tinst;
|
mmu_tinst = ld_tinst;
|
||||||
mmu_hs_ld_st_inst = ld_hs_ld_st_inst;
|
mmu_hs_ld_st_inst = ld_hs_ld_st_inst;
|
||||||
|
@ -534,9 +642,9 @@ module load_store_unit
|
||||||
end
|
end
|
||||||
// all stores go here
|
// all stores go here
|
||||||
STORE: begin
|
STORE: begin
|
||||||
st_valid_i = lsu_ctrl.valid;
|
st_valid_i = lsu_ctrl.valid;
|
||||||
translation_req = st_translation_req;
|
cva6_translation_req = st_translation_req;
|
||||||
mmu_vaddr = st_vaddr;
|
cva6_mmu_vaddr = st_vaddr;
|
||||||
if (CVA6Cfg.RVH) begin
|
if (CVA6Cfg.RVH) begin
|
||||||
mmu_tinst = st_tinst;
|
mmu_tinst = st_tinst;
|
||||||
mmu_hs_ld_st_inst = st_hs_ld_st_inst;
|
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
|
// 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
|
// can augment the exception if other memory related exceptions like a page fault or access errors
|
||||||
always_comb begin : data_misaligned_detection
|
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
|
{CVA6Cfg.XLEN{1'b0}}, {CVA6Cfg.XLEN{1'b0}}, {CVA6Cfg.GPLEN{1'b0}}, {32{1'b0}}, 1'b0, 1'b0
|
||||||
};
|
};
|
||||||
data_misaligned = 1'b0;
|
data_misaligned = 1'b0;
|
||||||
|
@ -640,26 +748,26 @@ module load_store_unit
|
||||||
if (data_misaligned) begin
|
if (data_misaligned) begin
|
||||||
case (lsu_ctrl.fu)
|
case (lsu_ctrl.fu)
|
||||||
LOAD: begin
|
LOAD: begin
|
||||||
misaligned_exception.cause = riscv::LD_ADDR_MISALIGNED;
|
cva6_misaligned_exception.cause = riscv::LD_ADDR_MISALIGNED;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STORE: begin
|
STORE: begin
|
||||||
|
|
||||||
misaligned_exception.cause = riscv::ST_ADDR_MISALIGNED;
|
cva6_misaligned_exception.cause = riscv::ST_ADDR_MISALIGNED;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
default: ;
|
default: ;
|
||||||
|
@ -670,25 +778,25 @@ module load_store_unit
|
||||||
|
|
||||||
case (lsu_ctrl.fu)
|
case (lsu_ctrl.fu)
|
||||||
LOAD: begin
|
LOAD: begin
|
||||||
misaligned_exception.cause = riscv::LOAD_PAGE_FAULT;
|
cva6_misaligned_exception.cause = riscv::LOAD_PAGE_FAULT;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STORE: begin
|
STORE: begin
|
||||||
misaligned_exception.cause = riscv::STORE_PAGE_FAULT;
|
cva6_misaligned_exception.cause = riscv::STORE_PAGE_FAULT;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
default: ;
|
default: ;
|
||||||
|
@ -699,25 +807,25 @@ module load_store_unit
|
||||||
|
|
||||||
case (lsu_ctrl.fu)
|
case (lsu_ctrl.fu)
|
||||||
LOAD: begin
|
LOAD: begin
|
||||||
misaligned_exception.cause = riscv::LOAD_GUEST_PAGE_FAULT;
|
cva6_misaligned_exception.cause = riscv::LOAD_GUEST_PAGE_FAULT;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STORE: begin
|
STORE: begin
|
||||||
misaligned_exception.cause = riscv::STORE_GUEST_PAGE_FAULT;
|
cva6_misaligned_exception.cause = riscv::STORE_GUEST_PAGE_FAULT;
|
||||||
misaligned_exception.valid = 1'b1;
|
cva6_misaligned_exception.valid = 1'b1;
|
||||||
if (CVA6Cfg.TvalEn)
|
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
|
if (CVA6Cfg.RVH) begin
|
||||||
misaligned_exception.tval2 = '0;
|
cva6_misaligned_exception.tval2 = '0;
|
||||||
misaligned_exception.tinst = lsu_ctrl.tinst;
|
cva6_misaligned_exception.tinst = lsu_ctrl.tinst;
|
||||||
misaligned_exception.gva = ld_st_v_i;
|
cva6_misaligned_exception.gva = ld_st_v_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
default: ;
|
default: ;
|
||||||
|
@ -759,12 +867,10 @@ module load_store_unit
|
||||||
.pop_ld_i (pop_ld),
|
.pop_ld_i (pop_ld),
|
||||||
.pop_st_i (pop_st),
|
.pop_st_i (pop_st),
|
||||||
|
|
||||||
.lsu_ctrl_o(lsu_ctrl),
|
.lsu_ctrl_o(lsu_ctrl_byp),
|
||||||
.ready_o (lsu_ready_o)
|
.ready_o (lsu_ready_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign rvfi_lsu_ctrl_o = lsu_ctrl;
|
assign rvfi_lsu_ctrl_o = lsu_ctrl;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
// Date: 2.10.2019
|
// Date: 2.10.2019
|
||||||
// Description: purely combinatorial PMP unit (with extraction for more complex configs such as NAPOT)
|
// 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
|
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty
|
||||||
) (
|
) (
|
||||||
// Input
|
// Input
|
||||||
|
@ -20,8 +22,8 @@ module pmp #(
|
||||||
input riscv::pmp_access_t access_type_i,
|
input riscv::pmp_access_t access_type_i,
|
||||||
input riscv::priv_lvl_t priv_lvl_i,
|
input riscv::priv_lvl_t priv_lvl_i,
|
||||||
// Configuration
|
// Configuration
|
||||||
input logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] conf_addr_i,
|
input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] conf_addr_i,
|
||||||
input riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] conf_i,
|
input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] conf_i,
|
||||||
// Output
|
// Output
|
||||||
output logic allow_o
|
output logic allow_o
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,8 +36,8 @@ module pmp_data_if
|
||||||
input riscv::priv_lvl_t ld_st_priv_lvl_i,
|
input riscv::priv_lvl_t ld_st_priv_lvl_i,
|
||||||
input logic ld_st_v_i,
|
input logic ld_st_v_i,
|
||||||
// PMP
|
// PMP
|
||||||
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,
|
||||||
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
|
||||||
);
|
);
|
||||||
// virtual address causing the exception
|
// virtual address causing the exception
|
||||||
logic [CVA6Cfg.XLEN-1:0] fetch_vaddr_xlen, lsu_vaddr_xlen;
|
logic [CVA6Cfg.XLEN-1:0] fetch_vaddr_xlen, lsu_vaddr_xlen;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue