[otbn] Split out ISA into a separate document
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/doc/_index.md b/hw/ip/otbn/doc/_index.md
index ce635c4..3425e63 100644
--- a/hw/ip/otbn/doc/_index.md
+++ b/hw/ip/otbn/doc/_index.md
@@ -25,7 +25,7 @@
* Full control-flow support with conditional branch and unconditional jump instructions, hardware loops, and hardware-managed call/return stacks.
* Reduced, security-focused instruction set architecture for easier verification and the prevention of data leaks.
* Built-in access to random numbers.
- Note: The (quality) properties of the provided random numbers it not specified currently; this gap in the specification will be addressed in a future revision.
+ Note: The (quality) properties of the provided random numbers are not currently specified; this gap in the specification will be addressed in a future revision.
## Description
@@ -47,7 +47,8 @@
# Instruction Set
-OTBN is a processor with a custom instruction set, which is described in this section.
+OTBN is a processor with a custom instruction set.
+The full ISA description can be found in our [ISA manual]({{< relref "hw/ip/otbn/doc/isa" >}}).
The instruction set is split into two groups:
* The **base instruction subset** operates on the 32b General Purpose Registers (GPRs).
@@ -55,9 +56,6 @@
The base instructions are inspired by RISC-V’s RV32I instruction set, but not compatible with it.
* The **big number instruction subset** operates on 256b Wide Data Registers (WDRs).
Its instructions are used for data processing.
- Also included are compare and select instructions to perform data-dependent control flow in a safe and constant time fashion.
-
-The subsequent sections describe first the processor state, followed by a description of the base and big number instruction subsets.
## Processor State
@@ -327,150 +325,6 @@
A WLEN bit wide accumulator used by the BN.MULQACC instruction.
-<!-- Documentation for the instructions in the ISA. Generated from ../data/insns.yml. -->
-## Base Instruction Subset
-
-{{< otbn_isa base >}}
-
-## Big Number Instruction Subset
-
-{{< otbn_isa bignum >}}
-
-## Pseudo-Code Functions for BN Instructions
-
-The instruction description uses Python-based pseudocode.
-Commonly used functions are defined once below.
-
-<div class="bd-callout bd-callout-warning">
- <h5>Note</h5>
-
- This "pseudo-code" is intended to be Python 3, and contains known inconsistencies at the moment.
- It will be further refined as we make progress in the implementation of a simulator using this syntax.
-</div>
-
-```python3
-class Flag(Enum):
- C: Bits[1]
- M: Bits[1]
- L: Bits[1]
- Z: Bits[1]
-
-class FlagGroup:
- C: Bits[1]
- M: Bits[1]
- L: Bits[1]
- Z: Bits[1]
-
- def set(self, flag: Flag, value: Bits[1]):
- assert flag in Flag
-
- if flag == Flag.C:
- self.C = value
- elif flag == Flag.M:
- self.M = value
- elif flag == Flag.L:
- self.L = value
- elif flag == Flag.Z:
- self.Z = value
-
- def get(self, flag: Flag):
- assert flag in Flag
-
- if flag == Flag.C:
- return self.C
- elif flag == Flag.M:
- return self.M
- elif flag == Flag.L:
- return self.L
- elif flag == Flag.Z:
- return self.Z
-
-
-class ShiftType(Enum):
- LSL = 0 # logical shift left
- LSR = 1 # logical shift right
-
-class HalfWord(Enum):
- LOWER = 0 # lower or less significant half-word
- UPPER = 1 # upper or more significant half-word
-
-def DecodeShiftType(st: Bits(1)) -> ShiftType:
- if st == 0:
- return ShiftType.LSL
- elif st == 1:
- return ShiftType.LSR
- else:
- raise UndefinedException()
-
-def DecodeFlagGroup(flag_group: Bits(1)) -> UInt:
- if flag_group > 1:
- raise UndefinedException()
- return UInt(flag_group)
-
-def DecodeFlag(flag: Bits(1)) -> Flag:
- if flag == 0:
- return ShiftType.C
- elif flag == 1:
- return ShiftType.M
- elif flag == 2:
- return ShiftType.L
- elif flag == 3:
- return ShiftType.Z
- else:
- raise UndefinedException()
-
-
-def ShiftReg(reg, shift_type, shift_bytes) -> Bits(N):
- if ShiftType == ShiftType.LSL:
- return GPR[reg] << shift_bytes << 3
- elif ShiftType == ShiftType.LSR:
- return GPR[reg] >> shift_bytes >> 3
-
-def AddWithCarry(a: Bits(WLEN), b: Bits(WLEN), carry_in: Bits(1)) -> (Bits(WLEN), FlagGroup):
- result: Bits[WLEN+1] = a + b + carry_in
-
- flags_out = FlagGroup()
- flags_out.C = result[WLEN]
- flags_out.L = result[0]
- flags_out.M = result[WLEN-1]
- flags_out.Z = (result[WLEN-1:0] == 0)
-
- return (result[WLEN-1:0], flags_out)
-
-def SubtractWithBorrow(a: Bits(WLEN), b: Bits(WLEN), borrow_in: Bits(1)) -> (Bits(WLEN), FlagGroup):
- result: Bits[WLEN+1] = a - b - borrow_in
-
- flags_out = FlagGroup()
- flags_out.C = result[WLEN]
- flags_out.L = result[0]
- flags_out.M = result[WLEN-1]
- flags_out.Z = (result[WLEN-1:0] == 0)
-
- return (result[WLEN-1:0], flags_out)
-
-def DecodeHalfWordSelect(hwsel: Bits(1)) -> HalfWord:
- if hwsel == 0:
- return HalfWord.LOWER
- elif hwsel == 1:
- return HalfWord.UPPER
- else:
- raise UndefinedException()
-
-def GetHalfWord(reg: integer, hwsel: HalfWord) -> Bits(WLEN/2):
- if hwsel == HalfWord.LOWER:
- return GPR[reg][WLEN/2-1:0]
- elif hwsel == HalfWord.UPPER:
- return GPR[reg][WLEN-1:WLEN/2]
-
-def LoadWlenWordFromMemory(byteaddr: integer) -> Bits(WLEN):
- wordaddr = byteaddr >> 5
- return DMEM[wordaddr]
-
-def StoreWlenWordToMemory(byteaddr: integer, storedata: Bits(WLEN)):
- wordaddr = byteaddr >> 5
- DMEM[wordaddr] = storedata
-```
-
# Theory of Operations
## Block Diagram
diff --git a/hw/ip/otbn/doc/isa.md b/hw/ip/otbn/doc/isa.md
new file mode 100644
index 0000000..504dcaa
--- /dev/null
+++ b/hw/ip/otbn/doc/isa.md
@@ -0,0 +1,157 @@
+---
+title: OpenTitan Big Number Accelerator (OTBN) Instruction Set Architecture
+---
+
+This document describes the instruction set for OTBN.
+For more details about the processor itself, see the [OTBN Technical Specification]({{< relref "hw/ip/otbn/doc" >}}).
+In particular, this document assumes knowledge of the *Processor State* section from that guide.
+
+The instruction set is split into *base* and *big number* subsets.
+The base subset (described first) is similar to RISC-V's RV32I instruction set.
+It also includes a hardware call stack and hardware loop instructions.
+The big number subset is designed to operate on 256b WDRs.
+It doesn't include any control flow instructions, and just supports load/store, logical and arithmetic operations.
+
+<!-- Documentation for the instructions in the ISA. Generated from ../data/insns.yml. -->
+# Base Instruction Subset
+
+{{< otbn_isa base >}}
+
+# Big Number Instruction Subset
+
+{{< otbn_isa bignum >}}
+
+# Pseudo-Code Functions for BN Instructions
+
+The instruction description uses Python-based pseudocode.
+Commonly used functions are defined once below.
+
+<div class="bd-callout bd-callout-warning">
+ <h5>Note</h5>
+
+ This "pseudo-code" is intended to be Python 3, and contains known inconsistencies at the moment.
+ It will be further refined as we make progress in the implementation of a simulator using this syntax.
+</div>
+
+```python3
+class Flag(Enum):
+ C: Bits[1]
+ M: Bits[1]
+ L: Bits[1]
+ Z: Bits[1]
+
+class FlagGroup:
+ C: Bits[1]
+ M: Bits[1]
+ L: Bits[1]
+ Z: Bits[1]
+
+ def set(self, flag: Flag, value: Bits[1]):
+ assert flag in Flag
+
+ if flag == Flag.C:
+ self.C = value
+ elif flag == Flag.M:
+ self.M = value
+ elif flag == Flag.L:
+ self.L = value
+ elif flag == Flag.Z:
+ self.Z = value
+
+ def get(self, flag: Flag):
+ assert flag in Flag
+
+ if flag == Flag.C:
+ return self.C
+ elif flag == Flag.M:
+ return self.M
+ elif flag == Flag.L:
+ return self.L
+ elif flag == Flag.Z:
+ return self.Z
+
+
+class ShiftType(Enum):
+ LSL = 0 # logical shift left
+ LSR = 1 # logical shift right
+
+class HalfWord(Enum):
+ LOWER = 0 # lower or less significant half-word
+ UPPER = 1 # upper or more significant half-word
+
+def DecodeShiftType(st: Bits(1)) -> ShiftType:
+ if st == 0:
+ return ShiftType.LSL
+ elif st == 1:
+ return ShiftType.LSR
+ else:
+ raise UndefinedException()
+
+def DecodeFlagGroup(flag_group: Bits(1)) -> UInt:
+ if flag_group > 1:
+ raise UndefinedException()
+ return UInt(flag_group)
+
+def DecodeFlag(flag: Bits(1)) -> Flag:
+ if flag == 0:
+ return ShiftType.C
+ elif flag == 1:
+ return ShiftType.M
+ elif flag == 2:
+ return ShiftType.L
+ elif flag == 3:
+ return ShiftType.Z
+ else:
+ raise UndefinedException()
+
+
+def ShiftReg(reg, shift_type, shift_bytes) -> Bits(N):
+ if ShiftType == ShiftType.LSL:
+ return GPR[reg] << shift_bytes << 3
+ elif ShiftType == ShiftType.LSR:
+ return GPR[reg] >> shift_bytes >> 3
+
+def AddWithCarry(a: Bits(WLEN), b: Bits(WLEN), carry_in: Bits(1)) -> (Bits(WLEN), FlagGroup):
+ result: Bits[WLEN+1] = a + b + carry_in
+
+ flags_out = FlagGroup()
+ flags_out.C = result[WLEN]
+ flags_out.L = result[0]
+ flags_out.M = result[WLEN-1]
+ flags_out.Z = (result[WLEN-1:0] == 0)
+
+ return (result[WLEN-1:0], flags_out)
+
+def SubtractWithBorrow(a: Bits(WLEN), b: Bits(WLEN), borrow_in: Bits(1)) -> (Bits(WLEN), FlagGroup):
+ result: Bits[WLEN+1] = a - b - borrow_in
+
+ flags_out = FlagGroup()
+ flags_out.C = result[WLEN]
+ flags_out.L = result[0]
+ flags_out.M = result[WLEN-1]
+ flags_out.Z = (result[WLEN-1:0] == 0)
+
+ return (result[WLEN-1:0], flags_out)
+
+def DecodeHalfWordSelect(hwsel: Bits(1)) -> HalfWord:
+ if hwsel == 0:
+ return HalfWord.LOWER
+ elif hwsel == 1:
+ return HalfWord.UPPER
+ else:
+ raise UndefinedException()
+
+def GetHalfWord(reg: integer, hwsel: HalfWord) -> Bits(WLEN/2):
+ if hwsel == HalfWord.LOWER:
+ return GPR[reg][WLEN/2-1:0]
+ elif hwsel == HalfWord.UPPER:
+ return GPR[reg][WLEN-1:WLEN/2]
+
+def LoadWlenWordFromMemory(byteaddr: integer) -> Bits(WLEN):
+ wordaddr = byteaddr >> 5
+ return DMEM[wordaddr]
+
+def StoreWlenWordToMemory(byteaddr: integer, storedata: Bits(WLEN)):
+ wordaddr = byteaddr >> 5
+ DMEM[wordaddr] = storedata
+```
diff --git a/hw/ip/otbn/util/yaml_to_doc.py b/hw/ip/otbn/util/yaml_to_doc.py
index 937ca8f..2d0119b 100755
--- a/hw/ip/otbn/util/yaml_to_doc.py
+++ b/hw/ip/otbn/util/yaml_to_doc.py
@@ -292,7 +292,7 @@
print('Failed to create output directory {!r}: {}.'
.format(args.out_dir, err))
- render_insns(insns, 3, args.out_dir)
+ render_insns(insns, 2, args.out_dir)
return 0