pureikyubu/Docs/HW/fifo.txt
ogamespec c21147ccff Cumulative changes all around project, regarding Stage 1
Docs: New TODO moved to EMU, old renamed to old_todo
Docs: Old coding style is deprecated (old_style.txt)
Docs: Removed mention about CubeDocumented and fixed old emails
RE: boot.s, proved first asm line (lis instruction parameter)
RE: Added PAL and NTSC Boot and IPL IDA files
RE: Some work on NTSC IPL (identified many lib calls, including OS, GX)
RE: Added EXI Bootrom descrambler by segher
RE: GXInit
RE: Internal GX lib structures (GXPrivate.h)
RE: More details on lomem (OS versions)
RE: OSInit and OS.c
RE: OSAlloc (heap allocator)
RE: Very first code of Metrowerk runtime (__start.c)
Docs: Added copy of http://gcdev.narod.ru
Source\Utils: Command processor (Cmd.c)
Source\Utils: File wrapper
Source\Utils: Gekko disasm cleaned up and ported to plain C
Source\Utils: Double-linked lists
Source\Utils: Ported old Profiler code
Source\Utils: String utils
2015-09-04 19:45:10 +03:00

179 lines
7.6 KiB
Text

--------------------------------------------------------------------------
GC FIFO Details.
--------------------------------------------------------------------------
This document was created, after hard reversing of GX fifo module. It was
not easy to handle whole thing, but I made it :) Hope it will be useful
for all, who was stuck on GX fifo.
Send your comments or questions to ogamespec@gmail.com
--------------------------------------------------------------------------
Thats how I understand GC graphics fifo logic.
There are two fifos : CPU (PI) and GP (CP). They are both implemented as
hardware circular buffers, and each fifo has its own registers set.
CP registers are used to control GP fifo flow and PI registers are used
for CPU fifo.
Fifos can run in two modes: immediate and multibuffer. CPU fifo is used
together with GP fifo in multibuffer mode to imitate N64 double-buffered
display lists, for easy N64's games porting.
Immediate fifo mode is same as "linked" fifo mode.
Details of GP Fifo
------------------
Important detail : GP command proccessor (which is inside ArtX GP logic,
not 'CP' interface) always reading data by 32-byte chunks. Im pretty sure,
that it doesnt matter, when sent 32-byte "packet" is teared in middle
of it, as example 'float' vertex X-position data. GP will stalls all
commands execution, until it get full set of current primitive or its
parameters. I dont think, that it has cache for big primitives, like
triangle-strips, its just stalls, until dont get whole current vertex
data to render. But Im sure, emulators can collect whole single primitive
in accumulation buffer to draw it all at once - it will be much faster :)
The 'read idle' and 'command idle' bits are showing GP state. When GP
have no new data to read - 'read idle' is set. And when GP command processor
is not busy by drawing primitive, or executing command, 'command idle' is
set. When both bits are cleared, then GP is free and ready for action.
Note : 'read idle' can be set in breakpoint condition, when GP stalls
until breakpoint is not cleared.
If 'GP read' bit enabled in CP control register, GP logic starts to read
fifo data by 32-byte chunks, using CP read pointer. When CP read pointer
wraps 'top' address, it automatically changes back to 'base'. No interrupts
generated.
If 'GP link' bit enabled in CP CR, following features are become enabled :
breakpoint, low watermark and high watermark. These features are used only
in immediate ('linked') mode.
Conditions for immediate fifo mode :
Breakpoint : if CP read pointer reaches breakpoint address, CP generates
breakpoint interrupt. GP stops reading fifo data, until breakpoint is not
cleared. Actually this condition can be set even in multibuffer mode, but
there is no reason to use it.
Low watermark : if CP read pointer reaches low watermark address, CP
generates low watermark interrupt.
High watermark : if CP write pointer reaches high watermark address, CP
generates high watermark interrupt.
Watermarks are used to sync GP and CPU. When high watermark is asserted,
CPU is stopping to write any commands/data to fifo, until GP reading it.
And when GP reaches low watermark, CPU will continue to write data. It is
also used to protect fifo data to be overwritten by CPU. On real hardware
GP reading will never overdrive CPU writing, so they work finely together
in single circular fifo buffer.
When CP write pointer wraps its 'top' address, it automatically changes
back to 'base'. No interrupts generated. Actually CP write pointer is dummy
in fifo processing, because GP can only read data, its used only to
calculate CP fifo "stride" = wrptr - rdptr. I believe, CP write pointer
is always the same as PI write pointer in immediate mode.
All pointers should be 32-byte aligned, when set.
Details of CPU Fifo
-------------------
CPU Fifo is used only to write data. The application of CPU fifo is to
create display lists, while GP is executing others from CP fifo (in
multibuffer mode).
When CPU fifo wraps the top fifo buffer, special 'wrap' bit is setting
in PI write pointer register. When CPU writes any new fifo data after
wrap, this bit is cleared. No interrupts generated.
All pointers should be 32-byte aligned, when set.
Application of write gather buffer
----------------------------------
Write gather buffer is used to collect and then quickly blast 32-byte
memory chunks, during any CPU writes. Thats why all fifo's are aligned
to 32-byte boundary. See YAGCD or any other Gekko manuals for more
information about it.
There are two applications for gather buffer. In first case it is used
together with PI fifo, otherwise it is assigned to be "redirected" and
used for other purposes. When its pointed to 0x0C008000, its said, that
gather buffer is not redirected. Well, I havent seen yet, that gather
buffer was redirected by any programs, and you can think, that its used
only together with 0x0C008000.
So whats exactly 0x0C008000 (or 0xCC008000, when used with Dolphin OS) ?
Thats simply hardware "pointer to pointer". When you're writing any
data through the bus to this address, Flipper hardware (PI) is redirecting
all writes to PI write pointer, and controlling further fifo flow. So
programmer dont need to care about increasing pointers, wrapping fifo
from the top to begin etc.
--------------------------------------------------------------------------
Appendix : Hardware registers.
Related hardware registers and bit layouts (cut from Dolwin source code) :
// CP registers (16-bit access)
#define CP_SR (0x0C000000)
#define CP_CR (0x0C000002)
#define CP_CLR (0x0C000004)
#define CP_BASE (0x0C000020)
#define CP_TOP (0x0C000024)
#define CP_HIWMARK (0x0C000028)
#define CP_LOWMARK (0x0C00002C)
#define CP_CNT (0x0C000030)
#define CP_WRPTR (0x0C000034)
#define CP_RDPTR (0x0C000038)
#define CP_BPPTR (0x0C00003C)
// PI registers (32-bit access)
#define PI_BASE (0x0C00300C)
#define PI_TOP (0x0C003010)
#define PI_WRPTR (0x0C003014)
// CP status register
#define CP_SR_OVF (1 << 0)
#define CP_SR_UVF (1 << 1)
#define CP_SR_RD_IDLE (1 << 2) // read idle
#define CP_SR_CMD_IDLE (1 << 3) // command idle
#define CP_SR_BPINT (1 << 4)
// CP control register
#define CP_CR_RDEN (1 << 0)
#define CP_CR_BPCLR (1 << 1)
#define CP_CR_OVFEN (1 << 2)
#define CP_CR_UVFEN (1 << 3)
#define CP_CR_LINK (1 << 4)
#define CP_CR_BPEN (1 << 5)
// CP clear register
#define CP_CLR_OVFCLR (1 << 0)
#define CP_CLR_UVFCLR (1 << 1)
// PE status register
#define PE_SR_DONE (1 << 0)
#define PE_SR_TOKEN (1 << 1)
#define PE_SR_DONEMSK (1 << 2)
#define PE_SR_TOKENMSK (1 << 3)
// PI wrap bit
#define PI_WRPTR_WRAP (1 << 27)
--------------------------------------------------------------------------
Referencies :
gxfifo.txt - GX fifo module reversing.
tips.txt - For fifo emulation tips.
This document is maintaining by Dolwin team.
Last edited by org, 16 Aug 2004