[otbn] Make stalling more explicit in instruction definitions
This is prompted by the fact that we couldn't properly model things
like faulting calls to BN.LID. We need to do some of the instruction
body on the first cycle (to spot that an address is bogus). However,
we can't run everything on the first cycle. For example accesses of
the RND WSR/CSR can't do their work until the data is available, and
this data isn't supplied by the Python simulator.
Solve the problem by splitting the execution over multiple calls to
the execute() method, using Python's "yield" statement to cause the
stall.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/doc/isa.md b/hw/ip/otbn/doc/isa.md
index 0c267e2..3d6dc8a 100644
--- a/hw/ip/otbn/doc/isa.md
+++ b/hw/ip/otbn/doc/isa.md
@@ -61,6 +61,9 @@
Memory stores are represented as `DMEM.store_u32(addr, value)` and `DMEM.store_u256(addr, value)`.
In all cases, memory values are interpreted as unsigned integers and, as for register accesses, the instruction descriptions are written to ensure that any value stored to memory is representable.
+Some instructions can stall for one or more cycles (those instructions that access memory, CSRs or WSRs).
+To represent this precisely in the pseudo-code, and the simulator reference model, such instructions execute a `yield` statement to stall the processor for a cycle.
+
There are a few other helper functions, defined here to avoid having to inline their bodies into each instruction.
```python3
def from_2s_complement(n: int) -> int: