Correcting memory map, better explaining the scratchpad, and adding a section about the write queue
This commit is contained in:
parent
b5a40c7895
commit
bd07b7ef5f
91
memorymap.md
91
memorymap.md
@ -7,7 +7,7 @@
|
|||||||
1F800000h 9F800000h -- 1K Scratchpad (D-Cache used as Fast RAM)
|
1F800000h 9F800000h -- 1K Scratchpad (D-Cache used as Fast RAM)
|
||||||
1F801000h 9F801000h BF801000h 8K I/O Ports
|
1F801000h 9F801000h BF801000h 8K I/O Ports
|
||||||
1F802000h 9F802000h BF802000h 8K Expansion Region 2 (I/O Ports)
|
1F802000h 9F802000h BF802000h 8K Expansion Region 2 (I/O Ports)
|
||||||
1FA00000h 9FA00000h BFA00000h 2048K Expansion Region 3 (whatever purpose)
|
1FA00000h 9FA00000h BFA00000h 2048K Expansion Region 3 (SRAM BIOS region for DTL cards)
|
||||||
1FC00000h 9FC00000h BFC00000h 512K BIOS ROM (Kernel) (4096K max)
|
1FC00000h 9FC00000h BFC00000h 512K BIOS ROM (Kernel) (4096K max)
|
||||||
FFFE0000h (KSEG2) 0.5K I/O Ports (Cache Control)
|
FFFE0000h (KSEG2) 0.5K I/O Ports (Cache Control)
|
||||||
```
|
```
|
||||||
@ -25,11 +25,11 @@ Additionally, there are a number of memory mirrors.<br/>
|
|||||||
|
|
||||||
#### KUSEG,KSEG0,KSEG1,KSEG2 Memory Regions
|
#### KUSEG,KSEG0,KSEG1,KSEG2 Memory Regions
|
||||||
```
|
```
|
||||||
Address Name Size Privilege Code-Cache Data-Cache
|
Address Name i-Cache Write-Queue
|
||||||
00000000h KUSEG 2048M Kernel/User Yes (Scratchpad)
|
00000000h KUSEG Yes Yes
|
||||||
80000000h KSEG0 512M Kernel Yes (Scratchpad)
|
80000000h KSEG0 Yes Yes
|
||||||
A0000000h KSEG1 512M Kernel No No
|
A0000000h KSEG1 No No
|
||||||
C0000000h KSEG2 1024M Kernel (No code) No
|
C0000000h KSEG2 (No code) No
|
||||||
```
|
```
|
||||||
Kernel Memory: KSEG1 is the normal physical memory (uncached), KSEG0 is a
|
Kernel Memory: KSEG1 is the normal physical memory (uncached), KSEG0 is a
|
||||||
mirror thereof (but with cache enabled). KSEG2 is usually intended to contain
|
mirror thereof (but with cache enabled). KSEG2 is usually intended to contain
|
||||||
@ -39,22 +39,29 @@ processors), the PSX doesn't support virtual memory, and KUSEG simply contains
|
|||||||
a mirror of KSEG0/KSEG1 (in the first 512MB) (trying to access memory in the
|
a mirror of KSEG0/KSEG1 (in the first 512MB) (trying to access memory in the
|
||||||
remaining 1.5GB causes an exception).<br/>
|
remaining 1.5GB causes an exception).<br/>
|
||||||
|
|
||||||
#### Code Cache
|
#### i-Cache
|
||||||
Works in the cached regions (KUSEG and KSEG0).<br/>
|
The i-Cache can hold 4096 bytes, or 1024 instructions.<br/>
|
||||||
|
It is only active in the cached regions (KUSEG and KSEG0).<br/>
|
||||||
There are reportedly some restrictions... not sure there... eventually it is
|
There are reportedly some restrictions... not sure there... eventually it is
|
||||||
using the LSBs of the address as cache-line number... so, for example, it
|
using the LSBs of the address as cache-line number... so, for example, it
|
||||||
couldn't simultaneously memorize opcodes at BOTH address 80001234h, AND at
|
couldn't simultaneously memorize opcodes at BOTH address 80001234h, AND at
|
||||||
address 800F1234h (?)<br/>
|
address 800F1234h (?)<br/>
|
||||||
|
|
||||||
#### Data Cache aka Scratchpad
|
#### Scratchpad
|
||||||
The MIPS CPU usually have a Data Cache, but, in the PSX, Sony has misused it as
|
MIPS CPUs usually have a d-Cache, but, in the PSX, Sony has assigned it as
|
||||||
"Scratchpad", that is, the "Data Cache" is mapped to a fixed memory location at
|
what's referenced as the "Scratchpad", mapped to a fixed memory location at
|
||||||
1F800000h..1F8003FFh (ie. it's used as Fast RAM, rather than as cache).<br/>
|
1F800000h..1F8003FFh, ie. it's used as Fast RAM, rather than as cache.<br/>
|
||||||
There \<might\> be a way to disable that behaviour (via Port FFFE0130h or
|
There \<might\> be a way to disable that behavior (via Port FFFE0130h or
|
||||||
so), but, the Kernel is accessing I/O ports via KUSEG, so activating Data Cache
|
so), but, the Kernel is accessing I/O ports via KUSEG, so activating Data Cache
|
||||||
would cause the Kernel to access cached I/O ports.<br/>
|
would cause the Kernel to access cached I/O ports.<br/>
|
||||||
Not tested yet, but most probably the Scratchpad can be used only for Data (ie.
|
The purpose of the scratchpad is to have a more flexible cache system available
|
||||||
NOT for program Code?).<br/>
|
to the programmer. Neither the kernel nor the Sony libraries will try to make use
|
||||||
|
of it, so it is therefore completely up for grabs to the programmer. A good example
|
||||||
|
would be if you were to write a piece of code that's doing a lot of CRC computation,
|
||||||
|
to use the 1KB scratchpad to initially load the CRC lookup tables, which incidentally,
|
||||||
|
is exactly 1KB large. Doing this will relieve SDRAM page changes overhead while reading
|
||||||
|
the data to checksum linearly, while also keeping the whole CRC code in the i-Cache,
|
||||||
|
hence being more optimal than what you'd get with an automatic d-Cache system.
|
||||||
|
|
||||||
#### Memory Mirrors
|
#### Memory Mirrors
|
||||||
As described above, the 512Mbyte KUSEG, KSEG0, and KSEG1 regions are mirrors of
|
As described above, the 512Mbyte KUSEG, KSEG0, and KSEG1 regions are mirrors of
|
||||||
@ -78,6 +85,60 @@ The Scratchpad is mirrored only in KUSEG and KSEG0, but not in KSEG1.<br/>
|
|||||||
(unless RAM/BIOS/Expansion mirrors are mapped to "unused" area)
|
(unless RAM/BIOS/Expansion mirrors are mapped to "unused" area)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Write queue
|
||||||
|
The MIPS CPU has a 4-words deep pass-through write queue, in order to relieve
|
||||||
|
some bus contention when writing to memory. If reading the same memory location
|
||||||
|
that just got written into the write queue, it will first be flushed before
|
||||||
|
being read back from memory.<br/>
|
||||||
|
It is important to realize that the write queue's mechanism is only viable for
|
||||||
|
normal memory attached to the main CPU, and that any hardware register state machine
|
||||||
|
will get messed up by it.<br/>
|
||||||
|
The typical example is the typical JEDEC standard to access flash, which usually does
|
||||||
|
the following sequence to read the ID of a flash chip:
|
||||||
|
```C
|
||||||
|
base[0xAAA] = 0xAA;
|
||||||
|
base[0x555] = 0x55;
|
||||||
|
base[0xAAA] = 0x90;
|
||||||
|
uint8_t mnfctrID = base[0x000];
|
||||||
|
uint8_t deviceId = base[0x002];
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example above, if `base` is located in a memory segment that has the write queue
|
||||||
|
enabled, even if the low level assembly code will do the first 3 stores before doing 2 loads,
|
||||||
|
the physical signals sent to that device through the CPU bus will be seen in the sequence:
|
||||||
|
```
|
||||||
|
store(0xaaa, 0xaa)
|
||||||
|
load(0x000)
|
||||||
|
store(0x555, 0x55)
|
||||||
|
load(0x002)
|
||||||
|
store(0xaaa, 0x90)
|
||||||
|
```
|
||||||
|
|
||||||
|
Therefore, using KSEG1 that disables the write queue is the only way to ensure that the
|
||||||
|
operations are done in the proper way.
|
||||||
|
|
||||||
|
The above is valid for most of the hardware connected to the main CPU, such as the CDROM
|
||||||
|
controller, exp1, exp2, the SPU, or the GPU. Therefore, using BF80180xh to access the
|
||||||
|
CDROM registers is more correct than using 1F80180xh.
|
||||||
|
|
||||||
|
It is noteworthy that the Sony code will still incorrectly use KUSEG as the memory map
|
||||||
|
for all hardware registers, and they then spend a lot of time writing 4 dummy values
|
||||||
|
somewhere, in order to ensure the write queue has been flushed.
|
||||||
|
|
||||||
|
The SN debugger in contrast is properly using the KSEG1 memory map for all the hardware
|
||||||
|
registers, nullifying the need to flush the write queue when accessing it.
|
||||||
|
|
||||||
|
It's also noteworthy that doing ANY KSEG1 access (read OR write) will automatically stall
|
||||||
|
the CPU in order to flush the whole write queue before proceeding with the operation.
|
||||||
|
Therefore, all BIOS ROM operations will naturally and effectively have the write queue
|
||||||
|
disabled, as this code requires the CPU to read from KSEG1 constantly.
|
||||||
|
|
||||||
|
This also means that if using KUSEG for the hardware registers, another method to flush
|
||||||
|
the write queue, albeit potentially slightly less efficient, would be to simply read
|
||||||
|
the first byte located at BFC00000h. The latter is what is effectively described as the
|
||||||
|
official method to flush the write queue in the MIPS handbook. This could be potentially
|
||||||
|
useful to flush the write queue all at once, instead of flushing it word by word.
|
||||||
|
|
||||||
#### More Memory Info
|
#### More Memory Info
|
||||||
For Info on Exception vectors, Unused/Garbage memory locations, I/O Ports,
|
For Info on Exception vectors, Unused/Garbage memory locations, I/O Ports,
|
||||||
Expansion ROM Headers, and Memory Waitstate Control, etc. see:<br/>
|
Expansion ROM Headers, and Memory Waitstate Control, etc. see:<br/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user