mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
5b3c7dd08d
Today's session work
- runtime/src/debug_server.c: freeze_check TCP cmd snapshots all liveness
counters (PC, exception entries, exception_reentry_blocks, dirty_ram
blocks/insns, fn_entry total + top-K histogram, SIO IRQ pending +
countdown, sio_stat/i_stat/i_mask, mc_max_state) for tight-loop
diagnosis when the runtime hangs
- runtime/src/debug_server.c: wtrace slot 12 covering [0x72F0..0x72F4]
(data-byte counter); measured peak=1 confirming setup_data_phase resets
the counter mid-cycle
- runtime/src/interrupts.c: exception_entries_total + exception_reentry_blocks
counters + psx_get_freeze_diag accessor
- runtime/src/sio.c: sio_get_freeze_diag accessor for IRQ pacing internals
- memory entries: phase4_card_gate_setup_writes_2026_04_28 (refutes the
prior \"missing [0x7568+slot] clearer\" framing — setup functions write
LSB=0 directly), phase4_72f0_one_byte_per_vblank_2026_04_28 (peak=1
measurement)
Overnight session work bundled in
- runtime/src/dirty_ram_interp.{c,h}: small MIPS interpreter for
install-at-runtime kernel RAM stubs (Rule 18; e.g., SIO data-byte
handler the BIOS writes to RAM 0xCF0)
- recompiler/src/full_function_emitter.{cpp,h}: 3057 jal/jalr continuation
return labels added to dispatch table (continuation fix); branch
fall-through fix for conditional-branch delay slots
- recompiler/src/strict_translator.cpp: matching translator updates
- generated/: regenerated SCPH1001 dispatch + full C output reflecting
the recompiler changes
- runtime/include/debug_server.h, src/memory.c: card_txn ring + SIO IRQ
ring + EvCB walk ring + per-PC dirty_ram counters + always-on wtrace
coverage for [0x755A], [0x7514], [0x7528], [0x7520], [0x74A4],
[0x75C0..C8], [0x74B8..C0]
- recompiler/tests/, runtime/tests/: SIO/card protocol unit tests
- tools/: 60+ Python diagnostic scripts (chain_trace analysis, SIO trace
diff, EvCB walker, wtrace dumpers, etc.)
- docs/: psx_bios_disasm reference + dynamic_handler_install rationale
- OVERNIGHT_2026_04_28.md, SUMMARY_20260412_2.md: session logs
Phase 4 status (still blocked, root cause better understood)
- BIOS card chain runs through R-handlers correctly (chain_trace shows
R1..R11 cycling 26x); shell IS retriggering _card_read
- Install handler at ROM 0xBFC15F1C increments [0x72F0] correctly per
SIO IRQ; gate at <0x80 / <0x7F is correct
- Bottleneck: SIO IRQ countdown is access-paced, fires ~1× per VBlank
vs ~128× needed; setup_data_phase (called from outer coord on VBlank)
zeroes [0x72F0] before counter reaches 128
- Both attempted fixes today caused freezes:
* VBlank deferral on [0x75C0]==1 — pending VBlank already in i_stat
delivered anyway; tighter dispatch gate also locked up
* Cycle-paced sio_tick at rates 50, 200 (and gated on [0x75C0]==1) —
runtime freezes once data phase activates, root cause unidentified
- delay=5 narrows the threshold (peak=2 vs peak=1, no freeze) but
doesn't get to 0x80
- Real fix likely requires deeper instrumentation of the freeze (call
stack / dispatch state at the moment of TCP starvation)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
59 lines
2.3 KiB
Python
59 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Parse sio_trace JSON output and display human-readable table."""
|
|
import json
|
|
import sys
|
|
|
|
MC_NAMES = {
|
|
0:'IDLE', 1:'CMD', 2:'ID1', 3:'ID2', 4:'ADDR_MSB', 5:'ADDR_LSB',
|
|
6:'R_ACK1', 7:'R_ACK2', 8:'R_DATA', 9:'R_CHK', 10:'R_END',
|
|
11:'W_DATA', 12:'W_CHK', 13:'W_ACK1', 14:'W_ACK2', 15:'W_END',
|
|
16:'GID1', 17:'GID2', 18:'GID3', 19:'GID4'
|
|
}
|
|
DEV_NAMES = {0:'NONE', 1:'PAD', 2:'MC'}
|
|
|
|
def main():
|
|
path = sys.argv[1] if len(sys.argv) > 1 else '/tmp/sio_trace.json'
|
|
filt = sys.argv[2] if len(sys.argv) > 2 else 'all' # 'all', 'mc', 'abort'
|
|
|
|
with open(path) as f:
|
|
data = json.load(f)
|
|
|
|
print(f"Total SIO bytes: {data['total']}, Showing: {data['count']}")
|
|
print(f"{'SEQ':>7} {'TX':>4} {'RX':>4} {'DEV':>10} {'MC_STATE':>20} {'CTRL':>6} {'FUNC':>10} {'IRQ':>3} {'FLAGS'}")
|
|
print("-" * 90)
|
|
|
|
for e in data['entries']:
|
|
# Handle both int and hex-string formats
|
|
tx_val = int(e['tx'], 16) if isinstance(e['tx'], str) else e['tx']
|
|
rx_val = int(e['rx'], 16) if isinstance(e['rx'], str) else e['rx']
|
|
ctrl_val = int(e['ctrl'], 16) if isinstance(e['ctrl'], str) else e['ctrl']
|
|
func_val = int(e['func'], 16) if isinstance(e['func'], str) else e['func']
|
|
mc_pre = MC_NAMES.get(e['mc_pre'], str(e['mc_pre']))
|
|
mc_post = MC_NAMES.get(e['mc_post'], str(e['mc_post']))
|
|
dev_pre = DEV_NAMES.get(e['dev_pre'], str(e['dev_pre']))
|
|
dev_post = DEV_NAMES.get(e['dev_post'], str(e['dev_post']))
|
|
|
|
flags = []
|
|
if e['abort']:
|
|
flags.append('ABORT')
|
|
if e['dev_pre'] != e['dev_post']:
|
|
flags.append('DEV_CHG')
|
|
if e['mc_pre'] != e['mc_post']:
|
|
flags.append('MC_CHG')
|
|
|
|
# Filter
|
|
is_card = e['dev_post'] == 2 or e['dev_pre'] == 2 or tx_val == 0x81
|
|
if filt == 'mc' and not is_card and not e['abort']:
|
|
continue
|
|
if filt == 'abort' and not e['abort']:
|
|
continue
|
|
|
|
flag_str = ' '.join(flags)
|
|
dev_str = f"{dev_pre}->{dev_post}"
|
|
mc_str = f"{mc_pre}->{mc_post}" if mc_pre != mc_post else mc_pre
|
|
|
|
print(f"{e['seq']:7d} 0x{tx_val:02X} 0x{rx_val:02X} {dev_str:>10} {mc_str:>20} 0x{ctrl_val:04X} 0x{func_val:08X} {e['irq_cd']:>3} {flag_str}")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|