"""Enumerate every IP block and its base addresses from the IP discovery table. Purpose: answer "what other mailboxes exist on SMN" with the card's own authoritative list instead of guessing address neighbourhoods. SAFETY: deliberately does NOT hand-read BAR0 at (vram_size - 64KiB). On the healthy card vram_size is 0x5ff000000, so that offset is ~24 GB -- far outside the BAR0 aperture, and a high-offset BAR0 read raises a TLP error that wedges PCIe until a power cycle. Instead we use tinygrad's normal AMDev path, which reads the table through the supported windowed accessor and parses it. READ-ONLY with respect to our own pokes; device init is tinygrad's standard path. """ import sys sys.path.insert(0, "/Users/user/src/tinygrad") from tinygrad import Device from tinygrad.runtime.autogen.am import am d = Device["AMD"] impl = None for attr in ("dev_iface", "iface"): o = getattr(d, attr, None) if o is None: continue impl = getattr(o, "dev_impl", None) or o if hasattr(impl, "regs_offset"): break if impl is None or not hasattr(impl, "regs_offset"): sys.exit("could not reach AMDev.regs_offset (got %r)" % (impl,)) print("vram_size = %#x (%d MB)" % (impl.vram_size, impl.vram_size >> 20)) print() name = {} for k in dir(am): if k.endswith("_HWIP"): try: name[getattr(am, k)] = k[:-5] except Exception: pass print("%-14s %-12s %-8s %s" % ("IP", "version", "inst", "base addresses")) rows = [] for hw_ip, insts in sorted(impl.regs_offset.items()): ver = impl.ip_ver.get(hw_ip) for inst, bases in sorted(insts.items()): rows.append((name.get(hw_ip, str(hw_ip)), ver, inst, bases)) print("%-14s %-12s %-8s %s" % (name.get(hw_ip, str(hw_ip)), ".".join(map(str, ver)) if ver else "?", inst, " ".join("%#x" % b for b in bases))) print("\n=== distinct base addresses (candidate SMN targets) ===") allb = sorted({b for _, _, _, bases in rows for b in bases}) print("count =", len(allb)) for b in allb: print(" %#x" % b)