121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
# tools/emu-dec-probe.py -- in-process DEC capture (no GDB server needed).
|
|
#
|
|
# Reproduces emu/gdb_decode.gdb semantics from inside renode: on every
|
|
# execution of the firmware's touch-conversion decode at 0x01035618, log
|
|
# pc/regs/flags/shadow exactly like the gdb recipe's printf:
|
|
# DEC pc=%08x r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x flags=%08x sh=%08x,%08x
|
|
# where flags = [0x010C5B18], sh = ([0x03FFF140], [0x03FFF144]).
|
|
#
|
|
# Why not GDB: renode 1.16's GDB stub fatally crashes on stray socket bytes,
|
|
# and this sandbox's runtime probes fresh localhost listeners -- any
|
|
# StartGdbServer port gets garbage within seconds. A cpu hook has no socket
|
|
# and runs at full emulation speed.
|
|
#
|
|
# Gate: active only when ROSE_DEC_TRACE=1. Log path: ROSE_DEC_LOG (default
|
|
# .build/emu/dec-trace.log relative to the renode host cwd -- prefer an
|
|
# absolute path). Bounded: first ROSE_DEC_MAX lines (default 200), then only
|
|
# a counter line every 10000 hits.
|
|
#
|
|
# Wire: include from a boot .resc BEFORE `start`, e.g.
|
|
# ROSE_EXTRA_INCLUDE=/path/to/emu-dec-probe.py
|
|
# or via emu/boot_probe.py --dec-trace.
|
|
#
|
|
# Manual use (already-running machine, paused):
|
|
# include @tools/emu-dec-probe.py
|
|
|
|
import os
|
|
|
|
DEC_PC = 0x01035618
|
|
FLAGS_ADDR = 0x010C5B18
|
|
SHADOW_ADDR = 0x03FFF140
|
|
TRANSFER_PTR_ADDR = 0x0183A458
|
|
|
|
_enabled = os.environ.get("ROSE_DEC_TRACE", "0") == "1"
|
|
|
|
|
|
def _env_int(name, default):
|
|
try:
|
|
return int(os.environ.get(name, str(default)))
|
|
except Exception:
|
|
return default
|
|
|
|
|
|
def _install():
|
|
# NOTE: keep the default absolute (/tmp); renode's python resolves
|
|
# relative paths against its install dir, not the repo. Harness runs
|
|
# always export an absolute ROSE_DEC_LOG.
|
|
log_path = os.environ.get("ROSE_DEC_LOG", "/tmp/rose_dec_trace.log")
|
|
max_lines = _env_int("ROSE_DEC_MAX", 200)
|
|
try:
|
|
parent = os.path.dirname(os.path.abspath(log_path))
|
|
if parent and not os.path.exists(parent):
|
|
os.makedirs(parent)
|
|
except Exception as e:
|
|
print("dec-probe: mkdir failed: %s" % e)
|
|
return
|
|
try:
|
|
log = open(log_path, "w")
|
|
log.write("# DEC trace (emu-dec-probe.py)\n")
|
|
log.flush()
|
|
except Exception as e:
|
|
print("dec-probe: open %s failed: %s" % (log_path, e))
|
|
return
|
|
sysbus = self.Machine["sysbus"]
|
|
state = {"n": 0}
|
|
|
|
def _reg(cpu, n):
|
|
try:
|
|
return cpu.GetRegister(n).RawValue & 0xFFFFFFFF
|
|
except Exception:
|
|
return 0
|
|
|
|
def _rd32(a):
|
|
try:
|
|
return int(sysbus.ReadDoubleWord(a)) & 0xFFFFFFFF
|
|
except Exception:
|
|
return 0
|
|
|
|
def _dec(cpu, _):
|
|
state["n"] += 1
|
|
n = state["n"]
|
|
tptr = _rd32(TRANSFER_PTR_ADDR)
|
|
tval0 = _rd32(tptr) if tptr else 0
|
|
tval4 = _rd32(tptr + 4) if tptr else 0
|
|
# Always log hits that carry a nonzero sample word (the press/lift
|
|
# records the driver publishes), even past the bounded cap, so the
|
|
# decode of an actual touch is never missed behind boot-turn DEC spam.
|
|
if n <= max_lines or tval4 != 0 or tval0 != 0:
|
|
log.write(
|
|
"DEC pc=%08X r0=%08X r1=%08X r2=%08X r3=%08X r4=%08X "
|
|
"flags=%08X sh=%08X,%08X raw=%08X,%08X,%08X,%08X "
|
|
"tptr=%08X tval=%08X,%08X\n"
|
|
% (_reg(cpu, 15), _reg(cpu, 0), _reg(cpu, 1),
|
|
_reg(cpu, 2), _reg(cpu, 3), _reg(cpu, 4),
|
|
_rd32(FLAGS_ADDR),
|
|
_rd32(SHADOW_ADDR), _rd32(SHADOW_ADDR + 4),
|
|
_rd32(SHADOW_ADDR + 6), _rd32(SHADOW_ADDR + 10),
|
|
_rd32(SHADOW_ADDR + 14), _rd32(SHADOW_ADDR + 18),
|
|
tptr, tval0, tval4))
|
|
log.flush()
|
|
elif n % 10000 == 0:
|
|
log.write("# DEC hits=%d\n" % n)
|
|
log.flush()
|
|
|
|
for cpu in sysbus.GetCPUs():
|
|
try:
|
|
name = cpu.GetName()
|
|
except Exception:
|
|
continue
|
|
if name.endswith("cpu0"):
|
|
cpu.AddHook(DEC_PC, _dec)
|
|
print("dec-probe: installed on %s -> %s (max %d)"
|
|
% (name, log_path, max_lines))
|
|
|
|
|
|
if _enabled:
|
|
try:
|
|
_install()
|
|
except Exception as e:
|
|
print("dec-probe: install failed: %s" % e)
|
|
else:
|
|
print("dec-probe: disabled (set ROSE_DEC_TRACE=1 to capture DEC tuples)")
|