diff --git a/docs/a5-sdma-overlay.md b/docs/a5-sdma-overlay.md index b0cf246545..34f5d2bee7 100644 --- a/docs/a5-sdma-overlay.md +++ b/docs/a5-sdma-overlay.md @@ -21,7 +21,9 @@ pre-allocates the per-rank PTO-ISA async-SDMA scratch workspace via read `workSpace` to submit SQEs to the SDMA hardware engine; the deferred completion machinery polls workspace event-records to signal consumers. -This is the a5 mirror of the a2a3 SDMA path, which is always on. +This is the a5 mirror of the a2a3 SDMA path. On a2a3 the provider is always +compiled in, but provisioning it is opt-in at runtime: `Worker(..., +enable_sdma=True)`, which defaults to `False`. ## Why it is gated off diff --git a/docs/aicpu-kernel-launch-mechanisms.md b/docs/aicpu-kernel-launch-mechanisms.md index 7e872c21ae..f856c6656d 100644 --- a/docs/aicpu-kernel-launch-mechanisms.md +++ b/docs/aicpu-kernel-launch-mechanisms.md @@ -268,7 +268,8 @@ above stays valid. - Issue [#822](https://github.com/hw-native-sys/simpler/issues/822) — the bug report with the diagnostic D2H recipe and CANN source pointers -- PR #537 — the migration that attempted Path B +- PR #537 — the migration that shipped Path A (dispatcher bootstrap plus + per-task `rtsLaunchCpuKernel`) - [`src/common/aicpu_loader/`](../src/common/aicpu_loader/) — the dispatcher bootstrap, three-symbol device contract, and per-task launch loader diff --git a/docs/comm-domain.md b/docs/comm-domain.md index a9cdc5d1d0..e0b3f8bfc4 100644 --- a/docs/comm-domain.md +++ b/docs/comm-domain.md @@ -108,7 +108,7 @@ symmetric window is realized: | Aspect | Sim | HCCL (onboard) | | ------ | --- | -------------- | -| Window memory | POSIX shm + `ftruncate`, mmap'd per rank | VMM physical allocation + shareable-handle import; peer access via `aclrtDeviceEnablePeerAccess` | +| Window memory | POSIX shm + `ftruncate`, mmap'd per rank | a2a3: Fabric V2 handle exchange (`ACL_MEM_SHARE_HANDLE_TYPE_FABRIC`), falling back to VMM + shareable-handle IPC where Fabric is unsupported. a5: VMM shareable handles only. Cross-card P2P via `aclrtDeviceEnablePeerAccess` on both | | Subset barrier | shm-header atomic, `allocation_id`-scoped | file barriers, `allocation_id`-scoped | | Window init | window zeroed before the subset barrier (`memset`) | window zeroed before the handle is announced (`aclrtMemset`) | | Async-DMA workspace | n/a | a2a3: opt-in per Worker (`enable_sdma`); a5: optional communication overlay, gated off by default | @@ -260,5 +260,5 @@ the child — allocate it with `create_host_buffer` instead. - `examples/workers/l3/dual_domain_overlap/` — overlapping domains where one worker participates in both. - `examples/a2a3/tensormap_and_ringbuffer/sdma_async_completion_demo/` — host - staging via `copy_to` + cross-rank `SdmaTget`; its producer `CoreCallable` - declares the SDMA workspace requirement. + staging via `copy_to` + cross-rank `SdmaTget`; the SDMA workspace is + provisioned by constructing the `Worker` with `enable_sdma=True`. diff --git a/docs/dynamic-linking.md b/docs/dynamic-linking.md index fb2b629060..2111c15ad7 100644 --- a/docs/dynamic-linking.md +++ b/docs/dynamic-linking.md @@ -256,7 +256,7 @@ Applies to all 4 runtime executors: a2a3 (hbg, tmr), a5 (hbg, tmr). | Dispatcher SO bytes | `DeviceRunnerBase::dispatcher_so_binary_` | Init-only: passed to `LoadAicpuOp::BootstrapDispatcher`, then cleared | | Runtime AICPU SO | Preinstall file `simpler_inner__.so` | Written once through dispatcher bootstrap, then registered via `rtsBinaryLoadFromFile` | | AICPU entry handles | `LoadAicpuOp` cached `rtFuncHandle`s | Per-runtime-group: reused by `rtsLaunchCpuKernel` on every task | -| AICore binary | `rtRegisterAllKernel` handle | Per-run: registered each `launch_aicore_kernel()` call | +| AICore binary | `rtRegisterAllKernel` handle | Lazily registered on the first `launch_aicore_kernel()`, then the cached handle is reused | | Kernel binaries | `func_id_to_addr_` (device GM addresses) | Per-task: uploaded to device GM, cached by func_id | | CANN HAL | `g_hal_handle` (file-scope static) | Process lifetime: loaded once for profiling, never closed | @@ -354,9 +354,10 @@ device_worker_main(device_id) bind_callable_to_runtime() replay + rtMalloc, rtMemcpy to device DeviceRunner::run() ensure_binaries_loaded() already done by init - rtsLaunchCpuKernel() cached rtFuncHandle - rtStreamSynchronize() wait for completion - launch_aicore_kernel() rtRegisterAllKernel + rtKernelLaunch + launch_aicore_kernel() cached rtRegisterAllKernel handle + + rtKernelLaunchWithHandleV2 + launch_aicpu_kernel(Run) rtsLaunchCpuKernel, cached rtFuncHandle + aclrtSynchronizeStreamWithTimeout() wait on both streams validate_runtime_impl() rtMemcpy results back to host ChipWorker.finalize() diff --git a/docs/hardware/chip-architecture.md b/docs/hardware/chip-architecture.md index b99fc2ec7b..c19e0f915e 100644 --- a/docs/hardware/chip-architecture.md +++ b/docs/hardware/chip-architecture.md @@ -229,7 +229,7 @@ A complete `Worker::run()` call traverses all three tiers: - writes FIN to its completion register 4. AICPU - - polls AICore completion registers (Device-nGnRnE MMIO) + - polls AICore completion registers (Device-nGnRE MMIO) - rmb() before reading any AICore-produced slot (see cache-coherency.md) - releases dependents into the ready queue diff --git a/docs/investigations/2026-07-a2a3-sdma-fault-teardown.md b/docs/investigations/2026-07-a2a3-sdma-fault-teardown.md index ed0b34e140..adada44d93 100644 --- a/docs/investigations/2026-07-a2a3-sdma-fault-teardown.md +++ b/docs/investigations/2026-07-a2a3-sdma-fault-teardown.md @@ -150,8 +150,10 @@ the rest of the system on the fast path. - A Worker constructed without `enable_sdma` creates no SDMA streams, so an AICore fault on it recovers on main's fast path (`507046`, ~0.3 s reset) rather than the ~306 s SDMA-generation stall documented above. -- The two-device `sdma_async_completion_demo` (a separate, pre-existing - comm-domain SDMA overlay, not the injection path) is unaffected by this change. +- The two-device `sdma_async_completion_demo` is a separate, pre-existing + comm-domain SDMA overlay rather than the injection path, but it does + provision SDMA itself (`enable_sdma=True`), so it carries the same + teardown cost. ## When to reconsider diff --git a/docs/worker-manager.md b/docs/worker-manager.md index 833ef607aa..8c544b58b7 100644 --- a/docs/worker-manager.md +++ b/docs/worker-manager.md @@ -169,9 +169,24 @@ WorkerCompletion LocalMailboxEndpoint::run(Ring *ring, WorkerDispatch d) { // Signal child write_state(mailbox_, MailboxState::TASK_READY); - // Poll for completion - while (read_state(mailbox_) != MailboxState::TASK_DONE) - std::this_thread::sleep_for(std::chrono::microseconds(50)); + // Spin-poll for completion. The task's latency runs through this wait, so + // it never sleeps (codestyle rule 5). A child that dies without publishing + // TASK_DONE would spin here forever, so its liveness is sampled on a + // kChildLivenessPollPeriod steady-clock period rather than an iteration + // count, which no longer maps to a bounded time at spin speed. + auto next_liveness_check = steady_clock::now() + kChildLivenessPollPeriod; + while (read_state(mailbox_) != MailboxState::TASK_DONE) { + auto now = steady_clock::now(); + if (now >= next_liveness_check) { + next_liveness_check = now + kChildLivenessPollPeriod; + std::string death = check_child_death(); + if (!death.empty()) { + completion.outcome = EndpointOutcome::ENDPOINT_FAILURE; + completion.error_message = "LocalMailboxEndpoint::run: " + death; + return completion; + } + } + } int err = read_error(mailbox_); write_state(mailbox_, MailboxState::IDLE); @@ -187,7 +202,10 @@ Parent-side cost per dispatch: - One reserved `uint64`, one `CallConfig`, one 32-byte digest, and one TaskArgs blob - One signal (`write_state`) -- Poll loop with `sleep_for(50us)` (not busy-wait) +- Spin-poll loop, never a sleep — a task's latency passes through this wait + ([codestyle](../.claude/rules/codestyle.md) rule 5). Child liveness is sampled + on a steady-clock period, so a dead child ends the wait with + `ENDPOINT_FAILURE` instead of spinning the parent forever - One explicit completion outcome: success, task failure, or endpoint failure Total ~nanoseconds overhead; the wait is dominated by actual kernel execution. diff --git a/src/a2a3/platform/onboard/host/CMakeLists.txt b/src/a2a3/platform/onboard/host/CMakeLists.txt index c0d0fb11d8..667322b969 100644 --- a/src/a2a3/platform/onboard/host/CMakeLists.txt +++ b/src/a2a3/platform/onboard/host/CMakeLists.txt @@ -71,7 +71,6 @@ list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/aicpu_loader/host/load_aicpu_op.cpp" ) # Add common/platform/onboard/host sources (shared between a2a3 / a5 onboard). -# See .docs/ONBOARD_HOST_COMMON_REFACTOR.md for the migration plan. list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/onboard/host/device_runner_helpers.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/onboard/host/device_runner_base.cpp" diff --git a/src/a2a3/platform/onboard/host/comm_hccl.cpp b/src/a2a3/platform/onboard/host/comm_hccl.cpp index 5f9f5ac4bd..f6e2e7d815 100644 --- a/src/a2a3/platform/onboard/host/comm_hccl.cpp +++ b/src/a2a3/platform/onboard/host/comm_hccl.cpp @@ -833,8 +833,7 @@ static FabricAttempt alloc_windows_via_fabric(CommHandle h, uint64_t win_size) { // windowsOut[] is intentionally left zero: no kernel path reads it // (verified by grep across simpler + pto-isa). The field is kept in // CommContext only to preserve byte-equivalence with pto-isa's parallel - // HcclDeviceContext declaration; removing it is gated on the F4 - // private-ization decision (see .docs/28.l3-comm/ext.01.pr-774-review.md). + // HcclDeviceContext declaration. // host_ctx was value-initialized at handle construction (CommContext{}), // and the idempotency guard in comm_alloc_windows prevents a second entry; // no re-zero needed before populating it here. diff --git a/src/a2a3/platform/sim/host/CMakeLists.txt b/src/a2a3/platform/sim/host/CMakeLists.txt index 4dbdb580a0..fdce2dc17f 100644 --- a/src/a2a3/platform/sim/host/CMakeLists.txt +++ b/src/a2a3/platform/sim/host/CMakeLists.txt @@ -54,8 +54,7 @@ list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform_comm/comm_sim.cpp" ) # Shared sim host sources (DeviceRunnerBase + c_api glue + MemoryAllocator), -# linked once per arch's libhost_runtime.so. Mirrors the onboard split from -# PR #928. See .docs/ONBOARD_HOST_COMMON_REFACTOR.md for the migration story. +# linked once per arch's libhost_runtime.so. Mirrors the onboard split. list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/sim/host/device_runner_base.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/sim/host/c_api_shared.cpp" diff --git a/src/a2a3/runtime/host_build_graph/runtime/backend/sdma/sdma_completion_kernel.h b/src/a2a3/runtime/host_build_graph/runtime/backend/sdma/sdma_completion_kernel.h index 49ee7cc11a..81aaab111b 100644 --- a/src/a2a3/runtime/host_build_graph/runtime/backend/sdma/sdma_completion_kernel.h +++ b/src/a2a3/runtime/host_build_graph/runtime/backend/sdma/sdma_completion_kernel.h @@ -45,7 +45,7 @@ enum class SdmaOp : uint8_t { // sync_id selects which event-record slot inside the workspace the engine // writes into. Concurrent dispatches must use distinct sync_ids; today every // caller submits one request per kernel invocation so passing 0 is safe. -// Future work (see .docs/25.comm-api-refactor/03.implementation-plan.md §5.2) +// Future work // will fold sync_id allocation into the adapter. template struct SdmaRequestDescriptor { diff --git a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h index 0ff21908fe..8a24b48f2b 100644 --- a/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h +++ b/src/a2a3/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h @@ -45,7 +45,7 @@ enum class SdmaOp : uint8_t { // sync_id selects which event-record slot inside the workspace the engine // writes into. Concurrent dispatches must use distinct sync_ids; today every // caller submits one request per kernel invocation so passing 0 is safe. -// Future work (see .docs/25.comm-api-refactor/03.implementation-plan.md §5.2) +// Future work // will fold sync_id allocation into the adapter. template struct SdmaRequestDescriptor { diff --git a/src/a5/platform/onboard/host/CMakeLists.txt b/src/a5/platform/onboard/host/CMakeLists.txt index c6bbbff57e..265f6e327a 100644 --- a/src/a5/platform/onboard/host/CMakeLists.txt +++ b/src/a5/platform/onboard/host/CMakeLists.txt @@ -84,7 +84,6 @@ list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/aicpu_loader/host/load_aicpu_op.cpp" ) # Add common/platform/onboard/host sources (shared between a2a3 / a5 onboard). -# See .docs/ONBOARD_HOST_COMMON_REFACTOR.md for the migration plan. list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/onboard/host/device_runner_helpers.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/onboard/host/device_runner_base.cpp" diff --git a/src/a5/platform/onboard/host/comm_hccl.cpp b/src/a5/platform/onboard/host/comm_hccl.cpp index 8cf6734ac2..4d8be9a529 100644 --- a/src/a5/platform/onboard/host/comm_hccl.cpp +++ b/src/a5/platform/onboard/host/comm_hccl.cpp @@ -19,8 +19,7 @@ * * Scope: L3 single-host multi-card only. The VMM shareable-handle * exchange is host-local, so cross-host (L4) deployments need a different - * windows backend -- see .docs/28.l3-comm/ext.01.pr-774-review.md F2 / - * 05.plan.zh.md for the channel-API direction. + * windows backend. */ #include "platform_comm/comm.h" @@ -613,8 +612,7 @@ static int alloc_windows_via_ipc(CommHandle h, uint64_t win_size) { // windowsOut[] is intentionally left zero: no kernel path reads it // (verified by grep across simpler + pto-isa). The field is kept in // CommContext only to preserve byte-equivalence with pto-isa's parallel - // HcclDeviceContext declaration; removing it is gated on the F4 - // private-ization decision (see .docs/28.l3-comm/ext.01.pr-774-review.md). + // HcclDeviceContext declaration. // host_ctx was value-initialized at handle construction (CommContext{}), // and the idempotency guard in comm_alloc_windows prevents a second entry; // no re-zero needed before populating it here. diff --git a/src/a5/platform/sim/host/CMakeLists.txt b/src/a5/platform/sim/host/CMakeLists.txt index 0d4907322b..c544dc4816 100644 --- a/src/a5/platform/sim/host/CMakeLists.txt +++ b/src/a5/platform/sim/host/CMakeLists.txt @@ -55,8 +55,7 @@ list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform_comm/comm_sim.cpp" ) # Shared sim host sources (DeviceRunnerBase + c_api glue + MemoryAllocator), -# linked once per arch's libhost_runtime.so. Mirrors the onboard split from -# PR #928. See .docs/ONBOARD_HOST_COMMON_REFACTOR.md for the migration story. +# linked once per arch's libhost_runtime.so. Mirrors the onboard split. list(APPEND HOST_RUNTIME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/sim/host/device_runner_base.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/platform/sim/host/c_api_shared.cpp" diff --git a/src/a5/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h b/src/a5/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h index 50f0f46c78..1de677520c 100644 --- a/src/a5/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h +++ b/src/a5/runtime/tensormap_and_ringbuffer/runtime/backend/sdma/sdma_completion_kernel.h @@ -46,7 +46,7 @@ enum class SdmaOp : uint8_t { // sync_id selects which event-record slot inside the workspace the engine // writes into. Concurrent dispatches must use distinct sync_ids; today every // caller submits one request per kernel invocation so passing 0 is safe. -// Future work (see .docs/25.comm-api-refactor/03.implementation-plan.md §5.2) +// Future work // will fold sync_id allocation into the adapter. template struct SdmaRequestDescriptor { diff --git a/src/common/aicpu_loader/README.md b/src/common/aicpu_loader/README.md index 4d93420ffa..5f9bab6a72 100644 --- a/src/common/aicpu_loader/README.md +++ b/src/common/aicpu_loader/README.md @@ -17,15 +17,16 @@ concurrent bootstrap on a shared file corrupted the mmap'd image and faulted The dispatcher SO itself is **never** persisted to disk and **never** dispatches at per-task launch time. After bootstrap, the host registers the preinstall file via `rtsBinaryLoadFromFile` (JSON load, cpuKernelMode=0) and -resolves `simpler_aicpu_exec` once via -`rtsFuncGetByName`; per-task launches go through `rtsLaunchCpuKernel` on the +resolves every symbol the runtime declares it exports via +`rtsFuncGetByName` (a miss is a build/registration error, not an optional +gap); per-task launches go through `rtsLaunchCpuKernel` on the cached `rtFuncHandle`. The main `aicpu_scheduler` owns the dlopen of the preinstall file; the dispatcher is out of the picture once bootstrap returns. The source is runtime-agnostic. It is built per-arch under -`build/lib//onboard//libsimpler_aicpu_dispatcher.so` as a -sibling of each runtime's host_runtime.so. A single process binding multiple -runtimes can share one dispatcher SO on disk; the host process-level +`build/lib//dispatcher/libsimpler_aicpu_dispatcher.so`, one per arch and +shared across every runtime. A single process binding multiple runtimes +therefore shares one dispatcher SO on disk; the host process-level fingerprint cache deduplicates bootstrap calls by inner-SO Build-ID. ## Argument ABI boundaries @@ -47,7 +48,8 @@ This private bootstrap structure is distinct from the platform runtime `KernelArgs` payload used by per-task launches. Per-task AICPU launch passes the front-less `KernelArgs` payload directly to `rtsLaunchCpuKernel` (no CANN launch front): `runtime_args` is at offset 0, followed by profiling/logging -fields, register tables, and `device_id`. AICore receives only the same +fields and register tables. `device_id` is not in this payload — it reaches +the device once via `InitArgs`. AICore receives only the same front-less `KernelArgs` via a host-owned device copy. ## Exported entry points diff --git a/src/common/platform/onboard/host/device_runner_helpers.h b/src/common/platform/onboard/host/device_runner_helpers.h index 18d95432ae..84719ee127 100644 --- a/src/common/platform/onboard/host/device_runner_helpers.h +++ b/src/common/platform/onboard/host/device_runner_helpers.h @@ -20,7 +20,7 @@ * - `KernelArgsHelper`: host-side `KernelArgs` wrapper with device-memory * management for the H2D `Runtime` and `KernelArgs` copies. * - * Future migrations (see `.docs/ONBOARD_HOST_COMMON_REFACTOR.md`): + * Future migrations: * - `DeviceRunnerBase` (lifecycle + registration + profiling init). * - C-API common shims. */ diff --git a/src/common/platform/sim/host/device_runner_base.h b/src/common/platform/sim/host/device_runner_base.h index 2990eea08a..fa94f8cc2e 100644 --- a/src/common/platform/sim/host/device_runner_base.h +++ b/src/common/platform/sim/host/device_runner_base.h @@ -59,9 +59,9 @@ struct CallConfig; // task_interface/call_config.h — per-run config threaded // PLATFORM_MAX_BLOCKDIM (24 on a2a3, 36 on a5). The simulator runs one OS // thread per AICore, so taking the whole modelled chip would be 72-108 threads // per case; under xdist that is several hundred threads for no added coverage. -// It is not a ceiling: an explicit block_dim is still honoured up to -// PLATFORM_MAX_BLOCKDIM. Onboard is unaffected — it auto-resolves from the real -// per-stream core limits. +// CallConfig exposes no block_dim knob, so this is what a sim run takes. +// Onboard is unaffected — it auto-resolves from the real per-stream core +// limits. constexpr int SIM_AUTO_BLOCKDIM = 8; class SimDeviceRunnerBase { diff --git a/src/common/platform_comm/comm_context.h b/src/common/platform_comm/comm_context.h index a00ce35008..d9aad3be1e 100644 --- a/src/common/platform_comm/comm_context.h +++ b/src/common/platform_comm/comm_context.h @@ -24,14 +24,8 @@ * layout is owned end-to-end by simpler. * - comm_sim.cpp: same shape, filled with malloc'd host pointers. * - * The earlier "HCCL MESH reinterpret_cast / RING reverse-parse of - * HcclOpResParam" paths have been deleted along with their internal-ABI - * coupling -- see .docs/28.l3-comm/ext.01.pr-774-review.md for context. - * - * Long-term private-ization of this struct (decouple from the pto-isa - * HcclDeviceContext parallel declaration) is tracked as F4 in the same - * doc; this file is intentionally left at the current shared layout - * until that decision lands. + * The layout is shared with pto-isa's parallel HcclDeviceContext + * declaration and must stay byte-equivalent with it. */ #pragma once diff --git a/src/common/worker/pto_runtime_c_api.h b/src/common/worker/pto_runtime_c_api.h index d137733985..8d659ee284 100644 --- a/src/common/worker/pto_runtime_c_api.h +++ b/src/common/worker/pto_runtime_c_api.h @@ -256,7 +256,7 @@ int simpler_register_callable(DeviceContextHandle ctx, int32_t callable_id, cons * Per-stage run timing is not returned — the platform emits it as `[STRACE]` * log markers (see docs/dfx/host-trace.md). * - * `config` carries block_dim (0 = auto), aicpu_thread_num, the five diagnostic + * `config` carries aicpu_thread_num, the five diagnostic * enables + output_prefix, and the per-task ring sizing overrides * (`runtime_env.ring_task_window` / `.ring_heap` / `.ring_dep_pool`, each a * per-scope-depth-ring array of RUNTIME_ENV_RING_COUNT entries; 0 = unset, diff --git a/tests/ut/cpp/a5/test_aicore_completion_mailbox.cpp b/tests/ut/cpp/a5/test_aicore_completion_mailbox.cpp index d533c1f1e4..e3aae03bfb 100644 --- a/tests/ut/cpp/a5/test_aicore_completion_mailbox.cpp +++ b/tests/ut/cpp/a5/test_aicore_completion_mailbox.cpp @@ -136,8 +136,8 @@ TEST(A5AICoreCompletionMailbox, ConditionAttachesToExistingEntry) { wait_list.entries[0].normal_done = false; wait_list.count = 1; - // a5 is counter-only (no SDMA event-record backend), so both conditions - // are COUNTER and bind counter_addr / expected_value. + // Both conditions here are COUNTER and bind counter_addr / expected_value; + // a5 also registers SDMA event-record and URMA event-handle backends. constexpr uint64_t kAddr1 = 0x1000; constexpr uint64_t kAddr2 = 0x2000; ASSERT_TRUE(mb->try_push_condition(token, kAddr1, /*expected=*/3, COMPLETION_ENGINE_SDMA, COMPLETION_TYPE_COUNTER));