65f358fdfa
Three coupled fixes so enable_data=False now reports byte-identical kernel-body sim latency (max(t_end) - min(t_start) over op_log) as enable_data=True, and skips setup-write sim events that were pure wall-clock overhead. Before this change, at Case 4 (Cube-SP x PE-SP) decode, S_kv=8K: enable_data=False -> latency_ns = 0 (op_log empty) enable_data=True -> latency_ns = 30.646 us (correct) After: enable_data=False -> latency_ns = 30.646 us (byte-equal) enable_data=True -> latency_ns = 30.646 us (unchanged) engine.py: always create OpLogger. Previously OpLogger was gated on enable_data=True together with MemoryStore, so op_log stayed empty when data mode was off. Decouple: MemoryStore is gated (Phase 2 DataExecutor still needs it) but OpLogger runs unconditionally, receiving memory_store=None when data mode is off. OpLogger already guards its arr.copy() snapshot paths on `if self._memory_store is not None`. pe_cpu.py: always use the ADR-0020 greenlet execution path. The if store is not None: _execute_greenlet(); else: _execute_legacy branch gated the *execution model* on data-mode presence. The legacy command-list path predates ADR-0020 and doesn't route IpcqSendCmd through PE_IPCQ (it goes to PE_SCHEDULER instead), so all 189 Case-4 ipcq_copy fabric transfers were silently no-op'd in that mode. Forcing greenlet gives identical sim behavior in both modes. KernelRunner already guards its store reads on `self._store is not None`. context.py: gate setup MemoryWriteMsg on memory_store presence. Under enable_data=False there is no MemoryStore to populate and no Phase 2 replay, so the per-shard sim events for Q/K/V deploy are pure wall-clock overhead with no effect on reported kernel latency (Yangwook's max-min formula excludes pre-kernel ops). Handle count for Case 4 at S_kv=8K drops 229 -> 37 under enable_data=False. Verified: - tests/attention/test_milestone_gqa_decode_long_ctx_4cases.py: 18/18 pass - Parity probe: enable_data=False/True both report 30.646 us kernel sim time, 1649 op_log records, 189 ipcq_copy events Known follow-up: pe_cpu._execute_legacy is now dead code but left in place; separate cleanup once we confirm no downstream caller. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>