mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
Parameterize TVAL to reduce size in embedded (#1784)
This commit is contained in:
parent
13a4a092ab
commit
fa101fae7a
30 changed files with 287 additions and 172 deletions
|
@ -1,3 +1,3 @@
|
|||
cv32a6_embedded:
|
||||
gates: 114319
|
||||
gates: 110519
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -93,6 +93,7 @@ module cva6_rvfi
|
|||
CVA6Cfg.BTBEntries,
|
||||
CVA6Cfg.BHTEntries,
|
||||
CVA6Cfg.DmBaseAddress,
|
||||
CVA6Cfg.TvalEn,
|
||||
CVA6Cfg.NrPMPEntries,
|
||||
CVA6Cfg.PMPCfgRstVal,
|
||||
CVA6Cfg.PMPAddrRstVal,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue