dcsr.stepie is unwired: single-step does not mask interrupts

Summary

dcsr.stepie is writable but has no effect. With an interrupt pending and enabled, single-stepping a non-branch instruction takes the interrupt mid-step regardless of stepie. Per the RISC-V Debug spec, stepie=0 must mask interrupts for the duration of a step.

Root cause

decoder.bsv chk_interrupt (~L79-152) gates pending interrupts on debug_mode only — there is no dcsr.stepie term. csrbox_grp2.bsv warlReg_dcsr_stepie is a writable pass-through with no consumer.

Evidence

  • stepie=0 and stepie=1 produce identical behavior: with a pending+enabled interrupt (e.g. CLINT MSI), the interrupt is taken mid-step, the stepped instruction never retires, the hart diverts to mtvec, and it re-halts with dcsr.cause=4 (step).
  • The edge case (stepping the instruction that enables MIE) defers correctly; no lost/double interrupt.

Expected

stepie=0 masks interrupts during a step (step exactly one instruction; leave the interrupt pending for a later normal resume). stepie=1 allows the interrupt during the step.

Suggested fix

One term in chk_interrupt: when dcsr.step && !dcsr.stepie, suppress take_interrupt. step/stepie are already available in the DebugStatus struct. (We are carrying this one-term patch locally and would prefer to drop it once it lands upstream.)

Question

Can dcsr.stepie be wired into the interrupt-take logic per the debug spec?