mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-06-28 17:23:59 -04:00
csr_regfile: Fix irq/ex delegation in RVH (#2689)
In RVH, interrupts are currently delegated if hxdeleg is set but mxdeleg is not, violating the spec ("A trap/irq *that has been delegated to HS-mode (using mxdeleg)* is further delegated to VS-mode if the corresponding hxdeleg bit is set"). Fix and simplify the corresponding logic.
This commit is contained in:
parent
bca4e1544f
commit
e55f25d23c
1 changed files with 10 additions and 24 deletions
|
@ -1791,38 +1791,24 @@ module csr_regfile
|
||||||
// a m-mode trap might be delegated if we are taking it in S mode
|
// 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)
|
// 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(CVA6Cfg.XLEN) bits long (as we only support XLEN exceptions)
|
// the cause register can only be $clog2(CVA6Cfg.XLEN) bits long (as we only support XLEN exceptions)
|
||||||
if (CVA6Cfg.RVH) begin
|
if (CVA6Cfg.RVS) begin
|
||||||
if ((ex_i.cause[CVA6Cfg.XLEN-1] && mideleg_q[ex_i.cause[$clog2(
|
if ((ex_i.cause[CVA6Cfg.XLEN-1] && mideleg_q[ex_i.cause[$clog2(
|
||||||
CVA6Cfg.XLEN
|
CVA6Cfg.XLEN
|
||||||
)-1:0]] && ~hideleg_q[ex_i.cause[$clog2(
|
|
||||||
CVA6Cfg.XLEN
|
|
||||||
)-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2(
|
)-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2(
|
||||||
CVA6Cfg.XLEN
|
CVA6Cfg.XLEN
|
||||||
)-1:0]] && ~hedeleg_q[ex_i.cause[$clog2(
|
|
||||||
CVA6Cfg.XLEN
|
|
||||||
)-1:0]])) begin
|
)-1:0]])) begin
|
||||||
// traps never transition from a more-privileged mode to a less privileged mode
|
// traps never transition from a more-privileged mode to a less privileged mode
|
||||||
// so if we are already in M mode, stay there
|
// 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;
|
trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S;
|
||||||
end else if ((ex_i.cause[CVA6Cfg.XLEN-1] && hideleg_q[ex_i.cause[$clog2(
|
if (CVA6Cfg.RVH) begin
|
||||||
CVA6Cfg.XLEN
|
if ((ex_i.cause[CVA6Cfg.XLEN-1] && hideleg_q[ex_i.cause[$clog2(
|
||||||
)-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && hedeleg_q[ex_i.cause[$clog2(
|
CVA6Cfg.XLEN
|
||||||
CVA6Cfg.XLEN
|
)-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && hedeleg_q[ex_i.cause[$clog2(
|
||||||
)-1:0]])) begin
|
CVA6Cfg.XLEN
|
||||||
trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S;
|
)-1:0]])) begin
|
||||||
// trap to VS only if it is the currently active mode
|
// trap to VS only if it is the currently active mode
|
||||||
trap_to_v = v_q;
|
trap_to_v = v_q;
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
if (CVA6Cfg.RVS) begin
|
|
||||||
if ((ex_i.cause[CVA6Cfg.XLEN-1] && mideleg_q[ex_i.cause[$clog2(
|
|
||||||
CVA6Cfg.XLEN
|
|
||||||
)-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2(
|
|
||||||
CVA6Cfg.XLEN
|
|
||||||
)-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
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue