[otbn,doc] Annotate instructions with the errors they can cause
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/data/base-insns.yml b/hw/ip/otbn/data/base-insns.yml
index 5ff9d2a..f0c0205 100644
--- a/hw/ip/otbn/data/base-insns.yml
+++ b/hw/ip/otbn/data/base-insns.yml
@@ -18,9 +18,9 @@
funct3: b000
rd: grd
opcode: b01100
- errs:
- - A `CALL_STACK` error from using `x1` as GRS1 or GRS2 when the call stack is empty.
- - A `CALL_STACK` error from using `x1` as GRD when the call stack is full.
+ errs: &enc-r-errors
+ - &grs12-call-stack A `CALL_STACK` error from using `x1` as `grs1` or `grs2` when the call stack is empty.
+ - &grd12-call-stack A `CALL_STACK` error from using `x1` as `grd` when the call stack is full and neither `grs1` nor `grs2` is `x1`.
- mnemonic: addi
rv32i: true
@@ -34,6 +34,9 @@
funct3: b000
rd: grd
opcode: b00100
+ errs: &enc-i-errors
+ - &grs1-call-stack A `CALL_STACK` error from using `x1` as `grs1` when the call stack is empty.
+ - &grd1-call-stack A `CALL_STACK` error from using `x1` as `grd` when the call stack is full and `grs1` is not `x1`.
- mnemonic: lui
rv32i: true
@@ -48,6 +51,8 @@
imm: imm
rd: grd
opcode: b01101
+ errs:
+ - &grd-call-stack A `CALL_STACK` error from using `x1` as `grd` when the call stack is full.
- mnemonic: sub
rv32i: true
@@ -62,6 +67,7 @@
funct3: b000
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: sll
rv32i: true
@@ -76,6 +82,7 @@
funct3: b001
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: slli
rv32i: true
@@ -95,6 +102,7 @@
funct3: b001
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: srl
rv32i: true
@@ -109,6 +117,7 @@
funct3: b101
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: srli
rv32i: true
@@ -126,6 +135,7 @@
funct3: b101
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: sra
rv32i: true
@@ -140,6 +150,7 @@
funct3: b101
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: srai
rv32i: true
@@ -157,6 +168,7 @@
funct3: b101
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: and
rv32i: true
@@ -171,6 +183,7 @@
funct3: b111
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: andi
rv32i: true
@@ -184,6 +197,7 @@
funct3: b111
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: or
rv32i: true
@@ -198,6 +212,7 @@
funct3: b110
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: ori
rv32i: true
@@ -211,6 +226,7 @@
funct3: b110
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: xor
rv32i: true
@@ -225,6 +241,7 @@
funct3: b100
rd: grd
opcode: b01100
+ errs: *enc-r-errors
- mnemonic: xori
rv32i: true
@@ -238,6 +255,7 @@
funct3: b100
rd: grd
opcode: b00100
+ errs: *enc-i-errors
- mnemonic: lw
rv32i: true
@@ -261,6 +279,10 @@
Unaligned loads are not supported.
Any address that is unaligned or is above the top of memory will result in an error (setting bit `bad_data_addr` in `ERR_BITS`).
This instruction takes 2 cycles.
+ errs:
+ - *grs1-call-stack
+ - &data-addr A `BAD_DATA_ADDR` error if the computed address is not a valid 4-byte aligned DMEM address.
+ - *grd1-call-stack
lsu:
type: mem-load
target: [offset, grs1]
@@ -287,6 +309,9 @@
Stores a 32b word in `grs2` to address `offset + grs1` in data memory.
Unaligned stores are not supported.
Any address that is unaligned or is above the top of memory will result in an error (setting bit `bad_data_addr` in `ERR_BITS`).
+ errs:
+ - *grs12-call-stack
+ - *data-addr
lsu:
type: mem-store
target: [offset, grs1]
@@ -312,6 +337,10 @@
rs1: grs1
funct3: b000
opcode: b11000
+ errs: &branch-errors
+ - *grs12-call-stack
+ - A `BAD_INSN_ADDR` error if the branch is taken and the computed address is not a valid PC.
+ - &loop-at-end A `LOOP` error if this instruction appears as the last instruction of a loop body.
- mnemonic: bne
rv32i: true
@@ -326,6 +355,7 @@
rs1: grs1
funct3: b001
opcode: b11000
+ errs: *branch-errors
- mnemonic: jal
rv32i: true
@@ -339,6 +369,10 @@
OTBN has a hardware managed call stack, accessed through `x1`, which should be used when calling subroutines.
Do so by using `x1` as the link register: `jal x1, <offset>`.
+ errs:
+ - *grd-call-stack
+ - &jump-bad-addr A `BAD_INSN_ADDR` error if the computed address is not a valid PC.
+ - *loop-at-end
encoding:
scheme: J
mapping:
@@ -359,6 +393,11 @@
This pops a link address from the call stack and branches to it.
To call a subroutine through a function pointer, use `jalr x1, <grs1>, 0`.
This jumps to the address in `<grs1>` and pushes the link address onto the call stack.
+ errs:
+ - *grs1-call-stack
+ - *grd1-call-stack
+ - *jump-bad-addr
+ - *loop-at-end
encoding:
scheme: I
mapping:
@@ -379,6 +418,9 @@
Other bits in the CSR are unaffected (though CSRs might have side effects when written).
If `csr` isn't the index of a valid CSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
+ errs:
+ - *grs1-call-stack
+ - &bad-csr An `ILLEGAL_INSN` error if `csr` doesn't name a valid CSR.
encoding:
scheme: I
mapping:
@@ -402,6 +444,10 @@
If `grd == x0` the instruction does not read the CSR or cause any read-related side-effects.
If `csr` isn't the index of a valid CSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
+ errs:
+ - *grs1-call-stack
+ - *grd1-call-stack
+ - *bad-csr
encoding:
scheme: I
mapping:
@@ -456,6 +502,10 @@
OTBN will stop on that instruction, setting bit `loop` in `ERR_BITS`.
For more information on how to correctly use `LOOP` see [loop nesting](../#loop-nesting).
+ errs:
+ - &grs-call-stack A `CALL_STACK` error from using `x1` as `grs` when the call stack is empty.
+ - A `LOOP` error if the value in `grs` is zero.
+ - *loop-at-end
encoding:
scheme: loop
mapping:
@@ -489,6 +539,9 @@
mapping:
bodysize: bodysize
iterations: iterations
+ errs:
+ - A `LOOP` error if `iterations` is zero.
+ - *loop-at-end
- mnemonic: nop
synopsis: No Operation
diff --git a/hw/ip/otbn/data/bignum-insns.yml b/hw/ip/otbn/data/bignum-insns.yml
index 7c0286c..db67e7d 100644
--- a/hw/ip/otbn/data/bignum-insns.yml
+++ b/hw/ip/otbn/data/bignum-insns.yml
@@ -37,6 +37,7 @@
Adds two WDR values, writes the result to the destination WDR and updates
flags. The content of the second source WDR can be shifted by an unsigned
immediate before it is consumed by the operation.
+ errs: []
encoding:
scheme: bnaf
mapping:
@@ -57,6 +58,7 @@
destination WDR, and updates the flags. The content of the second source
WDR can be shifted by an unsigned immediate before it is consumed by the
operation.
+ errs: []
encoding:
scheme: bnaf
mapping:
@@ -84,6 +86,7 @@
doc: |
Adds a zero-extended unsigned immediate to the value of a WDR, writes the
result to the destination WDR, and updates the flags.
+ errs: []
encoding:
scheme: bnai
mapping:
@@ -108,6 +111,7 @@
The intermediate result is small enough if both inputs are less than `MOD`.
Flags are not used or saved.
+ errs: []
encoding:
scheme: bnam
mapping:
@@ -168,6 +172,7 @@
Multiplies two `WLEN/4` WDR values, shifts the product by `acc_shift_imm` bits, and adds the result to the accumulator.
For versions of the instruction with writeback, see `BN.MULQACC.WO` and `BN.MULQACC.SO`.
+ errs: []
encoding:
scheme: bnaq
mapping:
@@ -201,6 +206,7 @@
doc: |
Multiplies two `WLEN/4` WDR values, shifts the product by `acc_shift_imm` bits, and adds the result to the accumulator.
Writes the resulting accumulator to `wrd`.
+ errs: []
encoding:
scheme: bnaq
mapping:
@@ -251,6 +257,7 @@
If `wrd_hwsel` is one (so the instruction is updating the upper half-word of `wrd`), it updates the `M` and `Z` flags and leaves `L` unchanged.
The `M` flag is set iff the top bit of the shifted-out result is zero.
The `Z` flag is left unchanged if the shifted-out result is zero and cleared if not.
+ errs: []
encoding:
scheme: bnaq
mapping:
@@ -281,6 +288,7 @@
doc: |
Subtracts the second WDR value from the first one, writes the result to the destination WDR and updates flags.
The content of the second source WDR can be shifted by an unsigned immediate before it is consumed by the operation.
+ errs: []
encoding:
scheme: bnaf
mapping:
@@ -325,6 +333,7 @@
doc: |
Subtracts a zero-extended unsigned immediate from the value of a WDR,
writes the result to the destination WDR, and updates the flags.
+ errs: []
encoding:
scheme: bnai
mapping:
@@ -349,6 +358,7 @@
This is guaranteed if both inputs are less than `MOD`.
Flags are not used or saved.
+ errs: []
encoding:
scheme: bnam
mapping:
@@ -377,6 +387,7 @@
Takes the values stored in registers referenced by `wrs1` and `wrs2` and stores the result in the register referenced by `wrd`.
The content of the second source register can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
+ errs: []
encoding:
scheme: bna
mapping:
@@ -397,6 +408,7 @@
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
+ errs: []
encoding:
scheme: bna
mapping:
@@ -424,6 +436,7 @@
Negates the value in `wrs` and stores the result in the register referenced by `wrd`.
The source value can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
+ errs: []
encoding:
scheme: bnan
mapping:
@@ -443,6 +456,7 @@
Takes the values stored in WDRs referenced by `wrs1` and `wrs2` and stores the result in the WDR referenced by `wrd`.
The content of the second source WDR can be shifted by an immediate before it is consumed by the operation.
The M, L and Z flags in flag group `flag_group` are updated with the result of the operation.
+ errs: []
encoding:
scheme: bna
mapping:
@@ -472,6 +486,7 @@
doc: |
Concatenates the content of WDRs referenced by `wrs1` and `wrs2` (`wrs1` forms the upper part), shifts it right by an immediate value and truncates to WLEN bit.
The result is stored in the WDR referenced by `wrd`.
+ errs: []
encoding:
scheme: bnr
mapping:
@@ -503,6 +518,7 @@
<wrd>, <wrs1>, <wrs2>, [FG<flag_group>.]<flag>
doc: |
Returns in the destination WDR the value of the first source WDR if the flag in the chosen flag group is set, otherwise returns the value of the second source WDR.
+ errs: []
encoding:
scheme: bns
mapping:
@@ -527,6 +543,7 @@
doc: |
Subtracts the second WDR value from the first one and updates flags.
This instruction is identical to BN.SUB, except that no result register is written.
+ errs: []
encoding:
scheme: bnc
mapping:
@@ -544,6 +561,7 @@
doc: |
Subtracts the second WDR value from the first one and updates flags.
This instruction is identical to BN.SUBB, except that no result register is written.
+ errs: []
encoding:
scheme: bnc
mapping:
@@ -607,6 +625,11 @@
type: mem-load
target: [offset, grs1]
bytes: 32
+ errs:
+ - A `CALL_STACK` error from using `x1` as `grs1` or `grd` when the call stack is empty.
+ - An `ILLEGAL_INSN` error if both `grd_inc` and `grs1_inc` are set.
+ - An `ILLEGAL_INSN` error if the value in GPR `grd` is greater than 31.
+ - &data-addr A `BAD_DATA_ADDR` error if the computed address is not a valid DMEM address aligned to WLEN bits.
encoding:
scheme: bnxid
mapping:
@@ -661,6 +684,11 @@
The memory address must be aligned to WLEN bits.
Any address that is unaligned or is above the top of memory results in an error (setting bit `bad_data_addr` in `ERR_BITS`).
Any `*grs2` value greater than 31 before executing the instruction results in an error (setting bit `illegal_insn` in `ERR_BITS`) and no store or optional increment occurring.
+ errs:
+ - A `CALL_STACK` error from using `x1` as `grs1` or `grs2` when the call stack is empty.
+ - An `ILLEGAL_INSN` error if both `grs1_inc` and `grs2_inc` are set.
+ - An `ILLEGAL_INSN` error if the value in GPR `grs2` is greater than 31.
+ - *data-addr
lsu:
type: mem-store
target: [offset, grs1]
@@ -683,6 +711,7 @@
mapping:
src: wrs
dst: wrd
+ errs: []
- mnemonic: bn.movr
synopsis: Copy content between WDRs (register-indirect addressing)
@@ -717,6 +746,10 @@
- If `grs_inc` is set, `grs` is updated to be `*grs + 1`.
Any `*grd` or `*grs` value greater than 31 results in an error (setting bit `illegal_insn` in `ERR_BITS`)
+ errs:
+ - A `CALL_STACK` error from using `x1` as `grs` or `grd` when the call stack is empty.
+ - An `ILLEGAL_INSN` error if either the value in GPR `grd` or the value in GPR `grs` is greater than 31.
+ - An `ILLEGAL_INSN` error if both `grs_inc` and `grd_inc` are set.
encoding:
scheme: bnmovr
mapping:
@@ -735,6 +768,8 @@
doc: |
Reads a WSR to a WDR.
If `wsr` isn't the index of a valid WSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
+ errs:
+ - &bad-wsr An `ILLEGAL_INSN` error if `wsr` doesn't name a valid WSR.
encoding:
scheme: wcsr
mapping:
@@ -757,6 +792,8 @@
doc: |
Writes a WDR to a WSR.
If `wsr` isn't the index of a valid WSR, this results in an error (setting bit `illegal_insn` in `ERR_BITS`).
+ errs:
+ - *bad-wsr
encoding:
scheme: wcsr
mapping:
diff --git a/hw/ip/otbn/util/yaml_to_doc.py b/hw/ip/otbn/util/yaml_to_doc.py
index 1460f6c..6ef8bd3 100755
--- a/hw/ip/otbn/util/yaml_to_doc.py
+++ b/hw/ip/otbn/util/yaml_to_doc.py
@@ -275,9 +275,9 @@
if insn.errs is not None:
parts.append(subhead + 'Errors\n')
if not insn.errs:
- parts.append('{} cannot cause any synchronous errors.\n'.format(mnem))
+ parts.append('{} cannot cause any software errors.\n'.format(mnem))
else:
- parts.append('{} might cause the following synchronous errors:\n'
+ parts.append('{} might cause the following software errors:\n'
.format(mnem))
for desc in insn.errs:
parts.append('- {}\n'.format(desc))