From fa101fae7a19a8b43387b07d9a8bfa4db61348e4 Mon Sep 17 00:00:00 2001 From: Guillaume Chauvon <94678394+Gchauvon@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:47:06 +0100 Subject: [PATCH] Parameterize TVAL to reduce size in embedded (#1784) --- .gitlab-ci/expected_synth.yml | 2 +- core/branch_unit.sv | 4 +- core/csr_regfile.sv | 43 +++-- core/cva6.sv | 4 + core/cva6_rvfi.sv | 1 + core/cvxif_fu.sv | 2 +- core/decoder.sv | 10 +- core/fpu_wrap.sv | 1 + core/frontend/instr_queue.sv | 12 +- core/id_stage.sv | 7 +- core/include/config_pkg.sv | 2 + core/include/cv32a60x_config_pkg.sv | 3 + core/include/cv32a6_embedded_config_pkg.sv | 3 + .../cv32a6_ima_sv32_fpga_config_pkg.sv | 3 + core/include/cv32a6_imac_sv0_config_pkg.sv | 3 + core/include/cv32a6_imac_sv32_config_pkg.sv | 3 + core/include/cv32a6_imafc_sv32_config_pkg.sv | 3 + .../cv64a6_imadfcv_sv39_polara_config_pkg.sv | 3 + core/include/cv64a6_imafdc_sv39_config_pkg.sv | 3 + .../cv64a6_imafdc_sv39_hpdcache_config_pkg.sv | 3 + ...cv64a6_imafdc_sv39_openpiton_config_pkg.sv | 3 + .../cv64a6_imafdc_sv39_wb_config_pkg.sv | 3 + .../include/cv64a6_imafdcv_sv39_config_pkg.sv | 3 + core/issue_read_operands.sv | 5 +- core/issue_stage.sv | 4 + core/load_store_unit.sv | 28 ++-- core/mmu_sv32/cva6_mmu_sv32.sv | 127 ++++++++------ core/mmu_sv39/mmu.sv | 155 ++++++++++-------- core/scoreboard.sv | 15 +- corev_apu/fpga/src/ariane_xilinx.sv | 1 + 30 files changed, 287 insertions(+), 172 deletions(-) diff --git a/.gitlab-ci/expected_synth.yml b/.gitlab-ci/expected_synth.yml index f2b365f14f..015c929907 100644 --- a/.gitlab-ci/expected_synth.yml +++ b/.gitlab-ci/expected_synth.yml @@ -1,3 +1,3 @@ cv32a6_embedded: - gates: 114319 + gates: 110519 diff --git a/core/branch_unit.sv b/core/branch_unit.sv index dfcb1c7671..d04adb7308 100644 --- a/core/branch_unit.sv +++ b/core/branch_unit.sv @@ -96,7 +96,9 @@ module branch_unit #( ((ariane_pkg::op_is_branch(fu_data_i.operation)) && branch_comp_res_i); branch_exception_o.cause = riscv::INSTR_ADDR_MISALIGNED; branch_exception_o.valid = 1'b0; - branch_exception_o.tval = {{riscv::XLEN - riscv::VLEN{pc_i[riscv::VLEN-1]}}, pc_i}; + if (CVA6Cfg.TvalEn) + branch_exception_o.tval = {{riscv::XLEN - riscv::VLEN{pc_i[riscv::VLEN-1]}}, pc_i}; + else branch_exception_o.tval = '0; // Only throw instruction address misaligned exception if this is indeed a `taken` conditional branch or // an unconditional jump if (branch_valid_i && (target_address[0] || (!CVA6Cfg.RVC && target_address[1])) && jump_taken) begin diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 8198b5a259..1f3b163177 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -760,7 +760,7 @@ module csr_regfile if (CVA6Cfg.RVS) scause_d = csr_wdata; else update_access_exception = 1'b1; riscv::CSR_STVAL: - if (CVA6Cfg.RVS) stval_d = csr_wdata; + if (CVA6Cfg.RVS && CVA6Cfg.TvalEn) stval_d = csr_wdata; else update_access_exception = 1'b1; // supervisor address translation and protection riscv::CSR_SATP: begin @@ -846,7 +846,10 @@ module csr_regfile riscv::CSR_MSCRATCH: mscratch_d = csr_wdata; riscv::CSR_MEPC: mepc_d = {csr_wdata[riscv::XLEN-1:1], 1'b0}; riscv::CSR_MCAUSE: mcause_d = csr_wdata; - riscv::CSR_MTVAL: mtval_d = csr_wdata; + riscv::CSR_MTVAL: begin + if (CVA6Cfg.TvalEn) mtval_d = csr_wdata; + else update_access_exception = 1'b1; + end riscv::CSR_MIP: begin mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP; mip_d = (mip_q & ~mask) | (csr_wdata & mask); @@ -1130,14 +1133,18 @@ module csr_regfile // set epc mepc_d = {{riscv::XLEN - riscv::VLEN{pc_i[riscv::VLEN-1]}}, pc_i}; // set mtval or stval - mtval_d = (ariane_pkg::ZERO_TVAL - && (ex_i.cause inside { - riscv::ILLEGAL_INSTR, - riscv::BREAKPOINT, - riscv::ENV_CALL_UMODE, - riscv::ENV_CALL_SMODE, - riscv::ENV_CALL_MMODE - } || ex_i.cause[riscv::XLEN-1])) ? '0 : ex_i.tval; + if (CVA6Cfg.TvalEn) begin + mtval_d = (ariane_pkg::ZERO_TVAL + && (ex_i.cause inside { + riscv::ILLEGAL_INSTR, + riscv::BREAKPOINT, + riscv::ENV_CALL_UMODE, + riscv::ENV_CALL_SMODE, + riscv::ENV_CALL_MMODE + } || ex_i.cause[riscv::XLEN-1])) ? '0 : ex_i.tval; + end else begin + mtval_d = '0; + end end priv_lvl_d = trap_to_priv_lvl; @@ -1590,12 +1597,12 @@ module csr_regfile mcause_q <= mcause_d; mcounteren_q <= mcounteren_d; mscratch_q <= mscratch_d; - mtval_q <= mtval_d; - fiom_q <= fiom_d; - dcache_q <= dcache_d; - icache_q <= icache_d; - mcountinhibit_q <= mcountinhibit_d; - acc_cons_q <= acc_cons_d; + if (CVA6Cfg.TvalEn) mtval_q <= mtval_d; + fiom_q <= fiom_d; + dcache_q <= dcache_d; + icache_q <= icache_d; + mcountinhibit_q <= mcountinhibit_d; + acc_cons_q <= acc_cons_d; // supervisor mode registers if (CVA6Cfg.RVS) begin medeleg_q <= medeleg_d; @@ -1605,8 +1612,8 @@ module csr_regfile stvec_q <= stvec_d; scounteren_q <= scounteren_d; sscratch_q <= sscratch_d; - stval_q <= stval_d; - satp_q <= satp_d; + if (CVA6Cfg.TvalEn) stval_q <= stval_d; + satp_q <= satp_d; end // timer and counters cycle_q <= cycle_d; diff --git a/core/cva6.sv b/core/cva6.sv index 4b9ccf0015..2d944e7682 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -204,6 +204,7 @@ module cva6 CVA6Cfg.BTBEntries, CVA6Cfg.BHTEntries, CVA6Cfg.DmBaseAddress, + CVA6Cfg.TvalEn, CVA6Cfg.NrPMPEntries, CVA6Cfg.PMPCfgRstVal, CVA6Cfg.PMPAddrRstVal, @@ -256,6 +257,7 @@ module cva6 // ID <-> ISSUE // -------------- scoreboard_entry_t issue_entry_id_issue; + logic [31:0] orig_instr_id_issue; logic issue_entry_valid_id_issue; logic is_ctrl_fow_id_issue; logic issue_instr_issue_id; @@ -504,6 +506,7 @@ module cva6 .fetch_entry_ready_o(fetch_ready_id_if), .issue_entry_o (issue_entry_id_issue), + .orig_instr_o (orig_instr_id_issue), .issue_entry_valid_o(issue_entry_valid_id_issue), .is_ctrl_flow_o (is_ctrl_fow_id_issue), .issue_instr_ack_i (issue_instr_issue_id), @@ -600,6 +603,7 @@ module cva6 .stall_i (stall_acc_id), // ID Stage .decoded_instr_i (issue_entry_id_issue), + .orig_instr_i (orig_instr_id_issue), .decoded_instr_valid_i (issue_entry_valid_id_issue), .is_ctrl_flow_i (is_ctrl_fow_id_issue), .decoded_instr_ack_o (issue_instr_issue_id), diff --git a/core/cva6_rvfi.sv b/core/cva6_rvfi.sv index 972a50a8f1..d4d9f10342 100644 --- a/core/cva6_rvfi.sv +++ b/core/cva6_rvfi.sv @@ -93,6 +93,7 @@ module cva6_rvfi CVA6Cfg.BTBEntries, CVA6Cfg.BHTEntries, CVA6Cfg.DmBaseAddress, + CVA6Cfg.TvalEn, CVA6Cfg.NrPMPEntries, CVA6Cfg.PMPCfgRstVal, CVA6Cfg.PMPAddrRstVal, diff --git a/core/cvxif_fu.sv b/core/cvxif_fu.sv index fb0058b9ca..ebe180621c 100644 --- a/core/cvxif_fu.sv +++ b/core/cvxif_fu.sv @@ -90,7 +90,7 @@ module cvxif_fu x_valid_o = 1'b1; x_exception_o.cause = riscv::ILLEGAL_INSTR; x_exception_o.valid = 1'b1; - x_exception_o.tval = illegal_instr_n; + if (CVA6Cfg.TvalEn) x_exception_o.tval = illegal_instr_n; x_we_o = '0; illegal_n = '0; // Reset flag for illegal instr. illegal_id and illegal instr values are a don't care, no need to reset it. end diff --git a/core/decoder.sv b/core/decoder.sv index eead0c4855..97812bffdc 100644 --- a/core/decoder.sv +++ b/core/decoder.sv @@ -44,6 +44,7 @@ module decoder input logic tw_i, // timeout wait input logic tsr_i, // trap sret output scoreboard_entry_t instruction_o, // scoreboard entry to scoreboard + output logic [31:0] orig_instr_o, // instruction opcode to issue read operand for CVXIF output logic is_control_flow_instr_o // this instruction will change the control flow ); logic illegal_instr; @@ -1304,14 +1305,19 @@ module decoder assign instruction_o.valid = instruction_o.ex.valid; always_comb begin : exception_handling - interrupt_cause = '0; + interrupt_cause = '0; instruction_o.ex = ex_i; + orig_instr_o = '0; // look if we didn't already get an exception in any previous // stage - we should not overwrite it as we retain order regarding the exception if (~ex_i.valid) begin // if we didn't already get an exception save the instruction here as we may need it // in the commit stage if we got a access exception to one of the CSR registers - instruction_o.ex.tval = (is_compressed_i) ? {{riscv::XLEN-16{1'b0}}, compressed_instr_i} : {{riscv::XLEN-32{1'b0}}, instruction_i}; + if (CVA6Cfg.CvxifEn || CVA6Cfg.FpuEn) + orig_instr_o = (is_compressed_i) ? {{riscv::XLEN-16{1'b0}}, compressed_instr_i} : {{riscv::XLEN-32{1'b0}}, instruction_i}; + if (CVA6Cfg.TvalEn) + instruction_o.ex.tval = (is_compressed_i) ? {{riscv::XLEN-16{1'b0}}, compressed_instr_i} : {{riscv::XLEN-32{1'b0}}, instruction_i}; + else instruction_o.ex.tval = '0; // instructions which will throw an exception are marked as valid // e.g.: they can be committed anytime and do not need to wait for any functional unit // check here if we decoded an invalid instruction or if the compressed decoder already decoded diff --git a/core/fpu_wrap.sv b/core/fpu_wrap.sv index 9219029d18..1cc0260d3a 100644 --- a/core/fpu_wrap.sv +++ b/core/fpu_wrap.sv @@ -557,6 +557,7 @@ module fpu_wrap // Pack status flag into exception cause, tval ignored in wb, exception is always invalid assign fpu_exception_o.cause = {59'h0, fpu_status}; assign fpu_exception_o.valid = 1'b0; + assign fpu_exception_o.tval = '0; // Donwstream write port is dedicated to FPU and always ready assign fpu_out_ready = 1'b1; diff --git a/core/frontend/instr_queue.sv b/core/frontend/instr_queue.sv index 3f955937a9..c4910cfca6 100644 --- a/core/frontend/instr_queue.sv +++ b/core/frontend/instr_queue.sv @@ -282,9 +282,10 @@ ariane_pkg::FETCH_FIFO_DEPTH end fetch_entry_o.instruction = instr_data_out[i].instr; fetch_entry_o.ex.valid = instr_data_out[i].ex != ariane_pkg::FE_NONE; - fetch_entry_o.ex.tval = { - {(riscv::XLEN - riscv::VLEN) {1'b0}}, instr_data_out[i].ex_vaddr - }; + if (CVA6Cfg.TvalEn) + fetch_entry_o.ex.tval = { + {(riscv::XLEN - riscv::VLEN) {1'b0}}, instr_data_out[i].ex_vaddr + }; fetch_entry_o.branch_predict.cf = instr_data_out[i].cf; pop_instr[i] = fetch_entry_valid_o & fetch_entry_ready_i; end @@ -309,8 +310,9 @@ ariane_pkg::FETCH_FIFO_DEPTH end else begin fetch_entry_o.ex.cause = riscv::INSTR_PAGE_FAULT; end - fetch_entry_o.ex.tval = {{64 - riscv::VLEN{1'b0}}, instr_data_out[0].ex_vaddr}; - + if (CVA6Cfg.TvalEn) + fetch_entry_o.ex.tval = {{64 - riscv::VLEN{1'b0}}, instr_data_out[0].ex_vaddr}; + else fetch_entry_o.ex.tval = '0; fetch_entry_o.branch_predict.predict_address = address_out; fetch_entry_o.branch_predict.cf = instr_data_out[0].cf; diff --git a/core/id_stage.sv b/core/id_stage.sv index 81d1640273..a442592785 100644 --- a/core/id_stage.sv +++ b/core/id_stage.sv @@ -27,6 +27,7 @@ module id_stage #( output logic fetch_entry_ready_o, // acknowledge the instruction (fetch entry) // to ID output ariane_pkg::scoreboard_entry_t issue_entry_o, // a decoded instruction + output logic [31:0] orig_instr_o, output logic issue_entry_valid_o, // issue entry is valid output logic is_ctrl_flow_o, // the instruction we issue is a ctrl flow instructions input logic issue_instr_ack_i, // issue stage acknowledged sampling of instructions @@ -47,12 +48,14 @@ module id_stage #( typedef struct packed { logic valid; ariane_pkg::scoreboard_entry_t sbe; + logic [31:0] orig_instr; logic is_ctrl_flow; } issue_struct_t; issue_struct_t issue_n, issue_q; logic is_control_flow_instr; ariane_pkg::scoreboard_entry_t decoded_instruction; + logic [31:0] orig_instr; logic is_illegal; logic [31:0] instruction; @@ -102,6 +105,7 @@ module id_stage #( .tw_i, .tsr_i, .instruction_o (decoded_instruction), + .orig_instr_o (orig_instr), .is_control_flow_instr_o(is_control_flow_instr) ); @@ -111,6 +115,7 @@ module id_stage #( assign issue_entry_o = issue_q.sbe; assign issue_entry_valid_o = issue_q.valid; assign is_ctrl_flow_o = issue_q.is_ctrl_flow; + assign orig_instr_o = issue_q.orig_instr; always_comb begin issue_n = issue_q; @@ -124,7 +129,7 @@ module id_stage #( // for a new instruction if ((!issue_q.valid || issue_instr_ack_i) && fetch_entry_valid_i) begin fetch_entry_ready_o = 1'b1; - issue_n = '{1'b1, decoded_instruction, is_control_flow_instr}; + issue_n = '{1'b1, decoded_instruction, orig_instr, is_control_flow_instr}; end // invalidate the pipeline register on a flush diff --git a/core/include/config_pkg.sv b/core/include/config_pkg.sv index 90d6bfe159..e54cce50ef 100644 --- a/core/include/config_pkg.sv +++ b/core/include/config_pkg.sv @@ -87,6 +87,8 @@ package config_pkg; int unsigned BHTEntries; /// Offset of the debug module. logic [63:0] DmBaseAddress; + /// Tval Support Enable + bit TvalEn; /// Number of PMP entries. int unsigned NrPMPEntries; /// Physical Memory Protection (PMP) CSR reset values and read-only bits diff --git a/core/include/cv32a60x_config_pkg.sv b/core/include/cv32a60x_config_pkg.sv index 318caf2ba1..81e5d29aef 100644 --- a/core/include/cv32a60x_config_pkg.sv +++ b/core/include/cv32a60x_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 0; localparam CVA6ConfigBHTEntries = 0; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 0; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv32a6_embedded_config_pkg.sv b/core/include/cv32a6_embedded_config_pkg.sv index 0181345a1e..dc0229a7f6 100644 --- a/core/include/cv32a6_embedded_config_pkg.sv +++ b/core/include/cv32a6_embedded_config_pkg.sv @@ -61,6 +61,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 0; localparam CVA6ConfigBHTEntries = 32; + localparam CVA6ConfigTvalEn = 0; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 0; @@ -114,6 +116,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv index 46b88ac4aa..def6dd6cf0 100644 --- a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv +++ b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 0; localparam CVA6ConfigPerfCounterEn = 0; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: unsigned'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv32a6_imac_sv0_config_pkg.sv b/core/include/cv32a6_imac_sv0_config_pkg.sv index 933e94be1a..a60ed63a1d 100644 --- a/core/include/cv32a6_imac_sv0_config_pkg.sv +++ b/core/include/cv32a6_imac_sv0_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: unsigned'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv32a6_imac_sv32_config_pkg.sv b/core/include/cv32a6_imac_sv32_config_pkg.sv index a9737428f7..a2f82895e1 100644 --- a/core/include/cv32a6_imac_sv32_config_pkg.sv +++ b/core/include/cv32a6_imac_sv32_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv32a6_imafc_sv32_config_pkg.sv b/core/include/cv32a6_imafc_sv32_config_pkg.sv index ab4ee2c287..e3c0e2f489 100644 --- a/core/include/cv32a6_imafc_sv32_config_pkg.sv +++ b/core/include/cv32a6_imafc_sv32_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv index 5b1ca3647a..c461a32acd 100644 --- a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv +++ b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv @@ -61,6 +61,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -114,6 +116,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imafdc_sv39_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_config_pkg.sv index ec4db64f57..29c5499114 100644 --- a/core/include/cv64a6_imafdc_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv index 7436decb25..c7a4ced7fe 100644 --- a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv @@ -69,6 +69,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -122,6 +124,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv index add8f15849..cc3e79c7e9 100644 --- a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv index f3ba6c40a4..b57d9c056c 100644 --- a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv @@ -62,6 +62,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -115,6 +117,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv index ff82a05cb5..a0c9b2862a 100644 --- a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv @@ -61,6 +61,8 @@ package cva6_config_pkg; localparam CVA6ConfigBTBEntries = 32; localparam CVA6ConfigBHTEntries = 128; + localparam CVA6ConfigTvalEn = 1; + localparam CVA6ConfigNrPMPEntries = 8; localparam CVA6ConfigPerfCounterEn = 1; @@ -114,6 +116,7 @@ package cva6_config_pkg; BTBEntries: unsigned'(CVA6ConfigBTBEntries), BHTEntries: unsigned'(CVA6ConfigBHTEntries), DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}}, diff --git a/core/issue_read_operands.sv b/core/issue_read_operands.sv index 2e32486173..b62d016b88 100644 --- a/core/issue_read_operands.sv +++ b/core/issue_read_operands.sv @@ -28,6 +28,7 @@ module issue_read_operands input logic stall_i, // coming from decoder input scoreboard_entry_t issue_instr_i, + input logic [31:0] orig_instr_i, input logic issue_instr_valid_i, output logic issue_ack_o, // lookup rd in scoreboard @@ -111,9 +112,9 @@ module issue_read_operands // forwarding signals logic forward_rs1, forward_rs2, forward_rs3; - // original instruction stored in tval + // original instruction riscv::instruction_t orig_instr; - assign orig_instr = riscv::instruction_t'(issue_instr_i.ex.tval[31:0]); + assign orig_instr = riscv::instruction_t'(orig_instr_i); // ID <-> EX registers diff --git a/core/issue_stage.sv b/core/issue_stage.sv index 64b8cb5921..bfc8173124 100644 --- a/core/issue_stage.sv +++ b/core/issue_stage.sv @@ -28,6 +28,7 @@ module issue_stage input logic stall_i, // Stall issue stage // from ISSUE input scoreboard_entry_t decoded_instr_i, + input logic [31:0] orig_instr_i, input logic decoded_instr_valid_i, input logic is_ctrl_flow_i, output logic decoded_instr_ack_o, @@ -111,6 +112,7 @@ module issue_stage logic rs3_valid_iro_sb; scoreboard_entry_t issue_instr_sb_iro; + logic [ 31:0] orig_instr_sb_iro; logic issue_instr_valid_sb_iro; logic issue_ack_iro_sb; @@ -149,6 +151,7 @@ module issue_stage .decoded_instr_valid_i(decoded_instr_valid_i), .decoded_instr_ack_o (decoded_instr_ack_o), .issue_instr_o (issue_instr_sb_iro), + .orig_instr_o (orig_instr_sb_iro), .issue_instr_valid_o (issue_instr_valid_sb_iro), .issue_ack_i (issue_ack_iro_sb), @@ -168,6 +171,7 @@ module issue_stage ) i_issue_read_operands ( .flush_i (flush_unissued_instr_i), .issue_instr_i (issue_instr_sb_iro), + .orig_instr_i (orig_instr_sb_iro), .issue_instr_valid_i(issue_instr_valid_sb_iro), .issue_ack_o (issue_ack_iro_sb), .fu_data_o (fu_data_o), diff --git a/core/load_store_unit.sv b/core/load_store_unit.sv index 14a281f491..9a5c9245c6 100644 --- a/core/load_store_unit.sv +++ b/core/load_store_unit.sv @@ -431,28 +431,32 @@ module load_store_unit if (data_misaligned) begin if (lsu_ctrl.fu == LOAD) begin - misaligned_exception = { - riscv::LD_ADDR_MISALIGNED, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}, 1'b1 - }; + misaligned_exception.cause = riscv::LD_ADDR_MISALIGNED; + misaligned_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + misaligned_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}; end else if (lsu_ctrl.fu == STORE) begin - misaligned_exception = { - riscv::ST_ADDR_MISALIGNED, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}, 1'b1 - }; + misaligned_exception.cause = riscv::ST_ADDR_MISALIGNED; + misaligned_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + misaligned_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}; end end if (ariane_pkg::MMU_PRESENT && en_ld_st_translation_i && lsu_ctrl.overflow) begin if (lsu_ctrl.fu == LOAD) begin - misaligned_exception = { - riscv::LD_ACCESS_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}, 1'b1 - }; + misaligned_exception.cause = riscv::LD_ACCESS_FAULT; + misaligned_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + misaligned_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}; end else if (lsu_ctrl.fu == STORE) begin - misaligned_exception = { - riscv::ST_ACCESS_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}, 1'b1 - }; + misaligned_exception.cause = riscv::ST_ACCESS_FAULT; + misaligned_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + misaligned_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_ctrl.vaddr}; end end end diff --git a/core/mmu_sv32/cva6_mmu_sv32.sv b/core/mmu_sv32/cva6_mmu_sv32.sv index d194306eb7..9c98793da4 100644 --- a/core/mmu_sv32/cva6_mmu_sv32.sv +++ b/core/mmu_sv32/cva6_mmu_sv32.sv @@ -296,11 +296,12 @@ module cva6_mmu_sv32 if (enable_translation_i) begin // we work with SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:riscv::SV-1] are equal if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, - {{riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, - 1'b1 - }; + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr + }; end icache_areq_o.fetch_valid = 1'b0; @@ -322,15 +323,18 @@ module cva6_mmu_sv32 // we got an access error if (iaccess_err) begin // throw a page fault - icache_areq_o.fetch_exception = { - riscv::INSTR_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, - 1'b1 - }; //to check on wave --> not connected + icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr + }; + //to check on wave --> not connected end else if (!pmp_instr_allow) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, icache_areq_i.fetch_vaddr, 1'b1 - }; //to check on wave --> not connected + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) icache_areq_o.fetch_exception.tval = icache_areq_i.fetch_vaddr; + //to check on wave --> not connected end end else // --------- @@ -339,23 +343,28 @@ module cva6_mmu_sv32 // watch out for exceptions happening during walking the page table if (ptw_active && walking_instr) begin icache_areq_o.fetch_valid = ptw_error | ptw_access_exception; - if (ptw_error) - icache_areq_o.fetch_exception = { - riscv::INSTR_PAGE_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}, 1'b1 - }; //to check on wave + if (ptw_error) begin + icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}; + end //to check on wave // TODO(moschn,zarubaf): What should the value of tval be in this case? - else - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, ptw_bad_paddr[riscv::PLEN-1:2], 1'b1 - }; //to check on wave --> not connected + else begin + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) icache_areq_o.fetch_exception.tval = ptw_bad_paddr[riscv::PLEN-1:2]; + end end end // if it didn't match any execute region throw an `Instruction Access Fault` // or: if we are not translating, check PMPs immediately on the paddr if (!match_any_execute_region || (!enable_translation_i && !pmp_instr_allow)) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, icache_areq_o.fetch_paddr[riscv::PLEN-1:2], 1'b1 - }; //to check on wave --> not connected + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = icache_areq_o.fetch_paddr[riscv::PLEN-1:2]; + //to check on wave --> not connected end end @@ -453,32 +462,36 @@ module cva6_mmu_sv32 // check if the page is write-able and we are not violating privileges // also check if the dirty flag is set if (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d) begin - lsu_exception_o = { - riscv::STORE_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; //to check on wave + lsu_exception_o.cause = riscv::STORE_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; + // to check on wave // Check if any PMPs are violated end else if (!pmp_data_allow) begin - lsu_exception_o = { - riscv::ST_ACCESS_FAULT, lsu_paddr_o[riscv::PLEN-1:2], 1'b1 - }; //only 32 bits on 34b of lsu_paddr_o are returned. + lsu_exception_o.cause = riscv::ST_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = lsu_paddr_o[riscv::PLEN-1:2]; + //only 32 bits on 34b of lsu_paddr_o are returned. end // this is a load end else begin // check for sufficient access privileges - throw a page fault if necessary if (daccess_err) begin - lsu_exception_o = { - riscv::LOAD_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; + lsu_exception_o.cause = riscv::LOAD_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; // Check if any PMPs are violated end else if (!pmp_data_allow) begin - lsu_exception_o = { - riscv::LD_ACCESS_FAULT, lsu_paddr_o[riscv::PLEN-1:2], 1'b1 - }; //only 32 bits on 34b of lsu_paddr_o are returned. + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = lsu_paddr_o[riscv::PLEN-1:2]; end end end else @@ -494,17 +507,19 @@ module cva6_mmu_sv32 lsu_valid_o = 1'b1; // the page table walker can only throw page faults if (lsu_is_store_q) begin - lsu_exception_o = { - riscv::STORE_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr}, - 1'b1 - }; + lsu_exception_o.cause = riscv::STORE_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr + }; end else begin - lsu_exception_o = { - riscv::LOAD_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr}, - 1'b1 - }; + lsu_exception_o.cause = riscv::LOAD_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr + }; end end @@ -512,15 +527,21 @@ module cva6_mmu_sv32 // an error makes the translation valid lsu_valid_o = 1'b1; // the page table walker can only throw page faults - lsu_exception_o = {riscv::LD_ACCESS_FAULT, ptw_bad_paddr[riscv::PLEN-1:2], 1'b1}; + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = ptw_bad_paddr[riscv::PLEN-1:2]; end end end // If translation is not enabled, check the paddr immediately against PMPs else if (lsu_req_q && !misaligned_ex_q.valid && !pmp_data_allow) begin if (lsu_is_store_q) begin - lsu_exception_o = {riscv::ST_ACCESS_FAULT, lsu_paddr_o[riscv::PLEN-1:2], 1'b1}; + lsu_exception_o.cause = riscv::ST_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = lsu_paddr_o[riscv::PLEN-1:2]; end else begin - lsu_exception_o = {riscv::LD_ACCESS_FAULT, lsu_paddr_o[riscv::PLEN-1:2], 1'b1}; + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = lsu_paddr_o[riscv::PLEN-1:2]; end end end diff --git a/core/mmu_sv39/mmu.sv b/core/mmu_sv39/mmu.sv index 39e9f34303..56994f260d 100644 --- a/core/mmu_sv39/mmu.sv +++ b/core/mmu_sv39/mmu.sv @@ -222,11 +222,12 @@ module mmu if (enable_translation_i) begin // we work with SV39 or SV32, so if VM is enabled, check that all bits [riscv::VLEN-1:riscv::SV-1] are equal if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, - {{riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, - 1'b1 - }; + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr + }; end icache_areq_o.fetch_valid = 1'b0; @@ -251,17 +252,19 @@ module mmu // we got an access error if (iaccess_err) begin // throw a page fault - icache_areq_o.fetch_exception = { - riscv::INSTR_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, - 1'b1 - }; + icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr + }; end else if (!pmp_instr_allow) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, - {{riscv::XLEN - riscv::PLEN{1'b0}}, icache_areq_i.fetch_vaddr}, - 1'b1 - }; + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr + }; end end else // --------- @@ -270,24 +273,28 @@ module mmu // watch out for exceptions happening during walking the page table if (ptw_active && walking_instr) begin icache_areq_o.fetch_valid = ptw_error | ptw_access_exception; - if (ptw_error) - icache_areq_o.fetch_exception = { - riscv::INSTR_PAGE_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}, 1'b1 - }; - else - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}, 1'b1 - }; + if (ptw_error) begin + icache_areq_o.fetch_exception.cause = riscv::INSTR_PAGE_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}; + end else begin + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, update_vaddr}; + end end end // if it didn't match any execute region throw an `Instruction Access Fault` // or: if we are not translating, check PMPs immediately on the paddr if ((!match_any_execute_region && !ptw_error) || (!enable_translation_i && !pmp_instr_allow)) begin - icache_areq_o.fetch_exception = { - riscv::INSTR_ACCESS_FAULT, - {{riscv::XLEN - riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr}, - 1'b1 - }; + icache_areq_o.fetch_exception.cause = riscv::INSTR_ACCESS_FAULT; + icache_areq_o.fetch_exception.valid = 1'b1; + if (CVA6Cfg.TvalEn) + icache_areq_o.fetch_exception.tval = { + {riscv::XLEN - riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr + }; end end @@ -388,36 +395,40 @@ module mmu // check if the page is write-able and we are not violating privileges // also check if the dirty flag is set if (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d) begin - lsu_exception_o = { - riscv::STORE_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; + lsu_exception_o.cause = riscv::STORE_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; // Check if any PMPs are violated end else if (!pmp_data_allow) begin - lsu_exception_o = { - riscv::ST_ACCESS_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; + lsu_exception_o.cause = riscv::ST_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; end // this is a load end else begin // check for sufficient access privileges - throw a page fault if necessary if (daccess_err) begin - lsu_exception_o = { - riscv::LOAD_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; + lsu_exception_o.cause = riscv::LOAD_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; // Check if any PMPs are violated end else if (!pmp_data_allow) begin - lsu_exception_o = { - riscv::LD_ACCESS_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q}, - 1'b1 - }; + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, lsu_vaddr_q + }; end end end else @@ -433,17 +444,19 @@ module mmu lsu_valid_o = 1'b1; // the page table walker can only throw page faults if (lsu_is_store_q) begin - lsu_exception_o = { - riscv::STORE_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr}, - 1'b1 - }; + lsu_exception_o.cause = riscv::STORE_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr + }; end else begin - lsu_exception_o = { - riscv::LOAD_PAGE_FAULT, - {{riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr}, - 1'b1 - }; + lsu_exception_o.cause = riscv::LOAD_PAGE_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = { + {riscv::XLEN - riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}}, update_vaddr + }; end end @@ -452,26 +465,28 @@ module mmu lsu_valid_o = 1'b1; // Any fault of the page table walk should be based of the original access type if (lsu_is_store_q) begin - lsu_exception_o = { - riscv::ST_ACCESS_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_vaddr_n}, 1'b1 - }; + lsu_exception_o.cause = riscv::ST_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_vaddr_n}; end else begin - lsu_exception_o = { - riscv::LD_ACCESS_FAULT, {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_vaddr_n}, 1'b1 - }; + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) + lsu_exception_o.tval = {{riscv::XLEN - riscv::VLEN{1'b0}}, lsu_vaddr_n}; end end end end // If translation is not enabled, check the paddr immediately against PMPs else if (lsu_req_q && !misaligned_ex_q.valid && !pmp_data_allow) begin if (lsu_is_store_q) begin - lsu_exception_o = { - riscv::ST_ACCESS_FAULT, {{riscv::XLEN - riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1 - }; + lsu_exception_o.cause = riscv::ST_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = {{riscv::XLEN - riscv::PLEN{1'b0}}, lsu_paddr_o}; end else begin - lsu_exception_o = { - riscv::LD_ACCESS_FAULT, {{riscv::XLEN - riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1 - }; + lsu_exception_o.cause = riscv::LD_ACCESS_FAULT; + lsu_exception_o.valid = 1'b1; + if (CVA6Cfg.TvalEn) lsu_exception_o.tval = {{riscv::XLEN - riscv::PLEN{1'b0}}, lsu_paddr_o}; end end end diff --git a/core/scoreboard.sv b/core/scoreboard.sv index 5ea29cdb4b..d5c06848e7 100644 --- a/core/scoreboard.sv +++ b/core/scoreboard.sv @@ -45,14 +45,16 @@ module scoreboard #( // instruction to put on top of scoreboard e.g.: top pointer // we can always put this instruction to the top unless we signal with asserted full_o - input ariane_pkg::scoreboard_entry_t decoded_instr_i, - input logic decoded_instr_valid_i, - output logic decoded_instr_ack_o, + input ariane_pkg::scoreboard_entry_t decoded_instr_i, + input logic [31:0] orig_instr_i, + input logic decoded_instr_valid_i, + output logic decoded_instr_ack_o, // instruction to issue logic, if issue_instr_valid and issue_ready is asserted, advance the issue pointer - output ariane_pkg::scoreboard_entry_t issue_instr_o, - output logic issue_instr_valid_o, - input logic issue_ack_i, + output ariane_pkg::scoreboard_entry_t issue_instr_o, + output logic [31:0] orig_instr_o, + output logic issue_instr_valid_o, + input logic issue_ack_i, // write-back port input ariane_pkg::bp_resolve_t resolved_branch_i, @@ -104,6 +106,7 @@ module scoreboard #( // an instruction is ready for issue if we have place in the issue FIFO and it the decoder says it is valid always_comb begin issue_instr_o = decoded_instr_i; + orig_instr_o = orig_instr_i; // make sure we assign the correct trans ID issue_instr_o.trans_id = issue_pointer_q; // we are ready if we are not full and don't have any unresolved branches, but it can be diff --git a/corev_apu/fpga/src/ariane_xilinx.sv b/corev_apu/fpga/src/ariane_xilinx.sv index 1a1f3c4a4c..7857e5d436 100644 --- a/corev_apu/fpga/src/ariane_xilinx.sv +++ b/corev_apu/fpga/src/ariane_xilinx.sv @@ -196,6 +196,7 @@ localparam config_pkg::cva6_cfg_t CVA6Cfg = '{ HaltAddress: dm::HaltAddress, ExceptionAddress: dm::ExceptionAddress, DmBaseAddress: ariane_soc::DebugBase, + TvalEn: bit'(cva6_config_pkg::CVA6ConfigTvalEn), NrPMPEntries: unsigned'(cva6_config_pkg::CVA6ConfigNrPMPEntries), PMPCfgRstVal: {16{64'h0}}, PMPAddrRstVal: {16{64'h0}},