Reorganise CSR section of docs
This commit is contained in:
parent
c5e85dea4c
commit
ebe87dce46
17343
doc/hazard3.pdf
17343
doc/hazard3.pdf
File diff suppressed because it is too large
Load Diff
|
@ -2,25 +2,24 @@
|
|||
|
||||
The RISC-V privileged specification affords flexibility as to which CSRs are implemented, and how they behave. This section documents the concrete behaviour of Hazard3's standard and nonstandard M-mode CSRs, as implemented.
|
||||
|
||||
NOTE: All CSR addresses not listed in this section are unimplemented. Accessing an unimplemented CSR will cause an illegal instruction exception (`mcause` = 2). This includes all U-mode and S-mode CSRs.
|
||||
All CSRs are 32-bit; MXLEN is fixed at 32 bits on Hazard3. All CSR addresses not listed in this section are unimplemented. Accessing an unimplemented CSR will cause an illegal instruction exception (`mcause` = 2). This includes all U-mode and S-mode CSRs.
|
||||
|
||||
All CSRs are 32-bit; MXLEN is fixed at 32 bits on Hazard3.
|
||||
|
||||
|
||||
=== Standard M-mode CSRs
|
||||
|
||||
IMPORTANT: The https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMFDQC-and-Priv-v1.11/riscv-privileged-20190608.pdf[RISC-V Privileged Specification] should be your primary reference for writing software to run on Hazard3. This section specifies those details which are left implementation-defined by the RISC-V Privileged Specification, for sake of completeness, but portable RISC-V software should not rely on these details.
|
||||
|
||||
=== Standard M-mode Identification CSRs
|
||||
|
||||
==== mvendorid
|
||||
|
||||
Address: `0xf11`
|
||||
|
||||
Vendor identifier. Read-only, configurable constant.
|
||||
Vendor identifier. Read-only, configurable constant. Should contain either all-zeroes, or a valid JEDEC JEP106 vendor ID using the encoding in the RISC-V specification.
|
||||
|
||||
[cols="10h,20h,~", options="header"]
|
||||
|===
|
||||
| Bits | Name | Description
|
||||
| 31:0 | - | Should contain either all-zeroes, or a valid JEDEC JEP106 vendor ID using the encoding in the RISC-V specification (_not_ the same as a JTAG IDCODE)
|
||||
| 31:7 | `bank` | The number of continuation codes in the vendor JEP106 ID. _One less than the JEP106 bank number._
|
||||
| 6:0 | `offset` | Vendor ID within the specified bank. LSB (parity) is not stored.
|
||||
|===
|
||||
|
||||
==== marchid
|
||||
|
@ -73,6 +72,23 @@ Pointer to configuration data structure. Read-only, configurable constant.
|
|||
| 31:0 | - | Either pointer to configuration data structure, containing information about the harts and system, or all-zeroes. At least 4-byte-aligned.
|
||||
|===
|
||||
|
||||
==== misa
|
||||
|
||||
Address: `0x301`
|
||||
|
||||
Read-only, constant. Value depends on which ISA extensions Hazard3 is configured with. The table below lists the fields which are _not_ always hardwired to 0:
|
||||
|
||||
[cols="10h,20h,~", options="header"]
|
||||
|===
|
||||
| Bits | Name | Description
|
||||
| 31:30 | `mxl` | Always `0x1`. Indicates this is a 32-bit processor.
|
||||
| 23 | `x` | 1 if the core is configured to support trap-handling, otherwise 0. Hazard3 has nonstandard CSRs to enable/disable external interrupts on a per-interrupt basis, see <<reg-meie0>> and <<reg-meip0>>. The `misa.x` bit must be set to indicate their presence. Hazard3 does not implement any custom instructions.
|
||||
| 12 | `m` | 1 if the M extension is present, otherwise 0.
|
||||
| 2 | `c` | 1 if the C extension is present, otherwise 0.
|
||||
|===
|
||||
|
||||
=== Standard M-mode Trap Handling CSRs
|
||||
|
||||
==== mstatus
|
||||
|
||||
Address: `0x300`
|
||||
|
@ -91,22 +107,8 @@ The below table lists the fields which are _not_ hardwired to 0:
|
|||
|
||||
Address: `0x310`
|
||||
|
||||
This CSR is present, but it is entirely hardwired to zero. Its presence is required for compliance.
|
||||
Hardwired to 0.
|
||||
|
||||
==== misa
|
||||
|
||||
Address: `0x301`
|
||||
|
||||
Read-only, constant. Value depends on which ISA extensions Hazard3 is configured with. The table below lists the fields which are _not_ always hardwired to 0:
|
||||
|
||||
[cols="10h,20h,~", options="header"]
|
||||
|===
|
||||
| Bits | Name | Description
|
||||
| 31:30 | `mxl` | Always `0x1`. Indicates this is a 32-bit processor.
|
||||
| 23 | `x` | 1 if the core is configured to support trap-handling, otherwise 0. Hazard3 has nonstandard CSRs to enable/disable external interrupts on a per-interrupt basis, see <<reg-meie0>> and <<reg-meip0>>. The `misa.x` bit must be set to indicate their presence. Hazard3 does not implement any custom instructions.
|
||||
| 12 | `m` | 1 if the M extension is present, otherwise 0.
|
||||
| 2 | `c` | 1 if the C extension is present, otherwise 0.
|
||||
|===
|
||||
|
||||
==== medeleg
|
||||
|
||||
|
@ -175,14 +177,6 @@ NOTE: In the RISC-V specification, `mode` is a 2-bit write-any read-legal field
|
|||
|
||||
NOTE: Hazard3 has an additional nonstandard vectoring mode, where external interrupts are each separated into distinct vectors and `mcause` values. This is enabled through the implementation-defined control register, <<reg-midcr>>, since the RISC-V specification reserves `mtvec.mode == 2, 3` for future standard use.
|
||||
|
||||
==== mcounteren
|
||||
|
||||
Address: `0x306`
|
||||
|
||||
Unimplemented, as only M-mode is supported. Access will cause an illegal instruction exception.
|
||||
|
||||
Not to be confused with <<reg-mcountinhibit>>.
|
||||
|
||||
==== mscratch
|
||||
|
||||
Address: `0x340`
|
||||
|
@ -242,6 +236,16 @@ Address: `0x343`
|
|||
|
||||
Hardwired to 0.
|
||||
|
||||
==== mcounteren
|
||||
|
||||
Address: `0x306`
|
||||
|
||||
Unimplemented, as only M-mode is supported. Access will cause an illegal instruction exception.
|
||||
|
||||
Not to be confused with <<reg-mcountinhibit>>.
|
||||
|
||||
=== Standard Memory Protection
|
||||
|
||||
==== pmpcfg0...3
|
||||
|
||||
Address: `0x3a0` through `0x3a3`
|
||||
|
@ -254,6 +258,8 @@ Address: `0x3b0` through `0x3bf`
|
|||
|
||||
Unimplemented. Access will cause an illegal instruction exception.
|
||||
|
||||
=== Standard M-mode Performance Counters
|
||||
|
||||
==== mcycle
|
||||
|
||||
Address: `0xb00`
|
||||
|
@ -313,6 +319,8 @@ Address: `0x323` through `0x33f`
|
|||
|
||||
Hardwired to 0.
|
||||
|
||||
=== Standard Trigger CSRs
|
||||
|
||||
==== tselect
|
||||
|
||||
Address: `0x7a0`
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
== Debug
|
||||
|
||||
Hazard3, along with its external debug components, implements version 0.13.2 of the RISC-V debug specification. The goals of this implementation are:
|
||||
|
||||
* Minimal impact on core timing when present
|
||||
* No external components which need integrating at the other end of your bus fabric -- just slap the Debug Module onto the core and away you go
|
||||
* Efficient block data transfers to target RAM for faster edit-compile-run cycle
|
||||
|
||||
Hazard3's debug support implements the following:
|
||||
Hazard3, along with its external debug components, implements version 0.13.2 of the RISC-V debug specification. It supports the following:
|
||||
|
||||
* Run/halt/reset control as required
|
||||
* Abstract GPR access as required
|
||||
|
@ -22,33 +16,23 @@ Hazard3's Debug Module has the following interfaces:
|
|||
* A downstream Hazard3-specific interface to one or more cores _(multicore support is experimental)_
|
||||
* Some reset request/acknowledge signals which require careful handshaking with system-level reset logic
|
||||
|
||||
The Debug Module _must_ be connected directly to the processors without intervening registers. This implies the Debug Module is in the same clock domain as the processors, so multiple processors on the same Debug Module must share a common clock. This is shown in the example topology below.
|
||||
This is shown in the example topology below.
|
||||
|
||||
image::diagrams/debug_topology.png[pdfwidth=50%]
|
||||
|
||||
Upstream of the Debug Module is at least one Debug Transport Module, which bridges some host-facing interface such as JTAG to the APB Debug Module Interface. An APB arbiter could be inserted here, to allow multiple transports to be used, provided the host(s) avoid using multiple transports concurrently.
|
||||
The Debug Module _must_ be connected directly to the processors without intervening registers. This implies the Debug Module is in the same clock domain as the processors, so multiple processors on the same Debug Module must share a common clock.
|
||||
|
||||
Hazard3 provides an implementation of a standard RISC-V JTAG-DTM, but any APB master could be used. The Debug Module requires at least 7 bits of word addressing, i.e. 9 bits of byte address space.
|
||||
Upstream of the Debug Module is at least one Debug Transport Module, which bridges some host-facing interface such as JTAG to the APB Debug Module Interface. Hazard3 provides an implementation of a standard RISC-V JTAG-DTM, but any APB master could be used. The Debug Module requires at least 7 bits of word addressing, i.e. 9 bits of byte address space.
|
||||
|
||||
An APB arbiter could be inserted here, to allow multiple transports to be used, provided the host(s) avoid using multiple transports concurrently. This also admits simple implementation of self-hosted debug, by mapping the Debug Module to a system-level peripheral address space.
|
||||
|
||||
The clock domain crossing (if any) occurs on the downstream port of the Debug Transport Module. Hazard3's JTAG-DTM implementation runs entirely in the TCK domain, and instantiates a bus clock-crossing module internally to bridge a TCK-domain internal APB bus to an external bus in the processor clock domain.
|
||||
|
||||
It is possible to instantiate multiple Debug Modules, one per core, and attach them to a single Debug Transport Module. This is not the preferred topology, but it does allow multiple cores to be independently clocked.
|
||||
|
||||
=== Debug Module to Core Interface
|
||||
|
||||
The DM can inject instructions directly into the core's instruction prefetch buffer. This mechanism is used to execute the Program Buffer, or used directly by the DM, issuing hardcoded instructions to manipulate core state.
|
||||
|
||||
The DM's `data0` register is exposed to the core as a debug mode CSR. By issuing instructions to make the core read or write this dummy CSR, the DM can exchange data with the core. To read from a GPR `x` into `data0`, the DM issues a `csrw data0, x` instruction. Similarly `csrr x, data0` will write `data0` to that GPR. The DM always follows the CSR instruction with an `ebreak`, just like the implicit `ebreak` at the end of the Program Buffer, so that it is notified by the core when the GPR read instruction sequence completes.
|
||||
|
||||
The debug host must use the Program Buffer to access CSRs and memory. This carries some overhead for individual accesses, but is efficient for bulk transfers: the `abstractauto` feature allows the DM to trigger the Program Buffer and/or a GPR tranfer automatically following every `data0` access, which can be used for e.g. autoincrementing read/write memory bursts. Program Buffer read/writes can also be used as `abstractauto` triggers: this is less useful than the `data0` trigger, but takes little extra effort to implement, and can be used to read/write a large number of CSRs efficiently.
|
||||
|
||||
Abstract memory access is not implemented because it offers no better throughput than Program Buffer execution with `abstractauto` for bulk transfers, and non-bulk transfers are still instantaneous from the perspective of the human at the other end of the wire.
|
||||
|
||||
The Hazard3 Debug Module has experimental support for multi-core debug. Each core possesses exactly one hardware thread (hart) which is exposed to the debugger. The RISC-V specification does not mandate what mapping is used between the Debug Module hart index `hartsel` and each core's `mhartid` CSR, but a 1:1 match of these values is the least likely to cause issues. Each core's `mhartid` can be configured using the `MHARTID_VAL` parameter during instantiation.
|
||||
|
||||
=== Implementation-defined behaviour
|
||||
|
||||
Features implemented by DM (beyond the mandatory):
|
||||
Features implemented by the Hazard3 Debug Module (beyond the mandatory):
|
||||
|
||||
* Halt-on-reset, selectable per-hart
|
||||
* Program Buffer, size 2 words, `impebreak` = 1.
|
||||
|
@ -64,7 +48,7 @@ Not implemented:
|
|||
* Post-incrementing abstract access GPR
|
||||
* System bus access
|
||||
|
||||
Core behaviour:
|
||||
The core behaves as follows:
|
||||
|
||||
* Branch, `jal`, `jalr` and `auipc` are illegal in debug mode, because they observe PC: attempting to execute will halt Program Buffer execution and report an exception in `abstractcs.cmderr`
|
||||
* The `dret` instruction is not implemented (a special purpose DM-to-core signal is used to signal resume)
|
||||
|
@ -77,32 +61,15 @@ Core behaviour:
|
|||
* `dcsr.mprven` is hardwired to 0
|
||||
* `dcsr.prv` is hardwired to 3 (M-mode)
|
||||
|
||||
=== UART DTM
|
||||
=== Debug Module to Core Interface
|
||||
|
||||
Hazard3 defines a minimal UART Debug Transport Module, which allows the Debug Module to be accessed via a standard 8n1 asynchronous serial port. The UART DTM is always accessed by the host using a two-wire serial interface (TXD RXD) running at 1 Mbaud. The interface between the DTM and DM is an AMBA 3 APB port with a 32-bit data bus and 8-bit address bus.
|
||||
The DM can inject instructions directly into the core's instruction prefetch buffer. This mechanism is used to execute the Program Buffer, or used directly by the DM, issuing hardcoded instructions to manipulate core state.
|
||||
|
||||
This is a quick hack, and not suitable for production systems:
|
||||
The DM's `data0` register is exposed to the core as a debug mode CSR. By issuing instructions to make the core read or write this dummy CSR, the DM can exchange data with the core. To read from a GPR `x` into `data0`, the DM issues a `csrw data0, x` instruction. Similarly `csrr x, data0` will write `data0` to that GPR. The DM always follows the CSR instruction with an `ebreak`, just like the implicit `ebreak` at the end of the Program Buffer, so that it is notified by the core when the GPR read instruction sequence completes.
|
||||
|
||||
* Debug hardware should not expect a frequency reference for a UART to be present
|
||||
* The UART DTM does not implement any flow control or error detection/correction
|
||||
The debug host must use the Program Buffer to access CSRs and memory. This carries some overhead for individual accesses, but is efficient for bulk transfers: the `abstractauto` feature allows the DM to trigger the Program Buffer and/or a GPR tranfer automatically following every `data0` access, which can be used for e.g. autoincrementing read/write memory bursts. Program Buffer read/writes can also be used as `abstractauto` triggers: this is less useful than the `data0` trigger, but takes little extra effort to implement, and can be used to read/write a large number of CSRs efficiently.
|
||||
|
||||
The host may send the following commands:
|
||||
Abstract memory access is not implemented because it offers no better throughput than Program Buffer execution with `abstractauto` for bulk transfers, and non-bulk transfers are still instantaneous from the perspective of the human at the other end of the wire.
|
||||
|
||||
[cols="20h,~,~", options="header"]
|
||||
|===
|
||||
| Command | To DTM | From DTM
|
||||
| `0x00` NOP | - | -
|
||||
| `0x01` Read ID | - | 4-byte ID, same format as JTAG-DTM ID (JEP106-compatible)
|
||||
| `0x02` Read DMI | 1 address byte | 4 data bytes
|
||||
| `0x03` Write DMI | 1 address byte, 4 data bytes | data bytes echoed back
|
||||
| `0xa5` Disconnect | - | -
|
||||
|===
|
||||
|
||||
Initially after power-on the DTM is in the Dormant state, and will ignore any commands. The host sends the magic sequence `"SUP?"` (`0x53, 0x55, 0x50, 0x3f`) to wake the DTM, and then issues a Read ID command to check the link is up. The DTM can be returned to the Dormant state at any time using the `0xa5` Disconnect command.
|
||||
|
||||
So that the host can queue up batches of commands in its transmit buffer, without overrunning the DTM's transmit bandwidth, it's recommended to pad each command with NOPs so that it is strictly larger than the response. For example, a Read ID should be followed by four NOPs, and a Read DMI should be followed by 3 NOPs.
|
||||
|
||||
To recover command framing, write 6 NOP commands (the length of the longest commands). This will be interpreted as between 1 and 6 NOPs depending on the DTM's state.
|
||||
|
||||
This interface assumes the DMI data transfer takes very little time compared with the UART access (typically less than one baud period). When the host-to-DTM bandwidth is kept greater than the DTM-to-host bandwidth, thanks to appropriate NOP padding, the host can queue up batches of commands in its transmit buffer, and this should never overrun the DTM's response channel. So, the 1 Mbaud 8n1 UART link provides 67 kB/s of half-duplex data bandwidth between host and DM, which is enough to get your system off the ground.
|
||||
The Hazard3 Debug Module has experimental support for multi-core debug. Each core possesses exactly one hardware thread (hart) which is exposed to the debugger. The RISC-V specification does not mandate what mapping is used between the Debug Module hart index `hartsel` and each core's `mhartid` CSR, but a 1:1 match of these values is the least likely to cause issues. Each core's `mhartid` can be configured using the `MHARTID_VAL` parameter during instantiation.
|
||||
|
||||
|
|
Loading…
Reference in New Issue