aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/vram_check.py
blob: bb2e968aa6994dd41243f8cda652b23514fdd43c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env python3
"""
READ-ONLY check: what VRAM size does a Navi31 (RX 7900 XTX) report over a
USB<->PCIe enclosure (ASM2464PD-class bridge)?

WHAT THIS DOES: reads four registers and prints them.
WHAT THIS DOES NOT DO: no writes, no flash access, no reset, no power cycling,
no firmware loading. It cannot change the state of your card.

REQUIREMENTS: `tinygrad` importable (a checkout on PYTHONPATH or installed),
plus whatever permissions you normally use for tinygrad AMD-over-USB.

RUN:
    python3 vram_check.py

Then paste the whole output back. Thanks!
"""
import struct, sys

try:
    from tinygrad.runtime.support.usb import USB3
    from tinygrad.runtime.support.system import USBPCIDevice
except Exception as e:
    sys.exit("could not import tinygrad (%s: %s)\n"
             "make sure a tinygrad checkout is on PYTHONPATH" % (type(e).__name__, e))

# Navi31 / MP0 13.0.0 specific offsets.
MEMSIZE_DWORD = 0xde3     # mmRCC_CONFIG_MEMSIZE, dword index (byte 0x378C).
                          # Fixed RCC register; readable before IP discovery,
                          # which is exactly why tinygrad uses it.
TSU_CMD       = 0x582CC   # = MP0 C2PMSG_115, PSP TSU mailbox command register
TSU_DATA      = 0x582D0   # = MP0 C2PMSG_116, its data register
BRIDGE_IDS    = ((0x3801, 0x0001), (0xADD1, 0x0001))

devs = []
for vid, pid in BRIDGE_IDS:
    devs += list(USB3.list_devices(vid, pid))
print("USB bridges found : %d" % len(devs))
if not devs:
    sys.exit("no bridge found - is the enclosure connected and powered on?")

gpu  = USBPCIDevice("AM", *devs[0])
bar5 = gpu.map_bar(5, fmt='B')
rd32 = lambda off: struct.unpack('<I', bytes(bar5[off:off+4]))[0]

memsize = rd32(MEMSIZE_DWORD * 4)
print()
print("mmRCC_CONFIG_MEMSIZE     = %#010x   -> VRAM = %d MB" % (memsize, memsize))
print("TSU mailbox (C2PMSG_115) = %#010x   (bit31 set = PSP task ready)" % rd32(TSU_CMD))
print("TSU data    (C2PMSG_116) = %#010x" % rd32(TSU_DATA))
try:
    print("VRAM[0:16]               = %s" % bytes(gpu.map_bar(0)[0:16]).hex())
except Exception as e:
    print("VRAM[0:16]               = <unreadable: %s>" % e)

print()
if memsize == 0:
    print(">>> MEMSIZE reads 0: the memory controller reports no VRAM,")
    print(">>> which means memory training has not completed.")
else:
    print(">>> MEMSIZE OK: %d MB (%.1f GB). Memory training completed." % (memsize, memsize / 1024))

print("""
-----------------------------------------------------------
Please paste this whole output back.

The key number is mmRCC_CONFIG_MEMSIZE:
  0x6000 (24576 MB) = healthy, memory trained
  0x0               = memory not trained
-----------------------------------------------------------""")