[otbn] Allow multiple errors in a single cycle in ISS This means we can't just raise an exception any more, which makes things a little more fiddly. Instead, any component of the state that might raise an error has an "errs" list, to which it appends an error if it sees one. These lists get concatenated in a tree, in much the same way as we gather up changes. After executing an instruction, the code checks whether there were any errors. If not, it commits pending changes. If there is an error, it figures out the correct value of ERR_BITS and stops. Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/dv/otbnsim/sim/insn.py b/hw/ip/otbn/dv/otbnsim/sim/insn.py index 594abee..2f2cc61 100644 --- a/hw/ip/otbn/dv/otbnsim/sim/insn.py +++ b/hw/ip/otbn/dv/otbnsim/sim/insn.py
@@ -4,7 +4,7 @@ from typing import Dict -from .alert import LoopError +from .alert import ERR_CODE_NO_ERROR, LoopError from .flags import FlagReg from .isa import (DecodeError, OTBNInsn, RV32RegReg, RV32RegImm, RV32ImmShift, insn_for_mnemonic, logical_byte_shift) @@ -315,7 +315,7 @@ def execute(self, state: OTBNState) -> None: # Set INTR_STATE.done and STATUS, reflecting the fact we've stopped. - state.stop(None) + state._stop(ERR_CODE_NO_ERROR) class LOOP(OTBNInsn): @@ -330,8 +330,9 @@ def execute(self, state: OTBNState) -> None: num_iters = state.gprs.get_reg(self.grs).read_unsigned() if num_iters == 0: - raise LoopError('loop count in x{} was zero' - .format(self.grs)) + state.on_error(LoopError('loop count in x{} was zero' + .format(self.grs))) + return state.loop_start(num_iters, self.bodysize)