#!/usr/bin/env python3 """mmio_regions.py — address → region classifier for RK3588 DDR TPL. Used by mmio_diff.py, blob_emu.py, call_trace.py, training_sim.py to stamp each access with a short human-readable tag so trace output is scannable without memorising hex ranges. Categories (tag, short description): DDRCTL uMCTL2 controller (per-channel ch+0x10000 window, or global 0xFE010000) DDRCTL:SW STAT/SWCTL/SWSTAT/PWRCTL subregion — frequently polled DDRCTL:MR mode-register ops (MRCTRL0/MRSTAT subregion) DDRPHY DDR PHY at 0xFE0C0000 (32 KB) DDRPHY:TR training status subregion (+0x080/090/0B4/3CC/514/684/A24) DDR_MEM actual DRAM content — 0x00000000..0x80000000 once trained SRAM boot SRAM 0xFF000000..0xFF100000 (blob + globals) CRU clock and reset 0xFD7C0000 DDR_CRU DDR PHY clock/reset (ch0..3) 0xFD800000..0xFD8C0000 SCRU secure clock/reset 0xFD8C0000 PMU_SRAM PMU SRAM 0xFF100000..0xFF110000 GRF general register file 0xFD580000 BUS_GRF bus-side GRF 0xFD5F0000 SGRF secure GRF 0xFE050000 PMU power-mgmt unit 0xFE400000 FW_DDR DDR firewall 0xFE030000 OTP OTP_NS — one-time-programmable controller 0xFECC0000 UART debug UART 0xFEB50000 OTHER unmapped / unclassified """ # Per-channel DDRCTL window repeats at these bases. Offset within # a channel identifies the real sub-register. DDRCTL_CHANNELS = (0xF7000000, 0xF8000000, 0xF9000000, 0xFA000000) DDRCTL_GLOBAL = 0xFE010000 DDRCTL_WIN = 0x20000 DDRCTL_SUB = 0x10000 # ch+0x10000 lands inside ctrl space # Training-status registers (the ones mmio_diff's REGION_OFF stubs). DDRPHY_TRAINING_OFFSETS = {0x080, 0x090, 0x0B4, 0x3CC, 0x514, 0x684, 0xA24} # DDRCTL sub-categories — offsets within the 0x10000 sub-window. DDRCTL_SW_OFFSETS = {0x10014, 0x10180, 0x10C80, 0x10C84} DDRCTL_MR_OFFSETS = {0x10080, 0x10090} def classify(addr: int) -> str: """Return short region tag for an absolute address.""" # Emulator-only scratch stack (0x00400000..0x00500000) — not a real # silicon region but tagged distinctly so tripwire can diff stack # writes (e.g. param_2[] buffers fn_de40 fills). if 0x00400000 <= addr < 0x00500000: return "STACK" # DDR memory (post-training) if addr < 0x80000000: return "DDR_MEM" # Per-channel DDRCTL windows for base in DDRCTL_CHANNELS: if base <= addr < base + 0x40000: off = addr - base if off in DDRCTL_SW_OFFSETS: return "DDRCTL:SW" if off in DDRCTL_MR_OFFSETS: return "DDRCTL:MR" return "DDRCTL" # Global DDRCTL (less common in TPL) if DDRCTL_GLOBAL <= addr < DDRCTL_GLOBAL + DDRCTL_WIN: return "DDRCTL" # DDRPHY 0xFE0C0000..0xFE100000 (256 KB per 4 ports; training at base) if 0xFE0C0000 <= addr < 0xFE100000: off = addr & 0xFFF if off in DDRPHY_TRAINING_OFFSETS: return "DDRPHY:TR" return "DDRPHY" # Clock/reset if 0xFD7C0000 <= addr < 0xFD800000: return "CRU" if 0xFD800000 <= addr < 0xFD8C0000: return "DDR_CRU" if 0xFD8C0000 <= addr < 0xFD8D0000: return "SCRU" # Register files if 0xFD580000 <= addr < 0xFD5A0000: return "GRF" if 0xFD5F0000 <= addr < 0xFD600000: return "BUS_GRF" if 0xFE050000 <= addr < 0xFE060000: return "SGRF" # PMU / firewall / scrambler if 0xFE400000 <= addr < 0xFE410000: return "PMU" if 0xFE030000 <= addr < 0xFE040000: return "FW_DDR" if 0xFECC0000 <= addr < 0xFECD0000: return "OTP" # Debug UART if 0xFEB50000 <= addr < 0xFEB60000: return "UART" # Boot SRAM (blob + globals) and PMU SRAM if 0xFF000000 <= addr < 0xFF100000: return "SRAM" if 0xFF100000 <= addr < 0xFF110000: return "PMU_SRAM" return "OTHER" def classify_rw(addr: int, is_write: bool) -> str: """Direction-aware tag: 'DDRCTL:SW wr' vs 'DDRCTL:SW rd'.""" return f"{classify(addr):10s} {'wr' if is_write else 'rd'}" if __name__ == "__main__": import sys # Smoke-test: classify a few known addresses tests = [ (0xFE0C0A24, "DDRPHY:TR"), # DfiStatus (0xFE0C0000, "DDRPHY"), # generic PHY reg (0xF7010C80, "DDRCTL:SW"), # SWCTL ch0 (0xF7010080, "DDRCTL:MR"), # MRCTRL0 ch0 (0xF7010500, "DDRCTL"), # other DDRCTL (0xFD7C0000, "CRU"), (0xFD800000, "DDR_CRU"), (0xFF001000, "SRAM"), (0xFF100000, "PMU_SRAM"), (0xFEB50000, "UART"), (0x00100000, "DDR_MEM"), ] fails = 0 for addr, want in tests: got = classify(addr) ok = "OK" if got == want else "FAIL" if got != want: fails += 1 print(f" {ok} 0x{addr:08x} -> {got:12s} (want {want})") sys.exit(1 if fails else 0)