Code_coverage: condition RTL with the S-MODE parameter (#1574)

This commit is contained in:
AEzzejjari 2023-10-27 21:38:52 +01:00 committed by GitHub
parent 53d388071d
commit 4b67475fa4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 251 additions and 161 deletions

View file

@ -1,2 +1,2 @@
cv32a6_embedded:
gates: 127005
gates: 123953

View file

@ -162,7 +162,7 @@ module csr_regfile
| (riscv::XLEN'(1) << 8) // I - RV32I/64I/128I base ISA
| (riscv::XLEN'(1) << 12) // M - Integer Multiply/Divide extension
| (riscv::XLEN'(0) << 13) // N - User level interrupts supported
| (riscv::XLEN'(1) << 18) // S - Supervisor mode implemented
| (riscv::XLEN'(CVA6Cfg.RVS) << 18) // S - Supervisor mode implemented
| (riscv::XLEN'(1) << 20) // U - User mode implemented
| (riscv::XLEN'(CVA6Cfg.RVV) << 21) // V - Vector extension
| (riscv::XLEN'(CVA6Cfg.NSX) << 23) // X - Non-standard extensions present
@ -235,22 +235,44 @@ module csr_regfile
riscv::CSR_TDATA3: ; // not implemented
// supervisor registers
riscv::CSR_SSTATUS: begin
csr_rdata = mstatus_extended & ariane_pkg::SMODE_STATUS_READ_MASK[riscv::XLEN-1:0];
if (CVA6Cfg.RVS)
csr_rdata = mstatus_extended & ariane_pkg::SMODE_STATUS_READ_MASK[riscv::XLEN-1:0];
else read_access_exception = 1'b1;
end
riscv::CSR_SIE: csr_rdata = mie_q & mideleg_q;
riscv::CSR_SIP: csr_rdata = mip_q & mideleg_q;
riscv::CSR_STVEC: csr_rdata = stvec_q;
riscv::CSR_SCOUNTEREN: csr_rdata = scounteren_q;
riscv::CSR_SSCRATCH: csr_rdata = sscratch_q;
riscv::CSR_SEPC: csr_rdata = sepc_q;
riscv::CSR_SCAUSE: csr_rdata = scause_q;
riscv::CSR_STVAL: csr_rdata = stval_q;
riscv::CSR_SIE:
if (CVA6Cfg.RVS) csr_rdata = mie_q & mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_SIP:
if (CVA6Cfg.RVS) csr_rdata = mip_q & mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_STVEC:
if (CVA6Cfg.RVS) csr_rdata = stvec_q;
else read_access_exception = 1'b1;
riscv::CSR_SCOUNTEREN:
if (CVA6Cfg.RVS) csr_rdata = scounteren_q;
else read_access_exception = 1'b1;
riscv::CSR_SSCRATCH:
if (CVA6Cfg.RVS) csr_rdata = sscratch_q;
else read_access_exception = 1'b1;
riscv::CSR_SEPC:
if (CVA6Cfg.RVS) csr_rdata = sepc_q;
else read_access_exception = 1'b1;
riscv::CSR_SCAUSE:
if (CVA6Cfg.RVS) csr_rdata = scause_q;
else read_access_exception = 1'b1;
riscv::CSR_STVAL:
if (CVA6Cfg.RVS) csr_rdata = stval_q;
else read_access_exception = 1'b1;
riscv::CSR_SATP: begin
// intercept reads to SATP if in S-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm) begin
read_access_exception = 1'b1;
if (CVA6Cfg.RVS) begin
// intercept reads to SATP if in S-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm) begin
read_access_exception = 1'b1;
end else begin
csr_rdata = satp_q;
end
end else begin
csr_rdata = satp_q;
read_access_exception = 1'b1;
end
end
// machine mode registers
@ -259,8 +281,12 @@ module csr_regfile
if (riscv::XLEN == 32) csr_rdata = '0;
else read_access_exception = 1'b1;
riscv::CSR_MISA: csr_rdata = IsaCode;
riscv::CSR_MEDELEG: csr_rdata = medeleg_q;
riscv::CSR_MIDELEG: csr_rdata = mideleg_q;
riscv::CSR_MEDELEG:
if (CVA6Cfg.RVS) csr_rdata = medeleg_q;
else read_access_exception = 1'b1;
riscv::CSR_MIDELEG:
if (CVA6Cfg.RVS) csr_rdata = mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_MIE: csr_rdata = mie_q;
riscv::CSR_MTVEC: csr_rdata = mtvec_q;
riscv::CSR_MCOUNTEREN: csr_rdata = mcounteren_q;
@ -654,54 +680,82 @@ module csr_regfile
riscv::CSR_TDATA3: ; // not implemented
// sstatus is a subset of mstatus - mask it accordingly
riscv::CSR_SSTATUS: begin
mask = ariane_pkg::SMODE_STATUS_WRITE_MASK[riscv::XLEN-1:0];
mstatus_d = (mstatus_q & ~{{64-riscv::XLEN{1'b0}}, mask}) | {{64-riscv::XLEN{1'b0}}, (csr_wdata & mask)};
// hardwire to zero if floating point extension is not present
if (!CVA6Cfg.FpPresent) begin
mstatus_d.fs = riscv::Off;
if (CVA6Cfg.RVS) begin
mask = ariane_pkg::SMODE_STATUS_WRITE_MASK[riscv::XLEN-1:0];
mstatus_d = (mstatus_q & ~{{64-riscv::XLEN{1'b0}}, mask}) | {{64-riscv::XLEN{1'b0}}, (csr_wdata & mask)};
// hardwire to zero if floating point extension is not present
if (!CVA6Cfg.FpPresent) begin
mstatus_d.fs = riscv::Off;
end
// hardwire to zero if vector extension is not present
if (!CVA6Cfg.RVV) begin
mstatus_d.vs = riscv::Off;
end
// this instruction has side-effects
flush_o = 1'b1;
end else begin
update_access_exception = 1'b1;
end
// hardwire to zero if vector extension is not present
if (!CVA6Cfg.RVV) begin
mstatus_d.vs = riscv::Off;
end
// this instruction has side-effects
flush_o = 1'b1;
end
// even machine mode interrupts can be visible and set-able to supervisor
// if the corresponding bit in mideleg is set
riscv::CSR_SIE: begin
// the mideleg makes sure only delegate-able register (and therefore also only implemented registers) are written
mie_d = (mie_q & ~mideleg_q) | (csr_wdata & mideleg_q);
if (CVA6Cfg.RVS) begin
// the mideleg makes sure only delegate-able register (and therefore also only implemented registers) are written
mie_d = (mie_q & ~mideleg_q) | (csr_wdata & mideleg_q);
end else begin
update_access_exception = 1'b1;
end
end
riscv::CSR_SIP: begin
// only the supervisor software interrupt is write-able, iff delegated
mask = riscv::MIP_SSIP & mideleg_q;
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
if (CVA6Cfg.RVS) begin
// only the supervisor software interrupt is write-able, iff delegated
mask = riscv::MIP_SSIP & mideleg_q;
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
end else begin
update_access_exception = 1'b1;
end
end
riscv::CSR_STVEC: stvec_d = {csr_wdata[riscv::XLEN-1:2], 1'b0, csr_wdata[0]};
riscv::CSR_SCOUNTEREN: scounteren_d = {{riscv::XLEN - 32{1'b0}}, csr_wdata[31:0]};
riscv::CSR_SSCRATCH: sscratch_d = csr_wdata;
riscv::CSR_SEPC: sepc_d = {csr_wdata[riscv::XLEN-1:1], 1'b0};
riscv::CSR_SCAUSE: scause_d = csr_wdata;
riscv::CSR_STVAL: stval_d = csr_wdata;
riscv::CSR_STVEC:
if (CVA6Cfg.RVS) stvec_d = {csr_wdata[riscv::XLEN-1:2], 1'b0, csr_wdata[0]};
else update_access_exception = 1'b1;
riscv::CSR_SCOUNTEREN:
if (CVA6Cfg.RVS) scounteren_d = {{riscv::XLEN - 32{1'b0}}, csr_wdata[31:0]};
else update_access_exception = 1'b1;
riscv::CSR_SSCRATCH:
if (CVA6Cfg.RVS) sscratch_d = csr_wdata;
else update_access_exception = 1'b1;
riscv::CSR_SEPC:
if (CVA6Cfg.RVS) sepc_d = {csr_wdata[riscv::XLEN-1:1], 1'b0};
else update_access_exception = 1'b1;
riscv::CSR_SCAUSE:
if (CVA6Cfg.RVS) scause_d = csr_wdata;
else update_access_exception = 1'b1;
riscv::CSR_STVAL:
if (CVA6Cfg.RVS) stval_d = csr_wdata;
else update_access_exception = 1'b1;
// supervisor address translation and protection
riscv::CSR_SATP: begin
// intercept SATP writes if in S-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm) update_access_exception = 1'b1;
else begin
satp = riscv::satp_t'(csr_wdata);
// only make ASID_LEN - 1 bit stick, that way software can figure out how many ASID bits are supported
satp.asid = satp.asid & {{(riscv::ASIDW - AsidWidth) {1'b0}}, {AsidWidth{1'b1}}};
// only update if we actually support this mode
if (riscv::vm_mode_t'(satp.mode) == riscv::ModeOff ||
riscv::vm_mode_t'(satp.mode) == riscv::MODE_SV)
satp_d = satp;
if (CVA6Cfg.RVS) begin
// intercept SATP writes if in S-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm) update_access_exception = 1'b1;
else begin
satp = riscv::satp_t'(csr_wdata);
// only make ASID_LEN - 1 bit stick, that way software can figure out how many ASID bits are supported
satp.asid = satp.asid & {{(riscv::ASIDW - AsidWidth) {1'b0}}, {AsidWidth{1'b1}}};
// only update if we actually support this mode
if (riscv::vm_mode_t'(satp.mode) == riscv::ModeOff ||
riscv::vm_mode_t'(satp.mode) == riscv::MODE_SV)
satp_d = satp;
end
// changing the mode can have side-effects on address translation (e.g.: other instructions), re-fetch
// the next instruction by executing a flush
flush_o = 1'b1;
end else begin
update_access_exception = 1'b1;
end
// changing the mode can have side-effects on address translation (e.g.: other instructions), re-fetch
// the next instruction by executing a flush
flush_o = 1'b1;
end
riscv::CSR_MSTATUS: begin
@ -726,19 +780,27 @@ module csr_regfile
// machine exception delegation register
// 0 - 15 exceptions supported
riscv::CSR_MEDELEG: begin
mask = (1 << riscv::INSTR_ADDR_MISALIGNED) |
(1 << riscv::BREAKPOINT) |
(1 << riscv::ENV_CALL_UMODE) |
(1 << riscv::INSTR_PAGE_FAULT) |
(1 << riscv::LOAD_PAGE_FAULT) |
(1 << riscv::STORE_PAGE_FAULT);
medeleg_d = (medeleg_q & ~mask) | (csr_wdata & mask);
if (CVA6Cfg.RVS) begin
mask = (1 << riscv::INSTR_ADDR_MISALIGNED) |
(1 << riscv::BREAKPOINT) |
(1 << riscv::ENV_CALL_UMODE) |
(1 << riscv::INSTR_PAGE_FAULT) |
(1 << riscv::LOAD_PAGE_FAULT) |
(1 << riscv::STORE_PAGE_FAULT);
medeleg_d = (medeleg_q & ~mask) | (csr_wdata & mask);
end else begin
update_access_exception = 1'b1;
end
end
// machine interrupt delegation register
// we do not support user interrupt delegation
riscv::CSR_MIDELEG: begin
mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP;
mideleg_d = (mideleg_q & ~mask) | (csr_wdata & mask);
if (CVA6Cfg.RVS) begin
mask = riscv::MIP_SSIP | riscv::MIP_STIP | riscv::MIP_SEIP;
mideleg_d = (mideleg_q & ~mask) | (csr_wdata & mask);
end else begin
update_access_exception = 1'b1;
end
end
// mask the register so that unsupported interrupts can never be set
riscv::CSR_MIE: begin
@ -993,18 +1055,18 @@ module csr_regfile
// a m-mode trap might be delegated if we are taking it in S mode
// first figure out if this was an exception or an interrupt e.g.: look at bit (XLEN-1)
// the cause register can only be $clog2(riscv::XLEN) bits long (as we only support XLEN exceptions)
if ((ex_i.cause[riscv::XLEN-1] && mideleg_q[ex_i.cause[$clog2(
if (CVA6Cfg.RVS && ((ex_i.cause[riscv::XLEN-1] && mideleg_q[ex_i.cause[$clog2(
riscv::XLEN
)-1:0]]) || (~ex_i.cause[riscv::XLEN-1] && medeleg_q[ex_i.cause[$clog2(
riscv::XLEN
)-1:0]])) begin
)-1:0]]))) begin
// traps never transition from a more-privileged mode to a less privileged mode
// so if we are already in M mode, stay there
trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S;
end
// trap to supervisor mode
if (trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
if (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
// update sstatus
mstatus_d.sie = 1'b0;
mstatus_d.spie = mstatus_q.sie;
@ -1071,8 +1133,10 @@ module csr_regfile
set_debug_pc_o = dcsr_q.ebreakm;
end
riscv::PRIV_LVL_S: begin
debug_mode_d = dcsr_q.ebreaks;
set_debug_pc_o = dcsr_q.ebreaks;
if (CVA6Cfg.RVS) begin
debug_mode_d = dcsr_q.ebreaks;
set_debug_pc_o = dcsr_q.ebreaks;
end
end
riscv::PRIV_LVL_U: begin
debug_mode_d = dcsr_q.ebreaku;
@ -1136,7 +1200,7 @@ module csr_regfile
// ------------------------------
// Set the address translation at which the load and stores should occur
// we can use the previous values since changing the address translation will always involve a pipeline flush
if (ariane_pkg::MMU_PRESENT && mprv && riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV && (mstatus_q.mpp != riscv::PRIV_LVL_M))
if (ariane_pkg::MMU_PRESENT && mprv && CVA6Cfg.RVS && riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV && (mstatus_q.mpp != riscv::PRIV_LVL_M))
en_ld_st_translation_d = 1'b1;
else // otherwise we go with the regular settings
en_ld_st_translation_d = en_translation_o;
@ -1162,7 +1226,7 @@ module csr_regfile
mstatus_d.mpie = 1'b1;
end
if (sret) begin
if (CVA6Cfg.RVS && sret) begin
// return from exception, IF doesn't care from where we are returning
eret_o = 1'b1;
// return the previous supervisor interrupt enable flag
@ -1203,10 +1267,12 @@ module csr_regfile
CSR_CLEAR: csr_wdata = (~csr_wdata_i) & csr_rdata;
CSR_READ: csr_we = 1'b0;
SRET: begin
// the return should not have any write or read side-effects
csr_we = 1'b0;
csr_read = 1'b0;
sret = 1'b1; // signal a return from supervisor mode
if (CVA6Cfg.RVS) begin
// the return should not have any write or read side-effects
csr_we = 1'b0;
csr_read = 1'b0;
sret = 1'b1; // signal a return from supervisor mode
end
end
MRET: begin
// the return should not have any write or read side-effects
@ -1262,7 +1328,7 @@ module csr_regfile
if (csr_addr_i inside {[riscv::CSR_CYCLE : riscv::CSR_HPM_COUNTER_31]}) begin
unique case (priv_lvl_o)
riscv::PRIV_LVL_M: privilege_violation = 1'b0;
riscv::PRIV_LVL_S: privilege_violation = ~mcounteren_q[csr_addr_i[4:0]];
riscv::PRIV_LVL_S: if (CVA6Cfg.RVS) privilege_violation = ~mcounteren_q[csr_addr_i[4:0]];
riscv::PRIV_LVL_U:
privilege_violation = ~mcounteren_q[csr_addr_i[4:0]] & ~scounteren_q[csr_addr_i[4:0]];
endcase
@ -1313,7 +1379,7 @@ module csr_regfile
always_comb begin : priv_output
trap_vector_base_o = {mtvec_q[riscv::VLEN-1:2], 2'b0};
// output user mode stvec
if (trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
if (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
trap_vector_base_o = {stvec_q[riscv::VLEN-1:2], 2'b0};
end
@ -1329,13 +1395,13 @@ module csr_regfile
// activated for _that_ privilege level.
if (ex_i.cause[riscv::XLEN-1] &&
((trap_to_priv_lvl == riscv::PRIV_LVL_M && mtvec_q[0])
|| trap_to_priv_lvl == riscv::PRIV_LVL_S && stvec_q[0])) begin
|| (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S && stvec_q[0]))) begin
trap_vector_base_o[7:2] = ex_i.cause[5:0];
end
epc_o = mepc_q[riscv::VLEN-1:0];
// we are returning from supervisor mode, so take the sepc register
if (sret) begin
if (CVA6Cfg.RVS && sret) begin
epc_o = sepc_q[riscv::VLEN-1:0];
end
// we are returning from debug mode, to take the dpc register
@ -1358,8 +1424,10 @@ module csr_regfile
csr_rdata_o = csr_rdata | ({{riscv::XLEN - 1{1'b0}}, irq_i[1]} << riscv::IRQ_S_EXT);
// in supervisor mode we also need to check whether we delegated this bit
riscv::CSR_SIP: begin
csr_rdata_o = csr_rdata
| ({{riscv::XLEN-1{1'b0}}, (irq_i[1] & mideleg_q[riscv::IRQ_S_EXT])} << riscv::IRQ_S_EXT);
if (CVA6Cfg.RVS) begin
csr_rdata_o = csr_rdata
| ({{riscv::XLEN-1{1'b0}}, (irq_i[1] & mideleg_q[riscv::IRQ_S_EXT])} << riscv::IRQ_S_EXT);
end
end
default: ;
endcase
@ -1376,7 +1444,7 @@ module csr_regfile
assign asid_o = satp_q.asid[AsidWidth-1:0];
assign sum_o = mstatus_q.sum;
// we support bare memory addressing and SV39
assign en_translation_o = (riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV &&
assign en_translation_o = ((CVA6Cfg.RVS && riscv::vm_mode_t'(satp_q.mode) == riscv::MODE_SV) &&
priv_lvl_o != riscv::PRIV_LVL_M)
? 1'b1
: 1'b0;
@ -1402,43 +1470,45 @@ module csr_regfile
// sequential process
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
priv_lvl_q <= riscv::PRIV_LVL_M;
priv_lvl_q <= riscv::PRIV_LVL_M;
// floating-point registers
fcsr_q <= '0;
fcsr_q <= '0;
// debug signals
debug_mode_q <= 1'b0;
dcsr_q <= '0;
dcsr_q.prv <= riscv::PRIV_LVL_M;
dcsr_q.xdebugver <= 4'h4;
dpc_q <= '0;
dscratch0_q <= {riscv::XLEN{1'b0}};
dscratch1_q <= {riscv::XLEN{1'b0}};
debug_mode_q <= 1'b0;
dcsr_q <= '0;
dcsr_q.prv <= riscv::PRIV_LVL_M;
dcsr_q.xdebugver <= 4'h4;
dpc_q <= '0;
dscratch0_q <= {riscv::XLEN{1'b0}};
dscratch1_q <= {riscv::XLEN{1'b0}};
// machine mode registers
mstatus_q <= 64'b0;
mstatus_q <= 64'b0;
// set to boot address + direct mode + 4 byte offset which is the initial trap
mtvec_rst_load_q <= 1'b1;
mtvec_q <= '0;
medeleg_q <= {riscv::XLEN{1'b0}};
mideleg_q <= {riscv::XLEN{1'b0}};
mip_q <= {riscv::XLEN{1'b0}};
mie_q <= {riscv::XLEN{1'b0}};
mepc_q <= {riscv::XLEN{1'b0}};
mcause_q <= {riscv::XLEN{1'b0}};
mcounteren_q <= {riscv::XLEN{1'b0}};
mscratch_q <= {riscv::XLEN{1'b0}};
mtval_q <= {riscv::XLEN{1'b0}};
dcache_q <= {{riscv::XLEN - 1{1'b0}}, 1'b1};
icache_q <= {{riscv::XLEN - 1{1'b0}}, 1'b1};
mcountinhibit_q <= '0;
acc_cons_q <= {{riscv::XLEN - 1{1'b0}}, CVA6Cfg.EnableAccelerator};
mtvec_rst_load_q <= 1'b1;
mtvec_q <= '0;
mip_q <= {riscv::XLEN{1'b0}};
mie_q <= {riscv::XLEN{1'b0}};
mepc_q <= {riscv::XLEN{1'b0}};
mcause_q <= {riscv::XLEN{1'b0}};
mcounteren_q <= {riscv::XLEN{1'b0}};
mscratch_q <= {riscv::XLEN{1'b0}};
mtval_q <= {riscv::XLEN{1'b0}};
dcache_q <= {{riscv::XLEN - 1{1'b0}}, 1'b1};
icache_q <= {{riscv::XLEN - 1{1'b0}}, 1'b1};
mcountinhibit_q <= '0;
acc_cons_q <= {{riscv::XLEN - 1{1'b0}}, CVA6Cfg.EnableAccelerator};
// supervisor mode registers
sepc_q <= {riscv::XLEN{1'b0}};
scause_q <= {riscv::XLEN{1'b0}};
stvec_q <= {riscv::XLEN{1'b0}};
scounteren_q <= {riscv::XLEN{1'b0}};
sscratch_q <= {riscv::XLEN{1'b0}};
stval_q <= {riscv::XLEN{1'b0}};
satp_q <= {riscv::XLEN{1'b0}};
if (CVA6Cfg.RVS) begin
medeleg_q <= {riscv::XLEN{1'b0}};
mideleg_q <= {riscv::XLEN{1'b0}};
sepc_q <= {riscv::XLEN{1'b0}};
scause_q <= {riscv::XLEN{1'b0}};
stvec_q <= {riscv::XLEN{1'b0}};
scounteren_q <= {riscv::XLEN{1'b0}};
sscratch_q <= {riscv::XLEN{1'b0}};
stval_q <= {riscv::XLEN{1'b0}};
satp_q <= {riscv::XLEN{1'b0}};
end
// timer and counters
cycle_q <= 64'b0;
instret_q <= 64'b0;
@ -1450,40 +1520,42 @@ module csr_regfile
pmpcfg_q <= '0;
pmpaddr_q <= '0;
end else begin
priv_lvl_q <= priv_lvl_d;
priv_lvl_q <= priv_lvl_d;
// floating-point registers
fcsr_q <= fcsr_d;
fcsr_q <= fcsr_d;
// debug signals
debug_mode_q <= debug_mode_d;
dcsr_q <= dcsr_d;
dpc_q <= dpc_d;
dscratch0_q <= dscratch0_d;
dscratch1_q <= dscratch1_d;
debug_mode_q <= debug_mode_d;
dcsr_q <= dcsr_d;
dpc_q <= dpc_d;
dscratch0_q <= dscratch0_d;
dscratch1_q <= dscratch1_d;
// machine mode registers
mstatus_q <= mstatus_d;
mtvec_rst_load_q <= 1'b0;
mtvec_q <= mtvec_d;
medeleg_q <= medeleg_d;
mideleg_q <= mideleg_d;
mip_q <= mip_d;
mie_q <= mie_d;
mepc_q <= mepc_d;
mcause_q <= mcause_d;
mcounteren_q <= mcounteren_d;
mscratch_q <= mscratch_d;
mtval_q <= mtval_d;
dcache_q <= dcache_d;
icache_q <= icache_d;
mcountinhibit_q <= mcountinhibit_d;
acc_cons_q <= acc_cons_d;
mstatus_q <= mstatus_d;
mtvec_rst_load_q <= 1'b0;
mtvec_q <= mtvec_d;
mip_q <= mip_d;
mie_q <= mie_d;
mepc_q <= mepc_d;
mcause_q <= mcause_d;
mcounteren_q <= mcounteren_d;
mscratch_q <= mscratch_d;
mtval_q <= mtval_d;
dcache_q <= dcache_d;
icache_q <= icache_d;
mcountinhibit_q <= mcountinhibit_d;
acc_cons_q <= acc_cons_d;
// supervisor mode registers
sepc_q <= sepc_d;
scause_q <= scause_d;
stvec_q <= stvec_d;
scounteren_q <= scounteren_d;
sscratch_q <= sscratch_d;
stval_q <= stval_d;
satp_q <= satp_d;
if (CVA6Cfg.RVS) begin
medeleg_q <= medeleg_d;
mideleg_q <= mideleg_d;
sepc_q <= sepc_d;
scause_q <= scause_d;
stvec_q <= stvec_d;
scounteren_q <= scounteren_d;
sscratch_q <= sscratch_d;
stval_q <= stval_d;
satp_q <= satp_d;
end
// timer and counters
cycle_q <= cycle_d;
instret_q <= instret_d;

View file

@ -194,6 +194,7 @@ module cva6
unsigned'(NrRgprPorts),
unsigned'(NrWbPorts),
bit'(EnableAccelerator),
CVA6Cfg.RVS,
CVA6Cfg.HaltAddress,
CVA6Cfg.ExceptionAddress,
CVA6Cfg.RASDepth,
@ -1306,7 +1307,7 @@ module cva6
else begin
case (priv_lvl)
riscv::PRIV_LVL_M: mode = "M";
riscv::PRIV_LVL_S: mode = "S";
riscv::PRIV_LVL_S: if(CVA6Cfg.RVS) mode = "S";
riscv::PRIV_LVL_U: mode = "U";
default: ; // Do nothing
endcase

View file

@ -143,19 +143,21 @@ module decoder
12'b1: ebreak = 1'b1;
// SRET
12'b1_0000_0010: begin
instruction_o.op = ariane_pkg::SRET;
// check privilege level, SRET can only be executed in S and M mode
// we'll just decode an illegal instruction if we are in the wrong privilege level
if (priv_lvl_i == riscv::PRIV_LVL_U) begin
illegal_instr = 1'b1;
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
end
// if we are in S-Mode and Trap SRET (tsr) is set -> trap on illegal instruction
if (priv_lvl_i == riscv::PRIV_LVL_S && tsr_i) begin
illegal_instr = 1'b1;
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
if (CVA6Cfg.RVS) begin
instruction_o.op = ariane_pkg::SRET;
// check privilege level, SRET can only be executed in S and M mode
// we'll just decode an illegal instruction if we are in the wrong privilege level
if (priv_lvl_i == riscv::PRIV_LVL_U) begin
illegal_instr = 1'b1;
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
end
// if we are in S-Mode and Trap SRET (tsr) is set -> trap on illegal instruction
if (priv_lvl_i == riscv::PRIV_LVL_S && tsr_i) begin
illegal_instr = 1'b1;
// do not change privilege level if this is an illegal instruction
instruction_o.op = ariane_pkg::ADD;
end
end
end
// MRET
@ -163,7 +165,7 @@ module decoder
instruction_o.op = ariane_pkg::MRET;
// check privilege level, MRET can only be executed in M mode
// otherwise we decode an illegal instruction
if (priv_lvl_i inside {riscv::PRIV_LVL_U, riscv::PRIV_LVL_S})
if ((CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S) || priv_lvl_i == riscv::PRIV_LVL_U)
illegal_instr = 1'b1;
end
// DRET
@ -177,7 +179,7 @@ module decoder
if (ENABLE_WFI) instruction_o.op = ariane_pkg::WFI;
// if timeout wait is set, trap on an illegal instruction in S Mode
// (after 0 cycles timeout)
if (priv_lvl_i == riscv::PRIV_LVL_S && tw_i) begin
if (CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S && tw_i) begin
illegal_instr = 1'b1;
instruction_o.op = ariane_pkg::ADD;
end
@ -192,10 +194,11 @@ module decoder
if (instr.instr[31:25] == 7'b1001) begin
// check privilege level, SFENCE.VMA can only be executed in M/S mode
// otherwise decode an illegal instruction
illegal_instr = ((priv_lvl_i inside {riscv::PRIV_LVL_M, riscv::PRIV_LVL_S}) && instr.itype.rd == '0) ? 1'b0 : 1'b1;
illegal_instr = (((CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S) || priv_lvl_i == riscv::PRIV_LVL_M) && instr.itype.rd == '0) ? 1'b0 : 1'b1;
instruction_o.op = ariane_pkg::SFENCE_VMA;
// check TVM flag and intercept SFENCE.VMA call if necessary
if (priv_lvl_i == riscv::PRIV_LVL_S && tvm_i) illegal_instr = 1'b1;
if (CVA6Cfg.RVS && priv_lvl_i == riscv::PRIV_LVL_S && tvm_i)
illegal_instr = 1'b1;
end else begin
illegal_instr = 1'b1;
end
@ -1317,7 +1320,7 @@ module decoder
// depending on the privilege mode, set the appropriate cause
case (priv_lvl_i)
riscv::PRIV_LVL_M: instruction_o.ex.cause = riscv::ENV_CALL_MMODE;
riscv::PRIV_LVL_S: instruction_o.ex.cause = riscv::ENV_CALL_SMODE;
riscv::PRIV_LVL_S: if (CVA6Cfg.RVS) instruction_o.ex.cause = riscv::ENV_CALL_SMODE;
riscv::PRIV_LVL_U: instruction_o.ex.cause = riscv::ENV_CALL_UMODE;
default: ; // this should not happen
endcase
@ -1390,7 +1393,7 @@ module decoder
// mode equals the delegated privilege mode (S or U) and that modes interrupt enable bit
// (SIE or UIE in mstatus) is set, or if the current privilege mode is less than the delegated privilege mode.
if (irq_ctrl_i.mideleg[interrupt_cause[$clog2(riscv::XLEN)-1:0]]) begin
if ((irq_ctrl_i.sie && priv_lvl_i == riscv::PRIV_LVL_S) || priv_lvl_i == riscv::PRIV_LVL_U) begin
if ((CVA6Cfg.RVS && irq_ctrl_i.sie && priv_lvl_i == riscv::PRIV_LVL_S) || priv_lvl_i == riscv::PRIV_LVL_U) begin
instruction_o.ex.valid = 1'b1;
instruction_o.ex.cause = interrupt_cause;
end

View file

@ -71,6 +71,7 @@ package config_pkg;
int unsigned NrRgprPorts;
int unsigned NrWbPorts;
bit EnableAccelerator;
bit RVS; //Supervisor mode
// Debug Module
// address to which a hart should jump when it was requested to halt
logic [63:0] HaltAddress;

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -105,6 +105,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(0),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -105,6 +105,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -113,6 +113,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -106,6 +106,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -105,6 +105,7 @@ package cva6_config_pkg;
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: 64'h800,
ExceptionAddress: 64'h808,
RASDepth: unsigned'(CVA6ConfigRASDepth),

View file

@ -190,6 +190,7 @@ localparam config_pkg::cva6_cfg_t CVA6Cfg = '{
NrRgprPorts: unsigned'(0),
NrWbPorts: unsigned'(0),
EnableAccelerator: bit'(0),
RVS: bit'(1),
HaltAddress: dm::HaltAddress,
ExceptionAddress: dm::ExceptionAddress,
DmBaseAddress: ariane_soc::DebugBase,