Add docs section for custom extensions

This commit is contained in:
Luke Wren 2022-08-28 15:50:26 +01:00
parent bf38d93d33
commit ce93c45e69
5 changed files with 11964 additions and 6641 deletions

View File

@ -14,6 +14,8 @@ include::sections/configuration_and_integration.adoc[]
include::sections/csr.adoc[]
include::sections/custom_extensions.adoc[]
[[debug-chapter]]
include::sections/debug.adoc[]

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@ These are both thin wrappers around the https://github.com/Wren6991/Hazard3/blob
The core module `hazard3_core` can also be instantiated directly, which may be more efficient if support for some other bus standard is desired. However, the interface of `hazard3_core` will not be documented and is not guaranteed to be stable.
[[config-parameters-section]]
=== Configuration Parameters
==== Reset state configuration

View File

@ -676,6 +676,7 @@ Note also that this is not the same as the "rule locking bypass" bit in the ePMP
=== Custom Power Control CSRs
[[reg-msleep]]
==== msleep
Address: `0xbf0`
@ -687,25 +688,4 @@ M-mode sleep control register.
| Bits | Name | Description
| 31:3 | - | RES0
| 2 | `deepsleep` | Deassert the clock request signal when entering the block or WFI state, and wait for clock acknowledge to reassert before leaving the block or WFI state.
| 1 | `block` | Write 1 to enter a WFI sleep state until either an unblock signal is received, or an interrupt is asserted that would cause a WFI to exit. Clears automatically when leaving the blocked state.
If an unblock signal has been received since the last time `block` was written to 1, the write is ignored. In other words, the blocked state falls through immediately in this case.
An unblock signal is received when another hart writes 1 to its `unblock` register, or for some other platform-specified reason.
| 0 | `unblock` | Write 1 to post an unblock signal to other harts in the system. Always reads back as 0.
|===
==== sleep
Address: `0x8f0`
U-mode sleep control register. A subset of the fields in `msleep`. If `mstatus.tw` is 1, then attempting to access this register from U-mode causes an illegal opcode trap.
[cols="10h,20h,~", options="header"]
|===
| Bits | Name | Description
| 31:2 | - | RES0
| 1 | `block` | U-mode access to the `msleep.block` bit
| 0 | `unblock` | U-mode access to the `msleep.unblock` bit
|===

View File

@ -0,0 +1,170 @@
== Custom Extensions
Hazard3 implements a small number of custom extensions. All are optional: custom extensions are only included if the relevant feature flags are set to 1 when instantiating the processor (<<config-parameters-section>>). Hazard3 is always a _conforming_ RISC-V implementation, and when these extensions are disabled it is also a _standard_ RISC-V implementation.
If any one of these extensions is enabled, the `x` bit in <<reg-misa>> is set to indicate the presence of a nonstandard extension.
=== Xh3power: Hazard3 power management
This extension adds a new M-mode CSR (<<reg-msleep>>), and two new hint instructions, `h3.block` and `h3.unblock`, in the `slt` nop-compatible custom hint space.
The hints are used to allow processors to sleep until woken by other processors in a multiprocessor environment. The `msleep` CSR is used to control some of the details of the processor's WFI sleep state, to trade off sleep power consumption against wakeup latency.
==== h3.block
Enter a WFI sleep state until either an unblock signal is received, or an interrupt is asserted that would cause a WFI to exit.
If `mstatus.tw` is set, attempting to execute this instruction in privilege modes lower than M-mode will generate an illegal instruction exception.
If an unblock signal has been received in the time since the last `h3.block`, this instruction executes as a `nop`, and the processor does not enter the sleep state. Conceptually, the sleep state falls through immediately because the corresponding unblock signal has already been received.
An unblock signal is received when a neighbouring processor (the exact definition of "neighbouring" being left to the implementor) executes an `h3.unblock` instruction, or for some other platform-defined reason.
This instruction is encoded as `slt x0, x0, x0`, which is part of the custom nop-compatible hint encoding space.
Example C macro:
----
#define __h3_block() asm ("slt x0, x0, x0")
----
Example assembly macro:
----
.macro h3.block
slt x0, x0, x0
.endm
----
==== h3.unblock
Post an unblock signal to other processors in the system. For example, to notify another processor that a work queue is now nonempty.
If `mstatus.tw` is set, attempting to execute this instruction in privilege modes lower than M-mode will generate an illegal instruction exception.
This instruction is encoded as `slt x0, x0, x1`, which is part of the custom nop-compatible hint encoding space.
Example C macro:
----
#define __h3_unblock() asm ("slt x0, x0, x1")
----
Example assembly macro:
----
.macro h3.unblock
slt x0, x0, x1
.endm
----
=== Xh3bextm: Hazard3 bit extract multiple
This is a small extension with multi-bit versions of the "bit extract" instructions from Zbs, used for extracting small, contiguous bit fields.
==== h3.bextm
"Bit extract multiple", a multi-bit version of the `bext` instruction from Zbs. Perform a right-shift followed by a mask of 1-8 LSBs.
Encoding (R-type):
[cols="10h,20h,20h,~", options="header"]
|===
| Bits | Name | Value | Description
| 31:29 | `funct7[6:4]` | `0b000` | RES0
| 28:26 | `size` | - | Number of ones in mask, values 0->7 encode 1->8 bits.
| 25 | `funct7[0]` | `0b0` | RES0, because aligns with `shamt[5]` of potential RV64 version of `h3.bextmi`
| 24:20 | `rs2` | - | Source register 2 (shift amount)
| 19:15 | `rs1` | - | Source register 1
| 14:12 | `funct3` | `0b000` | `h3.bextm`
| 11:7 | `rd` | - | Destination register
| 6:2 | `opc` | `0b01011`| custom0 opcode
| 1:0 | `size` | `0b11` | 32-bit instruction
|===
Example C macro (using GCC statement expressions):
----
// nbits must be a constant expression
#define __h3_bextm(nbits, rs1, rs2) ({\
uint32_t __h3_bextm_rd; \
asm (".insn r 0x0b, 0, %3, %0, %1, %2"\
: "=r" (__h3_bextm_rd) \
: "r" (rs1), "r" (rs2), "i" ((((nbits) - 1) & 0x7) << 1)\
); \
__h3_bextm_rd; \
})
----
Example assembly macro:
----
// rd = (rs1 >> rs2[4:0]) & ~(-1 << nbits)
.macro h3.bextm rd rs1 rs2 nbits
.if (\nbits < 1) || (\nbits > 8)
.err
.endif
#if NO_HAZARD3_CUSTOM
srl \rd, \rs1, \rs2
andi \rd, \rd, ((1 << \nbits) - 1)
#else
.insn r 0x0b, 0x0, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
#endif
.endm
----
==== h3.bextmi
Immediate variant of `h3.bextm`.
Encoding (I-type):
[cols="10h,20h,20h,~", options="header"]
|===
| Bits | Name | Value | Description
| 31:29 | `imm[11:9]` | `0b000` | RES0
| 28:26 | `size` | - | Number of ones in mask, values 0->7 encode 1->8 bits.
| 25 | `imm[5]` | `0b0` | RES0, for potential future RV64 version
| 24:20 | `shamt` | - | Shift amount, 0 through 31
| 19:15 | `rs1` | - | Source register 1
| 14:12 | `funct3` | `0b100` | `h3.bextmi`
| 11:7 | `rd` | - | Destination register
| 6:2 | `opc` | `0b01011`| custom0 opcode
| 1:0 | `size` | `0b11` | 32-bit instruction
|===
Example C macro (using GCC statement expressions):
----
// nbits and shamt must be constant expressions
#define __h3_bextmi(nbits, rs1, shamt) ({\
uint32_t __h3_bextmi_rd; \
asm (".insn i 0x0b, 0x4, %0, %1, %2"\
: "=r" (__h3_bextmi_rd) \
: "r" (rs1), "i" ((((nbits) - 1) & 0x7) << 6 | ((shamt) & 0x1f)) \
); \
__h3_bextmi_rd; \
})
----
Example assembly macro:
----
// rd = (rs1 >> shamt) & ~(-1 << nbits)
.macro h3.bextmi rd rs1 shamt nbits
.if (\nbits < 1) || (\nbits > 8)
.err
.endif
.if (\shamt < 0) || (\shamt > 31)
.err
.endif
#if NO_HAZARD3_CUSTOM
srli \rd, \rs1, \shamt
andi \rd, \rd, ((1 << \nbits) - 1)
#else
.insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
#endif
.endm
----