Reality Signal Processor/Interface: Difference between revisions
No edit summary |
|||
Line 29: | Line 29: | ||
The internal RSP registers are memory mapped into the VR4300 physical address space starting from 0x0404 0000. Normally, accessed are performed through the virtual uncached segment, so at 0xA404 0000. |
The internal RSP registers are memory mapped into the VR4300 physical address space starting from 0x0404 0000. Normally, accessed are performed through the virtual uncached segment, so at 0xA404 0000. |
||
The exact same physical registers are also exposed as COP0 registers to RSP itself, and can thus be accessed using the MTC0 / MFC0 opcodes. |
The exact same physical registers are also exposed as COP0 registers to RSP itself, and can thus be accessed using the MTC0 / MFC0 opcodes. Since access to all registers is shared by VR4300 and RSP, special care must be taken while writing software to decide who is in charge of each different resource / feature. For instance, normally DMA operations are performed by either the CPU or the RSP only; if the software architecture requires both to issue DMA transfers, some kind of mutex protocol must be established (for instance, using either the SIG bits in the SP_STATUS register, or the SP_SEMAPHORE register). |
||
{| class="wikitable" |
{| class="wikitable" |
||
|+ |
|+ |
||
Line 115: | Line 115: | ||
=== SP_STATUS === |
=== SP_STATUS === |
||
{{#invoke:Register table|head|850px|SP_STATUS <code>0x0404 0010</code> (RSP COP0: <code>c4</code>) - Read access}} |
The SP_STATUS register is the main status register for the RSP. Like many other flag registers in N64, it has two different layouts when accessed for reading and writing: this allows to perform atomic set / clear operations on each flag using a simple memory write operation, without risking race conditions that would be frequent if a read-modify-write sequence was issued by the processor. {{#invoke:Register table|head|850px|SP_STATUS <code>0x0404 0010</code> (RSP COP0: <code>c4</code>) - Read access}} |
||
{{#invoke:Register table|row|31:24}} |
{{#invoke:Register table|row|31:24}} |
||
| U-0 || U-0 || U-0 || U-0 || U-0 || U-0 || U-0 || U-0 |
| U-0 || U-0 || U-0 || U-0 || U-0 || U-0 || U-0 || U-0 |
Revision as of 13:53, 28 March 2022
The RSP interface is accessed by VR4300 via memory mapped registers at the physical address 0x040x xxxx.
DMEM and IMEM
Both RSP memory banks are fully memory mapped into the VR4300 address space, as follows:
Address range | Memory | |
---|---|---|
0x04000000 | 0x04000FFF | RSP DMEM |
0x04001000 | 0x04001FFF | RSP IMEM |
Access must be performed using 32-bit reads and writes. TODO: document exact behavior on different access sizes.
Since the memory is single-port, it can only be accessed by either the VR4300 or the RSP itself at the same time (including its internal DMA engine). Notice that there is no bus arbiter: an access happening at the same time by both processors will cause problems: typically what happens is that VR4300 wins the race, so the RSP write is lost, or the RSP read returns the same data read by the VR4300 (even if the address was different). Also, if a DMA was in progress, the address of the memory access performed by VR4300 becomes the current address of the DMA transfer, corrupting it. So, in general, VR4300 should access DMEM/IMEM only when RSP is halted.
DMA transfers
DMA transfers can be initiated by either VR4300 or RSP. They can transfer that from/to RDRAM to/from IMEM/DMEM very efficiently, much faster than copying the data word by word using VR4300 over the memory mapped addresses of the memory banks. The speed of transfer is about 3.7 bytes per VR4300 (PClock) cycle (plus some small fixed overhead). It is the fastest DMA engine in the N64.
The DMA engine allows to transfer multiple "rows" of data in RDRAM, separated by a "skip" value. This allows for instance to transfer a rectangular portion of a larger image, by specifying the size of each row of the selection portion, the number of rows, and a "skip" value that corresponds to the bytes between the end of a row and the beginning of the following one. Notice that this applies only to RDRAM: accesses in IMEM/DMEM are always linear.
All DMA registers are double-buffered: this means that it is possible to program a DMA transfer while another one is in progress. As soon as the first transfer finishes, the second one will start. The RSP status register reports in separate bits whether there is a transfer ongoing, and whether there is a transfer pending.
RSP Internal Registers
The internal RSP registers are memory mapped into the VR4300 physical address space starting from 0x0404 0000. Normally, accessed are performed through the virtual uncached segment, so at 0xA404 0000.
The exact same physical registers are also exposed as COP0 registers to RSP itself, and can thus be accessed using the MTC0 / MFC0 opcodes. Since access to all registers is shared by VR4300 and RSP, special care must be taken while writing software to decide who is in charge of each different resource / feature. For instance, normally DMA operations are performed by either the CPU or the RSP only; if the software architecture requires both to issue DMA transfers, some kind of mutex protocol must be established (for instance, using either the SIG bits in the SP_STATUS register, or the SP_SEMAPHORE register).
VR4300 address | RSP COP0 register | Name | Description |
---|---|---|---|
0x0404 0000 | c0 | SP_MEM_ADDR | Address in IMEM/DMEM for a DMA transfer |
0x0404 0004 | c1 | SP_DRAM_ADDR | Address in RDRAM for a DMA transfer |
0x0404 0008 | c2 | SP_RD_LEN | Length of a DMA transfer. Writing this register triggers a DMA transfer from RDRAM to IMEM/DMEM |
0x0404 000C | c3 | SP_WR_LEN | Length of a DMA transfer. Writing this register triggers a DMA transfer from IMEM/DMEM to RDRAM. |
0x0404 0010 | c4 | SP_STATUS | RSP status register. |
SP_MEM_ADDR
SP_MEM_ADDR 0x0404 0000 (RSP COP0: c0 )
| ||||||||
---|---|---|---|---|---|---|---|---|
31:24 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
23:16 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
15:8 | U-0 | U-0 | U-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
— | MEM_BANK | MEM_ADDR[11:8] | ||||||
7:0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
MEM_ADDR[7:0] |
bit 31-13 | Undefined: Initialized to 0
|
bit 12 | MEM_BANK: Bank accessed by the transfer 0 = DMEM 1 = IMEM |
bit 11-0 | MEM_ADDR[11:0]: DMEM or IMEM address used in SP DMAs |
Extra Details:
- MEM_BANK
- This bit select the memory bank that will be accessed by the DMA transfer. Notice that, even though the memory banks appear to be contiguous in VR4300 address space, it is not possible to perform a single DMA transfers that spans across two banks. Each transfer will only access a single bank. For instance, to load a microcode, it is normally necessary to do two separate transfers: one for IMEM and one for DMEM.
SP_DRAM_ADDR
SP_DRAM_ADDR 0x0404 0004 (RSP COP0: c1 )
| ||||||||
---|---|---|---|---|---|---|---|---|
31:24 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
23:16 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
DRAM_ADDR[23:16] | ||||||||
15:8 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
DRAM_ADDR[15:8] | ||||||||
7:0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
DRAM_ADDR[7:0] |
bit 31-24 | Undefined: Initialized to 0
|
bit 23-0 | DRAM_ADDR[23:0]: RDRAM address used in SP DMAs |
SP_STATUS
The SP_STATUS register is the main status register for the RSP. Like many other flag registers in N64, it has two different layouts when accessed for reading and writing: this allows to perform atomic set / clear operations on each flag using a simple memory write operation, without risking race conditions that would be frequent if a read-modify-write sequence was issued by the processor.
SP_STATUS 0x0404 0010 (RSP COP0: c4 ) - Read access
| ||||||||
---|---|---|---|---|---|---|---|---|
31:24 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
23:16 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
15:8 | U-0 | R-0 | R-0 | R-0 | R-0 | R-0 | R-0 | R-0 |
— | SIG7 | SIG6 | SIG5 | SIG4 | SIG3 | SIG2 | SIG1 | |
7:0 | R-0 | R-0 | R-0 | R-0 | R-0 | R-0 | R-0 | R-0 |
SIG0 | INTBREAK | SSTEP | IO_BUSY | DMA_FULL | DMA_BUSY | BROKE | HALTED |
bit 0 | HALTED: Current running status of the RSP 0 = Running 1 = Idle / halted |
bit 1 | BROKE: Set to 1 when the RSP executes a BREAK opcode. It must be manually reset.
|
bit 2 | DMA_BUSY: Set to 1 when there is a DMA transfer currently in progress.
|
bit 3 | DMA_FULL: Set to 1 when there is a DMA transfer pending in the DMA register in addition to a DMA already in progress.
|
bit 4 | IO_BUSY: Set to 1 when the RSP is accessing either DMEM or IMEM. (*TODO*: verify this)
|
bit 5 | SSTEP: Set to 1 when single-step mode is activated. In single-step mode, RSP auto-halts itself after a single opcode is run. See the details below.
|
bit 6 | INTBREAK: Configure the RSP to trigger a RSP MI interrupt when the BREAK is run. 0 = When BREAK is run, just halt the RSP core without triggering a RSP MI interrupt. 1 = When BREAK is run, halt the RSP core and trigger a MI interrupt.
|
bit 7-14 | SIG<n>: Status of the 8 custom bits that can be freely used to communicate state between VR4300 and RSP. |
SP_STATUS 0x0404 0010 (RSP COP0: c4 ) - Write access
| ||||||||
---|---|---|---|---|---|---|---|---|
31:24 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | W-0 |
— | — | — | — | — | — | — | SET_SIG7 | |
23:16 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 |
CLR_SIG7 | SET_SIG6 | CLR_SIG6 | SET_SIG5 | CLR_SIG5 | SET_SIG4 | CLR_SIG4 | SET_SIG3 | |
15:8 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 |
CLR_SIG3 | SET_SIG2 | CLR_SIG2 | SET_SIG1 | CLR_SIG1 | SET_SIG0 | CLR_SIG0 | SET_INTBREAK | |
7:0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 | W-0 |
CLR_INTBREAK | SET_SSTEP | CLR_SSTEP | SET_INTR | CLR_INTR | CLR_BROKE | SET_HALT | CLR_HALT |
bit 0 | CLR_HALT: Start running RSP code from the current RSP PC (clear the HALTED flag)
|
bit 1 | SET_HALT: Pause running RSP code (set the HALTED flag)
|
bit 2 | CLR_BROKE: Clear the BROKE flag, that is automatically set every time a BREAK opcode is run. This flag has no effect on the running/idle state of the RSP; it is just a latch that remembers whether a BREAK opcode was ever run.
|
bit 3 | CLR_INTR: Acknowledge a pending RSP MI interrupt. This must be done any time a RSP MI interrupt was generated, otherwise the interrupt line on the VR4300 will stay asserted. |
bit 4 | SET_INTR: Manually trigger a RSP MI interrupt on the VR4300. It might be useful if the RSP wants to manually trigger a VR4300 interrupt at any point during its execution. |
bit 5 | CLR_SSTEP: Disable single-step mode. |
bit 6 | SET_SSTEP: Enable single-step mode. When this mode is activated, the RSP auto-halts itself after every opcode that is run. The VR4300 can then trigger a new step by unhalting it. |
bit 7 | CLR_INTBREAK: Disable the INTBREAK flag. When this flag is disabled, running a BREAK opcode will not generate any RSP MI interrupt, but it will still halt the RSP.
|
bit 8 | SET_INTBREAK: Enable the INTBREAK flag. When this flag is enabled, running a BREAK opcode will generate a RSP MI interrupt, in addition to halting the RSP.
|
bit 9-24 | CLR_SIG<n>/SET_SIG<n>: Set to 0 or 1 the 8 available bitflags that can be used as communication protocol between RSP and CPU.
|
RSP PC register
RSP has an internal PC (program counter) register that cannot be explicitly accessed via RSP opcodes. Instead, a memory mapped register is available to VR4300 to control the RSP PC while RSP is halted. The register is called SP_PC
.
Notice that VR4300 is allowed to access SP_PC only while RSP is halted. Reading from SP_PC while RSP is running returns garbage data, and writing to it causes RSP to misbehave.
SP_PC
SP_PC 0x0408 0000
| ||||||||
---|---|---|---|---|---|---|---|---|
31:24 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
23:16 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 | U-0 |
— | — | — | — | — | — | — | — | |
15:8 | U-0 | U-0 | U-0 | U-0 | RW-0 | RW-0 | RW-0 | RW-0 |
— | PC[11:8] | |||||||
7:0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 | RW-0 |
PC[7:0] |
bit 31-12 | Undefined: Initialized to 0
|
bit 21-0 | PC[21:0]: Read/write the RSP PC (program counter) |
Extra Details:
- PC
- Reads while RSP is running returns random bits. Reads while RSP is halted return the address of the instruction that the RSP will execute when it is unhalted.
Writes will also reset the RSP CPU core pipeline, so any pending writeback or branch are discarded.
- Reads while RSP is running returns random bits. Reads while RSP is halted return the address of the instruction that the RSP will execute when it is unhalted.