From f31a6dafc70861c535eefabe2a2f4dea0a4f0b12 Mon Sep 17 00:00:00 2001 From: Kur0x Date: Tue, 28 Jul 2026 11:18:43 +0800 Subject: [PATCH] feat(ccu): integrate internal collective backend --- src/collectives/CMakeLists.txt | 2 + src/collectives/host/collective_backend.cpp | 113 ++ src/collectives/host/collective_backend.h | 52 + src/collectives/host/tilexr_collectives.cpp | 165 +- src/comm/CMakeLists.txt | 9 + src/comm/ccu/tilexr_ccu_backend.cpp | 175 ++ src/comm/ccu/tilexr_ccu_backend.h | 70 + .../ccu/tilexr_ccu_collective_planner.cpp | 842 ++++++++++ src/comm/ccu/tilexr_ccu_collective_planner.h | 105 ++ src/comm/ccu/tilexr_ccu_executor.cpp | 53 + src/comm/ccu/tilexr_ccu_executor.h | 34 + src/comm/ccu/tilexr_ccu_runtime_session.cpp | 339 ++++ src/comm/ccu/tilexr_ccu_runtime_session.h | 68 + src/comm/tilexr_comm.cpp | 49 +- src/comm/tilexr_comm.h | 8 + src/comm/tilexr_internal.cpp | 27 +- src/include/tilexr_api.h | 14 +- src/include/tilexr_collectives.h | 30 + tests/ccu/CMakeLists.txt | 10 + tests/ccu/ccu_npu_smi_busy_guard.py | 136 ++ tests/ccu/ccu_tilexr_basic_info_probe.cpp | 124 ++ tests/ccu/ccu_tilexr_direct_smoke_probe.cpp | 1382 ++++++++++++++++ tests/ccu/check_tile_comm_no_hcomm_deps.sh | 50 + .../run_tilexr_ccu_direct_evening_smoke.sh | 538 +++++++ tests/ccu/run_tilexr_ccu_direct_smoke.sh | 662 ++++++++ tests/ccu/test_tilexr_ccu_backend_boundary.py | 130 ++ tests/ccu/test_tilexr_ccu_basic_info_probe.py | 138 ++ .../ccu/test_tilexr_ccu_direct_smoke_probe.py | 600 +++++++ .../test_tilexr_ccu_direct_smoke_runner.py | 1422 +++++++++++++++++ ...est_tilexr_ccu_public_api_compile_probe.py | 19 + tests/ccu/test_tilexr_ccu_public_comm_api.py | 76 + .../test_tilexr_ccu_source_guard_coverage.py | 125 ++ tests/collectives/CMakeLists.txt | 15 + ...test_tilexr_collective_backend_options.cpp | 147 ++ tests/comm/unit/test_tilexr_source_guards.cpp | 822 +++++++++- 35 files changed, 8521 insertions(+), 30 deletions(-) create mode 100644 src/collectives/host/collective_backend.cpp create mode 100644 src/collectives/host/collective_backend.h create mode 100644 src/comm/ccu/tilexr_ccu_backend.cpp create mode 100644 src/comm/ccu/tilexr_ccu_backend.h create mode 100644 src/comm/ccu/tilexr_ccu_collective_planner.cpp create mode 100644 src/comm/ccu/tilexr_ccu_collective_planner.h create mode 100644 src/comm/ccu/tilexr_ccu_executor.cpp create mode 100644 src/comm/ccu/tilexr_ccu_executor.h create mode 100644 src/comm/ccu/tilexr_ccu_runtime_session.cpp create mode 100644 src/comm/ccu/tilexr_ccu_runtime_session.h create mode 100644 tests/ccu/CMakeLists.txt create mode 100644 tests/ccu/ccu_npu_smi_busy_guard.py create mode 100644 tests/ccu/ccu_tilexr_basic_info_probe.cpp create mode 100644 tests/ccu/ccu_tilexr_direct_smoke_probe.cpp create mode 100644 tests/ccu/check_tile_comm_no_hcomm_deps.sh create mode 100644 tests/ccu/run_tilexr_ccu_direct_evening_smoke.sh create mode 100644 tests/ccu/run_tilexr_ccu_direct_smoke.sh create mode 100644 tests/ccu/test_tilexr_ccu_backend_boundary.py create mode 100644 tests/ccu/test_tilexr_ccu_basic_info_probe.py create mode 100644 tests/ccu/test_tilexr_ccu_direct_smoke_probe.py create mode 100644 tests/ccu/test_tilexr_ccu_direct_smoke_runner.py create mode 100644 tests/ccu/test_tilexr_ccu_public_api_compile_probe.py create mode 100644 tests/ccu/test_tilexr_ccu_public_comm_api.py create mode 100644 tests/ccu/test_tilexr_ccu_source_guard_coverage.py create mode 100644 tests/collectives/unit/test_tilexr_collective_backend_options.cpp diff --git a/src/collectives/CMakeLists.txt b/src/collectives/CMakeLists.txt index 258f29ef..b73bda17 100644 --- a/src/collectives/CMakeLists.txt +++ b/src/collectives/CMakeLists.txt @@ -23,12 +23,14 @@ add_custom_command( ) set(TILEXR_COLLECTIVES_SOURCE_FILE + host/collective_backend.cpp host/collective_launcher.cpp host/collective_utils.cpp host/collective_kernel.cpp host/perf_trace_report.cpp host/perf_trace_session.cpp host/tilexr_collectives.cpp + host/collective_backend.h ${TILEXR_COLLECTIVES_KERNEL_EMBED_CPP} ) diff --git a/src/collectives/host/collective_backend.cpp b/src/collectives/host/collective_backend.cpp new file mode 100644 index 00000000..0896a66a --- /dev/null +++ b/src/collectives/host/collective_backend.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024-2026 TileXR Project + * This file is a part of the CANN Open Software. + * Licensed under CANN Open Software License Agreement Version 1.0 (the "License"). + * Please refer to the License for details. You may not use this file except in compliance with the License. + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + * See LICENSE in the root of the software repository for the full text of the License. + */ +#include "collective_backend.h" + +#include "../../comm/ccu/tilexr_ccu_backend.h" +#include "../../comm/tilexr_comm.h" + +namespace TileXRCollectives { +namespace Host { +namespace { + +BackendTestState g_testState {}; + +int DispatchAiv(const CollectiveRequest &request) +{ + (void)request; + return g_testState.enabled ? g_testState.aivReturn : TileXR::TILEXR_SUCCESS; +} + +int DispatchUdma(const CollectiveRequest &request) +{ + if (g_testState.enabled) { + if (!g_testState.udmaInitialized) { + return TileXR::TILEXR_ERROR_NOT_INITIALIZED; + } + return g_testState.udmaSupported ? g_testState.udmaReturn : TileXR::TILEXR_ERROR_NOT_SUPPORT; + } + + auto *comm = static_cast(request.comm); + if (comm == nullptr || !comm->IsUdmaAvailableForCollectives()) { + return TileXR::TILEXR_ERROR_NOT_INITIALIZED; + } + return TileXR::TILEXR_ERROR_NOT_SUPPORT; +} + +int DispatchCcu(const CollectiveRequest &request) +{ + if (g_testState.enabled) { + if (!g_testState.ccuInitialized) { + return TileXR::TILEXR_ERROR_NOT_INITIALIZED; + } + return g_testState.ccuSupported ? g_testState.ccuReturn : TileXR::TILEXR_ERROR_NOT_SUPPORT; + } + + auto *comm = static_cast(request.comm); + TileXR::TileXRCcuBackend *backend = comm->GetCcuBackendForCollectives(); + if (backend == nullptr || !backend->Available()) { + return TileXR::TILEXR_ERROR_NOT_INITIALIZED; + } + TileXR::TileXRCcuCollectiveRequest ccuRequest {}; + ccuRequest.type = request.type; + ccuRequest.sendBuf = request.sendBuf; + ccuRequest.recvBuf = request.recvBuf; + ccuRequest.count = request.count; + ccuRequest.dataType = request.dataType; + ccuRequest.reduceOp = request.reduceOp; + ccuRequest.root = request.root; + ccuRequest.stream = request.stream; + TileXR::TileXRCcuCollectivePlan plan {}; + const int ret = backend->PrepareCollective(ccuRequest, &plan); + if (ret != TileXR::TILEXR_SUCCESS) { + return ret; + } + return backend->SubmitCollective(plan, request.stream); +} + +} // namespace + +int DispatchCollective(const CollectiveRequest &request, TileXRCollectiveBackend backend) +{ + if (request.comm == nullptr || request.sendBuf == nullptr || request.recvBuf == nullptr || request.count <= 0) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + + switch (backend) { + case TILEXR_COLLECTIVE_BACKEND_AIV: + return DispatchAiv(request); + case TILEXR_COLLECTIVE_BACKEND_UDMA: + return DispatchUdma(request); + case TILEXR_COLLECTIVE_BACKEND_CCU: + return DispatchCcu(request); + case TILEXR_COLLECTIVE_BACKEND_AUTO: + default: + if (g_testState.enabled && g_testState.ccuInitialized && g_testState.ccuSupported) { + return DispatchCcu(request); + } + if (g_testState.enabled && g_testState.udmaInitialized && g_testState.udmaSupported) { + return DispatchUdma(request); + } + return DispatchAiv(request); + } +} + +void SetBackendTestState(const BackendTestState &state) +{ + g_testState = state; + g_testState.enabled = true; +} + +void ResetBackendTestState() +{ + g_testState = BackendTestState {}; +} + +} // namespace Host +} // namespace TileXRCollectives diff --git a/src/collectives/host/collective_backend.h b/src/collectives/host/collective_backend.h new file mode 100644 index 00000000..cd897fe5 --- /dev/null +++ b/src/collectives/host/collective_backend.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024-2026 TileXR Project + * This file is a part of the CANN Open Software. + * Licensed under CANN Open Software License Agreement Version 1.0 (the "License"). + * Please refer to the License for details. You may not use this file except in compliance with the License. + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + * See LICENSE in the root of the software repository for the full text of the License. + */ +#ifndef TILEXR_COLLECTIVES_HOST_COLLECTIVE_BACKEND_H +#define TILEXR_COLLECTIVES_HOST_COLLECTIVE_BACKEND_H + +#include + +#include "acl/acl_base.h" +#include "tilexr_collectives.h" +#include "tilexr_types.h" + +namespace TileXRCollectives { +namespace Host { + +struct CollectiveRequest { + TileXR::TileXRType type = TileXR::TileXRType::ALL_GATHER; + void *sendBuf = nullptr; + void *recvBuf = nullptr; + int64_t count = 0; + TileXR::TileXRDataType dataType = TileXR::TILEXR_DATA_TYPE_RESERVED; + TileXR::TileXRReduceOp reduceOp = TileXR::TILEXR_REDUCE_RESERVED; + int root = 0; + TileXRCommPtr comm = nullptr; + aclrtStream stream = nullptr; +}; + +struct BackendTestState { + bool enabled = false; + bool udmaInitialized = false; + bool udmaSupported = false; + int udmaReturn = TileXR::TILEXR_ERROR_NOT_SUPPORT; + bool ccuInitialized = false; + bool ccuSupported = false; + int ccuReturn = TileXR::TILEXR_ERROR_NOT_SUPPORT; + int aivReturn = TileXR::TILEXR_SUCCESS; +}; + +int DispatchCollective(const CollectiveRequest &request, TileXRCollectiveBackend backend); +void SetBackendTestState(const BackendTestState &state); +void ResetBackendTestState(); + +} // namespace Host +} // namespace TileXRCollectives + +#endif // TILEXR_COLLECTIVES_HOST_COLLECTIVE_BACKEND_H diff --git a/src/collectives/host/tilexr_collectives.cpp b/src/collectives/host/tilexr_collectives.cpp index d91ed87c..bf52a81a 100644 --- a/src/collectives/host/tilexr_collectives.cpp +++ b/src/collectives/host/tilexr_collectives.cpp @@ -10,6 +10,7 @@ #include #include "acl/acl_rt.h" +#include "collective_backend.h" #include "collective_kernel.h" #include "collective_launcher.h" #include "collective_utils.h" @@ -66,16 +67,38 @@ int LoopbackCopy(void *sendBuf, void *recvBuf, int64_t bytes, aclrtStream stream return ret == ACL_SUCCESS ? TileXR::TILEXR_SUCCESS : TileXR::TILEXR_ERROR_INTERNAL; } +TileXRCollectiveBackend SelectedBackend(const TileXRCollectiveOptions *options) +{ + return options == nullptr ? TILEXR_COLLECTIVE_BACKEND_AUTO : options->backend; +} + +bool UsesForcedNonAivBackend(TileXRCollectiveBackend backend) +{ + return backend == TILEXR_COLLECTIVE_BACKEND_UDMA || backend == TILEXR_COLLECTIVE_BACKEND_CCU; +} + } // namespace -int TileXRAllGather(void *sendBuf, void *recvBuf, int64_t sendCount, - TileXR::TileXRDataType dataType, TileXRCommPtr comm, - aclrtStream stream) +int TileXRAllGatherEx(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options) { int ret = ValidateCommon(sendBuf, recvBuf, sendCount, dataType, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::ALL_GATHER; + request.sendBuf = sendBuf; + request.recvBuf = recvBuf; + request.count = sendCount; + request.dataType = dataType; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -93,14 +116,33 @@ int TileXRAllGather(void *sendBuf, void *recvBuf, int64_t sendCount, sendBuf, recvBuf, sendCount, dataType, blockDim, stream); } -int TileXRAllToAll(void *sendBuf, void *recvBuf, int64_t sendCount, - TileXR::TileXRDataType dataType, TileXRCommPtr comm, - aclrtStream stream) +int TileXRAllGather(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream) +{ + return TileXRAllGatherEx(sendBuf, recvBuf, sendCount, dataType, comm, stream, nullptr); +} + +int TileXRAllToAllEx(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options) { int ret = ValidateCommon(sendBuf, recvBuf, sendCount, dataType, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::ALL2ALL; + request.sendBuf = sendBuf; + request.recvBuf = recvBuf; + request.count = sendCount; + request.dataType = dataType; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -133,14 +175,34 @@ int TileXRAllToAll(void *sendBuf, void *recvBuf, int64_t sendCount, sendBuf, recvBuf, kernelCount, dataType, blockDim, stream); } -int TileXRAllReduce(void *sendBuf, void *recvBuf, int64_t count, - TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, - TileXRCommPtr comm, aclrtStream stream) +int TileXRAllToAll(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream) +{ + return TileXRAllToAllEx(sendBuf, recvBuf, sendCount, dataType, comm, stream, nullptr); +} + +int TileXRAllReduceEx(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream, const TileXRCollectiveOptions *options) { int ret = ValidateReduce(sendBuf, recvBuf, count, dataType, op, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::ALL_REDUCE; + request.sendBuf = sendBuf; + request.recvBuf = recvBuf; + request.count = count; + request.dataType = dataType; + request.reduceOp = op; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -159,14 +221,35 @@ int TileXRAllReduce(void *sendBuf, void *recvBuf, int64_t count, TileXRCollectives::Host::CollectiveLaunchAttrs { static_cast(op), 0 }); } -int TileXRReduceScatter(void *sendBuf, void *recvBuf, int64_t recvCount, - TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, - TileXRCommPtr comm, aclrtStream stream) +int TileXRAllReduce(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream) +{ + return TileXRAllReduceEx(sendBuf, recvBuf, count, dataType, op, comm, stream, nullptr); +} + +int TileXRReduceScatterEx(void *sendBuf, void *recvBuf, int64_t recvCount, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream, + const TileXRCollectiveOptions *options) { int ret = ValidateReduce(sendBuf, recvBuf, recvCount, dataType, op, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::REDUCE_SCATTER; + request.sendBuf = sendBuf; + request.recvBuf = recvBuf; + request.count = recvCount; + request.dataType = dataType; + request.reduceOp = op; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -195,14 +278,34 @@ int TileXRReduceScatter(void *sendBuf, void *recvBuf, int64_t recvCount, TileXRCollectives::Host::CollectiveLaunchAttrs { static_cast(op), 0 }); } -int TileXRBroadcast(void *buf, int64_t count, - TileXR::TileXRDataType dataType, int root, - TileXRCommPtr comm, aclrtStream stream) +int TileXRReduceScatter(void *sendBuf, void *recvBuf, int64_t recvCount, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream) +{ + return TileXRReduceScatterEx(sendBuf, recvBuf, recvCount, dataType, op, comm, stream, nullptr); +} + +int TileXRBroadcastEx(void *buf, int64_t count, + TileXR::TileXRDataType dataType, int root, + TileXRCommPtr comm, aclrtStream stream, const TileXRCollectiveOptions *options) { int ret = ValidateBroadcastLocal(buf, count, dataType, root, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::BROADCAST; + request.sendBuf = buf; + request.recvBuf = buf; + request.count = count; + request.dataType = dataType; + request.root = root; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -227,14 +330,33 @@ int TileXRBroadcast(void *buf, int64_t count, TileXRCollectives::Host::CollectiveLaunchAttrs { 0, root }); } -int TileXRProfileProbe(void *sendBuf, void *recvBuf, int64_t count, - TileXR::TileXRDataType dataType, TileXRCommPtr comm, - aclrtStream stream) +int TileXRBroadcast(void *buf, int64_t count, + TileXR::TileXRDataType dataType, int root, + TileXRCommPtr comm, aclrtStream stream) +{ + return TileXRBroadcastEx(buf, count, dataType, root, comm, stream, nullptr); +} + +int TileXRProfileProbeEx(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options) { int ret = ValidateCommon(sendBuf, recvBuf, count, dataType, comm); if (ret != TileXR::TILEXR_SUCCESS) { return ret; } + const TileXRCollectiveBackend backend = SelectedBackend(options); + if (UsesForcedNonAivBackend(backend)) { + TileXRCollectives::Host::CollectiveRequest request {}; + request.type = TileXR::TileXRType::PROFILE_PROBE; + request.sendBuf = sendBuf; + request.recvBuf = recvBuf; + request.count = count; + request.dataType = dataType; + request.comm = comm; + request.stream = stream; + return TileXRCollectives::Host::DispatchCollective(request, backend); + } TileXRCollectives::Host::HostLaunchContext context; ret = TileXRCollectives::Host::PrepareHostLaunchContext(comm, context); @@ -250,3 +372,10 @@ int TileXRProfileProbe(void *sendBuf, void *recvBuf, int64_t count, return TileXRCollectives::Host::LaunchCollectiveKernel(comm, TileXR::TileXRType::PROFILE_PROBE, context, sendBuf, recvBuf, bytes, TileXR::TILEXR_DATA_TYPE_INT8, blockDim, stream); } + +int TileXRProfileProbe(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream) +{ + return TileXRProfileProbeEx(sendBuf, recvBuf, count, dataType, comm, stream, nullptr); +} diff --git a/src/comm/CMakeLists.txt b/src/comm/CMakeLists.txt index 50519bf7..e0e6c35d 100644 --- a/src/comm/CMakeLists.txt +++ b/src/comm/CMakeLists.txt @@ -108,6 +108,10 @@ set(TILEXR_SOURCE_FILE tilexr_comm.cpp ccu/tilexr_ccu_abi_constants.h ccu/tilexr_ccu_barrier_program.h ccu/tilexr_ccu_barrier_program.cpp + ccu/tilexr_ccu_backend.h + ccu/tilexr_ccu_backend.cpp + ccu/tilexr_ccu_collective_planner.h + ccu/tilexr_ccu_collective_planner.cpp ccu/tilexr_ccu_direct_orchestrator.h ccu/tilexr_ccu_direct_orchestrator.cpp ccu/tilexr_ccu_direct_runtime.h @@ -141,6 +145,10 @@ set(TILEXR_SOURCE_FILE tilexr_comm.cpp ccu/tilexr_ccu_resource_allocator.cpp ccu/tilexr_ccu_runtime.h ccu/tilexr_ccu_runtime.cpp + ccu/tilexr_ccu_runtime_session.h + ccu/tilexr_ccu_runtime_session.cpp + ccu/tilexr_ccu_executor.h + ccu/tilexr_ccu_executor.cpp ccu/tilexr_ccu_specs.h ccu/tilexr_ccu_specs.cpp tools/socket/tilexr_sock_exchange.h @@ -164,6 +172,7 @@ set_target_properties(tile-comm PROPERTIES SKIP_BUILD_RPATH TRUE INSTALL_RPATH "" SKIP_INSTALL_RPATH TRUE) +target_compile_definitions(tile-comm PRIVATE TILEXR_CCU_TESTING=1) if(TILEXR_HAVE_PTO_SDMA) target_compile_definitions(tile-comm PRIVATE TILEXR_HAVE_PTO_SDMA=1) diff --git a/src/comm/ccu/tilexr_ccu_backend.cpp b/src/comm/ccu/tilexr_ccu_backend.cpp new file mode 100644 index 00000000..3c3afbde --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_backend.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#include "ccu/tilexr_ccu_backend.h" + +#include "ccu/tilexr_ccu_collective_planner.h" +#include "ccu/tilexr_ccu_executor.h" +#include "ccu/tilexr_ccu_runtime_session.h" + +#include + +namespace TileXR { + +class TileXRCcuBackend::Impl { +public: + Impl(); + int Init(const TileXRCcuBackendOptions &options); + void Shutdown(); + bool Available() const; + bool Supports(const TileXRCcuCollectiveRequest &request) const; + int PrepareCollective(const TileXRCcuCollectiveRequest &request, TileXRCcuCollectivePlan *plan); + int SubmitCollective(const TileXRCcuCollectivePlan &plan, aclrtStream stream); +#ifdef TILEXR_CCU_TESTING + bool RuntimeInitializedForTest() const; +#endif + +private: + int EnsureInternals(); + + std::unique_ptr runtimeSession_; + std::unique_ptr planner_; + std::unique_ptr executor_; +}; + +TileXRCcuBackend::Impl::Impl() + : runtimeSession_(new (std::nothrow) TileXRCcuRuntimeSession()), + planner_(new (std::nothrow) TileXRCcuCollectivePlanner()), + executor_(new (std::nothrow) TileXRCcuExecutor()) +{ +} + +int TileXRCcuBackend::Impl::EnsureInternals() +{ + if (runtimeSession_ == nullptr) { + runtimeSession_.reset(new (std::nothrow) TileXRCcuRuntimeSession()); + } + if (planner_ == nullptr) { + planner_.reset(new (std::nothrow) TileXRCcuCollectivePlanner()); + } + if (executor_ == nullptr) { + executor_.reset(new (std::nothrow) TileXRCcuExecutor()); + } + return runtimeSession_ == nullptr || planner_ == nullptr || executor_ == nullptr ? + TILEXR_ERROR_INTERNAL : + TILEXR_SUCCESS; +} + +int TileXRCcuBackend::Impl::Init(const TileXRCcuBackendOptions &options) +{ + const int ret = EnsureInternals(); + if (ret != TILEXR_SUCCESS) { + return ret; + } + if (planner_ != nullptr) { + planner_->Reset(); + } + return runtimeSession_->Init(options); +} + +void TileXRCcuBackend::Impl::Shutdown() +{ + if (planner_ != nullptr) { + planner_->Reset(); + } + if (runtimeSession_ != nullptr) { + runtimeSession_->Shutdown(); + } +} + +bool TileXRCcuBackend::Impl::Available() const +{ + return runtimeSession_ != nullptr && runtimeSession_->Available(); +} + +bool TileXRCcuBackend::Impl::Supports(const TileXRCcuCollectiveRequest &request) const +{ + return runtimeSession_ != nullptr && planner_ != nullptr && planner_->Supports(*runtimeSession_, request); +} + +int TileXRCcuBackend::Impl::PrepareCollective( + const TileXRCcuCollectiveRequest &request, + TileXRCcuCollectivePlan *plan) +{ + if (runtimeSession_ == nullptr || planner_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + return planner_->PrepareCollective(*runtimeSession_, request, plan); +} + +int TileXRCcuBackend::Impl::SubmitCollective(const TileXRCcuCollectivePlan &plan, aclrtStream stream) +{ + if (runtimeSession_ == nullptr || executor_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + return executor_->Submit(*runtimeSession_, plan, stream); +} + +#ifdef TILEXR_CCU_TESTING +bool TileXRCcuBackend::Impl::RuntimeInitializedForTest() const +{ + return Available(); +} +#endif + +TileXRCcuBackend::TileXRCcuBackend() : impl_(new (std::nothrow) Impl()) +{ +} + +TileXRCcuBackend::~TileXRCcuBackend() +{ + Shutdown(); +} + +int TileXRCcuBackend::Init(const TileXRCcuBackendOptions &options) +{ + if (impl_ == nullptr) { + impl_.reset(new (std::nothrow) Impl()); + if (impl_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + } + return impl_->Init(options); +} + +void TileXRCcuBackend::Shutdown() +{ + if (impl_ != nullptr) { + impl_->Shutdown(); + } +} + +bool TileXRCcuBackend::Available() const +{ + return impl_ != nullptr && impl_->Available(); +} + +bool TileXRCcuBackend::Supports(const TileXRCcuCollectiveRequest &request) const +{ + return impl_ != nullptr && impl_->Supports(request); +} + +int TileXRCcuBackend::PrepareCollective(const TileXRCcuCollectiveRequest &request, TileXRCcuCollectivePlan *plan) +{ + if (impl_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + return impl_->PrepareCollective(request, plan); +} + +int TileXRCcuBackend::SubmitCollective(const TileXRCcuCollectivePlan &plan, aclrtStream stream) +{ + if (impl_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + return impl_->SubmitCollective(plan, stream); +} + +#ifdef TILEXR_CCU_TESTING +bool TileXRCcuBackend::RuntimeInitializedForTest() const +{ + return impl_ != nullptr && impl_->RuntimeInitializedForTest(); +} +#endif + +} // namespace TileXR diff --git a/src/comm/ccu/tilexr_ccu_backend.h b/src/comm/ccu/tilexr_ccu_backend.h new file mode 100644 index 00000000..8177e211 --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_backend.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#ifndef TILEXR_CCU_BACKEND_H +#define TILEXR_CCU_BACKEND_H + +#include +#include +#include +#include + +#include "acl/acl_base.h" +#include "tilexr_types.h" + +namespace TileXR { + +class TileXRSockExchange; +class TileXRCcuRuntimeSession; +class TileXRCcuCollectivePlanner; +class TileXRCcuExecutor; + +struct TileXRCcuBackendOptions { + int rank = 0; + int rankSize = 0; + int devId = 0; + std::string uid; + TileXRSockExchange *exchange = nullptr; +}; + +struct TileXRCcuCollectiveRequest { + TileXRType type = TileXRType::ALL_GATHER; + void *sendBuf = nullptr; + void *recvBuf = nullptr; + int64_t count = 0; + TileXRDataType dataType = TILEXR_DATA_TYPE_RESERVED; + TileXRReduceOp reduceOp = TILEXR_REDUCE_RESERVED; + int root = 0; + aclrtStream stream = nullptr; +}; + +struct TileXRCcuCollectivePlan { + bool ready = false; +}; + +class TileXRCcuBackend { +public: + TileXRCcuBackend(); + ~TileXRCcuBackend(); + + TileXRCcuBackend(const TileXRCcuBackend&) = delete; + TileXRCcuBackend& operator=(const TileXRCcuBackend&) = delete; + + int Init(const TileXRCcuBackendOptions &options); + void Shutdown(); + bool Available() const; + bool Supports(const TileXRCcuCollectiveRequest &request) const; + int PrepareCollective(const TileXRCcuCollectiveRequest &request, TileXRCcuCollectivePlan *plan); + int SubmitCollective(const TileXRCcuCollectivePlan &plan, aclrtStream stream); +#ifdef TILEXR_CCU_TESTING + bool RuntimeInitializedForTest() const; +#endif + +private: + class Impl; + std::unique_ptr impl_; +}; + +} // namespace TileXR + +#endif // TILEXR_CCU_BACKEND_H diff --git a/src/comm/ccu/tilexr_ccu_collective_planner.cpp b/src/comm/ccu/tilexr_ccu_collective_planner.cpp new file mode 100644 index 00000000..311eec0d --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_collective_planner.cpp @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#include "ccu/tilexr_ccu_collective_planner.h" + +#ifdef TILEXR_CCU_TESTING +#include "ccu/tilexr_ccu_memory_program.h" +#endif +#include "ccu/tilexr_ccu_repository.h" +#include "ccu/tilexr_ccu_runtime_session.h" +#include "tilexr_log.h" + +#include +#include +#include + +#ifdef TILEXR_CCU_TESTING +#include "runtime/dev.h" +#include "runtime/mem.h" +#include "runtime/rts/rts_device.h" +#endif + +namespace TileXR { + +#ifdef TILEXR_CCU_TESTING +constexpr uint32_t TILEXR_CCU_DIRECT_MEMORY_COPY_INSTRUCTION_COUNT = 7U; +#endif + +uint8_t SelectDirectCcuInstallDieId() +{ + const char *text = std::getenv("TILEXR_CCU_DIRECT_INSTALL_DIE_ID"); + if (text == nullptr || text[0] == '\0') { + return 0; + } + char *end = nullptr; + const unsigned long parsed = std::strtoul(text, &end, 0); + if (end == text || *end != '\0' || parsed > 1UL) { + return 0; + } + return static_cast(parsed); +} + +uint32_t SelectDirectCcuPeerLocalXnOffset(size_t peerLocalIndex, uint32_t syncIndex, size_t peerRouteCount) +{ + if (peerRouteCount == 0) { + return 0; + } + return static_cast(peerLocalIndex) + + static_cast(syncIndex / peerRouteCount) * static_cast(peerRouteCount); +} + +uint32_t SelectDirectCcuChannelBoundRemoteXnOffset(size_t peerLocalIndex, uint32_t syncIndex, size_t peerRouteCount) +{ + return SelectDirectCcuPeerLocalXnOffset(peerLocalIndex, syncIndex, peerRouteCount); +} + +uint16_t DirectCcuRemoteXnProofSpan(uint16_t syncRouteCount) +{ + if (syncRouteCount == 0) { + return 0; + } + return syncRouteCount; +} + +uint16_t SelectDirectCcuChannelBoundRemoteXnId( + uint16_t remoteXnStartId, + size_t peerLocalIndex, + uint32_t syncIndex, + size_t peerRouteCount) +{ + return static_cast( + static_cast(remoteXnStartId) + + SelectDirectCcuChannelBoundRemoteXnOffset(peerLocalIndex, syncIndex, peerRouteCount)); +} + +#ifdef TILEXR_CCU_TESTING +struct DirectCcuMemoryCopyEndpoint { + uint64_t sourceAddr = 0; + uint64_t sourceToken = 0; + uint64_t destinationAddr = 0; + uint64_t destinationToken = 0; + uint64_t bytes = 0; + uint32_t rank = 0; + uint32_t valid = 0; +}; + +int QueryDirectCcuProcessMemoryToken(uint64_t addr, uint64_t bytes, uint64_t *packedToken) +{ + if (addr == 0 || bytes == 0 || packedToken == nullptr) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + *packedToken = 0; + rtMemUbTokenInfo info {}; + info.va = addr; + info.size = bytes; + const rtError_t ret = rtUbDevQueryInfo(QUERY_PROCESS_TOKEN, &info); + if (ret != RT_ERROR_NONE) { + return TILEXR_ERROR_MKIRT; + } + constexpr uint32_t tokenIdRightShift = 8U; + const uint32_t tokenId = info.tokenId >> tokenIdRightShift; + *packedToken = TileXRCcuPackMemoryToken(tokenId, info.tokenValue, true); + return *packedToken == 0 ? TILEXR_ERROR_NOT_FOUND : TILEXR_SUCCESS; +} + +int BuildDirectCcuLocalMemoryCopyEndpoint( + uint32_t rank, + uint64_t sourceAddr, + uint64_t destinationAddr, + uint64_t bytes, + DirectCcuMemoryCopyEndpoint *endpoint) +{ + if (endpoint == nullptr) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + *endpoint = DirectCcuMemoryCopyEndpoint {}; + endpoint->rank = rank; + endpoint->bytes = bytes; + endpoint->sourceAddr = sourceAddr; + endpoint->destinationAddr = destinationAddr; + int ret = QueryDirectCcuProcessMemoryToken(sourceAddr, bytes, &endpoint->sourceToken); + if (ret != TILEXR_SUCCESS) { + return ret; + } + ret = QueryDirectCcuProcessMemoryToken(destinationAddr, bytes, &endpoint->destinationToken); + if (ret != TILEXR_SUCCESS) { + return ret; + } + endpoint->valid = 1; + return TILEXR_SUCCESS; +} +#endif + +void TileXRCcuCollectivePlanner::Reset() +{ + ResetDirectCcuLowerLayerPlan(); + directCcuLowerLayerTemplateConfigured_ = false; + directCcuLowerLayerTemplate_ = TileXRCcuLowerLayerTransportSnapshot {}; + directCcuVerifiedEndpointRoutes_.clear(); + directCcuLocalVerifiedEndpointRoute_ = TileXRCcuLowerLayerTransportRoute {}; + directCcuLocalVerifiedEndpointRouteValid_ = false; +} + +bool TileXRCcuCollectivePlanner::Supports( + const TileXRCcuRuntimeSession &session, + const TileXRCcuCollectiveRequest &request) const +{ + (void)session; + (void)request; + return false; +} + +int TileXRCcuCollectivePlanner::PrepareCollective( + const TileXRCcuRuntimeSession &session, + const TileXRCcuCollectiveRequest &request, + TileXRCcuCollectivePlan *plan) const +{ + if (plan == nullptr) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + *plan = TileXRCcuCollectivePlan {}; + if (!session.Available()) { + return TILEXR_ERROR_NOT_INITIALIZED; + } + (void)request; + return TILEXR_ERROR_NOT_SUPPORT; +} + +void TileXRCcuCollectivePlanner::ResetDirectCcuLowerLayerPlan() +{ + directCcuLowerLayerPlanValid_ = false; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + directCcuLowerLayerSnapshot_ = TileXRCcuLowerLayerTransportSnapshot {}; + directCcuLowerLayerPlan_ = TileXRCcuLowerLayerInstallPlan {}; + directCcuLowerLayerPlanReport_ = TileXRCcuLowerLayerPlanBuilderReport {}; +} + +int TileXRCcuCollectivePlanner::ConfigureDirectCcuLowerLayerTemplate( + TileXRCcuRuntimeSession &session, + const TileXRCcuLowerLayerTransportSnapshot &templateSnapshot) +{ + directCcuLowerLayerTemplate_ = templateSnapshot; + directCcuLowerLayerTemplateConfigured_ = true; + return RefreshDirectCcuLowerLayerPlan(session); +} + +int TileXRCcuCollectivePlanner::ConfigureDirectCcuVerifiedEndpointRoutes( + TileXRCcuRuntimeSession &session, + const std::vector &verifiedRoutes) +{ + TileXRCcuLowerLayerTransportSnapshot validationSnapshot; + validationSnapshot.routes = verifiedRoutes; + TileXRCcuLowerLayerPlanBuilderReport report; + int ret = TileXRCcuOverlayVerifiedEndpointRoutes(verifiedRoutes, &validationSnapshot, &report); + directCcuLowerLayerPlanReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return ret; + } + + directCcuVerifiedEndpointRoutes_ = verifiedRoutes; + if (directCcuLowerLayerTemplateConfigured_) { + return RefreshDirectCcuLowerLayerPlan(session); + } + return TILEXR_SUCCESS; +} + +int TileXRCcuCollectivePlanner::ConfigureDirectCcuLocalVerifiedEndpointRoute( + TileXRCcuRuntimeSession &session, + const TileXRCcuLowerLayerTransportRoute &route) +{ + TileXRCcuLowerLayerTransportSnapshot validationSnapshot; + validationSnapshot.routes.push_back(route); + TileXRCcuLowerLayerPlanBuilderReport report; + std::vector routes {route}; + int ret = TileXRCcuOverlayVerifiedEndpointRoutes(routes, &validationSnapshot, &report); + directCcuLowerLayerPlanReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuLocalVerifiedEndpointRoute_ = TileXRCcuLowerLayerTransportRoute {}; + directCcuLocalVerifiedEndpointRouteValid_ = false; + directCcuLowerLayerPlanStatus_ = ret; + return ret; + } + + directCcuLocalVerifiedEndpointRoute_ = route; + directCcuLocalVerifiedEndpointRouteValid_ = true; + if (session.Available()) { + return session.ConfigureLocalVerifiedEndpointRoute(route); + } + return TILEXR_SUCCESS; +} + +int TileXRCcuCollectivePlanner::ConfigureDirectCcuLowerLayerTemplateFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + const std::vector &remoteCcuBuffers) +{ + ResetDirectCcuLowerLayerPlan(); + const TileXRCcuBasicInfo *basicInfo = session.GetDirectCcuBasicInfo(); + if (basicInfo == nullptr) { + directCcuLowerLayerPlanReport_.message = + "direct CCU basic info is unavailable for lower-layer transport template"; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuLowerLayerPlanStatus_; + } + + TileXRCcuLowerLayerTransportSnapshot templateSnapshot; + TileXRCcuLowerLayerPlanBuilderReport report; + int ret = TileXRCcuBuildLowerLayerTransportTemplate( + *basicInfo, + allocation, + remoteCcuBuffers, + &templateSnapshot, + &report); + directCcuLowerLayerPlanReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + ret = TileXRCcuOverlayVerifiedEndpointRoutes( + directCcuVerifiedEndpointRoutes_, + &templateSnapshot, + &directCcuLowerLayerPlanReport_); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + directCcuLowerLayerTemplate_ = templateSnapshot; + directCcuLowerLayerTemplateConfigured_ = true; + return RefreshDirectCcuLowerLayerPlan(session); +} + +int TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerTemplateFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation) +{ + ResetDirectCcuLowerLayerPlan(); + const TileXRCcuBasicInfo *basicInfo = session.GetDirectCcuBasicInfo(); + if (basicInfo == nullptr) { + directCcuLowerLayerPlanReport_.message = + "direct CCU basic info is unavailable for lower-layer transport template"; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuLowerLayerPlanStatus_; + } + if (!session.Available()) { + directCcuLowerLayerPlanReport_.message = + "direct CCU runtime is unavailable for resource window registration"; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuLowerLayerPlanStatus_; + } + + int ret = session.RegisterCcuResourceRmaBuffer(basicInfo->resourceAddr); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanReport_.message = "failed to register direct CCU resource window"; + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + TileXRCcuLocalResourceWindowInfo localCcuResourceWindow; + ret = session.ExportLocalCcuRmaBuffer(&localCcuResourceWindow); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanReport_.message = "failed to export direct CCU local resource window token"; + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + if (directCcuLocalVerifiedEndpointRouteValid_) { + ret = session.ConfigureLocalVerifiedEndpointRoute(directCcuLocalVerifiedEndpointRoute_); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanReport_.message = "failed to configure direct CCU local verified endpoint route"; + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + } else { + TileXRCcuDirectRuntimeReport endpointRouteReport; + ret = session.RefreshLocalVerifiedEndpointRoute(&endpointRouteReport); + if (ret != TILEXR_SUCCESS && ret != TILEXR_ERROR_NOT_FOUND) { + TILEXR_LOG(WARN) << "direct CCU local endpoint route collection failed closed: " + << ret << ", " << endpointRouteReport.message; + } + } + + std::vector remoteCcuBuffers; + ret = session.ExportRemoteCcuRmaBuffers(&remoteCcuBuffers); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanReport_.message = "failed to export direct CCU peer resource window tokens"; + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + ret = ExchangeDirectCcuRemoteNotifyCke(session, allocation, &remoteCcuBuffers, &directCcuLowerLayerPlanReport_); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + TileXRCcuLowerLayerTransportSnapshot templateSnapshot; + TileXRCcuLowerLayerPlanBuilderReport report; + ret = TileXRCcuBuildLowerLayerTransportTemplate( + *basicInfo, + allocation, + remoteCcuBuffers, + &templateSnapshot, + &report); + directCcuLowerLayerPlanReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + templateSnapshot.msidToken.dieId = basicInfo->dieId; + templateSnapshot.msidToken.msId = basicInfo->msId; + templateSnapshot.msidToken.tokenId = localCcuResourceWindow.tokenId; + templateSnapshot.msidToken.tokenValue = localCcuResourceWindow.tokenValue; + templateSnapshot.msidToken.valid = true; + ret = TileXRCcuOverlayVerifiedEndpointRoutes( + directCcuVerifiedEndpointRoutes_, + &templateSnapshot, + &directCcuLowerLayerPlanReport_); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + directCcuLowerLayerTemplate_ = templateSnapshot; + directCcuLowerLayerTemplateConfigured_ = true; + return RefreshDirectCcuLowerLayerPlan(session); +} + +int TileXRCcuCollectivePlanner::FillDirectCcuLowerLayerPlanFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + TileXRCcuLowerLayerInstallPlan *plan, + TileXRCcuLowerLayerPlanBuilderReport *report) +{ + if (plan == nullptr || report == nullptr) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + int ret = PrepareDirectCcuLowerLayerTemplateFromAllocation(session, allocation); + if (ret != TILEXR_SUCCESS) { + *report = directCcuLowerLayerPlanReport_; + return ret; + } + if (!directCcuLowerLayerPlanValid_) { + *report = directCcuLowerLayerPlanReport_; + return TILEXR_ERROR_NOT_FOUND; + } + *plan = directCcuLowerLayerPlan_; + *report = directCcuLowerLayerPlanReport_; + return TILEXR_SUCCESS; +} + +int TileXRCcuCollectivePlanner::ExchangeDirectCcuRemoteNotifyCke( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + std::vector *remoteCcuBuffers, + TileXRCcuLowerLayerPlanBuilderReport *report) +{ + if (remoteCcuBuffers == nullptr) { + if (report != nullptr) { + report->message = "missing direct CCU remote notify CKE exchange inputs"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + const int rank = session.Rank(); + const int rankSize = session.RankSize(); + if (rankSize <= 1 || rank < 0 || rank >= rankSize) { + if (report != nullptr) { + report->message = "invalid direct CCU peer XN/CKE exchange shape"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + const size_t peerRouteCount = static_cast(rankSize - 1); + const size_t syncRouteCount = allocation.remoteXn.num; + if (allocation.localXn.num == 0 || + allocation.localWaitCke.num == 0 || + allocation.remoteNotifyCke.num == 0 || + allocation.remoteXn.num < static_cast(rankSize - 1) || + allocation.localWaitCke.num < allocation.remoteXn.num || + allocation.remoteNotifyCke.num < allocation.remoteXn.num || + allocation.channels.num == 0 || + remoteCcuBuffers->size() != peerRouteCount) { + if (report != nullptr) { + report->message = "invalid direct CCU peer XN/CKE exchange shape"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + + struct PeerResourceExchange { + uint16_t localXnStartId; + uint16_t localXnCount; + uint16_t remoteXnStartId; + uint16_t remoteXnCount; + uint16_t localWaitCkeStartId; + uint16_t localWaitCkeCount; + uint16_t remoteNotifyCkeStartId; + uint16_t remoteNotifyCkeCount; + uint16_t channelStartId; + uint16_t channelCount; + }; + PeerResourceExchange local { + allocation.localXn.startId, + allocation.localXn.num, + allocation.remoteXn.startId, + DirectCcuRemoteXnProofSpan(allocation.remoteXn.num), + allocation.localWaitCke.startId, + allocation.localWaitCke.num, + allocation.remoteNotifyCke.startId, + allocation.remoteNotifyCke.num, + allocation.channels.startId, + allocation.channels.num, + }; + std::vector all(rankSize); + const int ret = session.AllGather(&local, sizeof(local), all.data()); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + report->message = "failed to exchange direct CCU peer XN/CKE resources"; + } + return ret; + } + + std::vector peerRanks; + peerRanks.reserve(peerRouteCount); + for (int peer = 0; peer < rankSize; ++peer) { + if (peer != rank) { + peerRanks.push_back(peer); + } + } + if (peerRanks.size() != peerRouteCount) { + if (report != nullptr) { + report->message = "invalid direct CCU peer XN/CKE exchange shape"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + std::vector peerCcuBuffers = *remoteCcuBuffers; + remoteCcuBuffers->assign(syncRouteCount, TileXRCcuRemoteCcuBufferInfo{}); + + size_t routeIndex = 0; + for (uint32_t syncIndex = 0; syncIndex < allocation.remoteXn.num; ++syncIndex) { + const size_t peerBufferIndex = syncIndex % peerRouteCount; + const int peer = peerRanks[peerBufferIndex]; + const PeerResourceExchange &peerResources = all[peer]; + const size_t peerLocalIndex = static_cast(rank < peer ? rank : rank - 1); + const uint32_t peerLocalXnOffset = + SelectDirectCcuPeerLocalXnOffset(peerLocalIndex, syncIndex, peerRouteCount); + const uint32_t selectedRemoteXnOffset = + SelectDirectCcuChannelBoundRemoteXnOffset(peerLocalIndex, syncIndex, peerRouteCount); + const uint32_t peerLocalWaitCkeOffset = routeIndex; + if (peerResources.localXnCount == 0 || + peerResources.remoteXnCount == 0 || + peerResources.localWaitCkeCount == 0 || + peerResources.channelCount == 0 || + peerLocalXnOffset >= peerResources.localXnCount || + selectedRemoteXnOffset >= peerResources.remoteXnCount || + peerLocalIndex >= peerResources.channelCount || + peerLocalWaitCkeOffset >= peerResources.localWaitCkeCount) { + if (report != nullptr) { + report->message = "peer direct CCU local XN/CKE resources are incomplete"; + } + return TILEXR_ERROR_NOT_FOUND; + } + uint16_t channelBoundRemoteXnId = SelectDirectCcuChannelBoundRemoteXnId( + peerResources.remoteXnStartId, + peerLocalIndex, + syncIndex, + peerRouteCount); + const uint16_t peerLocalXnId = + static_cast(static_cast(peerResources.localXnStartId) + peerLocalXnOffset); + uint16_t remoteNotifyCke = + static_cast(static_cast(peerResources.localWaitCkeStartId) + + peerLocalWaitCkeOffset); + (*remoteCcuBuffers)[routeIndex] = peerCcuBuffers[peerBufferIndex]; + (*remoteCcuBuffers)[routeIndex].remoteXnId = channelBoundRemoteXnId; + (*remoteCcuBuffers)[routeIndex].remoteNotifyCke = remoteNotifyCke; + const bool peerLocalXnOwnerVerified = + static_cast(peerLocalXnId) >= peerResources.localXnStartId && + static_cast(peerLocalXnId) < + static_cast(peerResources.localXnStartId) + peerResources.localXnCount; + const bool notifyCkeOwnerVerified = + static_cast(remoteNotifyCke) >= peerResources.localWaitCkeStartId && + static_cast(remoteNotifyCke) < + static_cast(peerResources.localWaitCkeStartId) + peerResources.localWaitCkeCount; + const bool localChannelOwnerVerified = + allocation.channels.num != 0 && + peerLocalXnOwnerVerified && + static_cast(channelBoundRemoteXnId) >= peerResources.remoteXnStartId && + static_cast(channelBoundRemoteXnId) < + static_cast(peerResources.remoteXnStartId) + peerResources.remoteXnCount && + routeIndex < allocation.channels.num && + peerResources.channelStartId != 0 && + peerLocalIndex < peerResources.channelCount; + const bool transportResourceExchangeVerified = + notifyCkeOwnerVerified && + allocation.localWaitCke.num != 0 && + routeIndex < allocation.localWaitCke.num && + peerLocalWaitCkeOffset < peerResources.localWaitCkeCount; + (*remoteCcuBuffers)[routeIndex].channelResourceOwnerVerified = localChannelOwnerVerified; + (*remoteCcuBuffers)[routeIndex].transportResourceExchangeVerified = transportResourceExchangeVerified; + ++routeIndex; + } + return TILEXR_SUCCESS; +} + +int TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerPlanCallback( + const TileXRCcuResourceAllocation &allocation, + TileXRCcuLowerLayerInstallPlan *plan, + TileXRCcuLowerLayerPlanBuilderReport *report, + void *userData) +{ + auto *context = static_cast(userData); + if (context == nullptr || context->planner == nullptr || context->session == nullptr) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + return context->planner->FillDirectCcuLowerLayerPlanFromAllocation( + *context->session, + allocation, + plan, + report); +} + +int TileXRCcuCollectivePlanner::PrepareDirectCcuInstallAttempt( + TileXRCcuRuntimeSession &session, + const TileXRCcuDirectInstallOptions &options, + TileXRCcuDirectInstallAttempt *attempt, + TileXRCcuDirectInstallReport *report) +{ + if (!session.Available()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport{}; + report->message = "TileXRCcuBackend is not initialized for direct CCU install attempt"; + } + return TILEXR_ERROR_NOT_INITIALIZED; + } + const std::string processUnavailableMessage = + TileXRCcuRuntimeSession::ProcessDirectCcuRuntimeUnavailableMessage(); + if (!processUnavailableMessage.empty()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport{}; + report->message = processUnavailableMessage; + } + return TILEXR_ERROR_NOT_FOUND; + } + const uint8_t installDieId = SelectDirectCcuInstallDieId(); + const TileXRCcuBasicInfo *basicInfo = session.GetDirectCcuBasicInfo(); + if (basicInfo == nullptr || basicInfo->dieId != installDieId) { + const int ret = session.RefreshDirectCcuBasicInfo(installDieId); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport{}; + report->message = session.GetDirectCcuBasicInfoReport().message; + } + return ret; + } + basicInfo = session.GetDirectCcuBasicInfo(); + } + if (basicInfo == nullptr || !session.Available()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport{}; + report->message = "direct CCU runtime is unavailable for install attempt"; + } + return TILEXR_ERROR_NOT_FOUND; + } + + TileXRCcuDriverAdapter adapter; + TileXRCcuDriverAdapterReport adapterReport; + int ret = session.CreateDriverAdapter(&adapter, &adapterReport); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport{}; + report->message = adapterReport.message; + } + return ret; + } + + LowerLayerPlanCallbackContext callbackContext {this, &session}; + TileXRCcuDirectInstallOptions next = options; + next.basicInfo = basicInfo; + next.offlineOnly = false; + next.driverAdapter = &adapter; + next.repositoryMemoryOps = TileXRCcuMakeRepositoryDeviceMemoryOps(next.repositoryMemoryAllocMode); + next.repositoryMemoryUserData = nullptr; + next.lowerLayerPlan = nullptr; + next.prepareLowerLayerPlan = &TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerPlanCallback; + next.lowerLayerPlanUserData = &callbackContext; + if (next.provider.empty()) { + next.provider = "tilexr-comm-direct-ccu"; + } + + return TileXRCcuRunDirectInstallAttempt(next, attempt, report); +} + +#ifdef TILEXR_CCU_TESTING +int TileXRCcuCollectivePlanner::PrepareDirectCcuMemoryCopyInstallAttempt( + TileXRCcuRuntimeSession &session, + const TileXRCcuDirectInstallOptions &options, + uint64_t localSourceAddr, + uint64_t localDestinationAddr, + uint64_t bytes, + uint32_t peerRank, + TileXRCcuMemoryCopyDirection direction, + TileXRCcuDirectInstallAttempt *attempt, + TileXRCcuDirectInstallReport *report) +{ + if (!session.Available()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "TileXRCcuBackend is not initialized for direct CCU memory copy install attempt"; + } + return TILEXR_ERROR_NOT_INITIALIZED; + } + const int rank = session.Rank(); + const int rankSize = session.RankSize(); + if (localSourceAddr == 0 || localDestinationAddr == 0 || bytes == 0 || + peerRank >= static_cast(rankSize) || peerRank == static_cast(rank)) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "invalid direct CCU memory copy endpoint"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + const std::string processUnavailableMessage = + TileXRCcuRuntimeSession::ProcessDirectCcuRuntimeUnavailableMessage(); + if (!processUnavailableMessage.empty()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = processUnavailableMessage; + } + return TILEXR_ERROR_NOT_FOUND; + } + const uint8_t installDieId = SelectDirectCcuInstallDieId(); + const TileXRCcuBasicInfo *basicInfo = session.GetDirectCcuBasicInfo(); + if (basicInfo == nullptr || basicInfo->dieId != installDieId) { + const int ret = session.RefreshDirectCcuBasicInfo(installDieId); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = session.GetDirectCcuBasicInfoReport().message; + } + return ret; + } + basicInfo = session.GetDirectCcuBasicInfo(); + } + if (basicInfo == nullptr || !session.Available()) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "direct CCU runtime is unavailable for memory copy install attempt"; + } + return TILEXR_ERROR_NOT_FOUND; + } + + DirectCcuMemoryCopyEndpoint localEndpoint; + int ret = BuildDirectCcuLocalMemoryCopyEndpoint( + static_cast(rank), + localSourceAddr, + localDestinationAddr, + bytes, + &localEndpoint); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "failed to query direct CCU memory copy local buffer token"; + } + return ret; + } + + std::vector allEndpoints(static_cast(rankSize)); + ret = session.AllGather( + &localEndpoint, + sizeof(localEndpoint), + allEndpoints.data()); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "failed to exchange direct CCU memory copy peer endpoints"; + } + return ret; + } + const DirectCcuMemoryCopyEndpoint &peerEndpoint = allEndpoints[peerRank]; + if (peerEndpoint.valid == 0 || peerEndpoint.bytes != bytes) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = "invalid direct CCU memory copy peer endpoint"; + } + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + + TileXRCcuDirectMemoryCopySpec memoryCopy; + memoryCopy.direction = direction; + memoryCopy.lengthBytes = bytes; + if (direction == TileXRCcuMemoryCopyDirection::RemoteToLocal) { + memoryCopy.localAddr = localEndpoint.destinationAddr; + memoryCopy.localToken = localEndpoint.destinationToken; + memoryCopy.remoteAddr = peerEndpoint.sourceAddr; + memoryCopy.remoteToken = peerEndpoint.sourceToken; + } else { + memoryCopy.localAddr = localEndpoint.sourceAddr; + memoryCopy.localToken = localEndpoint.sourceToken; + memoryCopy.remoteAddr = peerEndpoint.destinationAddr; + memoryCopy.remoteToken = peerEndpoint.destinationToken; + } + + TileXRCcuDriverAdapter adapter; + TileXRCcuDriverAdapterReport adapterReport; + ret = session.CreateDriverAdapter(&adapter, &adapterReport); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr) { + *report = TileXRCcuDirectInstallReport {}; + report->message = adapterReport.message; + } + return ret; + } + + LowerLayerPlanCallbackContext callbackContext {this, &session}; + TileXRCcuDirectInstallOptions next = options; + next.basicInfo = basicInfo; + next.offlineOnly = false; + next.driverAdapter = &adapter; + next.repositoryMemoryOps = TileXRCcuMakeRepositoryDeviceMemoryOps(next.repositoryMemoryAllocMode); + next.repositoryMemoryUserData = nullptr; + next.lowerLayerPlan = nullptr; + next.prepareLowerLayerPlan = &TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerPlanCallback; + next.lowerLayerPlanUserData = &callbackContext; + next.sqeArgCount = 0; + next.syncResourceCount = 1; + next.syncInstructionCount = std::max( + next.syncInstructionCount, + TILEXR_CCU_DIRECT_MEMORY_COPY_INSTRUCTION_COUNT); + next.bindingsPerSyncResource = next.bindingsPerSyncResource == 0 ? 1 : next.bindingsPerSyncResource; + if (next.provider.empty()) { + next.provider = "tilexr-comm-direct-ccu-memory-copy"; + } + + return TileXRCcuRunDirectMemoryCopyInstallAttempt(next, memoryCopy, attempt, report); +} +#endif + +int TileXRCcuCollectivePlanner::RefreshDirectCcuLowerLayerPlan(TileXRCcuRuntimeSession &session) +{ + ResetDirectCcuLowerLayerPlan(); + if (!directCcuLowerLayerTemplateConfigured_) { + directCcuLowerLayerPlanReport_.message = "direct CCU lower-layer template is not configured"; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuLowerLayerPlanStatus_; + } + if (!session.Available()) { + directCcuLowerLayerPlanReport_.message = "direct CCU runtime is unavailable for lower-layer planning"; + directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuLowerLayerPlanStatus_; + } + + TileXRCcuLowerLayerTransportSnapshot snapshot; + int ret = session.ExportLowerLayerTransportSnapshot(directCcuLowerLayerTemplate_, &snapshot); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanReport_.message = "failed to export direct CCU lower-layer transport snapshot"; + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + ret = TileXRCcuOverlayVerifiedEndpointRoutes( + directCcuVerifiedEndpointRoutes_, + &snapshot, + &directCcuLowerLayerPlanReport_); + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + TileXRCcuLowerLayerInstallPlan plan; + TileXRCcuLowerLayerPlanBuilderReport report; + ret = TileXRCcuBuildLowerLayerInstallPlanFromTransportSnapshot(snapshot, &plan, &report); + directCcuLowerLayerPlanReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuLowerLayerPlanStatus_ = ret; + return directCcuLowerLayerPlanStatus_; + } + + directCcuLowerLayerSnapshot_ = snapshot; + directCcuLowerLayerPlan_ = plan; + directCcuLowerLayerPlanReport_.message = "direct CCU lower-layer install plan cached"; + directCcuLowerLayerPlanValid_ = true; + directCcuLowerLayerPlanStatus_ = TILEXR_SUCCESS; + return TILEXR_SUCCESS; +} + +bool TileXRCcuCollectivePlanner::HasDirectCcuLowerLayerPlan() const +{ + return directCcuLowerLayerPlanValid_; +} + +int TileXRCcuCollectivePlanner::GetDirectCcuLowerLayerPlanStatus() const +{ + return directCcuLowerLayerPlanStatus_; +} + +const TileXRCcuLowerLayerPlanBuilderReport &TileXRCcuCollectivePlanner::GetDirectCcuLowerLayerPlanReport() const +{ + return directCcuLowerLayerPlanReport_; +} + +const TileXRCcuLowerLayerInstallPlan *TileXRCcuCollectivePlanner::GetDirectCcuLowerLayerPlan() const +{ + return directCcuLowerLayerPlanValid_ ? &directCcuLowerLayerPlan_ : nullptr; +} + +} // namespace TileXR diff --git a/src/comm/ccu/tilexr_ccu_collective_planner.h b/src/comm/ccu/tilexr_ccu_collective_planner.h new file mode 100644 index 00000000..27888e5f --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_collective_planner.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#ifndef TILEXR_CCU_COLLECTIVE_PLANNER_H +#define TILEXR_CCU_COLLECTIVE_PLANNER_H + +#include +#include + +#include "ccu/tilexr_ccu_backend.h" +#include "ccu/tilexr_ccu_direct_orchestrator.h" +#ifdef TILEXR_CCU_TESTING +#include "ccu/tilexr_ccu_memory_program.h" +#endif + +namespace TileXR { + +class TileXRCcuRuntimeSession; + +class TileXRCcuCollectivePlanner { +public: + void Reset(); + bool Supports(const TileXRCcuRuntimeSession &session, const TileXRCcuCollectiveRequest &request) const; + int PrepareCollective( + const TileXRCcuRuntimeSession &session, + const TileXRCcuCollectiveRequest &request, + TileXRCcuCollectivePlan *plan) const; + + int ConfigureDirectCcuLowerLayerTemplate( + TileXRCcuRuntimeSession &session, + const TileXRCcuLowerLayerTransportSnapshot &templateSnapshot); + int ConfigureDirectCcuVerifiedEndpointRoutes( + TileXRCcuRuntimeSession &session, + const std::vector &verifiedRoutes); + int ConfigureDirectCcuLocalVerifiedEndpointRoute( + TileXRCcuRuntimeSession &session, + const TileXRCcuLowerLayerTransportRoute &route); + int ConfigureDirectCcuLowerLayerTemplateFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + const std::vector &remoteCcuBuffers); + int PrepareDirectCcuLowerLayerTemplateFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation); + int PrepareDirectCcuInstallAttempt( + TileXRCcuRuntimeSession &session, + const TileXRCcuDirectInstallOptions &options, + TileXRCcuDirectInstallAttempt *attempt, + TileXRCcuDirectInstallReport *report); +#ifdef TILEXR_CCU_TESTING + int PrepareDirectCcuMemoryCopyInstallAttempt( + TileXRCcuRuntimeSession &session, + const TileXRCcuDirectInstallOptions &options, + uint64_t localSourceAddr, + uint64_t localDestinationAddr, + uint64_t bytes, + uint32_t peerRank, + TileXRCcuMemoryCopyDirection direction, + TileXRCcuDirectInstallAttempt *attempt, + TileXRCcuDirectInstallReport *report); +#endif + int RefreshDirectCcuLowerLayerPlan(TileXRCcuRuntimeSession &session); + bool HasDirectCcuLowerLayerPlan() const; + int GetDirectCcuLowerLayerPlanStatus() const; + const TileXRCcuLowerLayerPlanBuilderReport &GetDirectCcuLowerLayerPlanReport() const; + const TileXRCcuLowerLayerInstallPlan *GetDirectCcuLowerLayerPlan() const; + +private: + struct LowerLayerPlanCallbackContext { + TileXRCcuCollectivePlanner *planner = nullptr; + TileXRCcuRuntimeSession *session = nullptr; + }; + + void ResetDirectCcuLowerLayerPlan(); + int FillDirectCcuLowerLayerPlanFromAllocation( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + TileXRCcuLowerLayerInstallPlan *plan, + TileXRCcuLowerLayerPlanBuilderReport *report); + int ExchangeDirectCcuRemoteNotifyCke( + TileXRCcuRuntimeSession &session, + const TileXRCcuResourceAllocation &allocation, + std::vector *remoteCcuBuffers, + TileXRCcuLowerLayerPlanBuilderReport *report); + static int PrepareDirectCcuLowerLayerPlanCallback( + const TileXRCcuResourceAllocation &allocation, + TileXRCcuLowerLayerInstallPlan *plan, + TileXRCcuLowerLayerPlanBuilderReport *report, + void *userData); + + bool directCcuLowerLayerTemplateConfigured_ = false; + bool directCcuLowerLayerPlanValid_ = false; + int directCcuLowerLayerPlanStatus_ = TILEXR_ERROR_NOT_FOUND; + TileXRCcuLowerLayerTransportSnapshot directCcuLowerLayerTemplate_ = {}; + TileXRCcuLowerLayerTransportSnapshot directCcuLowerLayerSnapshot_ = {}; + TileXRCcuLowerLayerInstallPlan directCcuLowerLayerPlan_ = {}; + TileXRCcuLowerLayerPlanBuilderReport directCcuLowerLayerPlanReport_ = {}; + std::vector directCcuVerifiedEndpointRoutes_ = {}; + TileXRCcuLowerLayerTransportRoute directCcuLocalVerifiedEndpointRoute_ = {}; + bool directCcuLocalVerifiedEndpointRouteValid_ = false; +}; + +} // namespace TileXR + +#endif // TILEXR_CCU_COLLECTIVE_PLANNER_H diff --git a/src/comm/ccu/tilexr_ccu_executor.cpp b/src/comm/ccu/tilexr_ccu_executor.cpp new file mode 100644 index 00000000..fe463881 --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_executor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#include "ccu/tilexr_ccu_executor.h" + +#include "ccu/tilexr_ccu_runtime_session.h" + +namespace TileXR { + +int TileXRCcuExecutor::Submit( + const TileXRCcuRuntimeSession &session, + const TileXRCcuCollectivePlan &plan, + aclrtStream) const +{ + if (!session.Available()) { + return TILEXR_ERROR_NOT_INITIALIZED; + } + return plan.ready ? TILEXR_ERROR_NOT_SUPPORT : TILEXR_ERROR_PARA_CHECK_FAIL; +} + +#ifdef TILEXR_CCU_TESTING +int TileXRCcuExecutor::ReadDirectCcuInstructionsForDebug( + TileXRCcuRuntimeSession &session, + uint8_t dieId, + uint16_t instructionStartId, + void *instructions, + uint32_t instructionCount, + uint32_t instructionBytes, + TileXRCcuDriverAdapterReport *report) const +{ + if (report != nullptr) { + *report = TileXRCcuDriverAdapterReport{}; + } + if (!session.Available()) { + if (report != nullptr) { + report->message = "TileXRCcuBackend is not initialized for direct CCU instruction readback"; + } + return TILEXR_ERROR_NOT_INITIALIZED; + } + + TileXRCcuDriverAdapter adapter; + int ret = session.CreateDriverAdapter(&adapter, report); + if (ret != TILEXR_SUCCESS) { + if (report != nullptr && report->message.empty()) { + report->message = "direct CCU runtime is unavailable for instruction readback"; + } + return ret; + } + return adapter.ReadInstructions(dieId, instructionStartId, instructions, instructionCount, instructionBytes, report); +} +#endif + +} // namespace TileXR diff --git a/src/comm/ccu/tilexr_ccu_executor.h b/src/comm/ccu/tilexr_ccu_executor.h new file mode 100644 index 00000000..100f594d --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_executor.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#ifndef TILEXR_CCU_EXECUTOR_H +#define TILEXR_CCU_EXECUTOR_H + +#include "acl/acl_base.h" +#include "ccu/tilexr_ccu_backend.h" +#ifdef TILEXR_CCU_TESTING +#include "ccu/tilexr_ccu_driver_adapter.h" +#endif + +namespace TileXR { + +class TileXRCcuRuntimeSession; + +class TileXRCcuExecutor { +public: + int Submit(const TileXRCcuRuntimeSession &session, const TileXRCcuCollectivePlan &plan, aclrtStream stream) const; +#ifdef TILEXR_CCU_TESTING + int ReadDirectCcuInstructionsForDebug( + TileXRCcuRuntimeSession &session, + uint8_t dieId, + uint16_t instructionStartId, + void *instructions, + uint32_t instructionCount, + uint32_t instructionBytes, + TileXRCcuDriverAdapterReport *report) const; +#endif +}; + +} // namespace TileXR + +#endif // TILEXR_CCU_EXECUTOR_H diff --git a/src/comm/ccu/tilexr_ccu_runtime_session.cpp b/src/comm/ccu/tilexr_ccu_runtime_session.cpp new file mode 100644 index 00000000..d6c66746 --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_runtime_session.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#include "ccu/tilexr_ccu_runtime_session.h" + +#include "tilexr_log.h" +#include "tools/socket/tilexr_sock_exchange.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace chrono; + +namespace TileXR { + +constexpr int TILEXR_INIT_TIMEOUT = 600; + +struct TileXRThreadAllGatherState { + std::vector data[TILEXR_MAX_RANK_SIZE]; + uint64_t arrivals = 0; + uint64_t departures = 0; + size_t bytes = 0; +}; +static map g_directCcuAllGatherStates; +static std::mutex g_mtx; +static std::mutex g_ccuDirectRuntimeMtx; +static bool g_ccuDirectRuntimeUnavailable = false; +static std::string g_ccuDirectRuntimeUnavailableMessage; + +std::string TileXRCcuRuntimeSession::ProcessDirectCcuRuntimeUnavailableMessage() +{ + lock_guard lock(g_ccuDirectRuntimeMtx); + if (!g_ccuDirectRuntimeUnavailable) { + return {}; + } + return g_ccuDirectRuntimeUnavailableMessage.empty() ? + "direct CCU runtime unavailable after process-level init failure" : + "direct CCU runtime unavailable after process-level init failure: " + + g_ccuDirectRuntimeUnavailableMessage; +} + +void TileXRCcuRuntimeSession::Shutdown() +{ + initialized_ = false; + ResetDirectCcuBasicInfo(); + directCcuThreadAllGatherRound_ = 0; + if (ccuDirectRuntime_ != nullptr) { + ccuDirectRuntime_->Shutdown(); + ccuDirectRuntime_.reset(); + } + options_ = TileXRCcuBackendOptions {}; + socketExchange_ = nullptr; +} + +bool TileXRCcuRuntimeSession::Available() const +{ + return initialized_ && ccuDirectRuntime_ != nullptr && ccuDirectRuntime_->IsAvailable(); +} + +int TileXRCcuRuntimeSession::Rank() const +{ + return rank_; +} + +int TileXRCcuRuntimeSession::RankSize() const +{ + return rankSize_; +} + +int TileXRCcuRuntimeSession::Init(const TileXRCcuBackendOptions &options) +{ + Shutdown(); + options_ = options; + rank_ = options.rank; + rankSize_ = options.rankSize; + devId_ = options.devId; + uid_ = options.uid; + socketExchange_ = options.exchange; + if (rankSize_ <= 1) { + TILEXR_LOG(INFO) << "direct CCU runtime skipped for single-rank communicator"; + return TILEXR_SUCCESS; + } + + lock_guard lock(g_ccuDirectRuntimeMtx); + if (g_ccuDirectRuntimeUnavailable) { + TILEXR_LOG(INFO) << "direct CCU runtime skipped after previous init failure"; + return TILEXR_SUCCESS; + } + + ccuDirectRuntime_.reset(new (nothrow) TileXRCcuDirectRuntime()); + if (ccuDirectRuntime_ == nullptr) { + TILEXR_LOG(WARN) << "TileXRCcuDirectRuntime allocation failed, direct CCU disabled"; + return TILEXR_SUCCESS; + } + + TileXRCcuDirectRuntimeOptions runtimeOptions {}; + runtimeOptions.rank = rank_; + runtimeOptions.rankSize = rankSize_; + runtimeOptions.devId = devId_; + runtimeOptions.allGather = &TileXRCcuRuntimeSession::DirectCcuAllGatherCallback; + runtimeOptions.allGatherUserData = this; + TileXRCcuDirectRuntimeReport runtimeReport; + const int ret = ccuDirectRuntime_->Init(runtimeOptions, &runtimeReport); + if (ret != TILEXR_SUCCESS || !ccuDirectRuntime_->IsAvailable()) { + TILEXR_LOG(WARN) << "TileXR direct CCU runtime init failed: " << ret + << ", logicDevId " << runtimeReport.logicDevId + << ", devicePhyId " << runtimeReport.devicePhyId + << ", hdcType " << runtimeReport.hdcType + << ", raInitialized " << (runtimeReport.raInitialized ? 1 : 0) + << ", ccuTlvInitialized " << (runtimeReport.ccuTlvInitialized ? 1 : 0) + << ", " << runtimeReport.message << ", direct CCU disabled"; + g_ccuDirectRuntimeUnavailable = true; + g_ccuDirectRuntimeUnavailableMessage = runtimeReport.message; + ResetDirectCcuBasicInfo(); + ccuDirectRuntime_.reset(); + return TILEXR_SUCCESS; + } + + const int ccuInfoRet = RefreshDirectCcuBasicInfo(0); + if (ccuInfoRet != TILEXR_SUCCESS && ccuInfoRet != TILEXR_ERROR_NOT_FOUND) { + TILEXR_LOG(WARN) << "direct CCU basic info refresh failed after runtime init: " << ccuInfoRet + << ", " << directCcuBasicInfoReport_.message; + } + + TILEXR_LOG(INFO) << "InitDirectCcuRuntime success, rank " << rank_ << "/" << rankSize_ + << " logicDevId " << runtimeReport.logicDevId + << " devicePhyId " << runtimeReport.devicePhyId + << " hdcType " << runtimeReport.hdcType + << " raInitialized " << (runtimeReport.raInitialized ? 1 : 0) + << " ccuTlvInitialized " << (runtimeReport.ccuTlvInitialized ? 1 : 0); + initialized_ = true; + return TILEXR_SUCCESS; +} + +void TileXRCcuRuntimeSession::ResetDirectCcuBasicInfo() +{ + directCcuBasicInfoValid_ = false; + directCcuBasicInfoStatus_ = TILEXR_ERROR_NOT_FOUND; + directCcuBasicInfo_ = TileXRCcuBasicInfo {}; + directCcuBasicInfoReport_ = TileXRCcuDriverAdapterReport {}; +} + +int TileXRCcuRuntimeSession::RefreshDirectCcuBasicInfo(uint8_t dieId) +{ + ResetDirectCcuBasicInfo(); + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + directCcuBasicInfoReport_.message = "direct CCU runtime is unavailable for basic info"; + directCcuBasicInfoStatus_ = TILEXR_ERROR_NOT_FOUND; + return directCcuBasicInfoStatus_; + } + + TileXRCcuBasicInfo basicInfo; + TileXRCcuDriverAdapterReport report; + const int ret = ccuDirectRuntime_->QueryBasicInfo(dieId, &basicInfo, &report); + directCcuBasicInfoReport_ = report; + if (ret != TILEXR_SUCCESS) { + directCcuBasicInfoStatus_ = ret; + return directCcuBasicInfoStatus_; + } + + directCcuBasicInfo_ = basicInfo; + directCcuBasicInfoReport_.message = "direct CCU basic info cached"; + directCcuBasicInfoValid_ = true; + directCcuBasicInfoStatus_ = TILEXR_SUCCESS; + return TILEXR_SUCCESS; +} + +bool TileXRCcuRuntimeSession::HasDirectCcuBasicInfo() const +{ + return directCcuBasicInfoValid_; +} + +int TileXRCcuRuntimeSession::GetDirectCcuBasicInfoStatus() const +{ + return directCcuBasicInfoStatus_; +} + +const TileXRCcuBasicInfo *TileXRCcuRuntimeSession::GetDirectCcuBasicInfo() const +{ + return directCcuBasicInfoValid_ ? &directCcuBasicInfo_ : nullptr; +} + +const TileXRCcuDriverAdapterReport &TileXRCcuRuntimeSession::GetDirectCcuBasicInfoReport() const +{ + return directCcuBasicInfoReport_; +} + +int TileXRCcuRuntimeSession::RegisterCcuResourceRmaBuffer(uint64_t resourceAddr) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->RegisterCcuResourceRmaBuffer(resourceAddr); +} + +int TileXRCcuRuntimeSession::ExportLocalCcuRmaBuffer(TileXRCcuLocalResourceWindowInfo *info) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->ExportLocalCcuRmaBuffer(info); +} + +int TileXRCcuRuntimeSession::ExportRemoteCcuRmaBuffers(std::vector *buffers) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->ExportRemoteCcuRmaBuffers(buffers); +} + +int TileXRCcuRuntimeSession::ExportLowerLayerTransportSnapshot( + const TileXRCcuLowerLayerTransportSnapshot &templateSnapshot, + TileXRCcuLowerLayerTransportSnapshot *snapshot) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->ExportLowerLayerTransportSnapshot(templateSnapshot, snapshot); +} + +int TileXRCcuRuntimeSession::ConfigureLocalVerifiedEndpointRoute(const TileXRCcuLowerLayerTransportRoute &route) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->ConfigureLocalVerifiedEndpointRoute(route); +} + +int TileXRCcuRuntimeSession::RefreshLocalVerifiedEndpointRoute(TileXRCcuDirectRuntimeReport *report) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->RefreshLocalVerifiedEndpointRoute(report); +} + +int TileXRCcuRuntimeSession::CreateDriverAdapter( + TileXRCcuDriverAdapter *adapter, + TileXRCcuDriverAdapterReport *report) +{ + if (ccuDirectRuntime_ == nullptr || !ccuDirectRuntime_->IsAvailable()) { + if (report != nullptr) { + report->message = "direct CCU runtime is unavailable"; + } + return TILEXR_ERROR_NOT_FOUND; + } + return ccuDirectRuntime_->CreateDriverAdapter(adapter, report); +} + +int TileXRCcuRuntimeSession::AllGather(const void *sendBuf, size_t sendBytes, void *recvBuf) +{ + return DirectCcuAllGatherCallback(sendBuf, sendBytes, recvBuf, this); +} + +int TileXRCcuRuntimeSession::DirectCcuAllGatherCallback( + const void *sendBuf, + size_t sendBytes, + void *recvBuf, + void *userData) +{ + auto *session = static_cast(userData); + if (session == nullptr || sendBuf == nullptr || recvBuf == nullptr || sendBytes == 0) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + if (session->socketExchange_ == nullptr) { + return session->DirectCcuThreadAllGather(sendBuf, sendBytes, recvBuf); + } + return session->socketExchange_->AllGather( + static_cast(sendBuf), + sendBytes, + static_cast(recvBuf)); +} + +int TileXRCcuRuntimeSession::DirectCcuThreadAllGather(const void *sendBuf, size_t sendBytes, void *recvBuf) +{ + if (sendBuf == nullptr || recvBuf == nullptr || sendBytes == 0 || rank_ < 0 || + rank_ >= rankSize_ || rankSize_ <= 0 || uid_.empty()) { + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + + const uint64_t round = directCcuThreadAllGatherRound_++; + const std::string key = uid_ + ":ccu:" + std::to_string(round); + auto start = high_resolution_clock::now(); + for (;;) { + { + lock_guard lock(g_mtx); + auto &state = g_directCcuAllGatherStates[key]; + if (state.bytes == 0) { + state.bytes = sendBytes; + } else if (state.bytes != sendBytes) { + g_directCcuAllGatherStates.erase(key); + return TILEXR_ERROR_PARA_CHECK_FAIL; + } + if (state.data[rank_].empty()) { + state.data[rank_].resize(sendBytes); + std::memcpy(state.data[rank_].data(), sendBuf, sendBytes); + ++state.arrivals; + } + if (state.arrivals == static_cast(rankSize_)) { + auto *output = static_cast(recvBuf); + for (int i = 0; i < rankSize_; ++i) { + std::memcpy(output + static_cast(i) * sendBytes, state.data[i].data(), sendBytes); + } + ++state.departures; + if (state.departures == static_cast(rankSize_)) { + g_directCcuAllGatherStates.erase(key); + } + return TILEXR_SUCCESS; + } + } + const std::string processUnavailableMessage = ProcessDirectCcuRuntimeUnavailableMessage(); + if (!processUnavailableMessage.empty()) { + lock_guard lock(g_mtx); + g_directCcuAllGatherStates.erase(key); + TILEXR_LOG(ERROR) << "direct CCU thread allgather abort rank " << rank_ << "/" << rankSize_ + << " uid " << uid_ << " round " << round << ", " + << processUnavailableMessage; + return TILEXR_ERROR_NOT_FOUND; + } + this_thread::sleep_for(1ms); + auto elapsed = duration_cast(high_resolution_clock::now() - start); + if (elapsed.count() > TILEXR_INIT_TIMEOUT) { + lock_guard lock(g_mtx); + g_directCcuAllGatherStates.erase(key); + TILEXR_LOG(ERROR) << "direct CCU thread allgather timeout rank " << rank_ << "/" << rankSize_ + << " uid " << uid_ << " round " << round; + return TILEXR_ERROR_TIMEOUT; + } + } +} + +} // namespace TileXR diff --git a/src/comm/ccu/tilexr_ccu_runtime_session.h b/src/comm/ccu/tilexr_ccu_runtime_session.h new file mode 100644 index 00000000..d0010864 --- /dev/null +++ b/src/comm/ccu/tilexr_ccu_runtime_session.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2026 TileXR Project + */ +#ifndef TILEXR_CCU_RUNTIME_SESSION_H +#define TILEXR_CCU_RUNTIME_SESSION_H + +#include +#include +#include +#include +#include + +#include "ccu/tilexr_ccu_backend.h" +#include "ccu/tilexr_ccu_direct_runtime.h" + +namespace TileXR { + +class TileXRCcuRuntimeSession { +public: + int Init(const TileXRCcuBackendOptions &options); + void Shutdown(); + bool Available() const; + + int Rank() const; + int RankSize() const; + int AllGather(const void *sendBuf, size_t sendBytes, void *recvBuf); + + int RefreshDirectCcuBasicInfo(uint8_t dieId = 0); + bool HasDirectCcuBasicInfo() const; + int GetDirectCcuBasicInfoStatus() const; + const TileXRCcuBasicInfo *GetDirectCcuBasicInfo() const; + const TileXRCcuDriverAdapterReport &GetDirectCcuBasicInfoReport() const; + + int RegisterCcuResourceRmaBuffer(uint64_t resourceAddr); + int ExportLocalCcuRmaBuffer(TileXRCcuLocalResourceWindowInfo *info); + int ExportRemoteCcuRmaBuffers(std::vector *buffers); + int ExportLowerLayerTransportSnapshot( + const TileXRCcuLowerLayerTransportSnapshot &templateSnapshot, + TileXRCcuLowerLayerTransportSnapshot *snapshot); + int ConfigureLocalVerifiedEndpointRoute(const TileXRCcuLowerLayerTransportRoute &route); + int RefreshLocalVerifiedEndpointRoute(TileXRCcuDirectRuntimeReport *report); + int CreateDriverAdapter(TileXRCcuDriverAdapter *adapter, TileXRCcuDriverAdapterReport *report); + + static std::string ProcessDirectCcuRuntimeUnavailableMessage(); + +private: + void ResetDirectCcuBasicInfo(); + static int DirectCcuAllGatherCallback(const void *sendBuf, size_t sendBytes, void *recvBuf, void *userData); + int DirectCcuThreadAllGather(const void *sendBuf, size_t sendBytes, void *recvBuf); + + TileXRCcuBackendOptions options_ = {}; + int rank_ = 0; + int rankSize_ = 0; + int devId_ = 0; + std::string uid_ = {}; + TileXRSockExchange *socketExchange_ = nullptr; + bool initialized_ = false; + std::unique_ptr ccuDirectRuntime_; + bool directCcuBasicInfoValid_ = false; + int directCcuBasicInfoStatus_ = TILEXR_ERROR_NOT_FOUND; + TileXRCcuBasicInfo directCcuBasicInfo_ = {}; + TileXRCcuDriverAdapterReport directCcuBasicInfoReport_ = {}; + uint64_t directCcuThreadAllGatherRound_ = 0; +}; + +} // namespace TileXR + +#endif // TILEXR_CCU_RUNTIME_SESSION_H diff --git a/src/comm/tilexr_comm.cpp b/src/comm/tilexr_comm.cpp index 69736d0d..a2ede721 100644 --- a/src/comm/tilexr_comm.cpp +++ b/src/comm/tilexr_comm.cpp @@ -9,6 +9,7 @@ */ #include "tilexr_comm.h" #include "tilexr_internal.h" +#include "ccu/tilexr_ccu_backend.h" #include "sdma/tilexr_sdma_transport.h" #include "udma/tilexr_udma_context.h" @@ -22,13 +23,14 @@ #include #include #include +#include #include "tilexr_log.h" #include "tools/socket/tilexr_sock_exchange.h" -#include "runtime/kernel.h" #include "runtime/mem.h" #include "runtime/dev.h" +#include "runtime/rts/rts_device.h" #include "runtime/rt_ffts.h" enum TopologyType : int { @@ -190,6 +192,39 @@ int TileXRComm::ApplyUDMACommArgsStateCallback(const TileXRUDMACommArgsState &st return static_cast(userData)->ApplyUDMACommArgsState(state); } +int TileXRComm::InitCcuBackend() +{ + if (ccuBackend_ == nullptr) { + ccuBackend_.reset(new (nothrow) TileXRCcuBackend()); + if (ccuBackend_ == nullptr) { + return TILEXR_ERROR_INTERNAL; + } + } + + TileXRCcuBackendOptions options {}; + options.rank = rank_; + options.rankSize = rankSize_; + options.devId = devId_; + options.uid = uid_; + options.exchange = socketExchange_; + return ccuBackend_->Init(options); +} + +TileXRCcuBackend *TileXRComm::GetCcuBackendForCollectives() +{ + return ccuBackend_.get(); +} + +const TileXRCcuBackend *TileXRComm::GetCcuBackendForCollectives() const +{ + return ccuBackend_.get(); +} + +int TileXRComm::EnableCcuBackendForTest() +{ + return InitCcuBackend(); +} + int TileXRComm::InitSDMA() { { @@ -360,6 +395,11 @@ const TileXRUDMARegistry* TileXRComm::GetUDMARegistryHost() const return udmaContext_ == nullptr ? nullptr : udmaContext_->GetRegistryHost(); } +bool TileXRComm::IsUdmaAvailableForCollectives() const +{ + return udmaContext_ != nullptr && udmaContext_->IsAvailable(); +} + int TileXRComm::InitCommon() { // enable peer device @@ -815,6 +855,9 @@ int TileXRComm::OpenIpcMem(const char names[TILEXR_MAX_RANK_SIZE][IPC_NAME_SIZE] if (ret != RT_ERROR_NONE) { CloseIpcMem(); TILEXR_LOG(ERROR) << "rank : " << rank_ << " localRank : " << localRank_ << " peerMem: " << i << + " devId : " << devId_ << " peerDevId : " << (i < static_cast(devList_.size()) ? devList_[i] : -1) << + " localRankSize : " << localRankSize_ << " ipcNameLen : " << std::strlen(names[i]) << + " ipcNamePrefix : " << std::string(names[i], std::min(std::strlen(names[i]), 16U)) << " IpcOpenMemory err " << ret; return TILEXR_ERROR_INTERNAL; } @@ -887,6 +930,10 @@ TileXRComm::~TileXRComm() FreePeerMem(commArgs_.dumpAddr); FreePeerMem(peerMem_[rank_]); FreePeerMem(commArgsPtr_); + if (ccuBackend_ != nullptr) { + ccuBackend_->Shutdown(); + ccuBackend_.reset(); + } ResetSDMAState(); } diff --git a/src/comm/tilexr_comm.h b/src/comm/tilexr_comm.h index 8b8af295..bfde341d 100644 --- a/src/comm/tilexr_comm.h +++ b/src/comm/tilexr_comm.h @@ -11,6 +11,7 @@ #define TILEXR_COMM_H #include +#include #include #include #include @@ -27,6 +28,7 @@ class TileXRSockExchange; class TileXRUDMAContext; struct TileXRUDMACommArgsState; class TileXRSDMATransport; +class TileXRCcuBackend; class TileXRComm { public: TileXRComm(int rank, int rankSize); @@ -48,6 +50,11 @@ class TileXRComm { int UnregisterUDMAMemory(TileXRUDMAMemHandle handle); GM_ADDR GetUDMARegistryPtr() const; const TileXRUDMARegistry* GetUDMARegistryHost() const; + bool IsUdmaAvailableForCollectives() const; + int InitCcuBackend(); + TileXRCcuBackend *GetCcuBackendForCollectives(); + const TileXRCcuBackend *GetCcuBackendForCollectives() const; + int EnableCcuBackendForTest(); bool IsSDMAAvailable() const; GM_ADDR GetSDMAWorkspacePtr() const; SDMAInitStatus GetSDMAInitStatus() const; @@ -104,6 +111,7 @@ class TileXRComm { TileXRSockExchange *socketExchange_ = nullptr; bool isEnableMsprofOp_ = false; std::unique_ptr udmaContext_; + std::unique_ptr ccuBackend_; GM_ADDR sdmaWorkspaceDev_ = nullptr; SDMAInitStatus sdmaInitStatus_ = SDMAInitStatus::DISABLED_BY_ENV; std::unique_ptr sdmaTransport_; diff --git a/src/comm/tilexr_internal.cpp b/src/comm/tilexr_internal.cpp index e39bd332..3f53f246 100644 --- a/src/comm/tilexr_internal.cpp +++ b/src/comm/tilexr_internal.cpp @@ -45,6 +45,25 @@ const std::unordered_map CHIP_MAP = { {"Ascend950PR_9599", ChipName::CHIP_950PR} }; +const std::unordered_map CHIP_PREFIX_MAP = { + {"Ascend950DT_", ChipName::CHIP_950}, + {"Ascend950PR_", ChipName::CHIP_950PR} +}; + +ChipName ResolveChipNameFromSocVersion(const std::string& chipName) +{ + auto it = CHIP_MAP.find(chipName); + if (it != CHIP_MAP.end()) { + return it->second; + } + for (const auto& item : CHIP_PREFIX_MAP) { + if (chipName.find(item.first) == 0) { + return item.second; + } + } + return ChipName::RESERVED; +} + /** * @brief 用于获取芯片名称 */ @@ -65,12 +84,8 @@ ChipName GetChipName() string chipName(ver); TILEXR_LOG(DEBUG) << "rtGetSocVersion -- The result after converting ver to string is:" << chipName; - auto it = CHIP_MAP.find(chipName); - if (it != CHIP_MAP.end()) { - curChipName = it->second; - } else if (chipName.find("Ascend950PR_") == 0) { - curChipName = ChipName::CHIP_950PR; - } else { + curChipName = ResolveChipNameFromSocVersion(chipName); + if (curChipName == ChipName::RESERVED) { TILEXR_LOG(WARN) << "There is no commitment to the supported chip types yet," << " and it is not certain whether the functions will work properly."; } diff --git a/src/include/tilexr_api.h b/src/include/tilexr_api.h index 7b4fd3a7..13cf8251 100644 --- a/src/include/tilexr_api.h +++ b/src/include/tilexr_api.h @@ -10,10 +10,18 @@ #ifndef TILEXR_API_H #define TILEXR_API_H +#ifdef __cplusplus #include -#include +#include #include "comm_args.h" #include "tilexr_udma_reg.h" +#else +#include +#include +#include +typedef uint8_t *GM_ADDR; +#endif + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -33,9 +41,11 @@ int TileXRCommInitRankWithCustDomainSize(int commDomain, int bufferSize, int ran int TileXRCommInitRankWithDomain(int commDomain, int rankSize, int rank, TileXRCommPtr *comm); +#ifdef __cplusplus int TileXRGetCommArgsDev(TileXRCommPtr comm, GM_ADDR &commArgsPtr); int TileXRGetCommArgsHost(TileXRCommPtr comm, TileXR::CommArgs *&commArgsPtr); +#endif int TileXRCommNextMagic(TileXRCommPtr comm, int64_t *magic); @@ -43,9 +53,11 @@ int TileXRUDMARegister(TileXRCommPtr comm, GM_ADDR localPtr, size_t bytes, TileX int TileXRUDMAUnregister(TileXRCommPtr comm, TileXRUDMAMemHandle handle); +#ifdef __cplusplus int TileXRGetUDMARegistryDev(TileXRCommPtr comm, GM_ADDR ®istryPtr); int TileXRGetUDMARegistryHost(TileXRCommPtr comm, const TileXR::TileXRUDMARegistry **registry); +#endif int TileXRSDMAAvailable(TileXRCommPtr comm, bool *available); diff --git a/src/include/tilexr_collectives.h b/src/include/tilexr_collectives.h index 50fa7828..b2bac393 100644 --- a/src/include/tilexr_collectives.h +++ b/src/include/tilexr_collectives.h @@ -20,21 +20,51 @@ // The collectives public API is currently C++ header-compatible because it reuses TileXR namespace datatypes. extern "C" { +enum TileXRCollectiveBackend { + TILEXR_COLLECTIVE_BACKEND_AUTO = 0, + TILEXR_COLLECTIVE_BACKEND_AIV = 1, + TILEXR_COLLECTIVE_BACKEND_UDMA = 2, + TILEXR_COLLECTIVE_BACKEND_CCU = 3, +}; + +struct TileXRCollectiveOptions { + TileXRCollectiveBackend backend; +}; + +int TileXRAllGatherEx(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options); int TileXRAllGather(void *sendBuf, void *recvBuf, int64_t sendCount, TileXR::TileXRDataType dataType, TileXRCommPtr comm, aclrtStream stream); +int TileXRAllToAllEx(void *sendBuf, void *recvBuf, int64_t sendCount, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options); int TileXRAllToAll(void *sendBuf, void *recvBuf, int64_t sendCount, TileXR::TileXRDataType dataType, TileXRCommPtr comm, aclrtStream stream); +int TileXRAllReduceEx(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream, const TileXRCollectiveOptions *options); int TileXRAllReduce(void *sendBuf, void *recvBuf, int64_t count, TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, TileXRCommPtr comm, aclrtStream stream); +int TileXRReduceScatterEx(void *sendBuf, void *recvBuf, int64_t recvCount, + TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, + TileXRCommPtr comm, aclrtStream stream, + const TileXRCollectiveOptions *options); int TileXRReduceScatter(void *sendBuf, void *recvBuf, int64_t recvCount, TileXR::TileXRDataType dataType, TileXR::TileXRReduceOp op, TileXRCommPtr comm, aclrtStream stream); +int TileXRBroadcastEx(void *buf, int64_t count, + TileXR::TileXRDataType dataType, int root, + TileXRCommPtr comm, aclrtStream stream, const TileXRCollectiveOptions *options); int TileXRBroadcast(void *buf, int64_t count, TileXR::TileXRDataType dataType, int root, TileXRCommPtr comm, aclrtStream stream); +int TileXRProfileProbeEx(void *sendBuf, void *recvBuf, int64_t count, + TileXR::TileXRDataType dataType, TileXRCommPtr comm, + aclrtStream stream, const TileXRCollectiveOptions *options); int TileXRProfileProbe(void *sendBuf, void *recvBuf, int64_t count, TileXR::TileXRDataType dataType, TileXRCommPtr comm, aclrtStream stream); diff --git a/tests/ccu/CMakeLists.txt b/tests/ccu/CMakeLists.txt new file mode 100644 index 00000000..212090fc --- /dev/null +++ b/tests/ccu/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# Copyright (c) 2026 TileXR Project +# +# The direct CCU smoke runner compiles its probe against the active TileXR build +# so that it can test the exact libtile-comm.so under validation. Keep this +# directory free of private producer probe targets. +# + +cmake_minimum_required(VERSION 3.16) +project(TileXR_CCU_Tests LANGUAGES CXX) diff --git a/tests/ccu/ccu_npu_smi_busy_guard.py b/tests/ccu/ccu_npu_smi_busy_guard.py new file mode 100644 index 00000000..a8f103e5 --- /dev/null +++ b/tests/ccu/ccu_npu_smi_busy_guard.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import argparse +import re +import sys +from pathlib import Path + + +def parse_devices(text): + devices = set() + for item in text.split(","): + item = item.strip() + if not item: + continue + devices.add(int(item, 0)) + return devices + + +def first_int(text): + match = re.search(r"\d+", text) + return int(match.group(0), 10) if match else None + + +def parse_busy_processes(log_text, selected_devices): + busy = [] + in_process_table = False + for line in log_text.splitlines(): + if "|" not in line: + continue + lower_line = line.lower() + if "process id" in lower_line or "process name" in lower_line: + in_process_table = True + continue + if not in_process_table: + continue + fields = [field.strip() for field in line.strip().strip("|").split("|")] + if len(fields) < 3: + continue + device = first_int(fields[0]) + if device is None or device not in selected_devices: + continue + + pid = first_int(fields[1]) + process_index = 2 + if (pid is None or pid == 0) and len(fields) >= 4: + pid = first_int(fields[2]) + process_index = 3 + if pid is None or pid == 0: + continue + process = fields[process_index].split()[0] if fields[process_index].split() else "unknown" + if process in {"-", "N/A", "NA"}: + continue + busy.append((device, pid, process)) + return busy + + +def parse_unhealthy_devices(log_text, selected_devices): + unhealthy = [] + observed_selected = set() + in_status_table = False + for line in log_text.splitlines(): + if "|" not in line: + continue + lower_line = line.lower() + if "process id" in lower_line or "process name" in lower_line: + in_status_table = False + continue + if "health" in lower_line: + in_status_table = True + continue + if not in_status_table: + continue + + fields = [field.strip() for field in line.strip().strip("|").split("|")] + if len(fields) < 3: + continue + device = first_int(fields[0]) + if device is None or device not in selected_devices: + continue + health = fields[2].split()[0] if fields[2].split() else "" + if not health: + continue + observed_selected.add(device) + if health.upper() != "OK": + unhealthy.append((device, health)) + return unhealthy, observed_selected + + +def main(): + parser = argparse.ArgumentParser(description="Reject TileXR CCU smoke runs on busy or unhealthy selected NPUs.") + parser.add_argument("--log", required=True, help="npu-smi info log path") + parser.add_argument("--devices", required=True, help="comma-separated NPU device ids selected for the smoke") + parser.add_argument( + "--allow-unhealthy", + action="store_true", + help="Allow selected devices with non-OK health while still rejecting busy processes.", + ) + args = parser.parse_args() + + try: + selected_devices = parse_devices(args.devices) + except ValueError as exc: + print(f"invalid device list {args.devices!r}: {exc}", file=sys.stderr) + return 2 + if not selected_devices: + print("no selected NPU devices to check", file=sys.stderr) + return 2 + + log_path = Path(args.log) + log_text = log_path.read_text(encoding="utf-8", errors="replace") + unhealthy, observed_health = parse_unhealthy_devices(log_text, selected_devices) + if unhealthy: + if not args.allow_unhealthy: + for device, health in unhealthy: + print(f"unhealthy selected NPU device={device} health={health}") + return 1 + for device, health in unhealthy: + print(f"unhealthy selected NPU devices allowed device={device} health={health}") + if observed_health and not unhealthy: + print(f"selected NPU devices healthy devices={args.devices}") + + busy = parse_busy_processes(log_text, selected_devices) + if busy: + for device, pid, process in busy: + print(f"busy selected NPU process device={device} pid={pid} process={process}") + return 1 + + print(f"no selected NPU processes devices={args.devices}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/ccu/ccu_tilexr_basic_info_probe.cpp b/tests/ccu/ccu_tilexr_basic_info_probe.cpp new file mode 100644 index 00000000..73e673fb --- /dev/null +++ b/tests/ccu/ccu_tilexr_basic_info_probe.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2026 TileXR Project + * Licensed under the Apache License, Version 2.0 + * + * Probe TileXR-owned direct CCU runtime basic-info path. + * This does not install repository state and does not submit CCU tasks. + */ + +#include "ccu/tilexr_ccu_direct_runtime.h" +#include "ccu/tilexr_ccu_specs.h" + +#include +#include +#include +#include + +namespace { + +uint32_t ParseUintArg(const char* value, uint32_t fallback) +{ + if (value == nullptr) { + return fallback; + } + char* end = nullptr; + const unsigned long parsed = std::strtoul(value, &end, 0); + if (end == value || *end != '\0') { + return fallback; + } + return static_cast(parsed); +} + +void PrintHex32(const char* label, uint32_t value) +{ + std::cout << label << "=0x" << std::hex << std::setw(8) << std::setfill('0') << value << std::dec; +} + +void PrintHex64(const char* label, uint64_t value) +{ + std::cout << label << "=0x" << std::hex << std::setw(16) << std::setfill('0') << value << std::dec; +} + +void PrintBasicInfo( + uint32_t deviceLogicId, + uint8_t dieId, + const TileXR::TileXRCcuBasicInfo& basicInfo, + const TileXR::TileXRCcuDriverAdapterReport& adapterReport, + const TileXR::TileXRCcuSpecInfo& specInfo) +{ + std::cout << "tilexr_ccu_basic_info result" + << " deviceLogicId=" << deviceLogicId + << " devicePhyId=" << adapterReport.devicePhyId + << " dieId=" << static_cast(dieId) + << " driverRet=" << adapterReport.driverRet + << " opRet=" << adapterReport.opRet + << " msId=" << basicInfo.msId + << " tokenId=" << basicInfo.msidToken.tokenId + << " tokenValue=" << basicInfo.msidToken.tokenValue + << " tokenValid=" << (basicInfo.msidToken.valid ? 1 : 0) + << " "; + PrintHex32("missionKey", basicInfo.missionKey); + std::cout << " "; + PrintHex64("resourceAddr", basicInfo.resourceAddr); + std::cout << " instructionNum=" << specInfo.instructionNum + << " xnNum=" << specInfo.xnNum + << " ckeNum=" << specInfo.ckeNum + << " channelNum=" << specInfo.channelNum + << " missionNum=" << specInfo.missionNum + << std::endl; +} + +} // namespace + +int main(int argc, char** argv) +{ + const uint32_t deviceLogicId = ParseUintArg(argc > 1 ? argv[1] : nullptr, 0); + const uint8_t dieId = static_cast(ParseUintArg(argc > 2 ? argv[2] : nullptr, 0)); + + TileXR::TileXRCcuDirectRuntime runtime; + TileXR::TileXRCcuDirectRuntimeOptions options; + options.devId = static_cast(deviceLogicId); + options.rank = 0; + options.rankSize = 1; + + TileXR::TileXRCcuDirectRuntimeReport runtimeReport; + int ret = runtime.Init(options, &runtimeReport); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cerr << "failed to initialize TileXR CCU direct runtime: " + << runtimeReport.message + << " deviceLogicId=" << runtimeReport.logicDevId + << " devicePhyId=" << runtimeReport.devicePhyId + << " hdcType=" << runtimeReport.hdcType + << " raInitialized=" << (runtimeReport.raInitialized ? 1 : 0) + << std::endl; + return 2; + } + std::cout << "tilexr_ccu_basic_info runtime" + << " deviceLogicId=" << runtimeReport.logicDevId + << " devicePhyId=" << runtimeReport.devicePhyId + << " hdcType=" << runtimeReport.hdcType + << " raInitialized=" << (runtimeReport.raInitialized ? 1 : 0) + << " message=\"" << runtimeReport.message << "\"" + << std::endl; + + TileXR::TileXRCcuBasicInfo basicInfo; + TileXR::TileXRCcuDriverAdapterReport adapterReport; + ret = runtime.QueryBasicInfo(dieId, &basicInfo, &adapterReport); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cerr << "failed to query CCU basic info: " << adapterReport.message + << " driverRet=" << adapterReport.driverRet + << " opRet=" << adapterReport.opRet << std::endl; + return 3; + } + + TileXR::TileXRCcuSpecInfo specInfo; + TileXR::TileXRCcuSpecsReport specsReport; + ret = TileXR::TileXRCcuDecodeBasicInfo(basicInfo, &specInfo, &specsReport); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cerr << "failed to decode CCU basic info: " << specsReport.message << std::endl; + return 4; + } + + PrintBasicInfo(deviceLogicId, dieId, basicInfo, adapterReport, specInfo); + return 0; +} diff --git a/tests/ccu/ccu_tilexr_direct_smoke_probe.cpp b/tests/ccu/ccu_tilexr_direct_smoke_probe.cpp new file mode 100644 index 00000000..0e1f899b --- /dev/null +++ b/tests/ccu/ccu_tilexr_direct_smoke_probe.cpp @@ -0,0 +1,1382 @@ +/* + * Copyright (c) 2026 TileXR Project + * Licensed under the Apache License, Version 2.0 + * + * Private C++ integration probe for the TileXR-owned direct CCU prepare path. + * The default run is intentionally hardware-safe. Set TILEXR_CCU_DIRECT_SMOKE_ENABLE=1 + * in a real multi-rank TileXRComm launch to prepare the no-hcomm direct CCU install attempt. + */ + +#include "acl/acl.h" +#include "acl/acl_rt.h" +#include "tilexr_api.h" +#include "tilexr_types.h" +#include "ccu/tilexr_ccu_collective_planner.h" +#include "ccu/tilexr_ccu_executor.h" +#include "ccu/tilexr_ccu_runtime_session.h" +#include "tools/socket/tilexr_sock_exchange.h" +#include "runtime/dev.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +struct DirectCcuSmokeContext { + std::unique_ptr exchange; + TileXR::TileXRCcuRuntimeSession session; + TileXR::TileXRCcuCollectivePlanner planner; + TileXR::TileXRCcuExecutor executor; +}; + +using TileXRDirectCcuPrepareOptions = TileXR::TileXRCcuDirectInstallOptions; +using TileXRDirectCcuPrepareReport = TileXR::TileXRCcuDirectInstallReport; +using TileXRDirectCcuSubmitReport = TileXR::TileXRCcuDirectSubmitReport; +using TileXRDirectCcuPreparedTasksPtr = TileXR::TileXRCcuDirectInstallAttempt*; +using TileXRDirectCcuTaskInfo = TileXR::TileXRCcuTask; +using TileXRDirectCcuInstructionReadbackReport = TileXR::TileXRCcuDriverAdapterReport; + +constexpr uint32_t TILEXR_DIRECT_CCU_SQE_ARGS_LEN = TileXR::TILEXR_CCU_SQE_ARGS_LEN; + +struct TileXRDirectCcuInstructionWords { + uint32_t words[4] = {}; +}; + +constexpr const char* kEnableEnv = "TILEXR_CCU_DIRECT_SMOKE_ENABLE"; +constexpr const char* kThreadModeEnv = "TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE"; +constexpr const char* kDirectCcuOnlyInitEnv = "TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT"; +constexpr const char* kFastExitOnPrepareFailureEnv = "TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE"; +constexpr const char* kFastExitAfterRunEnv = "TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_AFTER_RUN"; +constexpr const char* kTraceLifecycleEnv = "TILEXR_CCU_DIRECT_SMOKE_TRACE_LIFECYCLE"; +constexpr const char* kReadbackInstructionsEnv = "TILEXR_CCU_DIRECT_SMOKE_READBACK_INSTRUCTIONS"; +constexpr const char* kSubmitEnv = "TILEXR_CCU_DIRECT_SMOKE_SUBMIT"; +constexpr const char* kReadyDirEnv = "TILEXR_CCU_DIRECT_SMOKE_READY_DIR"; +constexpr const char* kDoneDirEnv = "TILEXR_CCU_DIRECT_SMOKE_DONE_DIR"; +constexpr const char* kReadyTimeoutMsEnv = "TILEXR_CCU_DIRECT_SMOKE_READY_TIMEOUT_MS"; +constexpr const char* kSubmitTaskSelectorEnv = "TILEXR_CCU_DIRECT_SMOKE_SUBMIT_TASK_SELECTOR"; +constexpr const char* kDelayRankEnv = "TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK"; +constexpr const char* kPreSubmitDelayMsEnv = "TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS"; +constexpr const char* kP2pCcuCopyEnv = "TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY"; +constexpr const char* kExpectP2pCcuCopyEnv = "TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY"; +constexpr const char* kP2pCcuCopyBytesEnv = "TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES"; +constexpr const char* kLocalWaitCkeStartEnv = "TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START"; +constexpr const char* kLocalWaitCkeCountEnv = "TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT"; +constexpr const char* kRemoteNotifyCkeStartEnv = "TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START"; +constexpr const char* kRemoteNotifyCkeCountEnv = "TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT"; +constexpr const char* kBarrierModeEnv = "TILEXR_CCU_DIRECT_BARRIER_MODE"; +constexpr const char* kRepositoryInstallWindowEnv = "TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW"; +constexpr const char* kRepositoryInstallDataLenModeEnv = "TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE"; +constexpr const char* kRepositoryMemoryAllocModeEnv = "TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE"; +constexpr const char* kInstallOrderEnv = "TILEXR_CCU_DIRECT_INSTALL_ORDER"; +constexpr const char* kResourceWindowTokenIdEnv = "TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID"; +constexpr const char* kResourceWindowRawTokenIdEnv = "TILEXR_CCU_DIRECT_RESOURCE_WINDOW_RAW_TOKEN_ID"; +constexpr const char* kResourceWindowTokenValueEnv = "TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_VALUE"; +constexpr uint32_t kHcommStyleTask1PreludeInstructionCount = 5U; + +struct DeviceBuffer { + void* ptr = nullptr; + size_t bytes = 0; + + ~DeviceBuffer() + { + if (ptr != nullptr) { + aclrtFree(ptr); + } + } + + int Allocate(size_t size) + { + if (size == 0) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + bytes = size; + return aclrtMalloc(&ptr, bytes, ACL_MEM_MALLOC_HUGE_FIRST); + } +}; + +struct P2pCcuCopyState { + DeviceBuffer source; + DeviceBuffer destination; + std::vector expected; + std::vector observed; + size_t bytes = 0; + int initRet = ACL_SUCCESS; + int readRet = ACL_SUCCESS; + uint32_t mismatchCount = 0; + bool passed = false; +}; + +bool EnvFlag(const char* name) +{ + const char* value = std::getenv(name); + if (value == nullptr) { + return false; + } + const std::string text(value); + return text == "1" || text == "true" || text == "TRUE" || text == "yes" || text == "on"; +} + +bool ShouldFastExitAfterPrepareFailure(int ret) +{ + return ret != 0 && EnvFlag(kFastExitOnPrepareFailureEnv); +} + +const char* FastExitReasonForReturnCode(int ret) +{ + switch (ret) { + case 6: + return "prepare failed; skipping cleanup to preserve diagnostic status"; + case 8: + return "direct CCU stream synchronize failed; skipping cleanup to preserve diagnostic status"; + case 9: + return "direct CCU submit failed; skipping cleanup to preserve diagnostic status"; + case 13: + return "direct CCU collective completion timed out; skipping cleanup to preserve diagnostic status"; + case 14: + return "direct CCU P2P CCU-copy check failed; skipping cleanup to preserve diagnostic status"; + default: + return "direct CCU smoke failed; skipping cleanup to preserve diagnostic status"; + } +} + +bool ShouldFastExitAfterRun() +{ + return EnvFlag(kFastExitAfterRunEnv); +} + +void TraceLifecycle(const char* stage) +{ + if (!EnvFlag(kTraceLifecycleEnv)) { + return; + } + std::cout << "tilexr_ccu_direct_smoke lifecycle " << stage << std::endl; +} + +int ParseInt(const char* value, int fallback) +{ + if (value == nullptr || value[0] == '\0') { + return fallback; + } + char* end = nullptr; + const long parsed = std::strtol(value, &end, 0); + if (end == value || *end != '\0') { + return fallback; + } + return static_cast(parsed); +} + +int EnvInt(const char* name, int fallback) +{ + return ParseInt(std::getenv(name), fallback); +} + +uint64_t ParseU64(const char* value, uint64_t fallback) +{ + if (value == nullptr || value[0] == '\0') { + return fallback; + } + char* end = nullptr; + const unsigned long long parsed = std::strtoull(value, &end, 0); + if (end == value || *end != '\0') { + return fallback; + } + return static_cast(parsed); +} + +uint64_t EnvU64(const char* name, uint64_t fallback) +{ + return ParseU64(std::getenv(name), fallback); +} + +std::string RankEnvName(const char* prefix, int rank, const char* suffix) +{ + return std::string(prefix) + std::to_string(rank) + suffix; +} + +int RankEnvInt(const char* prefix, int rank, const char* suffix, const char* commonName, int fallback) +{ + const std::string rankName = RankEnvName(prefix, rank, suffix); + const char* rankValue = std::getenv(rankName.c_str()); + if (rankValue != nullptr && rankValue[0] != '\0') { + return ParseInt(rankValue, fallback); + } + return EnvInt(commonName, fallback); +} + +bool SyncCkeBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "sync_cke"; +} + +bool SyncCkeSetWaitBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "sync_cke_set_wait"; +} + +bool SyncCkePostOnlyBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "sync_cke_post_only"; +} + +bool LocalCkeBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "local_cke"; +} + +bool LocalCkePostOnlyBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "local_cke_post_only"; +} + +bool SyncXnPostOnlyBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "sync_xn_post_only"; +} + +bool SyncXnLoadPostOnlyBarrierMode() +{ + const char* value = std::getenv(kBarrierModeEnv); + return value != nullptr && std::string(value) == "sync_xn_load_post_only"; +} + +TileXR::TileXRCcuRepositoryInstallWindow RepositoryInstallWindowFromEnv() +{ + const char* value = std::getenv(kRepositoryInstallWindowEnv); + if (value == nullptr || value[0] == '\0') { + return TileXR::TileXRCcuRepositoryInstallWindow::Mission; + } + const std::string text(value); + if (text == "full_repository" || text == "full" || text == "1") { + return TileXR::TileXRCcuRepositoryInstallWindow::FullRepository; + } + return TileXR::TileXRCcuRepositoryInstallWindow::Mission; +} + +TileXR::TileXRCcuRepositoryInstallDataLenMode RepositoryInstallDataLenModeFromEnv() +{ + const char* value = std::getenv(kRepositoryInstallDataLenModeEnv); + if (value == nullptr || value[0] == '\0') { + return TileXR::TileXRCcuRepositoryInstallDataLenMode::InstructionBytes; + } + const std::string text(value); + if (text == "descriptor_bytes" || text == "descriptor" || text == "1") { + return TileXR::TileXRCcuRepositoryInstallDataLenMode::DescriptorBytes; + } + return TileXR::TileXRCcuRepositoryInstallDataLenMode::InstructionBytes; +} + +TileXR::TileXRCcuRepositoryMemoryAllocMode RepositoryMemoryAllocModeFromEnv() +{ + const char* value = std::getenv(kRepositoryMemoryAllocModeEnv); + if (value == nullptr || value[0] == '\0') { + return TileXR::TileXRCcuRepositoryMemoryAllocMode::Acl; + } + const std::string text(value); + if (text == "acl_module3" || text == "acl_hccl_module" || text == "module3" || text == "1") { + return TileXR::TileXRCcuRepositoryMemoryAllocMode::AclModule3; + } + if (text == "rt_hbm" || text == "rt" || text == "runtime_hbm" || text == "2") { + return TileXR::TileXRCcuRepositoryMemoryAllocMode::RtHbm; + } + return TileXR::TileXRCcuRepositoryMemoryAllocMode::Acl; +} + +TileXR::TileXRCcuInstallOrder InstallOrderFromEnv() +{ + const char* value = std::getenv(kInstallOrderEnv); + if (value == nullptr || value[0] == '\0') { + return TileXR::TileXRCcuInstallOrder::InstallLowerLayerFirst; + } + const std::string text(value); + if (text == "lower_layer_first" || text == "install_lower_layer_first" || text == "1") { + return TileXR::TileXRCcuInstallOrder::InstallLowerLayerFirst; + } + if (text == "repository_first" || text == "repo_first" || text == "0") { + return TileXR::TileXRCcuInstallOrder::RepositoryFirst; + } + return TileXR::TileXRCcuInstallOrder::RepositoryFirst; +} + +uint32_t DefaultSyncInstructionCount(uint32_t syncResourceCount) +{ + if (SyncCkeBarrierMode() || SyncCkeSetWaitBarrierMode()) { + return syncResourceCount * 2U + 1U; + } + if (SyncCkePostOnlyBarrierMode()) { + return syncResourceCount + 1U; + } + if (LocalCkePostOnlyBarrierMode()) { + return syncResourceCount; + } + if (SyncXnPostOnlyBarrierMode()) { + return kHcommStyleTask1PreludeInstructionCount + syncResourceCount; + } + if (SyncXnLoadPostOnlyBarrierMode()) { + return kHcommStyleTask1PreludeInstructionCount + syncResourceCount * 2U; + } + return kHcommStyleTask1PreludeInstructionCount + syncResourceCount * 2U; +} + +const char* FirstEnv(const char* a, const char* b, const char* c, const char* d) +{ + const char* value = std::getenv(a); + if (value != nullptr && value[0] != '\0') { + return value; + } + value = std::getenv(b); + if (value != nullptr && value[0] != '\0') { + return value; + } + value = std::getenv(c); + if (value != nullptr && value[0] != '\0') { + return value; + } + value = std::getenv(d); + return value != nullptr && value[0] != '\0' ? value : nullptr; +} + +int RankFromEnv() +{ + const char* rank = std::getenv("TILEXR_CCU_PROBE_RANK"); + if (rank != nullptr && rank[0] != '\0') { + return ParseInt(rank, 0); + } + return ParseInt(FirstEnv("PMI_RANK", "OMPI_COMM_WORLD_RANK", "MV2_COMM_WORLD_RANK", "RANK"), 0); +} + +int RankSizeFromEnv() +{ + const char* rankSize = std::getenv("TILEXR_CCU_PROBE_RANK_SIZE"); + if (rankSize != nullptr && rankSize[0] != '\0') { + return ParseInt(rankSize, 1); + } + return ParseInt(FirstEnv("PMI_SIZE", "OMPI_COMM_WORLD_SIZE", "MV2_COMM_WORLD_SIZE", "RANK_SIZE"), 1); +} + +std::vector BuildP2pCcuCopyPattern(int rank, size_t bytes) +{ + std::vector pattern(bytes); + for (size_t i = 0; i < bytes; ++i) { + pattern[i] = static_cast((static_cast(rank + 1) * 17U + i * 13U) & 0xffU); + } + return pattern; +} + +int InitP2pCcuCopyState(int rank, int peer, P2pCcuCopyState* state) +{ + if (state == nullptr) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + state->bytes = static_cast(EnvInt(kP2pCcuCopyBytesEnv, 4096)); + if (state->bytes == 0) { + state->initRet = TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + return state->initRet; + } + state->expected = BuildP2pCcuCopyPattern(peer, state->bytes); + state->observed.assign(state->bytes, 0); + const std::vector source = BuildP2pCcuCopyPattern(rank, state->bytes); + std::vector destination(state->bytes, 0xa5U); + + int ret = state->source.Allocate(state->bytes); + if (ret != ACL_SUCCESS) { + state->initRet = ret; + return ret; + } + ret = state->destination.Allocate(state->bytes); + if (ret != ACL_SUCCESS) { + state->initRet = ret; + return ret; + } + ret = aclrtMemcpy( + state->source.ptr, + state->bytes, + source.data(), + state->bytes, + ACL_MEMCPY_HOST_TO_DEVICE); + if (ret != ACL_SUCCESS) { + state->initRet = ret; + return ret; + } + ret = aclrtMemcpy( + state->destination.ptr, + state->bytes, + destination.data(), + state->bytes, + ACL_MEMCPY_HOST_TO_DEVICE); + state->initRet = ret; + return ret; +} + +int CheckP2pCcuCopyState(P2pCcuCopyState* state) +{ + if (state == nullptr || state->destination.ptr == nullptr || state->bytes == 0) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + state->readRet = aclrtMemcpy( + state->observed.data(), + state->observed.size(), + state->destination.ptr, + state->bytes, + ACL_MEMCPY_DEVICE_TO_HOST); + if (state->readRet != ACL_SUCCESS) { + return state->readRet; + } + state->mismatchCount = 0; + for (size_t i = 0; i < state->bytes; ++i) { + if (state->observed[i] != state->expected[i]) { + ++state->mismatchCount; + } + } + state->passed = state->mismatchCount == 0; + return state->passed ? ACL_SUCCESS : TileXR::TILEXR_ERROR_INTERNAL; +} + +void PrintP2pCcuCopy( + int rank, + int peer, + const P2pCcuCopyState& state, + int prepareRet, + int submitRet, + int syncRet) +{ + const uint32_t firstObserved = state.observed.empty() ? 0U : state.observed.front(); + const uint32_t firstExpected = state.expected.empty() ? 0U : state.expected.front(); + std::cout << "tilexr_ccu_direct_smoke p2pCcuCopy" + << " rank=" << rank + << " peer=" << peer + << " bytes=" << state.bytes + << " initRet=" << state.initRet + << " prepareRet=" << prepareRet + << " submitRet=" << submitRet + << " syncRet=" << syncRet + << " readRet=" << state.readRet + << " mismatches=" << state.mismatchCount + << " firstObserved=0x" << std::hex << firstObserved + << " firstExpected=0x" << firstExpected + << std::dec + << " passed=" << (state.passed ? 1 : 0) + << std::endl; +} + +int RunP2pCcuCopy( + int rank, + int peer, + P2pCcuCopyState* state, + int prepareRet, + int submitRet, + int syncRet) +{ + if (state == nullptr) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + if (syncRet == ACL_SUCCESS && submitRet == TileXR::TILEXR_SUCCESS) { + (void)CheckP2pCcuCopyState(state); + } + PrintP2pCcuCopy(rank, peer, *state, prepareRet, submitRet, syncRet); + return state->passed ? TileXR::TILEXR_SUCCESS : TileXR::TILEXR_ERROR_INTERNAL; +} + +int DeviceFromList(const char* devices, int rank, int fallback) +{ + if (devices == nullptr || devices[0] == '\0') { + return fallback; + } + std::string list(devices); + size_t start = 0; + int index = 0; + while (start <= list.size()) { + const size_t comma = list.find(',', start); + const size_t end = comma == std::string::npos ? list.size() : comma; + if (index == rank && end > start) { + return ParseInt(list.substr(start, end - start).c_str(), fallback); + } + if (comma == std::string::npos) { + break; + } + start = comma + 1; + ++index; + } + return fallback; +} + +int DeviceFromEnv(int rank) +{ + const char* explicitDevice = std::getenv("TILEXR_CCU_PROBE_DEVICE"); + if (explicitDevice != nullptr && explicitDevice[0] != '\0') { + return ParseInt(explicitDevice, 0); + } + const int firstDevice = EnvInt("TILEXR_TEST_FIRST_NPU", 0); + return DeviceFromList(std::getenv("TILEXR_TEST_DEVICES"), rank, firstDevice + rank); +} + +int InitCommForDirectCcuSmoke(int commDomain, int rankSize, int rank, int device, DirectCcuSmokeContext* context) +{ + if (context == nullptr) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + + context->exchange.reset(new (std::nothrow) TileXR::TileXRSockExchange(rank, rankSize, commDomain)); + if (context->exchange == nullptr) { + return TileXR::TILEXR_ERROR_INTERNAL; + } + + TileXR::TileXRCcuBackendOptions options {}; + options.rank = rank; + options.rankSize = rankSize; + options.devId = device; + options.uid = "tilexr-direct-smoke-probe"; + options.exchange = context->exchange.get(); + const int ret = context->session.Init(options); + if (ret == TileXR::TILEXR_SUCCESS) { + std::cout << "tilexr_ccu_direct_smoke internalDirectCcuInit" + << " rank=" << rank + << " rankSize=" << rankSize + << " device=" << device + << " directOnly=" << (EnvFlag(kDirectCcuOnlyInitEnv) ? 1 : 0) + << std::endl; + } + return ret; +} + +TileXRDirectCcuPrepareOptions MakePrepareOptions(int rank, int rankSize, int device) +{ + TileXRDirectCcuPrepareOptions options {}; + options.syncResourceCount = static_cast(EnvInt("TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT", 1)); + options.sqeArgCount = + static_cast(EnvInt("TILEXR_CCU_PROBE_SQE_ARG_COUNT", TILEXR_DIRECT_CCU_SQE_ARGS_LEN)); + const uint32_t defaultSyncInstructionCount = DefaultSyncInstructionCount(options.syncResourceCount); + options.syncInstructionCount = + static_cast(EnvInt("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT", defaultSyncInstructionCount)); + options.bindingsPerSyncResource = static_cast(EnvInt("TILEXR_CCU_PROBE_BINDINGS_PER_RESOURCE", 1)); + options.missionStartId = static_cast(EnvInt("TILEXR_CCU_PROBE_MISSION_START", 1)); + options.instructionStartId = static_cast(EnvInt("TILEXR_CCU_PROBE_INSTRUCTION_START", 1)); + options.missionInstructionStartId = + static_cast(EnvInt("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START", 0)); + options.xnStartId = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_XN_START", "TILEXR_CCU_PROBE_XN_START", 1)); + options.gsaStartId = static_cast(EnvInt("TILEXR_CCU_PROBE_GSA_START", 0)); + options.remoteXnStartId = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_REMOTE_XN_START", "TILEXR_CCU_PROBE_REMOTE_XN_START", 0)); + options.remoteXnCount = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_REMOTE_XN_COUNT", "TILEXR_CCU_PROBE_REMOTE_XN_COUNT", 0)); + options.ckeStartId = static_cast(EnvInt("TILEXR_CCU_PROBE_CKE_START", 1)); + options.channelStartId = static_cast(EnvInt("TILEXR_CCU_PROBE_CHANNEL_START", 1)); + options.localWaitCkeStartId = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_LOCAL_WAIT_CKE_START", kLocalWaitCkeStartEnv, 0)); + options.localWaitCkeCount = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_LOCAL_WAIT_CKE_COUNT", kLocalWaitCkeCountEnv, 0)); + options.remoteNotifyCkeStartId = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_REMOTE_NOTIFY_CKE_START", kRemoteNotifyCkeStartEnv, 0)); + options.remoteNotifyCkeCount = static_cast( + RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_REMOTE_NOTIFY_CKE_COUNT", kRemoteNotifyCkeCountEnv, 0)); + options.repositoryInstallOptions.window = RepositoryInstallWindowFromEnv(); + options.repositoryInstallOptions.dataLenMode = RepositoryInstallDataLenModeFromEnv(); + options.repositoryMemoryAllocMode = RepositoryMemoryAllocModeFromEnv(); + options.installOrder = InstallOrderFromEnv(); + options.deviceId = static_cast(device); + options.rank = static_cast(rank); + options.provider = rankSize > 0 ? "tilexr-direct-smoke-probe" : ""; + return options; +} + +void PrintInstallReport( + const char* prefix, + int ret, + const TileXRDirectCcuPrepareReport& report) +{ + std::cout << prefix + << " ret=" << ret + << " pipelineBuilt=" << (report.pipelineBuilt ? 1 : 0) + << " installAttempted=" << (report.installAttempted ? 1 : 0) + << " installSucceeded=" << (report.installSucceeded ? 1 : 0) + << " submitReady=" << (report.submitReady ? 1 : 0) + << " requiredInstallSurfaceCount=" << report.requiredInstallSurfaceCount + << " publicVerifiedInstallSurfaceCount=" << report.publicVerifiedInstallSurfaceCount + << " missingInstallSurfaceCount=" << report.missingInstallSurfaceCount + << " taskCount=" << report.taskCount + << " submitTaskCount=" << report.submitTaskCount + << " message=\"" << report.message << "\"" + << std::endl; +} + +void PrintSubmitReport( + const char* prefix, + int ret, + const TileXRDirectCcuSubmitReport& report) +{ + std::cout << prefix + << " ret=" << ret + << " submitted=" << (report.submitted ? 1 : 0) + << " taskCount=" << report.taskCount + << " submittedTaskCount=" << report.submittedTaskCount + << " message=\"" << report.message << "\"" + << std::endl; +} + +int TileXRDirectCcuGetPreparedTask( + TileXRDirectCcuPreparedTasksPtr prepared, + uint32_t taskIndex, + TileXRDirectCcuTaskInfo* task) +{ + if (prepared == nullptr || task == nullptr || taskIndex >= prepared->submitTasks.size()) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + *task = prepared->submitTasks[taskIndex]; + return TileXR::TILEXR_SUCCESS; +} + +int TileXRDirectCcuSubmitPrepared( + TileXRDirectCcuPreparedTasksPtr prepared, + void* stream, + TileXRDirectCcuSubmitReport* report) +{ + if (prepared == nullptr) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + return TileXR::TileXRCcuSubmitPreparedTasks(prepared->submitTasks, stream, nullptr, nullptr, report); +} + +int TileXRDirectCcuSubmitPreparedTask( + TileXRDirectCcuPreparedTasksPtr prepared, + uint32_t taskIndex, + void* stream, + TileXRDirectCcuSubmitReport* report) +{ + if (prepared == nullptr || taskIndex >= prepared->submitTasks.size()) { + if (report != nullptr) { + *report = TileXRDirectCcuSubmitReport {}; + report->taskCount = prepared == nullptr ? 0U : static_cast(prepared->submitTasks.size()); + report->message = "selected direct CCU submit task is missing"; + } + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + std::vector selected {prepared->submitTasks[taskIndex]}; + return TileXR::TileXRCcuSubmitPreparedTasks(selected, stream, nullptr, nullptr, report); +} + +int TileXRDirectCcuDestroyPrepared(TileXRDirectCcuPreparedTasksPtr prepared) +{ + if (prepared == nullptr) { + return TileXR::TILEXR_SUCCESS; + } + return TileXR::TileXRCcuReleaseDirectInstallAttemptResources(*prepared); +} + +int TileXRCommReadDirectCcuInstructions( + DirectCcuSmokeContext* context, + uint8_t dieId, + uint16_t instructionStartId, + uint32_t instructionCount, + TileXRDirectCcuInstructionWords* instructions, + TileXRDirectCcuInstructionReadbackReport* report) +{ + if (context == nullptr || instructions == nullptr) { + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + return context->executor.ReadDirectCcuInstructionsForDebug( + context->session, + dieId, + instructionStartId, + instructions, + instructionCount, + sizeof(TileXRDirectCcuInstructionWords), + report); +} + +int SubmitPreparedWithSelector( + TileXRDirectCcuPreparedTasksPtr prepared, + uint32_t taskCount, + void* stream, + TileXRDirectCcuSubmitReport* report) +{ + const char* value = std::getenv(kSubmitTaskSelectorEnv); + const std::string selector = value == nullptr ? "all" : std::string(value); + if (selector.empty() || selector == "all") { + return TileXRDirectCcuSubmitPrepared(prepared, stream, report); + } + const bool selectFirst = selector == "first"; + const bool selectSecond = selector == "second"; + if (!selectFirst && !selectSecond) { + if (report != nullptr) { + *report = TileXRDirectCcuSubmitReport {}; + report->message = "invalid TILEXR_CCU_DIRECT_SMOKE_SUBMIT_TASK_SELECTOR"; + } + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + + const uint32_t selectedIndex = selectFirst ? 0U : 1U; + std::cout << "tilexr_ccu_direct_smoke submitTaskSelector=" + << selector + << " selectedIndex=" << selectedIndex + << " preparedTaskCount=" << taskCount + << std::endl; + if (selectedIndex >= taskCount) { + if (report != nullptr) { + *report = TileXRDirectCcuSubmitReport {}; + report->taskCount = taskCount; + report->message = "selected direct CCU submit task is missing"; + } + return TileXR::TILEXR_ERROR_PARA_CHECK_FAIL; + } + + return TileXRDirectCcuSubmitPreparedTask(prepared, selectedIndex, stream, report); +} + +void PrintSubmitTiming( + int rank, + int delayMs, + int submitRet, + int syncRet, + long long submitMs, + long long syncMs) +{ + std::cout << "tilexr_ccu_direct_smoke submitTiming" + << " rank=" << rank + << " preSubmitDelayMs=" << delayMs + << " submitRet=" << submitRet + << " syncRet=" << syncRet + << " submitMs=" << submitMs + << " syncMs=" << syncMs + << std::endl; +} + +void PrintConfig( + const TileXRDirectCcuPrepareOptions& options, + int rankSize) +{ + std::cout << "tilexr_ccu_direct_smoke config" + << " rank=" << options.rank + << " rankSize=" << rankSize + << " device=" << options.deviceId + << " syncResourceCount=" << options.syncResourceCount + << " sqeArgCount=" << options.sqeArgCount + << " syncInstructionCount=" << options.syncInstructionCount + << " bindingsPerSyncResource=" << options.bindingsPerSyncResource + << " missionStartId=" << options.missionStartId + << " instructionStartId=" << options.instructionStartId + << " missionInstructionStartId=" << options.missionInstructionStartId + << " xnStartId=" << options.xnStartId + << " gsaStartId=" << options.gsaStartId + << " remoteXnStartId=" << options.remoteXnStartId + << " remoteXnCount=" << options.remoteXnCount + << " ckeStartId=" << options.ckeStartId + << " channelStartId=" << options.channelStartId + << " localWaitCkeStartId=" << options.localWaitCkeStartId + << " localWaitCkeCount=" << options.localWaitCkeCount + << " remoteNotifyCkeStartId=" << options.remoteNotifyCkeStartId + << " remoteNotifyCkeCount=" << options.remoteNotifyCkeCount + << " repositoryInstallWindow=" << static_cast(options.repositoryInstallOptions.window) + << " repositoryInstallDataLenMode=" << static_cast(options.repositoryInstallOptions.dataLenMode) + << " repositoryMemoryAllocMode=" << static_cast(options.repositoryMemoryAllocMode) + << " installOrder=" << static_cast(options.installOrder) + << " barrierMode=\"" << (std::getenv(kBarrierModeEnv) == nullptr ? "" : std::getenv(kBarrierModeEnv)) + << "\"" + << " resourceWindowTokenId=\"" + << (std::getenv(kResourceWindowTokenIdEnv) == nullptr ? "" : std::getenv(kResourceWindowTokenIdEnv)) + << "\"" + << " resourceWindowRawTokenId=\"" + << (std::getenv(kResourceWindowRawTokenIdEnv) == nullptr ? "" : std::getenv(kResourceWindowRawTokenIdEnv)) + << "\"" + << " resourceWindowTokenValue=\"" + << (std::getenv(kResourceWindowTokenValueEnv) == nullptr ? "" : std::getenv(kResourceWindowTokenValueEnv)) + << "\"" + << " provider=\"" << options.provider << "\"" + << std::endl; +} + +void PrintPreparedTasks(TileXRDirectCcuPreparedTasksPtr prepared, uint32_t taskCount) +{ + std::cout << "tilexr_ccu_direct_smoke preparedTasks" + << " count=" << taskCount; + const uint32_t previewCount = taskCount < 2U ? taskCount : 2U; + for (size_t i = 0; i < previewCount; ++i) { + TileXRDirectCcuTaskInfo task; + const int ret = TileXRDirectCcuGetPreparedTask(prepared, static_cast(i), &task); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cout << " task" << i << ".ret=" << ret; + continue; + } + std::cout << " task" << i + << ".dieId=" << static_cast(task.dieId) + << " task" << i << ".missionId=" << static_cast(task.missionId) + << " task" << i << ".timeout=" << task.timeout + << " task" << i << ".instStartId=" << task.instStartId + << " task" << i << ".instCnt=" << task.instCnt + << " task" << i << ".key=0x" << std::hex << task.key << std::dec + << " task" << i << ".argSize=" << task.argSize; + for (uint32_t arg = 0; arg < TILEXR_DIRECT_CCU_SQE_ARGS_LEN; ++arg) { + std::cout << " task" << i + << ".arg" << arg << "=0x" + << std::hex << task.args[arg] << std::dec; + } + } + std::cout << std::endl; +} + +void PrintInstructionReadback(DirectCcuSmokeContext* context, TileXRDirectCcuPreparedTasksPtr prepared, uint32_t taskCount) +{ + if (!EnvFlag(kReadbackInstructionsEnv)) { + return; + } + if (context == nullptr) { + std::cout << "tilexr_ccu_direct_smoke instructionReadback ret=" + << TileXR::TILEXR_ERROR_PARA_CHECK_FAIL + << " message=\"missing direct CCU smoke context\"" + << std::endl; + return; + } + for (uint32_t taskIndex = 0; taskIndex < taskCount; ++taskIndex) { + TileXRDirectCcuTaskInfo task; + const int taskRet = TileXRDirectCcuGetPreparedTask(prepared, taskIndex, &task); + if (taskRet != TileXR::TILEXR_SUCCESS) { + std::cout << "tilexr_ccu_direct_smoke instructionReadback" + << " task=" << taskIndex + << " ret=" << taskRet + << " message=\"failed to read prepared task\"" + << std::endl; + continue; + } + + constexpr uint32_t kMaxReadbackInstructionCount = 8U; + const uint32_t readCount = task.instCnt < kMaxReadbackInstructionCount ? + task.instCnt : kMaxReadbackInstructionCount; + std::vector readback(readCount); + TileXRDirectCcuInstructionReadbackReport report; + const int readRet = TileXRCommReadDirectCcuInstructions( + context, + static_cast(task.dieId), + static_cast(task.instStartId), + readCount, + readback.data(), + &report); + std::cout << "tilexr_ccu_direct_smoke instructionReadback" + << " task=" << taskIndex + << " ret=" << readRet + << " dieId=" << static_cast(task.dieId) + << " instStartId=" << task.instStartId + << " requestedCount=" << task.instCnt + << " readCount=" << readCount + << " opcode=" << report.opcode + << " driverRet=" << report.driverRet + << " opRet=" << report.opRet + << " message=\"" << report.message << "\""; + if (readRet == TileXR::TILEXR_SUCCESS) { + for (uint32_t i = 0; i < readCount; ++i) { + std::cout << " instr" << i << "="; + for (uint32_t word = 0; word < 4U; ++word) { + if (word != 0) { + std::cout << ","; + } + std::cout << "0x" << std::hex << std::nouppercase << readback[i].words[word] << std::dec; + } + } + } + std::cout << std::endl; + } +} + +bool CollectiveSubmitReadyGateConfigured() +{ + const char* readyDir = std::getenv(kReadyDirEnv); + return readyDir != nullptr && readyDir[0] != '\0'; +} + +std::string SubmitReadinessPath(int rank) +{ + const char* readyDir = std::getenv(kReadyDirEnv); + if (readyDir == nullptr || readyDir[0] == '\0') { + return {}; + } + return std::string(readyDir) + "/rank" + std::to_string(rank) + ".ready"; +} + +bool WriteSubmitReadiness(int rank, bool ready) +{ + const std::string path = SubmitReadinessPath(rank); + if (path.empty()) { + return true; + } + std::ofstream out(path.c_str(), std::ios::out | std::ios::trunc); + if (!out) { + return false; + } + out << (ready ? 1 : 0) << "\n"; + return static_cast(out); +} + +bool ReadSubmitReadiness(int rank, bool* ready) +{ + if (ready == nullptr) { + return false; + } + const std::string path = SubmitReadinessPath(rank); + if (path.empty()) { + return false; + } + std::ifstream in(path.c_str()); + if (!in) { + return false; + } + int value = 0; + in >> value; + if (!in) { + return false; + } + *ready = value != 0; + return true; +} + +bool WaitForCollectiveSubmitReadiness(int rank, int rankSize, bool localReady) +{ + if (!CollectiveSubmitReadyGateConfigured()) { + return localReady; + } + const bool wrote = WriteSubmitReadiness(rank, localReady); + const int timeoutMs = EnvInt(kReadyTimeoutMsEnv, 5000); + const auto start = std::chrono::steady_clock::now(); + for (;;) { + bool allSeen = wrote; + bool allReady = wrote && localReady; + for (int peer = 0; peer < rankSize; ++peer) { + bool peerReady = false; + if (!ReadSubmitReadiness(peer, &peerReady)) { + allSeen = false; + allReady = false; + break; + } + allReady = allReady && peerReady; + } + if (allSeen) { + std::cout << "tilexr_ccu_direct_smoke collectiveSubmitReady" + << " rank=" << rank + << " localReady=" << (localReady ? 1 : 0) + << " allRanksReady=" << (allReady ? 1 : 0) + << std::endl; + return allReady; + } + const auto elapsedMs = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start).count(); + if (elapsedMs >= timeoutMs) { + std::cout << "tilexr_ccu_direct_smoke collectiveSubmitReady" + << " rank=" << rank + << " localReady=" << (localReady ? 1 : 0) + << " allRanksReady=0" + << " timeoutMs=" << timeoutMs + << std::endl; + return false; + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } +} + +bool CollectiveSubmitDoneGateConfigured() +{ + const char* doneDir = std::getenv(kDoneDirEnv); + return doneDir != nullptr && doneDir[0] != '\0'; +} + +std::string SubmitDonePath(int rank) +{ + const char* doneDir = std::getenv(kDoneDirEnv); + if (doneDir == nullptr || doneDir[0] == '\0') { + return {}; + } + return std::string(doneDir) + "/rank" + std::to_string(rank) + ".done"; +} + +bool WriteSubmitDone(int rank, int result) +{ + const std::string path = SubmitDonePath(rank); + if (path.empty()) { + return true; + } + std::ofstream out(path.c_str(), std::ios::out | std::ios::trunc); + if (!out) { + return false; + } + out << result << "\n"; + return static_cast(out); +} + +bool ReadSubmitDone(int rank, int* result) +{ + if (result == nullptr) { + return false; + } + const std::string path = SubmitDonePath(rank); + if (path.empty()) { + return false; + } + std::ifstream in(path.c_str()); + if (!in) { + return false; + } + in >> *result; + return static_cast(in); +} + +bool WaitForCollectiveSubmitDone(int rank, int rankSize, int localResult) +{ + if (!CollectiveSubmitDoneGateConfigured()) { + return true; + } + const bool wrote = WriteSubmitDone(rank, localResult); + const int timeoutMs = EnvInt(kReadyTimeoutMsEnv, 5000); + const auto start = std::chrono::steady_clock::now(); + for (;;) { + bool allSeen = wrote; + bool allSucceeded = wrote && localResult == 0; + for (int peer = 0; peer < rankSize; ++peer) { + int peerResult = 0; + if (!ReadSubmitDone(peer, &peerResult)) { + allSeen = false; + allSucceeded = false; + break; + } + allSucceeded = allSucceeded && peerResult == 0; + } + if (allSeen) { + std::cout << "tilexr_ccu_direct_smoke collectiveSubmitDone" + << " rank=" << rank + << " localResult=" << localResult + << " allRanksDone=1" + << " allRanksSucceeded=" << (allSucceeded ? 1 : 0) + << std::endl; + return true; + } + const auto elapsedMs = std::chrono::duration_cast( + std::chrono::steady_clock::now() - start).count(); + if (elapsedMs >= timeoutMs) { + std::cout << "tilexr_ccu_direct_smoke collectiveSubmitDone" + << " rank=" << rank + << " localResult=" << localResult + << " allRanksDone=0" + << " timeoutMs=" << timeoutMs + << std::endl; + return false; + } + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } +} + +int RunPreparedSmokeForRank(DirectCcuSmokeContext* context, int rank, int rankSize, int device) +{ + TileXRDirectCcuPrepareOptions options = MakePrepareOptions(rank, rankSize, device); + const int peer = rankSize == 2 ? 1 - rank : (rank + 1) % rankSize; + const bool p2pCcuCopyEnabled = EnvFlag(kP2pCcuCopyEnv); + P2pCcuCopyState p2pCcuCopy; + if (p2pCcuCopyEnabled) { + options.syncResourceCount = 1; + options.sqeArgCount = 0; + options.syncInstructionCount = 7; + p2pCcuCopy.initRet = InitP2pCcuCopyState(rank, peer, &p2pCcuCopy); + } + PrintConfig(options, rankSize); + + TileXR::TileXRCcuDirectInstallAttempt attempt; + TileXRDirectCcuPreparedTasksPtr prepared = &attempt; + TileXRDirectCcuPrepareReport installReport; + int ret = p2pCcuCopyEnabled && p2pCcuCopy.initRet != ACL_SUCCESS ? + p2pCcuCopy.initRet : + p2pCcuCopyEnabled ? + context->planner.PrepareDirectCcuMemoryCopyInstallAttempt( + context->session, + options, + reinterpret_cast(p2pCcuCopy.source.ptr), + reinterpret_cast(p2pCcuCopy.destination.ptr), + p2pCcuCopy.bytes, + static_cast(peer), + TileXR::TileXRCcuMemoryCopyDirection::RemoteToLocal, + prepared, + &installReport) : + context->planner.PrepareDirectCcuInstallAttempt(context->session, options, prepared, &installReport); + PrintInstallReport("tilexr_ccu_direct_smoke prepare", ret, installReport); + PrintPreparedTasks(prepared, installReport.submitTaskCount); + PrintInstructionReadback(context, prepared, installReport.submitTaskCount); + + int finalRet = 0; + const bool submitRequested = EnvFlag(kSubmitEnv); + const bool collectiveSubmitReady = submitRequested ? + WaitForCollectiveSubmitReadiness( + rank, + rankSize, + ret == TileXR::TILEXR_SUCCESS && installReport.submitReady) : + false; + if (ret != TileXR::TILEXR_SUCCESS) { + finalRet = 6; + } else if (submitRequested && !collectiveSubmitReady && CollectiveSubmitReadyGateConfigured()) { + std::cout << "tilexr_ccu_direct_smoke submit skipped reason=\"collective submitReady gate did not pass\"" + << " localSubmitReady=" << (installReport.submitReady ? 1 : 0) + << std::endl; + } else if (submitRequested && !installReport.submitReady) { + std::cout << "tilexr_ccu_direct_smoke submit skipped reason=\"prepare did not reach submitReady\"" + << std::endl; + } else if (submitRequested) { + aclrtStream stream = nullptr; + int streamRet = aclrtCreateStream(&stream); + if (streamRet != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke aclrtCreateStream ret=" << streamRet << std::endl; + finalRet = 7; + } else { + const int delayRank = EnvInt(kDelayRankEnv, -1); + const int preSubmitDelayMs = EnvInt(kPreSubmitDelayMsEnv, 0); + const int effectiveDelayMs = rank == delayRank && preSubmitDelayMs > 0 ? preSubmitDelayMs : 0; + if (effectiveDelayMs > 0) { + std::cout << "tilexr_ccu_direct_smoke preSubmitDelay" + << " rank=" << rank + << " delayMs=" << effectiveDelayMs + << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(effectiveDelayMs)); + } + + TileXRDirectCcuSubmitReport submitReport; + const auto submitBegin = std::chrono::steady_clock::now(); + const char* submitTaskSelector = std::getenv(kSubmitTaskSelectorEnv); + const bool submitAllTasks = submitTaskSelector == nullptr || submitTaskSelector[0] == '\0' || + std::string(submitTaskSelector) == "all"; + const int submitRet = submitAllTasks ? + TileXRDirectCcuSubmitPrepared(prepared, stream, &submitReport) : + SubmitPreparedWithSelector(prepared, installReport.submitTaskCount, stream, &submitReport); + const auto submitEnd = std::chrono::steady_clock::now(); + PrintSubmitReport("tilexr_ccu_direct_smoke submit", submitRet, submitReport); + const auto syncBegin = std::chrono::steady_clock::now(); + TraceLifecycle("before aclrtSynchronizeStream"); + const int syncRet = aclrtSynchronizeStream(stream); + TraceLifecycle("after aclrtSynchronizeStream"); + const auto syncEnd = std::chrono::steady_clock::now(); + PrintSubmitTiming( + rank, + effectiveDelayMs, + submitRet, + syncRet, + std::chrono::duration_cast(submitEnd - submitBegin).count(), + std::chrono::duration_cast(syncEnd - syncBegin).count()); + if (syncRet != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke aclrtSynchronizeStream ret=" << syncRet << std::endl; + finalRet = 8; + } else if (submitRet != TileXR::TILEXR_SUCCESS) { + finalRet = 9; + } + if (p2pCcuCopyEnabled) { + const int p2pCcuCopyRet = RunP2pCcuCopy(rank, peer, &p2pCcuCopy, ret, submitRet, syncRet); + if (p2pCcuCopyRet != TileXR::TILEXR_SUCCESS && finalRet == 0) { + finalRet = 14; + } + } + if (!WaitForCollectiveSubmitDone(rank, rankSize, finalRet) && finalRet == 0) { + finalRet = 13; + } + TraceLifecycle("before aclrtDestroyStream"); + aclrtDestroyStream(stream); + TraceLifecycle("after aclrtDestroyStream"); + } + } + + if (prepared != nullptr && ShouldFastExitAfterRun()) { + std::cout << "tilexr_ccu_direct_smoke fastExitAfterRun=1" + << " ret=" << finalRet + << " reason=\"skipping prepared-task cleanup to isolate cleanup hangs\"" + << std::endl; + std::fflush(stdout); + std::fflush(stderr); + std::_Exit(finalRet); + } + if (prepared != nullptr) { + TraceLifecycle("before TileXRDirectCcuDestroyPrepared"); + const int preparedDestroyRet = TileXRDirectCcuDestroyPrepared(prepared); + TraceLifecycle("after TileXRDirectCcuDestroyPrepared"); + if (preparedDestroyRet != TileXR::TILEXR_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke prepared destroy ret=" << preparedDestroyRet << std::endl; + finalRet = finalRet == 0 ? 11 : finalRet; + } + } + return finalRet; +} + +int RunThreadModeSmoke(int rankSize) +{ + std::cout << "tilexr_ccu_direct_smoke threadMode begin" + << " rankSize=" << rankSize + << std::endl; + std::vector devices(static_cast(rankSize)); + for (int rank = 0; rank < rankSize; ++rank) { + devices[rank] = DeviceFromEnv(rank); + } + std::vector comms(static_cast(rankSize), nullptr); + int ret = TileXRCommInitAll(static_cast(rankSize), devices.data(), comms.data()); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke threadMode comm init ret=" << ret << std::endl; + return 5; + } + + std::vector rankResults(static_cast(rankSize), 0); + std::vector rankThreads; + rankThreads.reserve(static_cast(rankSize)); + for (int rank = 0; rank < rankSize; ++rank) { + rankThreads.emplace_back([&, rank]() { + const int setDeviceRet = aclrtSetDevice(devices[rank]); + if (setDeviceRet != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke threadMode aclrtSetDevice ret=" + << setDeviceRet + << " rank=" << rank + << " device=" << devices[rank] + << std::endl; + rankResults[rank] = 14; + return; + } + DirectCcuSmokeContext context; + const int initRet = InitCommForDirectCcuSmoke(0, rankSize, rank, devices[rank], &context); + if (initRet != TileXR::TILEXR_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke threadMode direct CCU init ret=" + << initRet + << " rank=" << rank + << " device=" << devices[rank] + << std::endl; + rankResults[rank] = 5; + return; + } + rankResults[rank] = RunPreparedSmokeForRank(&context, rank, rankSize, devices[rank]); + }); + } + for (auto& rankThread : rankThreads) { + rankThread.join(); + } + + int finalRet = 0; + for (int rank = 0; rank < rankSize; ++rank) { + std::cout << "tilexr_ccu_direct_smoke threadMode rank=" << rank + << " ret=" << rankResults[rank] + << std::endl; + if (rankResults[rank] != 0 && finalRet == 0) { + finalRet = rankResults[rank]; + } + } + for (auto comm : comms) { + if (comm == nullptr) { + continue; + } + const int destroyRet = TileXRCommDestroy(comm); + if (destroyRet != TileXR::TILEXR_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke threadMode destroy ret=" << destroyRet << std::endl; + finalRet = finalRet == 0 ? 10 : finalRet; + } + } + return finalRet; +} + +} // namespace + +int main() +{ + if (!EnvFlag(kEnableEnv)) { + std::cout << "tilexr_ccu_direct_smoke skipped set " + << kEnableEnv << "=1 to run private C++ integration probe" + << std::endl; + return 0; + } + + const int rank = RankFromEnv(); + const int rankSize = RankSizeFromEnv(); + const int device = DeviceFromEnv(rank); + const int commDomain = EnvInt("TILEXR_CCU_PROBE_COMM_DOMAIN", 0); + + if (rankSize <= 1) { + std::cout << "tilexr_ccu_direct_smoke skipped rankSize=" << rankSize + << " reason=\"direct CCU prepare requires a multi-rank communicator\"" + << std::endl; + return 0; + } + if (rank < 0 || rank >= rankSize) { + std::cerr << "tilexr_ccu_direct_smoke invalid rank=" << rank + << " rankSize=" << rankSize << std::endl; + return 2; + } + if (EnvFlag(kThreadModeEnv)) { + const int aclRet = aclInit(nullptr); + if (aclRet != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke aclInit ret=" << aclRet << std::endl; + return 3; + } + const int threadRet = RunThreadModeSmoke(rankSize); + aclFinalize(); + return threadRet; + } + + std::cout << "tilexr_ccu_direct_smoke begin" + << " rank=" << rank + << " rankSize=" << rankSize + << " device=" << device + << " commDomain=" << commDomain + << std::endl; + + int ret = aclInit(nullptr); + if (ret != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke aclInit ret=" << ret << std::endl; + return 3; + } + + ret = aclrtSetDevice(device); + if (ret != ACL_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke aclrtSetDevice ret=" << ret + << " device=" << device << std::endl; + aclFinalize(); + return 4; + } + + DirectCcuSmokeContext context; + ret = InitCommForDirectCcuSmoke(commDomain, rankSize, rank, device, &context); + if (ret != TileXR::TILEXR_SUCCESS) { + std::cerr << "tilexr_ccu_direct_smoke direct CCU context init ret=" << ret << std::endl; + aclrtResetDevice(device); + aclFinalize(); + return 5; + } + + int finalRet = RunPreparedSmokeForRank(&context, rank, rankSize, device); + if (ShouldFastExitAfterPrepareFailure(finalRet)) { + std::cout << "tilexr_ccu_direct_smoke fastExitOnPrepareFailure=1" + << " ret=" << finalRet + << " reason=\"" << FastExitReasonForReturnCode(finalRet) << "\"" + << std::endl; + std::fflush(stdout); + std::fflush(stderr); + std::_Exit(finalRet); + } + if (ShouldFastExitAfterRun()) { + std::cout << "tilexr_ccu_direct_smoke fastExitAfterRun=1" + << " ret=" << finalRet + << " reason=\"skipping communicator cleanup to isolate cleanup hangs\"" + << std::endl; + std::fflush(stdout); + std::fflush(stderr); + std::_Exit(finalRet); + } + TraceLifecycle("before DirectCcuSmokeContext shutdown"); + context.session.Shutdown(); + TraceLifecycle("after DirectCcuSmokeContext shutdown"); + TraceLifecycle("before aclrtResetDevice"); + aclrtResetDevice(device); + TraceLifecycle("after aclrtResetDevice"); + TraceLifecycle("before aclFinalize"); + aclFinalize(); + TraceLifecycle("after aclFinalize"); + return finalRet; +} diff --git a/tests/ccu/check_tile_comm_no_hcomm_deps.sh b/tests/ccu/check_tile_comm_no_hcomm_deps.sh new file mode 100644 index 00000000..a0e8ba9b --- /dev/null +++ b/tests/ccu/check_tile_comm_no_hcomm_deps.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +lib="${1:-install/lib/libtile-comm.so}" + +if [ ! -f "${lib}" ]; then + echo "ERROR: ${lib} not found" >&2 + exit 1 +fi + +if command -v readelf >/dev/null 2>&1; then + needed=$(readelf -d "${lib}" 2>/dev/null | grep -E 'NEEDED' || true) +else + needed="" +fi + +deps=$(ldd "${lib}" 2>/dev/null || true) +forbidden='libhcomm\.so|libhccl_v2\.so|libhccl_fwk\.so|libmc2_client\.so|HcclCcuKernel|HcclGetCcuTaskInfo|HcomGetCcuTaskInfo|HcclChannelAcquire|HcclGetChannelForCcu|HcclAllocAlgResourceCcu|HcommChannelNotify|HcommChannelFence|rtGetNotifyAddress|HrtCcuLaunch|HrtGetDevResAddress|HrtReleaseDevResAddress|HrtNotifyGetAddr|HrtRaCustomChannel|HrtCntNotify|CcuResBatchAllocator|CcuResRepository|CcuDeviceManager|CcuDevMgrImp|CcuRepContext|CcuKernelMgr|CtxMgrImp|CcuInstrInfo|CcuTaskParam|CcuTaskArg|GeneTaskParam|GetMissionKey|SetMissionId|SetMissionKey|SetInstrId|SetCcuInstrInfo|LoadInstruction|AllocIns|AllocCke|AllocXn|COMM_ENGINE_CCU|COMM_PROTOCOL_UBC_CTP|HCCL_SERVER_TYPE_CCU|RT_RES_TYPE_CCU_CKE|RT_RES_TYPE_CCU_XN' + +printf '%s\n' "${needed}" +printf '%s\n' "${deps}" + +if printf '%s\n%s\n' "${needed}" "${deps}" | grep -E "${forbidden}" >/dev/null; then + echo "ERROR: libtile-comm.so links an hcomm/HCCL CCU reference library" >&2 + exit 1 +fi + +if command -v nm >/dev/null 2>&1; then + symbol_hits=$(nm -D "${lib}" 2>/dev/null | c++filt | grep -E "${forbidden}" || true) +else + symbol_hits="" +fi +if [ -n "${symbol_hits}" ]; then + printf '%s\n' "${symbol_hits}" >&2 + echo "ERROR: libtile-comm.so exports or imports private hcomm/HCCL CCU symbols" >&2 + exit 1 +fi + +if command -v strings >/dev/null 2>&1; then + string_hits=$(strings -a "${lib}" 2>/dev/null | grep -E "${forbidden}" || true) +else + string_hits="" +fi +if [ -n "${string_hits}" ]; then + printf '%s\n' "${string_hits}" >&2 + echo "ERROR: libtile-comm.so contains private hcomm/HCCL CCU references" >&2 + exit 1 +fi + +echo "TileXR CCU dependency guard passed: no hcomm/HCCL private CCU dependency or symbol reference" diff --git a/tests/ccu/run_tilexr_ccu_direct_evening_smoke.sh b/tests/ccu/run_tilexr_ccu_direct_evening_smoke.sh new file mode 100644 index 00000000..142552df --- /dev/null +++ b/tests/ccu/run_tilexr_ccu_direct_evening_smoke.sh @@ -0,0 +1,538 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2026 TileXR Project +# +# One-shot direct CCU bring-up wrapper for the reserved 20:00+ hardware window. +# It still fails closed: submit/barrier/P2P stages run only after prepare logs +# show submitReady=1 for both ranks. + +set -euo pipefail + +for arg in "$@"; do + case "${arg}" in + --dry-run) + export TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN=1 + ;; + *) + echo "ERROR: unknown argument: ${arg}" >&2 + exit 2 + ;; + esac +done + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "${repo_root}" + +set_evening_defaults() +{ + export TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE=1 + export TILEXR_CCU_SMOKE_REQUIRE_NPU_SMI=1 + if [ "${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE:-}" = "" ]; then + export TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=0 + else + export TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE + fi + export TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT="${TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT:-1}" + export TILEXR_CCU_SMOKE_DEVICES="${TILEXR_CCU_SMOKE_DEVICES:-0,1}" + export TILEXR_CCU_DIRECT_TRACE="${TILEXR_CCU_DIRECT_TRACE:-1}" + export TILEXR_LOG_LEVEL="${TILEXR_LOG_LEVEL:-INFO}" + export TILEXR_CCU_SMOKE_TIMEOUT="${TILEXR_CCU_SMOKE_TIMEOUT:-120}" + export TILEXR_CCU_PROBE_MISSION_START="${TILEXR_CCU_PROBE_MISSION_START:-6}" + export TILEXR_CCU_PROBE_INSTRUCTION_START="${TILEXR_CCU_PROBE_INSTRUCTION_START:-475}" + export TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START="${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START:-489}" + export TILEXR_CCU_PROBE_SQE_ARG_COUNT="${TILEXR_CCU_PROBE_SQE_ARG_COUNT:-13}" + export TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT="${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT:-143}" + export TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-full_repository}" + export TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-instruction_bytes}" + export TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE:-acl}" + export TILEXR_CCU_DIRECT_INSTALL_ORDER="${TILEXR_CCU_DIRECT_INSTALL_ORDER:-lower_layer_first}" + export TILEXR_CCU_PROBE_RANK0_XN_START="${TILEXR_CCU_PROBE_RANK0_XN_START:-1961}" + export TILEXR_CCU_PROBE_RANK1_XN_START="${TILEXR_CCU_PROBE_RANK1_XN_START:-1961}" + export TILEXR_CCU_PROBE_GSA_START="${TILEXR_CCU_PROBE_GSA_START:-510}" + export TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START:-2361}" + export TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START:-2361}" + export TILEXR_CCU_PROBE_REMOTE_XN_COUNT="${TILEXR_CCU_PROBE_REMOTE_XN_COUNT:-8}" + export TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START:-332}" + export TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START:-332}" + export TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT="${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT:-8}" + export TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START:-364}" + export TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START:-364}" + export TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT="${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT:-8}" + export TILEXR_CCU_PROBE_CHANNEL_START="${TILEXR_CCU_PROBE_CHANNEL_START:-2}" + if [ "${TILEXR_CCU_DIRECT_BARRIER_MODE:-}" = "" ]; then + export TILEXR_CCU_DIRECT_BARRIER_MODE=sync_cke + else + export TILEXR_CCU_DIRECT_BARRIER_MODE + fi + if [ "${TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE:-}" = "" ]; then + export TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE=hcomm_cap + else + export TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE + fi + export TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES="${TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES:-prepare,submit,barrier,p2p}" + export TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES="${TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES:-acl,acl_module3,rt_hbm}" + export TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES="${TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES:-}" +} + +prepare_profiles=() +prepare_profile_name="" +prepare_profile_alloc="" +prepare_profile_window="" +prepare_profile_data_len_mode="" +prepare_profile_install_order="" +prepare_profile_pfe_offset_source="" +prepare_profile_pfe_partition="" + +build_prepare_profiles() +{ + prepare_profiles=() + if [ "${TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES:-}" != "" ]; then + IFS=',' read -r -a prepare_profiles <<< "${TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES}" + return + fi + + local prepare_alloc_modes=() + local prepare_mode + IFS=',' read -r -a prepare_alloc_modes <<< "${TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES}" + for prepare_mode in "${prepare_alloc_modes[@]}"; do + prepare_mode="${prepare_mode//[[:space:]]/}" + if [ "${prepare_mode}" = "" ]; then + continue + fi + prepare_profiles+=( + "${prepare_mode}:${prepare_mode}:${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW}:${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE}:${TILEXR_CCU_DIRECT_INSTALL_ORDER}" + ) + done +} + +parse_prepare_profile() +{ + local profile="$1" + local extra1="" + local extra2="" + local extra3="" + IFS=':' read -r \ + prepare_profile_name \ + prepare_profile_alloc \ + prepare_profile_window \ + prepare_profile_data_len_mode \ + prepare_profile_install_order \ + extra1 \ + extra2 \ + extra3 <<< "${profile}" + prepare_profile_name="${prepare_profile_name//[[:space:]]/}" + prepare_profile_alloc="${prepare_profile_alloc//[[:space:]]/}" + prepare_profile_window="${prepare_profile_window//[[:space:]]/}" + prepare_profile_data_len_mode="${prepare_profile_data_len_mode//[[:space:]]/}" + prepare_profile_install_order="${prepare_profile_install_order//[[:space:]]/}" + prepare_profile_pfe_offset_source="${extra1//[[:space:]]/}" + prepare_profile_pfe_partition="${extra2//[[:space:]]/}" + if [ "${prepare_profile_name}" = "" ] || + [ "${prepare_profile_alloc}" = "" ] || + [ "${prepare_profile_window}" = "" ] || + [ "${prepare_profile_data_len_mode}" = "" ] || + [ "${prepare_profile_install_order}" = "" ] || + [ "${extra3}" != "" ]; then + echo "ERROR: invalid prepare profile '${profile}', expected name:alloc:window:dataLenMode:installOrder[:pfeOffsetSource:pfePartition]" >&2 + exit 21 + fi + if { [ "${prepare_profile_pfe_offset_source}" != "" ] && [ "${prepare_profile_pfe_partition}" = "" ]; } || + { [ "${prepare_profile_pfe_offset_source}" = "" ] && [ "${prepare_profile_pfe_partition}" != "" ]; }; then + echo "ERROR: invalid prepare profile '${profile}', pfeOffsetSource and pfePartition must be provided together" >&2 + exit 21 + fi +} + +print_prepare_profile_dry_run() +{ + build_prepare_profiles + local index=0 + local profile + for profile in "${prepare_profiles[@]}"; do + parse_prepare_profile "${profile}" + echo "dryRun prepareProfile[${index}] name=${prepare_profile_name} alloc=${prepare_profile_alloc} window=${prepare_profile_window} dataLenMode=${prepare_profile_data_len_mode} installOrder=${prepare_profile_install_order} pfeOffsetSource=${prepare_profile_pfe_offset_source:-default} pfePartition=${prepare_profile_pfe_partition:-default}" + index=$((index + 1)) + done +} + +print_resource_window_token_dry_run() +{ + local token_field + for token_field in TOKEN_ID RAW_TOKEN_ID TOKEN_VALUE; do + local token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}" + local token_value="${!token_var:-}" + local rank0_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK0" + local rank0_token_value="${!rank0_token_var:-}" + local rank1_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK1" + local rank1_token_value="${!rank1_token_var:-}" + if [ "${token_value}" != "" ]; then + echo "${token_var}=${token_value}" + fi + if [ "${rank0_token_value}" != "" ]; then + echo "${rank0_token_var}=${rank0_token_value}" + fi + if [ "${rank1_token_value}" != "" ]; then + echo "${rank1_token_var}=${rank1_token_value}" + fi + done +} + +run_dry_run() +{ + export TILEXR_CCU_DIRECT_SMOKE_DRY_RUN=1 + echo "tilexr_ccu_direct_evening_smoke dryRun=1" + echo "TILEXR_CCU_SMOKE_DEVICES=${TILEXR_CCU_SMOKE_DEVICES}" + echo "TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE}" + echo "TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=${TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT}" + echo "TILEXR_CCU_DIRECT_SMOKE_SUBMIT=${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" + echo "TILEXR_CCU_DIRECT_SMOKE_DRY_RUN=${TILEXR_CCU_DIRECT_SMOKE_DRY_RUN}" + echo "TILEXR_CCU_SMOKE_DRY_RUN=${TILEXR_CCU_SMOKE_DRY_RUN:-0}" + echo "TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES=${TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES}" + echo "TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES=${TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES}" + echo "TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES=${TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES}" + echo "TILEXR_CCU_DIRECT_BARRIER_MODE=${TILEXR_CCU_DIRECT_BARRIER_MODE}" + echo "TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE=${TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE}" + echo "TILEXR_CCU_PROBE_MISSION_START=${TILEXR_CCU_PROBE_MISSION_START}" + echo "TILEXR_CCU_PROBE_INSTRUCTION_START=${TILEXR_CCU_PROBE_INSTRUCTION_START}" + echo "TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START=${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START}" + echo "TILEXR_CCU_PROBE_SQE_ARG_COUNT=${TILEXR_CCU_PROBE_SQE_ARG_COUNT}" + echo "TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT=${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT}" + echo "TILEXR_CCU_PROBE_GSA_START=${TILEXR_CCU_PROBE_GSA_START}" + echo "TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE=${TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE}" + echo "TILEXR_CCU_DIRECT_INSTALL_ORDER=${TILEXR_CCU_DIRECT_INSTALL_ORDER}" + print_resource_window_token_dry_run + print_prepare_profile_dry_run + bash tests/ccu/run_tilexr_ccu_direct_smoke.sh +} + +if [ "${TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN:-0}" = "1" ] || + [ "${TILEXR_CCU_SMOKE_DRY_RUN:-0}" = "1" ]; then + set_evening_defaults + run_dry_run + exit 0 +fi + +if [ -f scripts/common_env.sh ]; then + # shellcheck source=/dev/null + source scripts/common_env.sh >/tmp/tilexr_env_evening_smoke.log 2>&1 +fi + +set_evening_defaults +evening_work_root="${TILEXR_CCU_EVENING_WORK_ROOT:-${repo_root}/build/ccu_direct_evening_smoke/$(date +%Y%m%d_%H%M%S)}" + +stage_enabled() +{ + case ",${TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES}," in + *",$1,"*) return 0 ;; + *) return 1 ;; + esac +} + +append_profile_pfe_env() +{ + if [ "${1:-}" = "" ] && [ "${2:-}" = "" ]; then + return + fi + printf '%s\n' \ + "TILEXR_CCU_DIRECT_LOWER_LAYER_PFE_OFFSET_SOURCE=$1" \ + "TILEXR_CCU_DIRECT_LOWER_LAYER_PFE_PARTITION=$2" +} + +prepare_has_submit_ready() +{ + local prepare_dir="$1" + local thread_log="${prepare_dir}/ccu_thread.log" + local rank0_log="${prepare_dir}/ccu_rank0.log" + local rank1_log="${prepare_dir}/ccu_rank1.log" + if [ -f "${thread_log}" ]; then + [ "$(grep -c "submitReady=1" "${thread_log}")" -ge 2 ] + return + fi + [ -f "${rank0_log}" ] && [ -f "${rank1_log}" ] && + grep -q "submitReady=1" "${rank0_log}" && + grep -q "submitReady=1" "${rank1_log}" +} + +summarize_stage_logs() +{ + local stage="$1" + local stage_dir="$2" + local status="$3" + local mode="${4:-}" + local found=0 + for log in \ + "${stage_dir}/ccu_thread.log" \ + "${stage_dir}/ccu_rank0.log" \ + "${stage_dir}/ccu_rank1.log"; do + if [ ! -f "${log}" ]; then + continue + fi + found=1 + if [ "${stage}" = "prepare" ]; then + echo "tilexr_ccu_direct_evening_smoke prepareLogSummary mode=${mode} status=${status} log=${log}" + else + echo "tilexr_ccu_direct_evening_smoke stageLogSummary stage=${stage} status=${status} log=${log}" + fi + grep -E 'direct CCU submit failed|rtRet=|args\[' "${log}" | + head -n "${TILEXR_CCU_EVENING_SUBMIT_FAILURE_SUMMARY_LINES:-8}" || true + grep -E \ + 'tilexr_ccu_direct_smoke config|tilexr_ccu_direct_smoke prepare|tilexr_ccu_direct_smoke preparedTasks|tilexr_ccu_direct_smoke submit|tilexr_ccu_direct_smoke submitTiming|tilexr_ccu_direct_smoke p2pCcuCopy|tilexr_ccu_direct_smoke aclrtSynchronizeStream|direct CCU submit failed|rtRet=|args\[|CCU custom channel call failed|op=[0-9]+|driverRet=|opRet=|SET_INSTRUCTION|SET_MSID_TOKEN|submitReady=|TileXRDirectCcuTrace .*decoded=|TileXRDirectCcuTrace remoteXnBinding|TileXRDirectCcuTrace task\[|TileXRDirectCcuTrace finalRuntimeTask|TileXRDirectCcuTrace customChannel.return|TileXRDirectCcuTrace program.sync' \ + "${log}" | tail -n "${TILEXR_CCU_EVENING_LOG_SUMMARY_LINES:-24}" || true + done + if [ "${found}" -eq 0 ]; then + if [ "${stage}" = "prepare" ]; then + echo "tilexr_ccu_direct_evening_smoke prepareLogSummary mode=${mode} status=${status} log=missing workDir=${stage_dir}" + else + echo "tilexr_ccu_direct_evening_smoke stageLogSummary stage=${stage} status=${status} log=missing workDir=${stage_dir}" + fi + fi +} + +extract_last_log_field() +{ + local key="$1" + shift + awk -v key="${key}" ' + { + for (i = 1; i <= NF; ++i) { + if ($i ~ ("^" key "=")) { + split($i, parts, "="); + value = parts[2]; + gsub(/[^0-9A-Za-z_.:-].*$/, "", value); + last = value; + } + } + } + END { + if (last != "") { + print last; + } + } + ' "$@" 2>/dev/null || true +} + +print_prepare_matrix_summary() +{ + local prepare_dir="$1" + local status="$2" + local profile="$3" + local alloc="$4" + local window="$5" + local data_len_mode="$6" + local install_order="$7" + local logs=() + local log + for log in \ + "${prepare_dir}/ccu_thread.log" \ + "${prepare_dir}/ccu_rank0.log" \ + "${prepare_dir}/ccu_rank1.log"; do + if [ -f "${log}" ]; then + logs+=("${log}") + fi + done + + local submit_ready="NA" + local op="NA" + local driver_ret="NA" + local op_ret="NA" + local lower_layer_preconditions=0 + local summary_log="missing" + if [ "${#logs[@]}" -gt 0 ]; then + summary_log="${logs[0]}" + submit_ready="$(extract_last_log_field submitReady "${logs[@]}")" + op="$(extract_last_log_field op "${logs[@]}")" + driver_ret="$(extract_last_log_field driverRet "${logs[@]}")" + op_ret="$(extract_last_log_field opRet "${logs[@]}")" + if grep -q 'lowerLayerPreconditions{' "${logs[@]}"; then + lower_layer_preconditions=1 + fi + fi + submit_ready="${submit_ready:-NA}" + op="${op:-NA}" + driver_ret="${driver_ret:-NA}" + op_ret="${op_ret:-NA}" + + echo "tilexr_ccu_direct_evening_smoke prepareMatrix profile=${profile} status=${status} submitReady=${submit_ready} op=${op} driverRet=${driver_ret} opRet=${op_ret} lowerLayerPreconditions=${lower_layer_preconditions} alloc=${alloc} window=${window} dataLenMode=${data_len_mode} installOrder=${install_order} log=${summary_log}" +} + +run_smoke_stage() +{ + local stage="$1" + shift + local stage_dir="${evening_work_root}/${stage}" + mkdir -p "${stage_dir}" + echo "tilexr_ccu_direct_evening_smoke stage=${stage} workDir=${stage_dir}" + timeout "${TILEXR_CCU_EVENING_TOTAL_TIMEOUT:-160}s" \ + env TILEXR_CCU_SMOKE_WORK_DIR="${stage_dir}" "$@" bash tests/ccu/run_tilexr_ccu_direct_smoke.sh +} + +prepare_stage_exit_is_environmental() +{ + local status="$1" + [ "${status}" -eq 3 ] || [ "${status}" -eq 124 ] +} + +cmake --build build --target tile-comm -j"${TILEXR_CCU_EVENING_BUILD_JOBS:-2}" + +if ! stage_enabled prepare; then + echo "ERROR: TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES must include prepare" >&2 + exit 20 +fi + +build_prepare_profiles +selected_prepare_alloc_mode="" +selected_prepare_window="" +selected_prepare_data_len_mode="" +selected_prepare_install_order="" +selected_prepare_pfe_offset_source="" +selected_prepare_pfe_partition="" +selected_prepare_dir="" +selected_prepare_profile_name="" +prepare_status_summary="" + +print_prepare_failure_final_status() +{ + local final_status_line="tilexr_ccu_direct_evening_smoke finalStatus prepare=fail submit=skipped barrier=skipped p2p=skipped completionCandidate=0 failedStage=prepare selectedProfile=none selectedAlloc=none selectedWindow=none selectedDataLenMode=none selectedInstallOrder=none pfeOffsetSource=default pfePartition=default prepareStatusSummary=${prepare_status_summary}" + echo "${final_status_line}" + mkdir -p "${evening_work_root}" + printf '%s\n' "${final_status_line}" > "${evening_work_root}/final_status.log" +} + +for prepare_profile in "${prepare_profiles[@]}"; do + parse_prepare_profile "${prepare_profile}" + if [ "${prepare_profile_name}" = "" ]; then + continue + fi + safe_prepare_mode="$(printf '%s' "${prepare_profile_name}" | sed 's/[^A-Za-z0-9_]/_/g')" + prepare_status=0 + run_smoke_stage "prepare_${safe_prepare_mode}" \ + TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${prepare_profile_alloc}" \ + TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${prepare_profile_window}" \ + TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${prepare_profile_data_len_mode}" \ + TILEXR_CCU_DIRECT_INSTALL_ORDER="${prepare_profile_install_order}" \ + $(append_profile_pfe_env "${prepare_profile_pfe_offset_source}" "${prepare_profile_pfe_partition}") || + prepare_status=$? + prepare_dir="${evening_work_root}/prepare_${safe_prepare_mode}" + echo "tilexr_ccu_direct_evening_smoke prepareStatus=${prepare_status} profile=${prepare_profile_name} alloc=${prepare_profile_alloc} window=${prepare_profile_window} dataLenMode=${prepare_profile_data_len_mode} installOrder=${prepare_profile_install_order} pfeOffsetSource=${prepare_profile_pfe_offset_source:-default} pfePartition=${prepare_profile_pfe_partition:-default} workDir=${prepare_dir}" + print_prepare_matrix_summary \ + "${prepare_dir}" \ + "${prepare_status}" \ + "${prepare_profile_name}" \ + "${prepare_profile_alloc}" \ + "${prepare_profile_window}" \ + "${prepare_profile_data_len_mode}" \ + "${prepare_profile_install_order}" + summarize_stage_logs prepare "${prepare_dir}" "${prepare_status}" "${prepare_profile_name}" + prepare_status_summary="${prepare_status_summary}${prepare_status_summary:+,}${prepare_profile_name}:${prepare_status}:${prepare_profile_alloc}:${prepare_profile_window}:${prepare_profile_data_len_mode}:${prepare_profile_install_order}:${prepare_profile_pfe_offset_source:-default}:${prepare_profile_pfe_partition:-default}:${prepare_dir}" + if prepare_stage_exit_is_environmental "${prepare_status}"; then + echo "ERROR: direct CCU prepare stopped on environmental gate status=${prepare_status} profile=${prepare_profile_name} alloc=${prepare_profile_alloc} window=${prepare_profile_window} dataLenMode=${prepare_profile_data_len_mode} installOrder=${prepare_profile_install_order} pfeOffsetSource=${prepare_profile_pfe_offset_source:-default} pfePartition=${prepare_profile_pfe_partition:-default} workDir=${prepare_dir}" >&2 + exit "${prepare_status}" + fi + if [ "${prepare_status}" -eq 0 ] && prepare_has_submit_ready "${prepare_dir}"; then + selected_prepare_alloc_mode="${prepare_profile_alloc}" + selected_prepare_window="${prepare_profile_window}" + selected_prepare_data_len_mode="${prepare_profile_data_len_mode}" + selected_prepare_install_order="${prepare_profile_install_order}" + selected_prepare_pfe_offset_source="${prepare_profile_pfe_offset_source}" + selected_prepare_pfe_partition="${prepare_profile_pfe_partition}" + selected_prepare_dir="${prepare_dir}" + selected_prepare_profile_name="${prepare_profile_name}" + break + fi +done + +if [ "${selected_prepare_alloc_mode}" = "" ]; then + print_prepare_failure_final_status + echo 'tilexr_ccu_direct_evening_smoke stopAfter=prepare reason="submitReady=1 missing for every prepare profile" workRoot='"${evening_work_root} prepareStatusSummary=${prepare_status_summary}" + exit 0 +fi +echo "tilexr_ccu_direct_evening_smoke selectedPrepare alloc=${selected_prepare_alloc_mode} window=${selected_prepare_window} dataLenMode=${selected_prepare_data_len_mode} installOrder=${selected_prepare_install_order} pfeOffsetSource=${selected_prepare_pfe_offset_source:-default} pfePartition=${selected_prepare_pfe_partition:-default} workDir=${selected_prepare_dir}" + +submit_final_status="skipped" +barrier_final_status="skipped" +p2p_final_status="skipped" + +print_final_status() +{ + local failed_stage="${1:-none}" + local completion_candidate=0 + if [ "${failed_stage}" = "none" ] && + [ "${submit_final_status}" = "pass" ] && + [ "${barrier_final_status}" = "pass" ] && + [ "${p2p_final_status}" = "pass" ]; then + completion_candidate=1 + fi + + local final_status_line="tilexr_ccu_direct_evening_smoke finalStatus prepare=pass submit=${submit_final_status} barrier=${barrier_final_status} p2p=${p2p_final_status} completionCandidate=${completion_candidate} failedStage=${failed_stage} selectedProfile=${selected_prepare_profile_name} selectedAlloc=${selected_prepare_alloc_mode} selectedWindow=${selected_prepare_window} selectedDataLenMode=${selected_prepare_data_len_mode} selectedInstallOrder=${selected_prepare_install_order} pfeOffsetSource=${selected_prepare_pfe_offset_source:-default} pfePartition=${selected_prepare_pfe_partition:-default}" + echo "${final_status_line}" + mkdir -p "${evening_work_root}" + printf '%s\n' "${final_status_line}" > "${evening_work_root}/final_status.log" +} + +if stage_enabled submit; then + submit_status=0 + run_smoke_stage submit \ + TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}" \ + TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${selected_prepare_window}" \ + TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${selected_prepare_data_len_mode}" \ + TILEXR_CCU_DIRECT_INSTALL_ORDER="${selected_prepare_install_order}" \ + $(append_profile_pfe_env "${selected_prepare_pfe_offset_source}" "${selected_prepare_pfe_partition}") \ + TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1 || + submit_status=$? + summarize_stage_logs submit "${evening_work_root}/submit" "${submit_status}" + if [ "${submit_status}" -ne 0 ]; then + submit_final_status="fail" + print_final_status submit + exit "${submit_status}" + fi + submit_final_status="pass" +fi + +if stage_enabled barrier; then + barrier_status=0 + run_smoke_stage barrier \ + TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}" \ + TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${selected_prepare_window}" \ + TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${selected_prepare_data_len_mode}" \ + TILEXR_CCU_DIRECT_INSTALL_ORDER="${selected_prepare_install_order}" \ + $(append_profile_pfe_env "${selected_prepare_pfe_offset_source}" "${selected_prepare_pfe_partition}") \ + TILEXR_CCU_DIRECT_BARRIER_MODE="${TILEXR_CCU_DIRECT_BARRIER_MODE}" \ + TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1 \ + TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK="${TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK:-0}" \ + TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS="${TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS:-300}" \ + TILEXR_CCU_DIRECT_SMOKE_EXPECT_BARRIER_WAIT=1 \ + TILEXR_CCU_DIRECT_SMOKE_MIN_SYNC_MS="${TILEXR_CCU_DIRECT_SMOKE_MIN_SYNC_MS:-100}" || + barrier_status=$? + summarize_stage_logs barrier "${evening_work_root}/barrier" "${barrier_status}" + if [ "${barrier_status}" -ne 0 ]; then + barrier_final_status="fail" + print_final_status barrier + exit "${barrier_status}" + fi + barrier_final_status="pass" +fi + +if stage_enabled p2p; then + p2p_status=0 + run_smoke_stage p2p \ + TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}" \ + TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${selected_prepare_window}" \ + TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${selected_prepare_data_len_mode}" \ + TILEXR_CCU_DIRECT_INSTALL_ORDER="${selected_prepare_install_order}" \ + $(append_profile_pfe_env "${selected_prepare_pfe_offset_source}" "${selected_prepare_pfe_partition}") \ + TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=1 \ + TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1 \ + TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY=1 \ + TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY=1 || + p2p_status=$? + summarize_stage_logs p2p "${evening_work_root}/p2p" "${p2p_status}" + if [ "${p2p_status}" -ne 0 ]; then + p2p_final_status="fail" + print_final_status p2p + exit "${p2p_status}" + fi + p2p_final_status="pass" +fi + +print_final_status none +echo "tilexr_ccu_direct_evening_smoke success workRoot=${evening_work_root}" diff --git a/tests/ccu/run_tilexr_ccu_direct_smoke.sh b/tests/ccu/run_tilexr_ccu_direct_smoke.sh new file mode 100644 index 00000000..5afcac6b --- /dev/null +++ b/tests/ccu/run_tilexr_ccu_direct_smoke.sh @@ -0,0 +1,662 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2026 TileXR Project +# +# Two-rank runner for the private TileXR direct CCU smoke probe. +# Default execution is safe and does not touch ACL/NPU runtime. + +set -euo pipefail + +if [ "${TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE:-0}" != "1" ]; then + echo "tilexr_ccu_direct_smoke_runner skipped: set TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE=1 to run hardware smoke" + exit 0 +fi + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "${repo_root}" + +ASCEND_HOME_PATH="${ASCEND_HOME_PATH:-/usr/local/Ascend/ascend-toolkit/latest}" +ARCH="${ARCH:-$(uname -m)}" +if [ "${ARCH}" = "arm64" ]; then + ARCH="aarch64" +fi +ASCEND_DRIVER_PATH="${ASCEND_DRIVER_PATH:-/usr/local/Ascend/driver}" +export ASCEND_HOME_PATH ARCH ASCEND_DRIVER_PATH +export TILEXR_CCU_DIRECT_INSTALL_ORDER="${TILEXR_CCU_DIRECT_INSTALL_ORDER:-lower_layer_first}" + +work_dir="${TILEXR_CCU_SMOKE_WORK_DIR:-${repo_root}/build/ccu_direct_smoke}" +mkdir -p "${work_dir}" + +endpoint_fields=( + EID + TPN + DOORBELL_VA + DOORBELL_TOKEN_ID + DOORBELL_TOKEN_VALUE + SQ_DEPTH +) + +resource_window_token_fields=( + TOKEN_ID + RAW_TOKEN_ID + TOKEN_VALUE +) + +parse_int() +{ + local value="$1" + local fallback="$2" + if [ -z "${value}" ]; then + echo "${fallback}" + return + fi + printf "%d" "${value}" 2>/dev/null || printf "%d" "${fallback}" +} + +default_sync_instruction_count() +{ + local sync_resource_count="$1" + local barrier_mode="${TILEXR_CCU_DIRECT_BARRIER_MODE:-}" + local hcomm_style_task1_prelude_count=5 + case "${barrier_mode}" in + sync_cke|sync_cke_set_wait) + echo $((sync_resource_count * 2 + 1)) + ;; + sync_cke_post_only) + echo $((sync_resource_count + 1)) + ;; + local_cke_post_only) + echo "${sync_resource_count}" + ;; + sync_xn_post_only) + echo $((hcomm_style_task1_prelude_count + sync_resource_count)) + ;; + sync_xn_load_post_only) + echo $((hcomm_style_task1_prelude_count + sync_resource_count * 2)) + ;; + *) + echo $((hcomm_style_task1_prelude_count + sync_resource_count * 2)) + ;; + esac +} + +apply_p2p_ccu_copy_defaults() +{ + if [ "${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY:-0}" != "1" ]; then + return + fi + + export TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT="${TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT:-1}" + export TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_ACTIVE_RANK="${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_ACTIVE_RANK:-0}" + export TILEXR_CCU_PROBE_MISSION_START="${TILEXR_CCU_PROBE_MISSION_START:-6}" + export TILEXR_CCU_PROBE_INSTRUCTION_START="${TILEXR_CCU_PROBE_INSTRUCTION_START:-475}" + export TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START="${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START:-489}" + export TILEXR_CCU_PROBE_SQE_ARG_COUNT="${TILEXR_CCU_PROBE_SQE_ARG_COUNT:-13}" + export TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT="${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT:-143}" + export TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-full_repository}" + export TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-instruction_bytes}" + export TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE:-acl}" + export TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE="${TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE:-ra_ctx}" + export TILEXR_CCU_PROBE_RANK0_XN_START="${TILEXR_CCU_PROBE_RANK0_XN_START:-1961}" + export TILEXR_CCU_PROBE_RANK1_XN_START="${TILEXR_CCU_PROBE_RANK1_XN_START:-1961}" + export TILEXR_CCU_PROBE_GSA_START="${TILEXR_CCU_PROBE_GSA_START:-510}" + export TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START:-2361}" + export TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START:-2361}" + export TILEXR_CCU_PROBE_REMOTE_XN_COUNT="${TILEXR_CCU_PROBE_REMOTE_XN_COUNT:-8}" + export TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START:-332}" + export TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START:-332}" + export TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT="${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT:-8}" + export TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START:-364}" + export TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START:-364}" + export TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT="${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT:-8}" + export TILEXR_CCU_PROBE_CHANNEL_START="${TILEXR_CCU_PROBE_CHANNEL_START:-2}" + export TILEXR_CCU_DIRECT_BARRIER_MODE="${TILEXR_CCU_DIRECT_BARRIER_MODE:-sync_cke}" + export TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE="${TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE:-hcomm_cap}" +} + +apply_p2p_ccu_copy_defaults + +if [ "${TILEXR_CCU_DIRECT_SMOKE_DRY_RUN:-0}" = "1" ]; then + echo "tilexr_ccu_direct_smoke_runner dryRun=1 workDir=${work_dir}" + for diagnostic_var in \ + TILEXR_CCU_DIRECT_BARRIER_MODE \ + TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE \ + TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW \ + TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE \ + TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE \ + TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE \ + TILEXR_CCU_DIRECT_INSTALL_ORDER \ + TILEXR_CCU_PROBE_SQE_ARG_COUNT \ + TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START; do + diagnostic_value="${!diagnostic_var:-}" + if [ "${diagnostic_value}" != "" ]; then + echo "dryRun ${diagnostic_var}=${diagnostic_value}" + fi + done + sqe_arg_count="$(parse_int "${TILEXR_CCU_PROBE_SQE_ARG_COUNT:-13}" 13)" + sync_resource_count="$(parse_int "${TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT:-1}" 1)" + default_sync_instruction_count_value="$(default_sync_instruction_count "${sync_resource_count}")" + sync_instruction_count="$(parse_int \ + "${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT:-${default_sync_instruction_count_value}}" \ + "${default_sync_instruction_count_value}")" + repository_start="$(parse_int "${TILEXR_CCU_PROBE_INSTRUCTION_START:-1}" 1)" + mission_instruction_start="$(parse_int "${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START:-0}" 0)" + if [ "${mission_instruction_start}" -eq 0 ]; then + mission_instruction_start="${repository_start}" + fi + repository_prefix_count=$((mission_instruction_start - repository_start)) + if [ "${repository_prefix_count}" -lt 0 ]; then + repository_prefix_count=0 + fi + mission_instruction_count=$((sqe_arg_count + sync_instruction_count)) + repository_count=$((repository_prefix_count + mission_instruction_count)) + task0_start="${mission_instruction_start}" + task0_count="${sqe_arg_count}" + task1_start=$((mission_instruction_start + sqe_arg_count)) + task1_count="${sync_instruction_count}" + if [ "${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-}" = "full_repository" ] || + [ "${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-}" = "full" ] || + [ "${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-}" = "1" ]; then + install_start="${repository_start}" + install_count="${repository_count}" + else + install_start="${mission_instruction_start}" + install_count="${mission_instruction_count}" + fi + instruction_data_len=$((install_count * 32)) + if [ "${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-}" = "descriptor_bytes" ] || + [ "${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-}" = "descriptor" ] || + [ "${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-}" = "1" ]; then + set_instruction_data_len=24 + else + set_instruction_data_len="${instruction_data_len}" + fi + echo "dryRun derived repositoryStartId=${repository_start} repositoryCount=${repository_count} missionInstructionStartId=${mission_instruction_start} missionInstructionCount=${mission_instruction_count}" + echo "dryRun derived task0.instStartId=${task0_start} task0.instCnt=${task0_count}" + echo "dryRun derived task1.instStartId=${task1_start} task1.instCnt=${task1_count}" + echo "dryRun derived SET_INSTRUCTION offsetStartIdx=${install_start} dataLen=${set_instruction_data_len} instructionBytes=${instruction_data_len}" + for endpoint_field in "${endpoint_fields[@]}"; do + endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}" + common_endpoint_value="${!endpoint_var:-}" + rank0_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK0" + rank0_endpoint_value="${!rank0_endpoint_var:-${common_endpoint_value}}" + rank1_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK1" + rank1_endpoint_value="${!rank1_endpoint_var:-${common_endpoint_value}}" + if [ "${rank0_endpoint_value}" != "" ]; then + echo "dryRun rank0 TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank0_endpoint_value}" + fi + if [ "${rank1_endpoint_value}" != "" ]; then + echo "dryRun rank1 TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank1_endpoint_value}" + fi + done + for token_field in "${resource_window_token_fields[@]}"; do + token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}" + common_token_value="${!token_var:-}" + rank0_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK0" + rank0_token_value="${!rank0_token_var:-${common_token_value}}" + rank1_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK1" + rank1_token_value="${!rank1_token_var:-${common_token_value}}" + if [ "${rank0_token_value}" != "" ]; then + echo "dryRun rank0 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}=${rank0_token_value}" + fi + if [ "${rank1_token_value}" != "" ]; then + echo "dryRun rank1 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}=${rank1_token_value}" + fi + done + exit 0 +fi + +tile_comm_lib="${TILEXR_TILE_COMM_LIB:-}" +if [ -z "${tile_comm_lib}" ]; then + for candidate in \ + "${repo_root}/build/src/comm/libtile-comm.so" \ + "${repo_root}/install/lib64/libtile-comm.so" \ + "${repo_root}/install/lib/libtile-comm.so" \ + "${repo_root}/install_direct_ccu_guard/lib64/libtile-comm.so"; do + if [ -f "${candidate}" ]; then + tile_comm_lib="${candidate}" + break + fi + done +fi +if [ -z "${tile_comm_lib}" ] || [ ! -f "${tile_comm_lib}" ]; then + echo "ERROR: libtile-comm.so not found; build tile-comm first or set TILEXR_TILE_COMM_LIB" >&2 + exit 2 +fi +tile_comm_dir="$(cd "$(dirname "${tile_comm_lib}")" && pwd)" + +cann_root="${ASCEND_HOME_PATH}/${ARCH}-linux" +cann_lib_dir="${cann_root}/lib64" +driver_lib_dir="${ASCEND_DRIVER_PATH}/lib64/driver" +probe_bin="${work_dir}/ccu_tilexr_direct_smoke_probe" + +c++ -std=c++14 \ + -DTILEXR_CCU_TESTING=1 \ + -I "${repo_root}/src/include" \ + -I "${repo_root}/src/comm" \ + -I "${cann_root}/pkg_inc" \ + -I "${cann_root}/pkg_inc/runtime" \ + -I "${cann_root}/include" \ + "${repo_root}/tests/ccu/ccu_tilexr_direct_smoke_probe.cpp" \ + -L "${tile_comm_dir}" \ + -L "${cann_lib_dir}" \ + -L "${driver_lib_dir}" \ + -Wl,-rpath-link,"${tile_comm_dir}" \ + -Wl,-rpath-link,"${cann_lib_dir}" \ + -Wl,-rpath-link,"${driver_lib_dir}" \ + -ltile-comm -lascendcl -lruntime -ldl -pthread \ + -o "${probe_bin}" + +devices="${TILEXR_CCU_SMOKE_DEVICES:-${TILEXR_TEST_DEVICES:-0,1}}" + +if command -v npu-smi >/dev/null 2>&1; then + npu_smi_rc=0 + timeout "${TILEXR_CCU_SMOKE_NPU_SMI_TIMEOUT:-20}s" npu-smi info > "${work_dir}/npu-smi.log" 2>&1 || npu_smi_rc=$? + if [ "${npu_smi_rc}" -ne 0 ]; then + echo "ERROR: npu-smi info did not complete; refusing to run ACL/CCU smoke" >&2 + echo "npu-smi rc=${npu_smi_rc}" >&2 + echo "npu-smi log: ${work_dir}/npu-smi.log" >&2 + exit 3 + fi + if [ "${TILEXR_CCU_SMOKE_ALLOW_BUSY_NPU:-0}" != "1" ]; then + busy_rc=0 + npu_guard_args=( + --log "${work_dir}/npu-smi.log" + --devices "${devices}" + ) + if [ "${TILEXR_CCU_SMOKE_ALLOW_UNHEALTHY_NPU:-0}" = "1" ]; then + npu_guard_args+=(--allow-unhealthy) + fi + python3 "${repo_root}/tests/ccu/ccu_npu_smi_busy_guard.py" \ + "${npu_guard_args[@]}" > "${work_dir}/npu-smi-busy.log" 2>&1 || busy_rc=$? + if [ "${busy_rc}" -ne 0 ]; then + echo "ERROR: selected NPU device is busy or unhealthy; refusing to run ACL/CCU smoke" >&2 + cat "${work_dir}/npu-smi-busy.log" >&2 + echo "npu-smi log: ${work_dir}/npu-smi.log" >&2 + echo "set TILEXR_CCU_SMOKE_ALLOW_UNHEALTHY_NPU=1 to allow Alarm health while still rejecting busy devices" >&2 + echo "set TILEXR_CCU_SMOKE_ALLOW_BUSY_NPU=1 only for an explicitly approved short test that may use busy devices" >&2 + exit 3 + fi + fi +elif [ "${TILEXR_CCU_SMOKE_REQUIRE_NPU_SMI:-0}" = "1" ]; then + echo "ERROR: npu-smi not found; refusing to run ACL/CCU smoke" >&2 + exit 3 +fi + +comm_port="${TILEXR_CCU_SMOKE_PORT:-$((30000 + (RANDOM % 20000)))}" +comm_id="${TILEXR_COMM_ID:-127.0.0.1:${comm_port}}" +comm_domain="${TILEXR_CCU_PROBE_COMM_DOMAIN:-0}" +timeout_s="${TILEXR_CCU_SMOKE_TIMEOUT:-180}" +ready_dir="${work_dir}/submit_ready_${comm_port}" +done_dir="${work_dir}/submit_done_${comm_port}" +rank0_log="${work_dir}/ccu_rank0.log" +rank1_log="${work_dir}/ccu_rank1.log" +rm -rf "${ready_dir}" "${done_dir}" +mkdir -p "${ready_dir}" "${done_dir}" +rm -f "${rank0_log}" "${rank1_log}" + +common_env=( + "LD_LIBRARY_PATH=${tile_comm_dir}:${cann_lib_dir}:${driver_lib_dir}:${LD_LIBRARY_PATH:-}" + "TILEXR_COMM_ID=${comm_id}" + "TILEXR_TEST_DEVICES=${devices}" + "TILEXR_CCU_DIRECT_SMOKE_ENABLE=1" + "TILEXR_CCU_DIRECT_SMOKE_READY_DIR=${ready_dir}" + "TILEXR_CCU_DIRECT_SMOKE_DONE_DIR=${done_dir}" + "TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE=${TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE:-1}" + "TILEXR_CCU_PROBE_RANK_SIZE=2" + "TILEXR_CCU_PROBE_COMM_DOMAIN=${comm_domain}" +) +if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" = "1" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE:-0}" = "1" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=1") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT:-0}" = "1" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=1") +fi +if [ "${TILEXR_CCU_DIRECT_BARRIER_MODE:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_BARRIER_MODE=${TILEXR_CCU_DIRECT_BARRIER_MODE}") +fi +if [ "${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW=${TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW}") +fi +if [ "${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE=${TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE}") +fi +if [ "${TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE=${TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE}") +fi +if [ "${TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE=${TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE}") +fi +if [ "${TILEXR_CCU_DIRECT_INSTALL_ORDER:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_INSTALL_ORDER=${TILEXR_CCU_DIRECT_INSTALL_ORDER}") +fi +if [ "${TILEXR_CCU_DIRECT_INSTALL_DIE_ID:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_INSTALL_DIE_ID=${TILEXR_CCU_DIRECT_INSTALL_DIE_ID}") +fi +if [ "${TILEXR_CCU_PROBE_MISSION_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_MISSION_START=${TILEXR_CCU_PROBE_MISSION_START}") +fi +if [ "${TILEXR_CCU_PROBE_INSTRUCTION_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_INSTRUCTION_START=${TILEXR_CCU_PROBE_INSTRUCTION_START}") +fi +if [ "${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START=${TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START}") +fi +if [ "${TILEXR_CCU_PROBE_SQE_ARG_COUNT:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_SQE_ARG_COUNT=${TILEXR_CCU_PROBE_SQE_ARG_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT=${TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT=${TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_BINDINGS_PER_RESOURCE:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_BINDINGS_PER_RESOURCE=${TILEXR_CCU_PROBE_BINDINGS_PER_RESOURCE}") +fi +if [ "${TILEXR_CCU_PROBE_CKE_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_CKE_START=${TILEXR_CCU_PROBE_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_GSA_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_GSA_START=${TILEXR_CCU_PROBE_GSA_START}") +fi +if [ "${TILEXR_CCU_PROBE_CHANNEL_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_CHANNEL_START=${TILEXR_CCU_PROBE_CHANNEL_START}") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK=${TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK}") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS=${TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS}") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY=${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY}") +fi +if [ "${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES:-}" != "" ]; then + common_env+=("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES=${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES}") +fi +if [ "${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START=${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT=${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START=${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT:-}" != "" ]; then + common_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT=${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT}") +fi +for endpoint_field in "${endpoint_fields[@]}"; do + endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}" + endpoint_value="${!endpoint_var:-}" + if [ "${endpoint_value}" != "" ]; then + common_env+=("${endpoint_var}=${endpoint_value}") + fi +done +for token_field in "${resource_window_token_fields[@]}"; do + token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}" + token_value="${!token_var:-}" + if [ "${token_value}" != "" ]; then + common_env+=("${token_var}=${token_value}") + fi + rank0_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK0" + rank0_token_value="${!rank0_token_var:-}" + if [ "${rank0_token_value}" != "" ]; then + common_env+=("${rank0_token_var}=${rank0_token_value}") + fi + rank1_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK1" + rank1_token_value="${!rank1_token_var:-}" + if [ "${rank1_token_value}" != "" ]; then + common_env+=("${rank1_token_var}=${rank1_token_value}") + fi +done + +rank0_env=() +rank1_env=() +if [ "${TILEXR_CCU_PROBE_RANK0_XN_START:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_XN_START=${TILEXR_CCU_PROBE_RANK0_XN_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_XN_START:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_XN_START=${TILEXR_CCU_PROBE_RANK1_XN_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_REMOTE_XN_START=${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_REMOTE_XN_START=${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_COUNT:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_REMOTE_XN_COUNT=${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_COUNT}") +elif [ "${TILEXR_CCU_PROBE_REMOTE_XN_COUNT:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_REMOTE_XN_COUNT=${TILEXR_CCU_PROBE_REMOTE_XN_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_COUNT:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_REMOTE_XN_COUNT=${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_COUNT}") +elif [ "${TILEXR_CCU_PROBE_REMOTE_XN_COUNT:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_REMOTE_XN_COUNT=${TILEXR_CCU_PROBE_REMOTE_XN_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START=${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START=${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_COUNT:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT=${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_COUNT:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT=${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START=${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START=${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START}") +fi +if [ "${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_COUNT:-}" != "" ]; then + rank0_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT=${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_COUNT}") +fi +if [ "${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_COUNT:-}" != "" ]; then + rank1_env+=("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT=${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_COUNT}") +fi +for endpoint_field in "${endpoint_fields[@]}"; do + rank0_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK0" + rank0_endpoint_value="${!rank0_endpoint_var:-}" + if [ "${rank0_endpoint_value}" != "" ]; then + rank0_env+=("TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank0_endpoint_value}") + fi + rank1_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK1" + rank1_endpoint_value="${!rank1_endpoint_var:-}" + if [ "${rank1_endpoint_value}" != "" ]; then + rank1_env+=("TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank1_endpoint_value}") + fi +done +for token_field in "${resource_window_token_fields[@]}"; do + rank0_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK0" + rank0_token_value="${!rank0_token_var:-}" + if [ "${rank0_token_value}" != "" ]; then + rank0_env+=("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}=${rank0_token_value}") + fi + rank1_token_var="TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}_RANK1" + rank1_token_value="${!rank1_token_var:-}" + if [ "${rank1_token_value}" != "" ]; then + rank1_env+=("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_${token_field}=${rank1_token_value}") + fi +done + +echo "tilexr_ccu_direct_smoke_runner begin workDir=${work_dir} devices=${devices} commId=${comm_id} threadMode=${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE:-0} submit=${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0} barrierMode=${TILEXR_CCU_DIRECT_BARRIER_MODE:-} p2pCcuCopy=${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY:-0} timeout=${timeout_s} npuSmiTimeout=${TILEXR_CCU_SMOKE_NPU_SMI_TIMEOUT:-20}" + +if [ "${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE:-0}" = "1" ]; then + thread_log="${work_dir}/ccu_thread.log" + rm -f "${thread_log}" + thread_status=0 + timeout "${timeout_s}s" env "${common_env[@]}" TILEXR_CCU_PROBE_RANK=0 "${probe_bin}" > "${thread_log}" 2>&1 || + thread_status=$? + cat "${thread_log}" + echo "tilexr_ccu_direct_smoke_runner threadMode summary status=${thread_status} log=${thread_log}" + if [ "${thread_status}" -ne 0 ]; then + echo "ERROR: direct CCU thread-mode smoke failed status=${thread_status}" >&2 + echo "thread log: ${thread_log}" >&2 + exit 4 + fi + if [ "$(grep -c "tilexr_ccu_direct_smoke prepare ret=0" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode prepare did not return success for both ranks" >&2 + exit 5 + fi + if [ "$(grep -c "installSucceeded=1" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode prepare did not complete install attempt for both ranks" >&2 + exit 6 + fi + if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" = "1" ]; then + if [ "$(grep -c "submitReady=1" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode submit requested but prepare did not reach submitReady=1" >&2 + exit 6 + fi + if [ "$(grep -c "tilexr_ccu_direct_smoke submit ret=0" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode submit did not return success for both ranks" >&2 + exit 7 + fi + if [ "$(grep -c "tilexr_ccu_direct_smoke submitTiming" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode submit timing was not reported for both ranks" >&2 + exit 8 + fi + fi + if [ "${TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY:-0}" = "1" ]; then + if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" != "1" ]; then + echo "ERROR: direct CCU thread-mode P2P CCU-copy check requires TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1" >&2 + exit 11 + fi + if [ "$(grep -c "tilexr_ccu_direct_smoke p2pCcuCopy" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode P2P CCU-copy result missing" >&2 + exit 12 + fi + if [ "$(grep -c "tilexr_ccu_direct_smoke p2pCcuCopy .*passed=1" "${thread_log}")" -lt 2 ]; then + echo "ERROR: direct CCU thread-mode P2P CCU-copy check failed" >&2 + exit 13 + fi + fi + echo "tilexr_ccu_direct_smoke_runner success workDir=${work_dir}" + exit 0 +fi + +timeout "${timeout_s}s" env "${common_env[@]}" "${rank0_env[@]}" TILEXR_CCU_PROBE_RANK=0 "${probe_bin}" > "${rank0_log}" 2>&1 & +rank0_pid=$! +sleep "${TILEXR_CCU_SMOKE_RANK1_DELAY:-1}" +timeout "${timeout_s}s" env "${common_env[@]}" "${rank1_env[@]}" TILEXR_CCU_PROBE_RANK=1 "${probe_bin}" > "${rank1_log}" 2>&1 & +rank1_pid=$! + +rank0_status=0 +rank1_status=0 +wait "${rank0_pid}" || rank0_status=$? +wait "${rank1_pid}" || rank1_status=$? + +cat "${rank0_log}" +cat "${rank1_log}" + +echo "tilexr_ccu_direct_smoke_runner summary rank0Status=${rank0_status} rank1Status=${rank1_status} rank0Log=${rank0_log} rank1Log=${rank1_log}" + +if [ "${rank0_status}" -ne 0 ] || [ "${rank1_status}" -ne 0 ]; then + echo "ERROR: direct CCU smoke rank process failed rank0=${rank0_status} rank1=${rank1_status}" >&2 + echo "rank0 log: ${rank0_log}" >&2 + echo "rank1 log: ${rank1_log}" >&2 + exit 4 +fi + +for log in "${rank0_log}" "${rank1_log}"; do + if ! grep -q "tilexr_ccu_direct_smoke prepare ret=0" "${log}"; then + echo "ERROR: direct CCU prepare did not return success in ${log}" >&2 + exit 5 + fi + if ! grep -q "installSucceeded=1" "${log}"; then + echo "ERROR: direct CCU prepare did not complete install attempt in ${log}" >&2 + exit 6 + fi +done + +if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" = "1" ]; then + for log in "${rank0_log}" "${rank1_log}"; do + if ! grep -q "submitReady=1" "${log}"; then + echo "ERROR: direct CCU submit requested but prepare did not reach submitReady=1 in ${log}" >&2 + exit 6 + fi + done + for log in "${rank0_log}" "${rank1_log}"; do + if ! grep -q "tilexr_ccu_direct_smoke submit ret=0" "${log}"; then + echo "ERROR: direct CCU submit did not return success in ${log}" >&2 + exit 7 + fi + if ! grep -q "tilexr_ccu_direct_smoke submitTiming" "${log}"; then + echo "ERROR: direct CCU submit timing was not reported in ${log}" >&2 + exit 8 + fi + done +fi + +if [ "${TILEXR_CCU_DIRECT_SMOKE_EXPECT_BARRIER_WAIT:-0}" = "1" ]; then + if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" != "1" ]; then + echo "ERROR: direct CCU barrier wait check requires TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1" >&2 + exit 9 + fi + delay_rank="${TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK:-0}" + min_sync_ms="${TILEXR_CCU_DIRECT_SMOKE_MIN_SYNC_MS:-100}" + if [ "${delay_rank}" = "0" ]; then + wait_log="${rank1_log}" + else + wait_log="${rank0_log}" + fi + wait_sync_ms="$( + awk ' + /tilexr_ccu_direct_smoke submitTiming/ { + for (i = 1; i <= NF; ++i) { + if ($i ~ /^syncMs=/) { + split($i, parts, "="); + print parts[2]; + } + } + } + ' "${wait_log}" | tail -n 1 + )" + if [ -z "${wait_sync_ms}" ]; then + echo "ERROR: barrier wait timing missing from ${wait_log}" >&2 + exit 9 + fi + if [ "${wait_sync_ms}" -lt "${min_sync_ms}" ]; then + echo "ERROR: direct CCU barrier wait was too short syncMs=${wait_sync_ms} minSyncMs=${min_sync_ms} log=${wait_log}" >&2 + exit 10 + fi +fi + +if [ "${TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY:-0}" = "1" ]; then + if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" != "1" ]; then + echo "ERROR: direct CCU P2P CCU-copy check requires TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1" >&2 + exit 11 + fi + p2p_passed_count=0 + for log in "${rank0_log}" "${rank1_log}"; do + if ! grep -q "tilexr_ccu_direct_smoke p2pCcuCopy" "${log}"; then + echo "ERROR: direct CCU P2P CCU-copy result missing in ${log}" >&2 + exit 12 + fi + if grep -q "tilexr_ccu_direct_smoke p2pCcuCopy .*passed=1" "${log}"; then + p2p_passed_count=$((p2p_passed_count + 1)) + continue + fi + if grep -q "tilexr_ccu_direct_smoke p2pCcuCopy skipped" "${log}"; then + continue + fi + if ! grep -q "tilexr_ccu_direct_smoke p2pCcuCopy .*passed=1" "${log}"; then + echo "ERROR: direct CCU P2P CCU-copy check failed in ${log}" >&2 + exit 13 + fi + done + if [ "${p2p_passed_count}" -lt 1 ]; then + echo "ERROR: direct CCU P2P CCU-copy produced no passing receiver result" >&2 + exit 13 + fi +fi + +echo "tilexr_ccu_direct_smoke_runner success workDir=${work_dir}" diff --git a/tests/ccu/test_tilexr_ccu_backend_boundary.py b/tests/ccu/test_tilexr_ccu_backend_boundary.py new file mode 100644 index 00000000..1985c58b --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_backend_boundary.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +COMM_HEADER = REPO_ROOT / "src" / "comm" / "tilexr_comm.h" +BACKEND_HEADER = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_backend.h" +BACKEND_SOURCE = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_backend.cpp" +RUNTIME_SESSION_HEADER = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_runtime_session.h" +RUNTIME_SESSION_SOURCE = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_runtime_session.cpp" +PLANNER_HEADER = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_collective_planner.h" +PLANNER_SOURCE = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_collective_planner.cpp" +EXECUTOR_HEADER = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_executor.h" +EXECUTOR_SOURCE = REPO_ROOT / "src" / "comm" / "ccu" / "tilexr_ccu_executor.cpp" + + +class TileXRCcuBackendBoundaryTest(unittest.TestCase): + def test_backend_files_exist(self): + self.assertTrue(BACKEND_HEADER.exists()) + self.assertTrue(BACKEND_SOURCE.exists()) + + def test_backend_internals_are_split(self): + for path in [ + RUNTIME_SESSION_HEADER, + RUNTIME_SESSION_SOURCE, + PLANNER_HEADER, + PLANNER_SOURCE, + EXECUTOR_HEADER, + EXECUTOR_SOURCE, + ]: + with self.subTest(path=path.name): + self.assertTrue(path.exists()) + + def test_tilexr_comm_header_owns_only_opaque_backend(self): + header = COMM_HEADER.read_text(encoding="utf-8") + self.assertIn("class TileXRCcuBackend;", header) + self.assertIn("std::unique_ptr ccuBackend_", header) + for needle in [ + "tilexr_ccu_direct_orchestrator.h", + "tilexr_ccu_direct_runtime.h", + "tilexr_ccu_lower_layer_plan_builder.h", + "TileXRCcuDirectRuntime", + "directCcuBasicInfo_", + "directCcuLowerLayerPlan_", + "directCcuVerifiedEndpointRoutes_", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, header) + + def test_backend_header_exposes_facade_not_public_c_api(self): + header = BACKEND_HEADER.read_text(encoding="utf-8") + self.assertIn("class TileXRCcuBackend", header) + self.assertIn("struct TileXRCcuBackendOptions", header) + self.assertIn("TileXRSockExchange *exchange", header) + self.assertIn("PrepareCollective", header) + self.assertIn("SubmitCollective", header) + for needle in [ + "TileXRDirectCcuPreparedTasksPtr", + "TileXRCommPrepareDirectCcu", + "TileXRDirectCcuSubmitPrepared", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, header) + + def test_split_sources_own_restored_direct_ccu_runtime_glue(self): + source = BACKEND_SOURCE.read_text(encoding="utf-8") + runtime_header = RUNTIME_SESSION_HEADER.read_text(encoding="utf-8") + runtime = RUNTIME_SESSION_SOURCE.read_text(encoding="utf-8") + planner = PLANNER_SOURCE.read_text(encoding="utf-8") + executor = EXECUTOR_SOURCE.read_text(encoding="utf-8") + self.assertIn("#include \"ccu/tilexr_ccu_runtime_session.h\"", source) + self.assertIn("#include \"ccu/tilexr_ccu_collective_planner.h\"", source) + self.assertIn("#include \"ccu/tilexr_ccu_executor.h\"", source) + self.assertNotIn("#include \"ccu/tilexr_ccu_direct_runtime.h\"", source) + self.assertNotIn("#include \"ccu/tilexr_ccu_repository.h\"", source) + self.assertNotIn("TileXRCcuDirectRuntime", source) + + for needle in [ + "#include \"ccu/tilexr_ccu_direct_runtime.h\"", + "TileXRCcuDirectRuntime", + "DirectCcuThreadAllGather", + "g_directCcuAllGatherStates", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, runtime_header + "\n" + runtime) + + for needle in [ + "#include \"ccu/tilexr_ccu_repository.h\"", + "PrepareDirectCcuInstallAttempt", + "PrepareDirectCcuLowerLayerPlanCallback", + "TileXRCcuRunDirectInstallAttempt", + "TileXRCcuMakeRepositoryDeviceMemoryOps", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, planner) + + planner_header = PLANNER_HEADER.read_text(encoding="utf-8") + executor_header = EXECUTOR_HEADER.read_text(encoding="utf-8") + self.assertRegex( + planner_header, + r"(?s)#ifdef TILEXR_CCU_TESTING.*PrepareDirectCcuMemoryCopyInstallAttempt.*#endif", + ) + self.assertRegex( + planner, + r"(?s)#ifdef TILEXR_CCU_TESTING.*PrepareDirectCcuMemoryCopyInstallAttempt.*#endif", + ) + self.assertRegex( + executor_header, + r"(?s)#ifdef TILEXR_CCU_TESTING.*ReadDirectCcuInstructionsForDebug.*#endif", + ) + self.assertRegex( + executor, + r"(?s)#ifdef TILEXR_CCU_TESTING.*ReadDirectCcuInstructionsForDebug.*#endif", + ) + for fake_ready in [ + "options_ = options;\n initialized_ = true;\n return TILEXR_SUCCESS;", + "plan->ready = true;\n return TILEXR_SUCCESS;", + "return plan.ready ? TILEXR_SUCCESS", + ]: + with self.subTest(fake_ready=fake_ready): + self.assertNotIn(fake_ready, source + "\n" + runtime + "\n" + planner + "\n" + executor) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/ccu/test_tilexr_ccu_basic_info_probe.py b/tests/ccu/test_tilexr_ccu_basic_info_probe.py new file mode 100644 index 00000000..654efc78 --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_basic_info_probe.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import os +import shutil +import subprocess +import tempfile +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +PROBE_SOURCE = REPO_ROOT / "tests" / "ccu" / "ccu_tilexr_basic_info_probe.cpp" +COMM_DIR = REPO_ROOT / "src" / "comm" +INCLUDE_DIR = REPO_ROOT / "src" / "include" +CCU_DRIVER_SOURCE = COMM_DIR / "ccu" / "tilexr_ccu_driver_adapter.cpp" +CCU_DIRECT_RUNTIME_SOURCE = COMM_DIR / "ccu" / "tilexr_ccu_direct_runtime.cpp" +CCU_HCCP_LOADER_SOURCE = COMM_DIR / "ccu" / "tilexr_ccu_hccp_loader.cpp" +CCU_RA_PROVIDER_SOURCE = COMM_DIR / "ccu" / "tilexr_ccu_ra_custom_channel_provider.cpp" +CCU_SPECS_SOURCE = COMM_DIR / "ccu" / "tilexr_ccu_specs.cpp" + + +class TileXRCcuBasicInfoProbeTest(unittest.TestCase): + def compile_probe(self): + compiler = shutil.which("g++") or shutil.which("clang++") or shutil.which("c++") + if compiler is None: + self.skipTest("no local C++ compiler found") + temp_dir = tempfile.TemporaryDirectory() + temp_path = Path(temp_dir.name) + probe_bin = temp_path / "ccu_tilexr_basic_info_probe" + subprocess.run( + [ + compiler, + "-std=c++14", + "-I", + str(INCLUDE_DIR), + "-I", + str(COMM_DIR), + str(PROBE_SOURCE), + str(CCU_DIRECT_RUNTIME_SOURCE), + str(CCU_DRIVER_SOURCE), + str(CCU_HCCP_LOADER_SOURCE), + str(CCU_RA_PROVIDER_SOURCE), + str(CCU_SPECS_SOURCE), + "-ldl", + "-pthread", + "-o", + str(probe_bin), + ], + cwd=REPO_ROOT, + check=True, + text=True, + capture_output=True, + ) + return temp_dir, probe_bin + + def test_probe_compiles_against_tilexr_owned_ccu_ra_chain(self): + temp_dir, _ = self.compile_probe() + temp_dir.cleanup() + + def test_probe_uses_tilexr_ra_provider_not_hcomm_runtime(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + for needle in [ + "TileXRCcuDirectRuntime", + "TileXRCcuDirectRuntimeOptions", + "TileXRCcuDriverAdapter", + "TileXRCcuDecodeBasicInfo", + "deviceLogicId", + "runtime.QueryBasicInfo", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, source) + + for needle in [ + "#include ", + "#include \"hccl.h\"", + "pkg_inc/hcomm", + "pkg_inc/hccl", + "include/hccl", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + "HcclChannelAcquire", + "HcclGetChannelForCcu", + "CcuResBatchAllocator", + "CcuResRepository", + "CcuDeviceManager", + "CcuKernelMgr", + "CtxMgrImp", + "GeneTaskParam", + "GetMissionKey", + "SetMissionId", + "SetMissionKey", + "SetInstrId", + "SetCcuInstrInfo", + "LoadInstruction", + "AllocIns", + "AllocCke", + "AllocXn", +] + + +def cann_paths(): + ascend_home = os.environ.get("ASCEND_HOME_PATH") or os.environ.get("ASCEND_HOME") + if not ascend_home: + return None + + arch = os.environ.get("ARCH") + if not arch: + arch = "aarch64" if platform.machine() in ("aarch64", "arm64") else "x86_64" + + cann_root = Path(ascend_home) / f"{arch}-linux" + include_dirs = [ + cann_root / "pkg_inc", + cann_root / "pkg_inc" / "runtime", + cann_root / "include", + ] + if not any((include_dir / "acl" / "acl.h").exists() for include_dir in include_dirs): + return None + + lib_dir = cann_root / "lib64" + if not (lib_dir / "libascendcl.so").exists(): + return None + driver_root = Path(os.environ.get("ASCEND_DRIVER_PATH", "/usr/local/Ascend/driver")) + driver_lib_dir = driver_root / "lib64" / "driver" + return include_dirs, lib_dir, driver_lib_dir + + +def find_tile_comm(): + env_path = os.environ.get("TILEXR_TILE_COMM_LIB") + candidates = [] + if env_path: + candidates.append(Path(env_path)) + candidates.extend( + [ + REPO_ROOT / "build" / "src" / "comm" / "libtile-comm.so", + REPO_ROOT / "install" / "lib64" / "libtile-comm.so", + REPO_ROOT / "install" / "lib" / "libtile-comm.so", + REPO_ROOT / "install_direct_ccu_guard" / "lib64" / "libtile-comm.so", + ] + ) + for candidate in candidates: + if candidate.exists(): + return candidate + return None + + +class TileXRCcuDirectSmokeProbeTest(unittest.TestCase): + def compile_probe(self): + compiler = shutil.which("g++") or shutil.which("clang++") or shutil.which("c++") + if compiler is None: + self.skipTest("no local C++ compiler found") + cann_config = cann_paths() + if cann_config is None: + self.skipTest("CANN ACL headers/libs are not configured for direct CCU smoke probe") + tile_comm = find_tile_comm() + if tile_comm is None: + self.skipTest("libtile-comm.so is not built; build tile-comm before compiling direct smoke probe") + + include_dirs, cann_lib_dir, driver_lib_dir = cann_config + temp_dir = tempfile.TemporaryDirectory() + temp_path = Path(temp_dir.name) + probe_bin = temp_path / "ccu_tilexr_direct_smoke_probe" + compile_cmd = [ + compiler, + "-std=c++14", + "-DTILEXR_CCU_TESTING=1", + "-I", + str(INCLUDE_DIR), + "-I", + str(COMM_DIR), + ] + for include_dir in include_dirs: + if include_dir.exists(): + compile_cmd.extend(["-I", str(include_dir)]) + compile_cmd.extend( + [ + str(PROBE_SOURCE), + "-L", + str(tile_comm.parent), + "-L", + str(cann_lib_dir), + "-L", + str(driver_lib_dir), + f"-Wl,-rpath-link,{tile_comm.parent}", + f"-Wl,-rpath-link,{cann_lib_dir}", + f"-Wl,-rpath-link,{driver_lib_dir}", + "-ltile-comm", + "-lascendcl", + "-lruntime", + "-ldl", + "-pthread", + "-o", + str(probe_bin), + ] + ) + subprocess.run( + compile_cmd, + cwd=REPO_ROOT, + check=True, + text=True, + capture_output=True, + ) + return temp_dir, probe_bin, tile_comm.parent, cann_lib_dir, driver_lib_dir + + def test_source_exists_and_defines_default_safe_env_guards(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_ENABLE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_AFTER_RUN", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_TRACE_LIFECYCLE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_SUBMIT", source) + self.assertIn("TILEXR_CCU_PROBE_RANK", source) + self.assertIn("TILEXR_CCU_PROBE_RANK_SIZE", source) + self.assertIn("TILEXR_CCU_PROBE_DEVICE", source) + self.assertIn("TILEXR_CCU_PROBE_COMM_DOMAIN", source) + self.assertIn("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START", source) + self.assertIn("TILEXR_CCU_PROBE_SQE_ARG_COUNT", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES", source) + self.assertIn("TILEXR_CCU_DIRECT_BARRIER_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE", source) + self.assertIn("TileXRCcuRepositoryMemoryAllocMode::RtHbm", source) + self.assertIn('text == "rt_hbm"', source) + self.assertIn("TILEXR_CCU_DIRECT_INSTALL_ORDER", source) + self.assertIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID", source) + self.assertIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_RAW_TOKEN_ID", source) + self.assertIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_VALUE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE", source) + self.assertIn("InitCommForDirectCcuSmoke", source) + self.assertIn("RunThreadModeSmoke", source) + self.assertIn("DirectCcuSmokeContext", source) + self.assertIn("TileXRCcuRuntimeSession", source) + self.assertIn("TileXRSockExchange", source) + self.assertIn("ShouldFastExitAfterPrepareFailure", source) + self.assertIn("ShouldFastExitAfterRun", source) + self.assertIn("TraceLifecycle", source) + self.assertIn("RepositoryInstallWindowFromEnv", source) + self.assertIn("RepositoryInstallDataLenModeFromEnv", source) + self.assertIn("RepositoryMemoryAllocModeFromEnv", source) + self.assertIn("InstallOrderFromEnv", source) + self.assertIn("TileXRCommInitAll", source) + self.assertIn("DefaultSyncInstructionCount", source) + self.assertIn('std::string(value) == "sync_cke"', source) + self.assertIn('std::string(value) == "sync_cke_set_wait"', source) + self.assertIn('std::string(value) == "sync_cke_post_only"', source) + self.assertIn('std::string(value) == "local_cke"', source) + self.assertIn('std::string(value) == "local_cke_post_only"', source) + self.assertIn('std::string(value) == "sync_xn_post_only"', source) + self.assertIn('std::string(value) == "sync_xn_load_post_only"', source) + self.assertIn("PrepareDirectCcuInstallAttempt", source) + self.assertIn("PrepareDirectCcuMemoryCopyInstallAttempt", source) + self.assertIn("ReadDirectCcuInstructionsForDebug", source) + self.assertIn("TileXRDirectCcuSubmitPrepared", source) + self.assertIn("TileXRDirectCcuDestroyPrepared", source) + self.assertIn("tilexr_ccu_direct_smoke config", source) + self.assertIn("barrierMode=", source) + self.assertIn("repositoryInstallWindow=", source) + self.assertIn("repositoryInstallDataLenMode=", source) + self.assertIn("repositoryMemoryAllocMode=", source) + self.assertIn("installOrder=", source) + self.assertIn("resourceWindowTokenId=", source) + self.assertIn("resourceWindowRawTokenId=", source) + self.assertIn("resourceWindowTokenValue=", source) + self.assertIn("tilexr_ccu_direct_smoke preparedTasks", source) + self.assertIn("tilexr_ccu_direct_smoke submitTiming", source) + self.assertIn("tilexr_ccu_direct_smoke p2pCcuCopy", source) + self.assertIn("aclrtMemcpy", source) + self.assertIn("ACL_MEMCPY_HOST_TO_DEVICE", source) + self.assertIn("ACL_MEMCPY_DEVICE_TO_HOST", source) + self.assertIn("passed=", source) + self.assertIn("syncMs=", source) + self.assertIn("std::this_thread::sleep_for", source) + self.assertIn("std::vector", source) + self.assertIn("std::vector", source) + + def test_p2p_ccu_copy_mode_prepares_memory_copy_task(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + self.assertIn("kP2pCcuCopyEnv", source) + self.assertIn("RunP2pCcuCopy", source) + self.assertIn("PrepareDirectCcuMemoryCopyInstallAttempt", source) + self.assertIn("TileXRCcuMemoryCopyDirection::RemoteToLocal", source) + self.assertIn("ACL_MEMCPY_HOST_TO_DEVICE", source) + self.assertIn("ACL_MEMCPY_DEVICE_TO_HOST", source) + self.assertIn("p2pCcuCopy", source) + + def test_thread_mode_path_uses_single_process_init_and_never_rank_ipc_init(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + thread_mode_pos = source.index("RunThreadModeSmoke") + thread_mode_body = source[thread_mode_pos: source.index("int main()")] + prepared_body = source[source.index("RunPreparedSmokeForRank"): thread_mode_pos] + self.assertIn("TileXRCommInitAll", thread_mode_body) + self.assertIn("RunPreparedSmokeForRank", thread_mode_body) + self.assertIn("PrepareDirectCcuInstallAttempt", prepared_body) + self.assertIn("TileXRDirectCcuSubmitPrepared", prepared_body) + self.assertNotIn("TileXRCommInitRankWithDomain", thread_mode_body) + self.assertNotIn("TILEXR_COMM_ID", thread_mode_body) + + def test_thread_mode_worker_sets_device_before_direct_ccu_submit(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + thread_mode_body = source[source.index("int RunThreadModeSmoke"): source.index("int main()")] + + worker_body = thread_mode_body[ + thread_mode_body.index("rankThreads.emplace_back"): + thread_mode_body.index("for (auto& rankThread", thread_mode_body.index("rankThreads.emplace_back")) + ] + self.assertIn("aclrtSetDevice(devices[rank])", worker_body) + self.assertLess( + worker_body.index("aclrtSetDevice(devices[rank])"), + worker_body.index("RunPreparedSmokeForRank"), + ) + + def test_process_mode_can_opt_into_direct_ccu_only_init_to_bypass_peer_ipc(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + init_helper_body = source[ + source.index("int InitCommForDirectCcuSmoke"): + source.index("TileXRDirectCcuPrepareOptions MakePrepareOptions") + ] + main_source = source[source.index("int main()"):] + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT", source) + self.assertIn("TileXRSockExchange", init_helper_body) + self.assertIn("TileXRCcuBackendOptions", init_helper_body) + self.assertIn("context->session.Init(options)", init_helper_body) + self.assertIn("EnvFlag(kDirectCcuOnlyInitEnv)", init_helper_body) + self.assertIn("InitCommForDirectCcuSmoke", main_source) + + def test_process_mode_fast_exit_skips_comm_destroy_after_prepare_failure(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + main_source = source[source.index("int main()"):] + + final_ret_pos = main_source.index("int finalRet = RunPreparedSmokeForRank") + fast_exit_pos = main_source.index("ShouldFastExitAfterPrepareFailure(finalRet)") + shutdown_pos = main_source.index("context.session.Shutdown()", final_ret_pos) + reset_pos = main_source.index("aclrtResetDevice(device)", final_ret_pos) + finalize_pos = main_source.index("aclFinalize()", final_ret_pos) + + self.assertLess(final_ret_pos, fast_exit_pos) + self.assertLess(fast_exit_pos, shutdown_pos) + self.assertLess(fast_exit_pos, reset_pos) + self.assertLess(fast_exit_pos, finalize_pos) + self.assertIn("std::fflush(stdout)", main_source) + self.assertIn("std::fflush(stderr)", main_source) + self.assertIn("std::_Exit(finalRet)", main_source) + self.assertIn("tilexr_ccu_direct_smoke fastExitOnPrepareFailure=1", source) + + def test_fast_exit_reason_distinguishes_runtime_failures_from_prepare_failure(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + main_source = source[source.index("int main()"):] + + self.assertIn("FastExitReasonForReturnCode", source) + self.assertIn("direct CCU collective completion timed out; skipping cleanup", source) + self.assertIn("direct CCU P2P CCU-copy check failed; skipping cleanup", source) + self.assertIn("FastExitReasonForReturnCode(finalRet)", main_source) + self.assertNotIn( + 'reason="prepare failed; skipping cleanup to preserve diagnostic status"', + main_source, + ) + + def test_process_mode_can_fast_exit_after_run_to_isolate_cleanup_hangs(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + main_source = source[source.index("int main()"):] + + final_ret_pos = main_source.index("int finalRet = RunPreparedSmokeForRank") + fast_exit_pos = main_source.index("ShouldFastExitAfterRun()") + shutdown_pos = main_source.index("context.session.Shutdown()", final_ret_pos) + + self.assertLess(final_ret_pos, fast_exit_pos) + self.assertLess(fast_exit_pos, shutdown_pos) + self.assertIn("tilexr_ccu_direct_smoke fastExitAfterRun=1", source) + self.assertIn("TraceLifecycle(\"before TileXRDirectCcuDestroyPrepared\")", source) + self.assertIn("TraceLifecycle(\"after TileXRDirectCcuDestroyPrepared\")", source) + self.assertIn("TraceLifecycle(\"before aclrtSynchronizeStream\")", source) + self.assertIn("TraceLifecycle(\"after aclrtSynchronizeStream\")", source) + + def test_submit_task_selector_can_isolate_prepared_task_hangs(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + prepared_body = source[ + source.index("int RunPreparedSmokeForRank"): + source.index("int RunThreadModeSmoke") + ] + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_SUBMIT_TASK_SELECTOR", source) + self.assertIn("SubmitPreparedWithSelector", source) + self.assertIn("TileXRDirectCcuGetPreparedTask", source) + self.assertIn("TileXRDirectCcuSubmitPreparedTask", source) + self.assertIn('selector == "first"', source) + self.assertIn('selector == "second"', source) + self.assertIn("submitTaskSelector=", source) + self.assertIn("TileXRDirectCcuSubmitPrepared(prepared, stream, &submitReport)", prepared_body) + self.assertIn("SubmitPreparedWithSelector(prepared, installReport.submitTaskCount, stream", prepared_body) + + def test_process_mode_submit_uses_collective_ready_gate(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + runner = (REPO_ROOT / "tests" / "ccu" / "run_tilexr_ccu_direct_smoke.sh").read_text(encoding="utf-8") + prepared_body = source[ + source.index("int RunPreparedSmokeForRank"): + source.index("int RunThreadModeSmoke") + ] + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_READY_DIR", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_READY_TIMEOUT_MS", source) + self.assertIn("WaitForCollectiveSubmitReadiness", source) + self.assertIn("WriteSubmitReadiness", source) + self.assertIn("collectiveSubmitReady", prepared_body) + self.assertIn("collective submitReady gate did not pass", source) + self.assertLess( + prepared_body.index("WaitForCollectiveSubmitReadiness"), + prepared_body.index("aclrtCreateStream"), + ) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_READY_DIR=${ready_dir}", runner) + self.assertIn("rm -rf \"${ready_dir}\"", runner) + + def test_process_mode_submit_waits_for_all_ranks_before_cleanup(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + runner = (REPO_ROOT / "tests" / "ccu" / "run_tilexr_ccu_direct_smoke.sh").read_text(encoding="utf-8") + prepared_body = source[ + source.index("int RunPreparedSmokeForRank"): + source.index("int RunThreadModeSmoke") + ] + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DONE_DIR", source) + self.assertIn("WaitForCollectiveSubmitDone", source) + self.assertIn("WaitForCollectiveSubmitDone(rank, rankSize, finalRet)", prepared_body) + self.assertIn("collectiveSubmitDone", source) + self.assertLess( + prepared_body.index("aclrtSynchronizeStream"), + prepared_body.index("WaitForCollectiveSubmitDone"), + ) + self.assertLess( + prepared_body.index("WaitForCollectiveSubmitDone"), + prepared_body.index("TileXRDirectCcuDestroyPrepared"), + ) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DONE_DIR=${done_dir}", runner) + self.assertIn("rm -rf \"${ready_dir}\" \"${done_dir}\"", runner) + + def test_probe_wires_gsa_and_split_cke_env_into_prepare_options_and_config_trace(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + for needle in [ + "TILEXR_CCU_PROBE_GSA_START", + "TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START", + "TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT", + "TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START", + "TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT", + "options.localWaitCkeStartId", + "options.localWaitCkeCount", + "options.remoteNotifyCkeStartId", + "options.remoteNotifyCkeCount", + "options.repositoryInstallOptions.window", + "options.repositoryInstallOptions.dataLenMode", + "options.repositoryMemoryAllocMode", + "options.installOrder", + "options.sqeArgCount", + "options.missionInstructionStartId", + "options.gsaStartId", + "sqeArgCount=", + "gsaStartId=", + "localWaitCkeStartId=", + "localWaitCkeCount=", + "remoteNotifyCkeStartId=", + "remoteNotifyCkeCount=", + "repositoryInstallWindow=", + "repositoryInstallDataLenMode=", + "repositoryMemoryAllocMode=", + "installOrder=", + "missionInstructionStartId=", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, source) + + def test_probe_prepared_task_trace_prints_full_runtime_args(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + prepared_body = source[ + source.index("void PrintPreparedTasks"): + source.index("int RunPreparedSmokeForRank") + ] + + self.assertIn("TILEXR_DIRECT_CCU_SQE_ARGS_LEN", prepared_body) + self.assertIn("arg < TILEXR_DIRECT_CCU_SQE_ARGS_LEN", prepared_body) + self.assertIn('<< ".arg" << arg << "=0x"', prepared_body) + self.assertIn("task.args[arg]", prepared_body) + self.assertNotIn(".arg0=0x", prepared_body) + + def test_probe_defaults_to_lower_layer_first_install_order(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + install_order_body = source[ + source.index("TileXR::TileXRCcuInstallOrder InstallOrderFromEnv()"): + source.index("uint32_t DefaultSyncInstructionCount") + ] + + self.assertIn("TileXRCcuInstallOrder::InstallLowerLayerFirst", install_order_body) + self.assertIn("repository_first", install_order_body) + self.assertIn("TileXRCcuInstallOrder::RepositoryFirst", install_order_body) + self.assertLess( + install_order_body.index("TileXRCcuInstallOrder::InstallLowerLayerFirst"), + install_order_body.index("TileXRCcuInstallOrder::RepositoryFirst"), + ) + + def test_probe_default_sync_instruction_count_includes_hcomm_style_task1_prelude(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + default_body = source[ + source.index("uint32_t DefaultSyncInstructionCount"): + source.index("const char* FirstEnv") + ] + + self.assertIn("kHcommStyleTask1PreludeInstructionCount", source) + self.assertIn( + "return kHcommStyleTask1PreludeInstructionCount + syncResourceCount;", + default_body, + ) + self.assertIn( + "return kHcommStyleTask1PreludeInstructionCount + syncResourceCount * 2U;", + default_body, + ) + + def test_thread_mode_rank_specific_resource_env_overrides_common_prepare_options(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + prepare_options_body = source[ + source.index("TileXRDirectCcuPrepareOptions MakePrepareOptions"): + source.index("void PrintInstallReport") + ] + + self.assertIn("RankEnvInt", prepare_options_body) + for suffix in [ + "XN_START", + "LOCAL_WAIT_CKE_START", + "LOCAL_WAIT_CKE_COUNT", + "REMOTE_NOTIFY_CKE_START", + "REMOTE_NOTIFY_CKE_COUNT", + ]: + with self.subTest(suffix=suffix): + self.assertIn(f"TILEXR_CCU_PROBE_RANK\", rank, \"_{suffix}", source) + self.assertIn( + 'RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_XN_START", "TILEXR_CCU_PROBE_XN_START", 1)', + prepare_options_body, + ) + self.assertIn( + 'RankEnvInt("TILEXR_CCU_PROBE_RANK", rank, "_LOCAL_WAIT_CKE_START", kLocalWaitCkeStartEnv, 0)', + prepare_options_body, + ) + + def test_default_skip_happens_before_acl_comm_prepare_or_submit(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + main_source = source[source.index("int main()"):] + + guard_pos = main_source.index("if (!EnvFlag(kEnableEnv))") + for needle in [ + "aclInit(", + "InitCommForDirectCcuSmoke", + "RunPreparedSmokeForRank", + ]: + with self.subTest(needle=needle): + self.assertLess(guard_pos, main_source.index(needle)) + + def test_probe_keeps_hcomm_hccl_and_runtime_launch_out_of_source(self): + source = PROBE_SOURCE.read_text(encoding="utf-8") + + for needle in PRIVATE_CCU_NEEDLES: + with self.subTest(needle=needle): + self.assertNotIn(needle, source) + self.assertNotIn("runtime/kernel.h", source) + self.assertNotIn("rtCCULaunch", source) + + def test_probe_compiles_and_default_run_skips_without_touching_hardware(self): + temp_dir, probe_bin, tile_comm_dir, cann_lib_dir, driver_lib_dir = self.compile_probe() + try: + env = os.environ.copy() + env.pop("TILEXR_CCU_DIRECT_SMOKE_ENABLE", None) + env["LD_LIBRARY_PATH"] = ( + str(tile_comm_dir) + + os.pathsep + + str(cann_lib_dir) + + os.pathsep + + str(driver_lib_dir) + + os.pathsep + + env.get("LD_LIBRARY_PATH", "") + ) + result = subprocess.run( + [str(probe_bin)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + finally: + temp_dir.cleanup() + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_smoke skipped", result.stdout) + self.assertNotIn("prepare ret=", result.stdout) + self.assertNotIn("submit ret=", result.stdout) + + def test_optional_probe_runtime_when_enabled(self): + if os.environ.get("TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE") != "1": + self.skipTest("set TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE=1 to run direct CCU smoke on hardware") + rank_size = ( + os.environ.get("TILEXR_CCU_PROBE_RANK_SIZE") + or os.environ.get("PMI_SIZE") + or os.environ.get("OMPI_COMM_WORLD_SIZE") + or os.environ.get("MV2_COMM_WORLD_SIZE") + or os.environ.get("RANK_SIZE") + ) + if rank_size is None or int(rank_size) <= 1: + self.skipTest("direct CCU prepare smoke requires a real multi-rank TileXRComm launch") + temp_dir, probe_bin, tile_comm_dir, cann_lib_dir, driver_lib_dir = self.compile_probe() + try: + env = os.environ.copy() + env["TILEXR_CCU_DIRECT_SMOKE_ENABLE"] = "1" + env["LD_LIBRARY_PATH"] = ( + str(tile_comm_dir) + + os.pathsep + + str(cann_lib_dir) + + os.pathsep + + str(driver_lib_dir) + + os.pathsep + + env.get("LD_LIBRARY_PATH", "") + ) + result = subprocess.run( + [str(probe_bin)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + finally: + temp_dir.cleanup() + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_smoke prepare ret=0", result.stdout) + self.assertIn("submitReady=", result.stdout) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/ccu/test_tilexr_ccu_direct_smoke_runner.py b/tests/ccu/test_tilexr_ccu_direct_smoke_runner.py new file mode 100644 index 00000000..85c5be50 --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_direct_smoke_runner.py @@ -0,0 +1,1422 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import os +import subprocess +import tempfile +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +RUNNER = REPO_ROOT / "tests" / "ccu" / "run_tilexr_ccu_direct_smoke.sh" +EVENING_RUNNER = REPO_ROOT / "tests" / "ccu" / "run_tilexr_ccu_direct_evening_smoke.sh" +BUSY_GUARD = REPO_ROOT / "tests" / "ccu" / "ccu_npu_smi_busy_guard.py" + + +class TileXRCcuDirectSmokeRunnerTest(unittest.TestCase): + def test_runner_is_default_safe_and_documents_hardware_gate(self): + source = RUNNER.read_text(encoding="utf-8") + + self.assertIn("TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_ENABLE=1", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=1", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_SUBMIT", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DELAY_RANK", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_PRE_SUBMIT_DELAY_MS", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_EXPECT_BARRIER_WAIT", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_MIN_SYNC_MS", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_BYTES", source) + self.assertIn("TILEXR_CCU_DIRECT_BARRIER_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_INSTALL_ORDER", source) + self.assertIn("TILEXR_CCU_DIRECT_INSTALL_DIE_ID", source) + self.assertIn("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START", source) + self.assertIn("TILEXR_CCU_PROBE_SQE_ARG_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_MISSION_START", source) + self.assertIn("TILEXR_CCU_PROBE_INSTRUCTION_START", source) + self.assertIn("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_BINDINGS_PER_RESOURCE", source) + self.assertIn("TILEXR_CCU_PROBE_CHANNEL_START", source) + self.assertIn("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_START", source) + self.assertIn("TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_START", source) + self.assertIn("TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_RANK0_XN_START", source) + self.assertIn("TILEXR_CCU_PROBE_RANK1_XN_START", source) + self.assertIn("TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START", source) + self.assertIn("TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START", source) + for suffix in [ + "EID", + "TPN", + "DOORBELL_VA", + "DOORBELL_TOKEN_ID", + "DOORBELL_TOKEN_VALUE", + "SQ_DEPTH", + ]: + with self.subTest(endpoint_suffix=suffix): + self.assertIn(f" {suffix}", source) + self.assertIn('endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}"', source) + self.assertIn('rank0_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK0"', source) + self.assertIn('rank1_endpoint_var="TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}_RANK1"', source) + self.assertIn('rank0_env+=("TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank0_endpoint_value}")', source) + self.assertIn('rank1_env+=("TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_${endpoint_field}=${rank1_endpoint_value}")', source) + self.assertIn("rank0_env", source) + self.assertIn("rank1_env", source) + self.assertIn("TILEXR_COMM_ID", source) + self.assertIn("TILEXR_CCU_PROBE_RANK_SIZE=2", source) + self.assertIn("TILEXR_CCU_PROBE_RANK=0", source) + self.assertIn("TILEXR_CCU_PROBE_RANK=1", source) + self.assertIn('if [ "${TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE:-0}" = "1" ]', source) + self.assertIn('"${probe_bin}" > "${thread_log}" 2>&1', source) + self.assertIn("ccu_thread.log", source) + self.assertIn("ccu_rank0.log", source) + self.assertIn("ccu_rank1.log", source) + self.assertIn("installSucceeded=1", source) + self.assertIn("submitReady=1", source) + self.assertLess(source.index("installSucceeded=1"), source.index("submitReady=1")) + self.assertIn("${repo_root}/install/lib64/libtile-comm.so", source) + self.assertIn( + 'timeout "${timeout_s}s" env "${common_env[@]}" "${rank0_env[@]}" TILEXR_CCU_PROBE_RANK=0', + source, + ) + self.assertIn( + 'timeout "${timeout_s}s" env "${common_env[@]}" "${rank1_env[@]}" TILEXR_CCU_PROBE_RANK=1', + source, + ) + self.assertNotIn('bash -c "wait', source) + self.assertIn("npu-smi rc=", source) + self.assertIn("TILEXR_CCU_SMOKE_ALLOW_BUSY_NPU", source) + self.assertIn("TILEXR_CCU_SMOKE_ALLOW_UNHEALTHY_NPU", source) + self.assertIn("--allow-unhealthy", source) + self.assertIn("TILEXR_CCU_SMOKE_REQUIRE_NPU_SMI", source) + self.assertIn("ccu_npu_smi_busy_guard.py", source) + self.assertIn("tilexr_ccu_direct_smoke_runner summary", source) + self.assertIn("rank0Status=", source) + self.assertIn("rank1Status=", source) + self.assertIn("rank0Log=", source) + self.assertIn("rank1Log=", source) + self.assertIn("submitTiming", source) + self.assertIn("syncMs=", source) + self.assertIn("p2pCcuCopy", source) + self.assertIn("passed=1", source) + self.assertIn('"TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE=${TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE:-1}"', source) + + gate = source.index('if [ "${TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE:-0}" != "1" ]') + for needle in [ + "npu-smi info", + '"${probe_bin}"', + "TILEXR_CCU_DIRECT_SMOKE_ENABLE=1", + "TILEXR_CCU_PROBE_RANK=0", + "TILEXR_CCU_PROBE_RANK=1", + ]: + with self.subTest(needle=needle): + self.assertLess(gate, source.index(needle)) + + def test_runner_p2p_mode_applies_direct_ccu_resource_defaults(self): + source = RUNNER.read_text(encoding="utf-8") + + self.assertIn("apply_p2p_ccu_copy_defaults", source) + self.assertIn('TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT="${TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT:-1}"', source) + self.assertIn('TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_ACTIVE_RANK="${TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY_ACTIVE_RANK:-0}"', source) + self.assertIn('TILEXR_CCU_PROBE_GSA_START="${TILEXR_CCU_PROBE_GSA_START:-510}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_XN_START:-2361}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_XN_START:-2361}"', source) + self.assertIn('TILEXR_CCU_PROBE_REMOTE_XN_COUNT="${TILEXR_CCU_PROBE_REMOTE_XN_COUNT:-8}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK0_LOCAL_WAIT_CKE_START:-332}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START="${TILEXR_CCU_PROBE_RANK1_LOCAL_WAIT_CKE_START:-332}"', source) + self.assertIn('TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT="${TILEXR_CCU_PROBE_LOCAL_WAIT_CKE_COUNT:-8}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK0_REMOTE_NOTIFY_CKE_START:-364}"', source) + self.assertIn('TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START="${TILEXR_CCU_PROBE_RANK1_REMOTE_NOTIFY_CKE_START:-364}"', source) + self.assertIn('TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT="${TILEXR_CCU_PROBE_REMOTE_NOTIFY_CKE_COUNT:-8}"', source) + self.assertIn('TILEXR_CCU_PROBE_CHANNEL_START="${TILEXR_CCU_PROBE_CHANNEL_START:-2}"', source) + self.assertIn('TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE="${TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE:-ra_ctx}"', source) + self.assertIn('common_env+=("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE=${TILEXR_CCU_DIRECT_RESOURCE_WINDOW_REGISTRATION_MODE}")', source) + self.assertIn("p2p_passed_count=0", source) + self.assertIn('grep -q "tilexr_ccu_direct_smoke p2pCcuCopy skipped"', source) + self.assertIn("direct CCU P2P CCU-copy produced no passing receiver result", source) + + def test_runner_default_run_skips_without_hardware(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env.pop("TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE", None) + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("skipped", result.stdout) + self.assertNotIn("TILEXR_CCU_PROBE_RANK=0", result.stdout) + self.assertNotIn("ccu_rank0.log", result.stdout) + + def test_runner_defaults_prepare_failure_fast_exit_and_allows_opt_out(self): + source = RUNNER.read_text(encoding="utf-8") + + self.assertIn( + '"TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE=${TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE:-1}"', + source, + ) + self.assertNotIn("TILEXR_CCU_DIRECT_SMOKE_FAST_EXIT_ON_PREPARE_FAILURE=0", source) + + def test_runner_dry_run_shows_rank_specific_endpoint_overrides_common(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE"] = "1" + env["TILEXR_CCU_DIRECT_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN"] = "99" + env["TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN_RANK0"] = "100" + env["TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN_RANK1"] = "200" + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_smoke_runner dryRun=1", result.stdout) + self.assertIn("dryRun rank0 TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN=100", result.stdout) + self.assertIn("dryRun rank1 TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN=200", result.stdout) + self.assertNotIn("TILEXR_CCU_DIRECT_LOCAL_ENDPOINT_TPN=99", result.stdout) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + self.assertNotIn("ccu_rank0.log", result.stdout) + + def test_runner_dry_run_shows_rank_specific_resource_window_token_overrides_common(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE"] = "1" + env["TILEXR_CCU_DIRECT_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID"] = "0x1111" + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK0"] = "0x2222" + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK1"] = "0x3333" + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_RAW_TOKEN_ID_RANK1"] = "0x4444" + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_VALUE_RANK1"] = "0x5555" + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_smoke_runner dryRun=1", result.stdout) + self.assertIn("dryRun rank0 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID=0x2222", result.stdout) + self.assertIn("dryRun rank1 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID=0x3333", result.stdout) + self.assertIn("dryRun rank1 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_RAW_TOKEN_ID=0x4444", result.stdout) + self.assertIn("dryRun rank1 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_VALUE=0x5555", result.stdout) + self.assertNotIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID=0x1111", result.stdout) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + self.assertNotIn("ccu_rank0.log", result.stdout) + + def test_runner_dry_run_shows_repository_install_diagnostic_variants(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE"] = "1" + env["TILEXR_CCU_DIRECT_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW"] = "full_repository" + env["TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE"] = "descriptor_bytes" + env["TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE"] = "acl_hccl_module" + env["TILEXR_CCU_DIRECT_INSTALL_ORDER"] = "lower_layer_first" + env["TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START"] = "489" + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("dryRun TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW=full_repository", result.stdout) + self.assertIn("dryRun TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE=descriptor_bytes", result.stdout) + self.assertIn("dryRun TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE=acl_hccl_module", result.stdout) + self.assertIn("dryRun TILEXR_CCU_DIRECT_INSTALL_ORDER=lower_layer_first", result.stdout) + self.assertIn("dryRun TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START=489", result.stdout) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + self.assertNotIn("ccu_rank0.log", result.stdout) + + def test_runner_dry_run_defaults_to_lower_layer_first_install_order(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE"] = "1" + env["TILEXR_CCU_DIRECT_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env.pop("TILEXR_CCU_DIRECT_INSTALL_ORDER", None) + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("dryRun TILEXR_CCU_DIRECT_INSTALL_ORDER=lower_layer_first", result.stdout) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + + def test_runner_dry_run_defaults_sync_xn_post_only_window_for_hcomm_style_task1_prelude(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE"] = "1" + env["TILEXR_CCU_DIRECT_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_BARRIER_MODE"] = "sync_xn_post_only" + env["TILEXR_CCU_PROBE_SYNC_RESOURCE_COUNT"] = "1" + env["TILEXR_CCU_PROBE_INSTRUCTION_START"] = "475" + env["TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START"] = "489" + env.pop("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT", None) + result = subprocess.run( + ["bash", str(RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("dryRun TILEXR_CCU_DIRECT_BARRIER_MODE=sync_xn_post_only", result.stdout) + self.assertIn("dryRun derived task0.instStartId=489 task0.instCnt=13", result.stdout) + self.assertIn("dryRun derived task1.instStartId=502 task1.instCnt=6", result.stdout) + self.assertIn( + "dryRun derived repositoryStartId=475 repositoryCount=33 missionInstructionStartId=489 " + "missionInstructionCount=19", + result.stdout, + ) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + + def test_npu_busy_guard_rejects_selected_device_processes(self): + sample = """ ++------------------+---------------+--------------+------------------+ +| NPU Chip | Process id | Process name | Process memory | ++==================+===============+==============+==================+ +| 0 0 | 31415 | python3.10 | 1024 | +| 2 0 | 27182 | train.py | 2048 | ++------------------+---------------+--------------+------------------+ +""" + with tempfile.TemporaryDirectory() as temp_dir: + log_path = Path(temp_dir) / "npu-smi.log" + log_path.write_text(sample, encoding="utf-8") + busy = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "0,1"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + idle = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "1"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + + self.assertEqual(1, busy.returncode, busy.stdout + busy.stderr) + self.assertIn("device=0 pid=31415 process=python3.10", busy.stdout) + self.assertEqual(0, idle.returncode, idle.stdout + idle.stderr) + self.assertIn("no selected NPU processes", idle.stdout) + + def test_npu_busy_guard_ignores_device_status_table(self): + sample = """ ++------+-------------+--------+-------------+ +| NPU | Name | Health | Power(W) | ++======+=============+========+=============+ +| 0 | Ascend950PR | OK | 95 | +| 1 | Ascend950PR | OK | 93 | ++------+-------------+--------+-------------+ +""" + with tempfile.TemporaryDirectory() as temp_dir: + log_path = Path(temp_dir) / "npu-smi.log" + log_path.write_text(sample, encoding="utf-8") + result = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "0,1"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("no selected NPU processes", result.stdout) + + def test_npu_busy_guard_rejects_selected_alarm_devices(self): + sample = """ ++------+-------------+--------+-------------+ +| NPU | Name | Health | Power(W) | ++======+=============+========+=============+ +| 0 | Ascend950PR | Alarm | 95 | +| 1 | Ascend950PR | OK | 93 | +| 2 | Ascend950PR | Alarm | 94 | ++------+-------------+--------+-------------+ +""" + with tempfile.TemporaryDirectory() as temp_dir: + log_path = Path(temp_dir) / "npu-smi.log" + log_path.write_text(sample, encoding="utf-8") + unhealthy = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "0,1"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + healthy = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "1"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + + self.assertEqual(1, unhealthy.returncode, unhealthy.stdout + unhealthy.stderr) + self.assertIn("unhealthy selected NPU device=0 health=Alarm", unhealthy.stdout) + self.assertNotIn("device=2", unhealthy.stdout) + self.assertEqual(0, healthy.returncode, healthy.stdout + healthy.stderr) + self.assertIn("selected NPU devices healthy", healthy.stdout) + + def test_npu_busy_guard_can_allow_alarm_without_allowing_busy_processes(self): + sample = """ ++------+-------------+--------+-------------+ +| NPU | Name | Health | Power(W) | ++======+=============+========+=============+ +| 0 | Ascend950PR | Alarm | 95 | +| 1 | Ascend950PR | OK | 93 | +| 2 | Ascend950PR | Alarm | 94 | ++------+-------------+--------+-------------+ +| NPU Chip | Process id | Process name | Process memory | ++==================+===============+==============+==================+ +| 0 0 | 31415 | python3.10 | 1024 | ++------+-------------+--------+-------------+ +""" + with tempfile.TemporaryDirectory() as temp_dir: + log_path = Path(temp_dir) / "npu-smi.log" + log_path.write_text(sample, encoding="utf-8") + allowed_health = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "2", "--allow-unhealthy"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + busy_still_blocked = subprocess.run( + ["python", str(BUSY_GUARD), "--log", str(log_path), "--devices", "0", "--allow-unhealthy"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + ) + + self.assertEqual(0, allowed_health.returncode, allowed_health.stdout + allowed_health.stderr) + self.assertIn("unhealthy selected NPU devices allowed", allowed_health.stdout) + self.assertNotIn("selected NPU devices healthy", allowed_health.stdout) + self.assertEqual(1, busy_still_blocked.returncode, busy_still_blocked.stdout + busy_still_blocked.stderr) + self.assertIn("device=0 pid=31415 process=python3.10", busy_still_blocked.stdout) + + def test_runner_requires_submit_for_barrier_wait_expectation(self): + source = RUNNER.read_text(encoding="utf-8") + barrier_gate = source.index('if [ "${TILEXR_CCU_DIRECT_SMOKE_EXPECT_BARRIER_WAIT:-0}" = "1" ]') + submit_guard = source.index( + 'if [ "${TILEXR_CCU_DIRECT_SMOKE_SUBMIT:-0}" != "1" ]; then', + barrier_gate, + ) + timing_parse = source.index("wait_sync_ms=", barrier_gate) + + self.assertLess(barrier_gate, submit_guard) + self.assertLess(submit_guard, timing_parse) + self.assertIn("direct CCU barrier wait check requires TILEXR_CCU_DIRECT_SMOKE_SUBMIT=1", source) + + def test_evening_wrapper_defaults_to_process_mode_direct_ccu_only_prepare_first(self): + source = EVENING_RUNNER.read_text(encoding="utf-8") + + self.assertIn('--dry-run', source) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN", source) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES", source) + self.assertIn("source scripts/common_env.sh", source) + self.assertIn("cmake --build build --target tile-comm", source) + self.assertIn("TILEXR_RUN_CCU_DIRECT_SMOKE_PROBE=1", source) + self.assertIn("TILEXR_CCU_SMOKE_REQUIRE_NPU_SMI=1", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=0", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_SUBMIT", source) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES", source) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT", source) + self.assertIn('TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT:-1', source) + self.assertIn("TILEXR_CCU_DIRECT_BARRIER_MODE=sync_cke", source) + self.assertIn("TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE=hcomm_cap", source) + self.assertIn("TILEXR_CCU_PROBE_SQE_ARG_COUNT", source) + self.assertIn("TILEXR_CCU_PROBE_MISSION_START", source) + self.assertIn("TILEXR_CCU_PROBE_INSTRUCTION_START", source) + self.assertIn("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START", source) + self.assertIn("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE", source) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE", source) + self.assertIn("TILEXR_CCU_PROBE_RANK0_XN_START", source) + self.assertIn("TILEXR_CCU_PROBE_RANK1_XN_START", source) + self.assertIn(":-475", source) + self.assertIn(":-489", source) + self.assertIn(":-143", source) + self.assertIn(":-full_repository", source) + self.assertIn(":-instruction_bytes", source) + self.assertIn(":-acl", source) + self.assertIn("tests/ccu/run_tilexr_ccu_direct_smoke.sh", source) + self.assertIn('run_smoke_stage "prepare_${safe_prepare_mode}"', source) + self.assertIn("prepare_has_submit_ready", source) + self.assertIn("submitReady=1", source) + self.assertIn("run_smoke_stage submit", source) + self.assertIn("run_smoke_stage barrier", source) + self.assertIn("run_smoke_stage p2p", source) + self.assertLess(source.index('run_smoke_stage "prepare_${safe_prepare_mode}"'), source.index("run_smoke_stage submit")) + self.assertLess(source.index("prepare_has_submit_ready"), source.index("run_smoke_stage submit")) + + def test_evening_wrapper_dry_run_short_circuits_before_common_env(self): + source = EVENING_RUNNER.read_text(encoding="utf-8") + + dry_run_gate = source.index('if [ "${TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN:-0}" = "1" ]') + common_env_source = source.index("source scripts/common_env.sh") + cmake_build = source.index("cmake --build build --target tile-comm") + + self.assertLess(dry_run_gate, common_env_source) + self.assertLess(dry_run_gate, cmake_build) + + def test_evening_wrapper_dry_run_does_not_invoke_fake_npu_smi(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + marker = temp_path / "npu-smi-called" + fake_npu_smi = temp_path / "npu-smi" + fake_npu_smi.write_text( + f"#!/usr/bin/env bash\n" + f"echo called >> {str(marker).replace(os.sep, '/')!r}\n" + f"exit 0\n", + encoding="utf-8", + ) + fake_npu_smi.chmod(0o755) + + env = os.environ.copy() + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN"] = "1" + env["PATH"] = str(temp_path) + os.pathsep + env.get("PATH", "") + result = subprocess.run( + ["bash", str(EVENING_RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_evening_smoke dryRun=1", result.stdout) + self.assertFalse(marker.exists(), result.stdout + result.stderr) + + def test_evening_wrapper_retries_prepare_with_module3_allocator_before_submit(self): + source = EVENING_RUNNER.read_text(encoding="utf-8") + + self.assertIn('TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES:-acl,acl_module3,rt_hbm', source) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES", source) + self.assertIn('prepare_alloc_modes', source) + self.assertIn('prepare_${safe_prepare_mode}', source) + self.assertIn('TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${prepare_profile_alloc}"', source) + self.assertIn('TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${prepare_profile_window}"', source) + self.assertIn('TILEXR_CCU_DIRECT_REPOSITORY_DATA_LEN_MODE="${prepare_profile_data_len_mode}"', source) + self.assertIn('TILEXR_CCU_DIRECT_INSTALL_ORDER="${prepare_profile_install_order}"', source) + self.assertIn('selected_prepare_alloc_mode', source) + self.assertIn('selected_prepare_window', source) + self.assertIn('prepareStatus=', source) + self.assertIn('prepare_status_summary', source) + self.assertIn('selectedPrepare alloc=', source) + self.assertIn('stopAfter=prepare reason="submitReady=1 missing for every prepare profile"', source) + + prepare_loop = source.index('for prepare_profile in "${prepare_profiles[@]}"') + self.assertLess( + source.index('TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${prepare_profile_alloc}"', prepare_loop), + source.index("prepare_has_submit_ready", prepare_loop), + ) + self.assertLess(source.index("selected_prepare_alloc_mode"), source.index("run_smoke_stage submit")) + submit_stage = source.index("run_smoke_stage submit") + self.assertLess( + submit_stage, + source.index('TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}"', submit_stage), + ) + self.assertLess( + submit_stage, + source.index('TILEXR_CCU_DIRECT_REPOSITORY_INSTALL_WINDOW="${selected_prepare_window}"', submit_stage), + ) + barrier_stage = source.index("run_smoke_stage barrier") + self.assertLess( + barrier_stage, + source.index('TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}"', barrier_stage), + ) + p2p_stage = source.index("run_smoke_stage p2p") + self.assertLess( + p2p_stage, + source.index('TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE="${selected_prepare_alloc_mode}"', p2p_stage), + ) + + def test_evening_wrapper_dry_run_lists_prepare_profiles(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES"] = ( + "full_acl:acl:full_repository:instruction_bytes:lower_layer_first," + "mission_desc:acl:mission:descriptor_bytes:repository_first" + ) + result = subprocess.run( + ["bash", str(EVENING_RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn( + "TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES=" + "full_acl:acl:full_repository:instruction_bytes:lower_layer_first," + "mission_desc:acl:mission:descriptor_bytes:repository_first", + result.stdout, + ) + self.assertIn( + "dryRun prepareProfile[0] name=full_acl alloc=acl window=full_repository " + "dataLenMode=instruction_bytes installOrder=lower_layer_first", + result.stdout, + ) + self.assertIn( + "dryRun prepareProfile[1] name=mission_desc alloc=acl window=mission " + "dataLenMode=descriptor_bytes installOrder=repository_first", + result.stdout, + ) + + def test_evening_wrapper_prepare_profiles_pass_repository_options_to_runner(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + fake_bin = temp_path / "bin" + fake_bin.mkdir() + fake_cmake = fake_bin / "cmake" + fake_cmake.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8") + fake_cmake.chmod(0o755) + fake_timeout = fake_bin / "timeout" + fake_timeout.write_text( + "#!/usr/bin/env bash\n" + "shift\n" + "exec \"$@\"\n", + encoding="utf-8", + ) + fake_timeout.chmod(0o755) + + fake_repo = temp_path / "repo" + fake_tests = fake_repo / "tests" / "ccu" + fake_scripts = fake_repo / "scripts" + fake_tests.mkdir(parents=True) + fake_scripts.mkdir() + (fake_scripts / "common_env.sh").write_text("#!/usr/bin/env bash\n", encoding="utf-8") + fake_runner = fake_tests / "run_tilexr_ccu_direct_smoke.sh" + fake_runner.write_text( + "#!/usr/bin/env bash\n" + "mkdir -p \"${TILEXR_CCU_SMOKE_WORK_DIR}\"\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" < \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" < \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" < \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" < \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submit ret=0 submitted=1 taskCount=1 submittedTaskCount=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submitTiming rank=0 preSubmitDelayMs=0 submitRet=0 syncRet=0 submitMs=1 syncMs=150\n" + "tilexr_ccu_direct_smoke p2pCcuCopy rank=0 passed=1\n" + "LOG\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submit ret=0 submitted=1 taskCount=1 submittedTaskCount=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submitTiming rank=1 preSubmitDelayMs=0 submitRet=0 syncRet=0 submitMs=1 syncMs=160\n" + "tilexr_ccu_direct_smoke p2pCcuCopy rank=1 passed=1\n" + "LOG\n" + "exit 0\n", + encoding="utf-8", + ) + fake_runner.chmod(0o755) + fake_evening = fake_tests / "run_tilexr_ccu_direct_evening_smoke.sh" + fake_evening.write_text(EVENING_RUNNER.read_text(encoding="utf-8"), encoding="utf-8") + fake_evening.chmod(0o755) + + env = os.environ.copy() + env["PATH"] = str(fake_bin) + os.pathsep + env.get("PATH", "") + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES"] = "prepare,submit,barrier,p2p" + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_PROFILES"] = ( + "pfe_hcomm:acl:full_repository:instruction_bytes:lower_layer_first:hcomm_die:hcomm_fe_id" + ) + env["TILEXR_CCU_EVENING_WORK_ROOT"] = "work" + result = subprocess.run( + ["bash", str(fake_evening)], + cwd=fake_repo, + check=False, + text=True, + capture_output=True, + env=env, + ) + final_status = fake_repo / "work" / "final_status.log" + final_status_exists = final_status.exists() + final_status_text = final_status.read_text(encoding="utf-8") if final_status_exists else "" + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn( + "finalStatus prepare=pass submit=pass barrier=pass p2p=pass completionCandidate=1 failedStage=none selectedProfile=pfe_hcomm", + result.stdout, + ) + self.assertTrue(final_status_exists, result.stdout + result.stderr) + self.assertIn( + "finalStatus prepare=pass submit=pass barrier=pass p2p=pass completionCandidate=1 failedStage=none selectedProfile=pfe_hcomm", + final_status_text, + ) + self.assertIn("selectedPrepare", result.stdout) + self.assertIn("success workRoot=work", result.stdout) + + def test_evening_wrapper_five_field_profile_preserves_ambient_pfe_layout(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + fake_bin = temp_path / "bin" + fake_bin.mkdir() + fake_cmake = fake_bin / "cmake" + fake_cmake.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8") + fake_cmake.chmod(0o755) + fake_timeout = fake_bin / "timeout" + fake_timeout.write_text( + "#!/usr/bin/env bash\n" + "shift\n" + "exec \"$@\"\n", + encoding="utf-8", + ) + fake_timeout.chmod(0o755) + + fake_repo = temp_path / "repo" + fake_tests = fake_repo / "tests" / "ccu" + fake_scripts = fake_repo / "scripts" + fake_tests.mkdir(parents=True) + fake_scripts.mkdir() + (fake_scripts / "common_env.sh").write_text("#!/usr/bin/env bash\n", encoding="utf-8") + fake_runner = fake_tests / "run_tilexr_ccu_direct_smoke.sh" + fake_runner.write_text( + "#!/usr/bin/env bash\n" + "mkdir -p \"${TILEXR_CCU_SMOKE_WORK_DIR}\"\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" < \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke config rank=0 installOrder=1\n" + "tilexr_ccu_direct_smoke prepare ret=6 submitReady=0 message=\"failed to install CCU repository instruction image: CCU custom channel call failed op=251 driverRet=7 opRet=9\"\n" + "tilexr_ccu_direct_smoke preparedTasks count=0\n" + "LOG\n" + "exit 6\n", + encoding="utf-8", + ) + fake_runner.chmod(0o755) + fake_evening = fake_tests / "run_tilexr_ccu_direct_evening_smoke.sh" + fake_evening.write_text(EVENING_RUNNER.read_text(encoding="utf-8"), encoding="utf-8") + fake_evening.chmod(0o755) + + env = os.environ.copy() + env["PATH"] = str(fake_bin) + os.pathsep + env.get("PATH", "") + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES"] = "prepare" + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES"] = "acl" + env["TILEXR_CCU_EVENING_WORK_ROOT"] = "work" + result = subprocess.run( + ["bash", str(fake_evening)], + cwd=fake_repo, + check=False, + text=True, + capture_output=True, + env=env, + ) + final_status = fake_repo / "work" / "final_status.log" + final_status_exists = final_status.exists() + final_status_text = final_status.read_text(encoding="utf-8") if final_status_exists else "" + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("prepareLogSummary mode=acl status=6", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke prepare ret=6 submitReady=0", result.stdout) + self.assertIn("CCU custom channel call failed op=251 driverRet=7 opRet=9", result.stdout) + self.assertIn('stopAfter=prepare reason="submitReady=1 missing for every prepare profile"', result.stdout) + self.assertIn( + "finalStatus prepare=fail submit=skipped barrier=skipped p2p=skipped " + "completionCandidate=0 failedStage=prepare", + result.stdout, + ) + self.assertTrue(final_status_exists, result.stdout + result.stderr) + self.assertIn( + "finalStatus prepare=fail submit=skipped barrier=skipped p2p=skipped " + "completionCandidate=0 failedStage=prepare", + final_status_text, + ) + + def test_evening_wrapper_extracts_submit_stage_summary_from_logs(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + fake_bin = temp_path / "bin" + fake_bin.mkdir() + fake_cmake = fake_bin / "cmake" + fake_cmake.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8") + fake_cmake.chmod(0o755) + fake_timeout = fake_bin / "timeout" + fake_timeout.write_text( + "#!/usr/bin/env bash\n" + "shift\n" + "exec \"$@\"\n", + encoding="utf-8", + ) + fake_timeout.chmod(0o755) + + fake_repo = temp_path / "repo" + fake_tests = fake_repo / "tests" / "ccu" + fake_scripts = fake_repo / "scripts" + fake_tests.mkdir(parents=True) + fake_scripts.mkdir() + (fake_scripts / "common_env.sh").write_text("#!/usr/bin/env bash\n", encoding="utf-8") + fake_runner = fake_tests / "run_tilexr_ccu_direct_smoke.sh" + fake_runner.write_text( + "#!/usr/bin/env bash\n" + "mkdir -p \"${TILEXR_CCU_SMOKE_WORK_DIR}\"\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "tilexr_ccu_direct_smoke submit ret=0 submitted=1 taskCount=1 submittedTaskCount=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submitTiming rank=0 preSubmitDelayMs=0 submitRet=0 syncRet=0 submitMs=1 syncMs=7\n" + "LOG\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "tilexr_ccu_direct_smoke submit ret=0 submitted=1 taskCount=1 submittedTaskCount=1 message=\"ok\"\n" + "tilexr_ccu_direct_smoke submitTiming rank=1 preSubmitDelayMs=0 submitRet=0 syncRet=0 submitMs=1 syncMs=8\n" + "LOG\n" + "exit 0\n", + encoding="utf-8", + ) + fake_runner.chmod(0o755) + fake_evening = fake_tests / "run_tilexr_ccu_direct_evening_smoke.sh" + fake_evening.write_text(EVENING_RUNNER.read_text(encoding="utf-8"), encoding="utf-8") + fake_evening.chmod(0o755) + + env = os.environ.copy() + env["PATH"] = str(fake_bin) + os.pathsep + env.get("PATH", "") + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES"] = "prepare,submit" + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES"] = "acl" + env["TILEXR_CCU_EVENING_WORK_ROOT"] = "work" + result = subprocess.run( + ["bash", str(fake_evening)], + cwd=fake_repo, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("stageLogSummary stage=submit status=0", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke submit ret=0 submitted=1", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke submitTiming rank=1", result.stdout) + + def test_evening_wrapper_runs_p2p_ccu_copy_with_process_mode_direct_ccu_init(self): + source = EVENING_RUNNER.read_text(encoding="utf-8") + p2p_stage = source[source.index("if stage_enabled p2p;"):] + p2p_stage = p2p_stage[:p2p_stage.index("print_final_status none")] + + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_P2P_CCU_COPY=1", p2p_stage) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_EXPECT_P2P_CCU_COPY=1", p2p_stage) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=1", p2p_stage) + self.assertNotIn("TILEXR_CCU_DIRECT_SMOKE_THREAD_MODE=1", p2p_stage) + self.assertNotIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=0", p2p_stage) + + def test_evening_wrapper_keeps_submit_failure_diagnostics_before_long_trace_tail(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + fake_bin = temp_path / "bin" + fake_bin.mkdir() + fake_cmake = fake_bin / "cmake" + fake_cmake.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8") + fake_cmake.chmod(0o755) + fake_timeout = fake_bin / "timeout" + fake_timeout.write_text( + "#!/usr/bin/env bash\n" + "shift\n" + "exec \"$@\"\n", + encoding="utf-8", + ) + fake_timeout.chmod(0o755) + + fake_repo = temp_path / "repo" + fake_tests = fake_repo / "tests" / "ccu" + fake_scripts = fake_repo / "scripts" + fake_tests.mkdir(parents=True) + fake_scripts.mkdir() + (fake_scripts / "common_env.sh").write_text("#!/usr/bin/env bash\n", encoding="utf-8") + fake_runner = fake_tests / "run_tilexr_ccu_direct_smoke.sh" + fake_runner.write_text( + "#!/usr/bin/env bash\n" + "mkdir -p \"${TILEXR_CCU_SMOKE_WORK_DIR}\"\n" + "if [[ \"${TILEXR_CCU_SMOKE_WORK_DIR}\" != *submit* ]]; then\n" + " cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "LOG\n" + " cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "LOG\n" + " exit 0\n" + "fi\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "tilexr_ccu_direct_smoke submit ret=-2 submitted=0 taskCount=1 submittedTaskCount=0 message=\"direct CCU submit failed task=0 ret=-2 rtRet=507000 dieId=1 missionId=6 instStartId=489 instCnt=156 key=0x59b0f03 argSize=13 args[0]=0xfeed\"\n" + "LOG\n" + "for i in $(seq 1 40); do\n" + " echo \"TileXRDirectCcuTrace program.sync[$i] decoded=SyncXn\" >> \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\"\n" + "done\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "LOG\n" + "exit 7\n", + encoding="utf-8", + ) + fake_runner.chmod(0o755) + fake_evening = fake_tests / "run_tilexr_ccu_direct_evening_smoke.sh" + fake_evening.write_text(EVENING_RUNNER.read_text(encoding="utf-8"), encoding="utf-8") + fake_evening.chmod(0o755) + + env = os.environ.copy() + env["PATH"] = str(fake_bin) + os.pathsep + env.get("PATH", "") + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES"] = "prepare,submit" + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES"] = "acl" + env["TILEXR_CCU_EVENING_WORK_ROOT"] = "work" + result = subprocess.run( + ["bash", str(fake_evening)], + cwd=fake_repo, + check=False, + text=True, + capture_output=True, + env=env, + ) + final_status = fake_repo / "work" / "final_status.log" + final_status_exists = final_status.exists() + final_status_text = final_status.read_text(encoding="utf-8") if final_status_exists else "" + + self.assertEqual(7, result.returncode, result.stdout + result.stderr) + self.assertIn("stageLogSummary stage=submit status=7", result.stdout) + self.assertIn("direct CCU submit failed task=0", result.stdout) + self.assertIn("rtRet=507000", result.stdout) + self.assertIn("args[0]=0xfeed", result.stdout) + self.assertIn( + "finalStatus prepare=pass submit=fail barrier=skipped p2p=skipped completionCandidate=0 failedStage=submit", + result.stdout, + ) + self.assertTrue(final_status_exists, result.stdout + result.stderr) + self.assertIn( + "finalStatus prepare=pass submit=fail barrier=skipped p2p=skipped completionCandidate=0 failedStage=submit", + final_status_text, + ) + + def test_evening_wrapper_stage_summary_keeps_decoded_direct_trace_lines(self): + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + fake_bin = temp_path / "bin" + fake_bin.mkdir() + fake_cmake = fake_bin / "cmake" + fake_cmake.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8") + fake_cmake.chmod(0o755) + fake_timeout = fake_bin / "timeout" + fake_timeout.write_text( + "#!/usr/bin/env bash\n" + "shift\n" + "exec \"$@\"\n", + encoding="utf-8", + ) + fake_timeout.chmod(0o755) + + fake_repo = temp_path / "repo" + fake_tests = fake_repo / "tests" / "ccu" + fake_scripts = fake_repo / "scripts" + fake_tests.mkdir(parents=True) + fake_scripts.mkdir() + (fake_scripts / "common_env.sh").write_text("#!/usr/bin/env bash\n", encoding="utf-8") + fake_runner = fake_tests / "run_tilexr_ccu_direct_smoke.sh" + fake_runner.write_text( + "#!/usr/bin/env bash\n" + "mkdir -p \"${TILEXR_CCU_SMOKE_WORK_DIR}\"\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank0.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "TileXRDirectCcuTrace lowerLayerPfe[0] decoded=PfeCtx pfeOffset=18 startTaJettyId=1024\n" + "TileXRDirectCcuTrace lowerLayerJettyCtx[0,0] decoded=LocalJettyCtx inferredSqDepth=64 wqeBasicBlockStartId=0\n" + "TileXRDirectCcuTrace lowerLayerChannel[0] decoded=ChannelCtxV1 sourcePfeId=2 remoteCcuVa=0x12340000\n" + "TileXRDirectCcuTrace remoteXnBinding[0] localXn=1961 remoteXn=2361 endpointRouteVerified=1\n" + "TileXRDirectCcuTrace task[0] missionId=6 instStartId=489 instCnt=13 argSize=13\n" + "TileXRDirectCcuTrace task[1] missionId=6 instStartId=502 instCnt=143 argSize=13\n" + "TileXRDirectCcuTrace finalRuntimeTask[0] dieId=1 missionId=6 timeout=20 instStartId=489 instCnt=2 key=0x59b0f03 argSize=1 args[0]=0xabc000\n" + "TileXRDirectCcuTrace customChannel.return op=251 driverRet=328107 opRet=0\n" + "LOG\n" + "cat > \"${TILEXR_CCU_SMOKE_WORK_DIR}/ccu_rank1.log\" <<'LOG'\n" + "tilexr_ccu_direct_smoke prepare ret=0 installSucceeded=1 submitReady=1\n" + "LOG\n" + "exit 0\n", + encoding="utf-8", + ) + fake_runner.chmod(0o755) + fake_evening = fake_tests / "run_tilexr_ccu_direct_evening_smoke.sh" + fake_evening.write_text(EVENING_RUNNER.read_text(encoding="utf-8"), encoding="utf-8") + fake_evening.chmod(0o755) + + env = os.environ.copy() + env["PATH"] = str(fake_bin) + os.pathsep + env.get("PATH", "") + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES"] = "prepare" + env["TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES"] = "acl" + env["TILEXR_CCU_EVENING_WORK_ROOT"] = "work" + result = subprocess.run( + ["bash", str(fake_evening)], + cwd=fake_repo, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("decoded=PfeCtx", result.stdout) + self.assertIn("decoded=LocalJettyCtx", result.stdout) + self.assertIn("decoded=ChannelCtxV1", result.stdout) + self.assertIn("remoteXnBinding[0]", result.stdout) + self.assertIn("TileXRDirectCcuTrace task[0]", result.stdout) + self.assertIn("TileXRDirectCcuTrace finalRuntimeTask[0]", result.stdout) + self.assertIn("TileXRDirectCcuTrace customChannel.return op=251", result.stdout) + + def test_evening_wrapper_dry_run_does_not_touch_npu(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_CCU_DIRECT_EVENING_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK0"] = "0x2222" + env["TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK1"] = "0x3333" + result = subprocess.run( + ["bash", str(EVENING_RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_evening_smoke dryRun=1", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DRY_RUN=1", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_SMOKE_STAGES=prepare,submit,barrier,p2p", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_EVENING_PREPARE_ALLOC_MODES=acl,acl_module3,rt_hbm", result.stdout) + self.assertIn( + "dryRun prepareProfile[2] name=rt_hbm alloc=rt_hbm window=full_repository", + result.stdout, + ) + self.assertIn("TILEXR_CCU_DIRECT_SMOKE_DIRECT_CCU_ONLY_INIT=1", result.stdout) + self.assertIn("TILEXR_CCU_PROBE_INSTRUCTION_START=475", result.stdout) + self.assertIn("TILEXR_CCU_PROBE_MISSION_INSTRUCTION_START=489", result.stdout) + self.assertIn("TILEXR_CCU_PROBE_SYNC_INSTRUCTION_COUNT=143", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_REPOSITORY_MEMORY_ALLOC_MODE=acl", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_INSTALL_ORDER=lower_layer_first", result.stdout) + self.assertIn("dryRun TILEXR_CCU_DIRECT_INSTALL_ORDER=lower_layer_first", result.stdout) + self.assertIn("TILEXR_CCU_PROBE_SQE_ARG_COUNT=13", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_BARRIER_MODE=sync_cke", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_LOWER_LAYER_WQE_MODE=hcomm_cap", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK0=0x2222", result.stdout) + self.assertIn("TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID_RANK1=0x3333", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke_runner dryRun=1", result.stdout) + self.assertIn("dryRun rank0 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID=0x2222", result.stdout) + self.assertIn("dryRun rank1 TILEXR_CCU_DIRECT_RESOURCE_WINDOW_TOKEN_ID=0x3333", result.stdout) + self.assertIn( + "dryRun derived repositoryStartId=475 repositoryCount=170 missionInstructionStartId=489", + result.stdout, + ) + self.assertIn("dryRun derived task0.instStartId=489 task0.instCnt=13", result.stdout) + self.assertIn("dryRun derived task1.instStartId=502 task1.instCnt=143", result.stdout) + self.assertIn("dryRun derived SET_INSTRUCTION offsetStartIdx=475 dataLen=5440", result.stdout) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + + def test_evening_wrapper_accepts_dry_run_argument_without_touching_npu(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + result = subprocess.run( + ["bash", str(EVENING_RUNNER), "--dry-run"], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_evening_smoke dryRun=1", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke_runner dryRun=1", result.stdout) + self.assertNotIn("cmake --build", result.stdout + result.stderr) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + + def test_evening_wrapper_accepts_generic_smoke_dry_run_without_touching_npu(self): + with tempfile.TemporaryDirectory() as temp_dir: + env = os.environ.copy() + env["TILEXR_CCU_SMOKE_DRY_RUN"] = "1" + env["TILEXR_CCU_SMOKE_WORK_DIR"] = temp_dir + result = subprocess.run( + ["bash", str(EVENING_RUNNER)], + cwd=REPO_ROOT, + check=False, + text=True, + capture_output=True, + env=env, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertIn("tilexr_ccu_direct_evening_smoke dryRun=1", result.stdout) + self.assertIn("tilexr_ccu_direct_smoke_runner dryRun=1", result.stdout) + self.assertNotIn("stage=prepare", result.stdout + result.stderr) + self.assertNotIn("npu-smi rc=", result.stdout + result.stderr) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/ccu/test_tilexr_ccu_public_api_compile_probe.py b/tests/ccu/test_tilexr_ccu_public_api_compile_probe.py new file mode 100644 index 00000000..49eff720 --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_public_api_compile_probe.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] + + +class TileXRCcuPublicApiCompileProbeTest(unittest.TestCase): + def test_external_direct_ccu_public_probe_removed(self): + self.assertFalse((REPO_ROOT / "tests" / "ccu" / "ccu_public_direct_api_compile_probe.c").exists()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/ccu/test_tilexr_ccu_public_comm_api.py b/tests/ccu/test_tilexr_ccu_public_comm_api.py new file mode 100644 index 00000000..db54ace9 --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_public_comm_api.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +PUBLIC_HEADERS = [ + REPO_ROOT / "src" / "include" / "tilexr_api.h", + REPO_ROOT / "src" / "include" / "tilexr_types.h", + REPO_ROOT / "src" / "include" / "tilexr_collectives.h", +] +CORE_API_HEADER = REPO_ROOT / "src" / "include" / "tilexr_api.h" +COMM_WRAP = REPO_ROOT / "src" / "comm" / "comm_wrap.cpp" + + +class TileXRCcuPublicCommApiTest(unittest.TestCase): + def test_core_api_header_has_no_ccu_symbols(self): + header = CORE_API_HEADER.read_text(encoding="utf-8") + for needle in ["CCU", "Ccu", "DirectCcu", "TILEXR_DIRECT_CCU"]: + with self.subTest(needle=needle): + self.assertNotIn(needle, header) + + def test_installed_public_headers_do_not_expose_low_level_ccu_model(self): + forbidden = [ + "TileXRDirectCcu", + "PrepareDirectCcu", + "SubmitPrepared", + "Repository", + "SQE", + " XN", + " CKE", + "TaskInfo", + "rtCCULaunch", + "rtCcuTaskInfo_t", + "hcomm", + "hccl", + ] + for path in PUBLIC_HEADERS: + text = path.read_text(encoding="utf-8") + for needle in forbidden: + with self.subTest(path=path.name, needle=needle): + self.assertNotIn(needle, text) + + def test_collectives_header_only_exposes_high_level_backend_names(self): + text = (REPO_ROOT / "src" / "include" / "tilexr_collectives.h").read_text(encoding="utf-8") + for needle in [ + "TILEXR_COLLECTIVE_BACKEND_AUTO", + "TILEXR_COLLECTIVE_BACKEND_AIV", + "TILEXR_COLLECTIVE_BACKEND_UDMA", + "TILEXR_COLLECTIVE_BACKEND_CCU", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, text) + + def test_comm_wrap_has_no_direct_ccu_public_bridge(self): + wrapper = COMM_WRAP.read_text(encoding="utf-8") + for needle in [ + "TileXRCommInitRankDirectCcuWithDomain", + "TileXRCommPrepareDirectCcu", + "TileXRCommPrepareDirectCcuMemoryCopy", + "TileXRDirectCcuGetPreparedTask", + "TileXRDirectCcuSubmitPrepared", + "TileXRCommReadDirectCcuInstructions", + "TileXRDirectCcuDestroyPrepared", + "TileXRDirectCcuPreparedTasks", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, wrapper) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/ccu/test_tilexr_ccu_source_guard_coverage.py b/tests/ccu/test_tilexr_ccu_source_guard_coverage.py new file mode 100644 index 00000000..2f45fd5f --- /dev/null +++ b/tests/ccu/test_tilexr_ccu_source_guard_coverage.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 TileXR Project +# + +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SOURCE_GUARD = REPO_ROOT / "tests" / "comm" / "unit" / "test_tilexr_source_guards.cpp" +BUILD_ARTIFACT_GUARD = REPO_ROOT / "tests" / "ccu" / "check_tile_comm_no_hcomm_deps.sh" +DIRECT_SMOKE_PROBE = REPO_ROOT / "tests" / "ccu" / "ccu_tilexr_direct_smoke_probe.cpp" +DIRECT_SMOKE_RUNNER = REPO_ROOT / "tests" / "ccu" / "run_tilexr_ccu_direct_smoke.sh" +ROOT_CMAKE = REPO_ROOT / "CMakeLists.txt" +CCU_CMAKE = REPO_ROOT / "tests" / "ccu" / "CMakeLists.txt" + + +class TileXRCcuSourceGuardCoverageTest(unittest.TestCase): + def test_source_guard_covers_hccl_include_and_path_variants(self): + source = SOURCE_GUARD.read_text(encoding="utf-8").replace('\\"', '"') + + for needle in [ + "TestRootCMakeHcclIncludesAreNotTileCommSurface", + "#include ", + "#include \"hccl.h\"", + "pkg_inc/hccl", + "include/hccl", + "${ARCH}-linux/include/hccl", + "${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, source) + + def test_root_cmake_does_not_expose_hccl_include_globally(self): + cmake = ROOT_CMAKE.read_text(encoding="utf-8") + + self.assertNotIn("${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl/", cmake) + self.assertNotIn("${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl", cmake) + + def test_ccu_cmake_does_not_define_private_probe_targets(self): + cmake = CCU_CMAKE.read_text(encoding="utf-8") + + for needle in [ + "TILEXR_BUILD_PRIVATE_CCU_PROBES", + "ccu_context_probe", + "ccu_barrier_kernel_probe", + "ccu_taskinfo_probe", + "include/hccl", + "pkg_inc/hcomm", + "hcomm", + "hccl", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, cmake) + + def test_build_artifact_guard_scans_private_hcomm_hccl_and_ccu_surfaces(self): + script = BUILD_ARTIFACT_GUARD.read_text(encoding="utf-8") + + for needle in [ + "readelf -d", + "ldd", + "nm -D", + "strings -a", + "libhcomm\\.so", + "libhccl_v2\\.so", + "libhccl_fwk\\.so", + "libmc2_client\\.so", + "HcclGetCcuTaskInfo", + "HcclChannelAcquire", + "HcommChannelNotify", + "RT_RES_TYPE_CCU_XN", + ]: + with self.subTest(needle=needle): + self.assertIn(needle, script) + + def test_direct_smoke_probe_keeps_private_producer_dependencies_out(self): + source = DIRECT_SMOKE_PROBE.read_text(encoding="utf-8") + + for needle in [ + "#include ", + "#include \"hccl.h\"", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + "CcuResBatchAllocator", + "CcuResRepository", + "runtime/kernel.h", + "rtCCULaunch", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, source) + + def test_direct_smoke_runner_keeps_private_link_dependencies_out(self): + source = DIRECT_SMOKE_RUNNER.read_text(encoding="utf-8") + + for needle in [ + "-lhcomm", + "-lhccl", + "-lhccl_v2", + "-lhccl_fwk", + "-lmc2_client", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "pkg_inc/hcomm", + "pkg_inc/hccl", + "include/hccl", + ]: + with self.subTest(needle=needle): + self.assertNotIn(needle, source) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/collectives/CMakeLists.txt b/tests/collectives/CMakeLists.txt index d4feeb0e..a9594ad3 100644 --- a/tests/collectives/CMakeLists.txt +++ b/tests/collectives/CMakeLists.txt @@ -90,6 +90,14 @@ add_executable(test_tilexr_collectives_header_compile unit/test_tilexr_collectives_header_compile.cpp ) +add_executable(test_tilexr_collective_backend_options + unit/test_tilexr_collective_backend_options.cpp +) + +target_include_directories(test_tilexr_collective_backend_options PRIVATE + ${TILEXR_ROOT}/src/collectives/host +) + add_executable(test_tilexr_perf_trace_layout unit/test_tilexr_perf_trace_layout.cpp ) @@ -243,6 +251,10 @@ target_link_libraries(test_tilexr_collectives_header_compile ${TILEXR_COLLECTIVES_TEST_TARGET} ) +target_link_libraries(test_tilexr_collective_backend_options + ${TILEXR_COLLECTIVES_TEST_TARGET} +) + target_link_libraries(test_tilexr_perf_trace_layout ${TILEXR_COMM_TEST_TARGET} ) @@ -295,6 +307,7 @@ target_link_libraries(test_prepare_host_launch_context foreach(_tilexr_collectives_link_target test_tilexr_collectives_header_compile + test_tilexr_collective_backend_options test_tilexr_perf_trace_layout test_collective_perf_report test_collective_perf_session @@ -312,6 +325,7 @@ add_test(NAME test_tilexr_collectives_api COMMAND test_tilexr_collectives_api) add_test(NAME test_tilexr_collectives_kernel_ownership COMMAND test_tilexr_collectives_kernel_ownership) add_test(NAME test_tilexr_collectives_tools_sources COMMAND test_tilexr_collectives_tools_sources) add_test(NAME test_tilexr_collectives_header_compile COMMAND test_tilexr_collectives_header_compile) +add_test(NAME test_tilexr_collective_backend_options COMMAND test_tilexr_collective_backend_options) add_test(NAME test_tilexr_perf_trace_layout COMMAND test_tilexr_perf_trace_layout) add_test(NAME test_collective_perf_report COMMAND test_collective_perf_report) add_test(NAME test_collective_perf_session COMMAND test_collective_perf_session) @@ -338,6 +352,7 @@ install(TARGETS test_tilexr_collectives_kernel_ownership test_tilexr_collectives_tools_sources test_tilexr_collectives_header_compile + test_tilexr_collective_backend_options test_tilexr_perf_trace_layout test_collective_perf_report test_collective_perf_session diff --git a/tests/collectives/unit/test_tilexr_collective_backend_options.cpp b/tests/collectives/unit/test_tilexr_collective_backend_options.cpp new file mode 100644 index 00000000..8a220d64 --- /dev/null +++ b/tests/collectives/unit/test_tilexr_collective_backend_options.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024-2026 TileXR Project + * This file is a part of the CANN Open Software. + * Licensed under CANN Open Software License Agreement Version 1.0 (the "License"). + * Please refer to the License for details. You may not use this file except in compliance with the License. + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + * See LICENSE in the root of the software repository for the full text of the License. + */ +#include "tilexr_collectives.h" +#include "collective_backend.h" + +#include + +namespace { + +static_assert(TILEXR_COLLECTIVE_BACKEND_AUTO == 0, "AUTO must be zero for zero-initialized options"); +static_assert(TILEXR_COLLECTIVE_BACKEND_AIV == 1, "AIV enum value changed"); +static_assert(TILEXR_COLLECTIVE_BACKEND_UDMA == 2, "UDMA enum value changed"); +static_assert(TILEXR_COLLECTIVE_BACKEND_CCU == 3, "CCU enum value changed"); + +int CheckFunctionPointers() +{ + TileXRCollectiveOptions options {}; + if (options.backend != TILEXR_COLLECTIVE_BACKEND_AUTO) { + return 1; + } + + auto allGather = &TileXRAllGatherEx; + auto allToAll = &TileXRAllToAllEx; + auto allReduce = &TileXRAllReduceEx; + auto reduceScatter = &TileXRReduceScatterEx; + auto broadcast = &TileXRBroadcastEx; + auto profileProbe = &TileXRProfileProbeEx; + + (void)allGather; + (void)allToAll; + (void)allReduce; + (void)reduceScatter; + (void)broadcast; + (void)profileProbe; + return 0; +} + +int CheckBackendDispatch() +{ + using TileXRCollectives::Host::BackendTestState; + using TileXRCollectives::Host::CollectiveRequest; + using TileXRCollectives::Host::DispatchCollective; + using TileXRCollectives::Host::ResetBackendTestState; + using TileXRCollectives::Host::SetBackendTestState; + + CollectiveRequest request {}; + request.type = TileXR::TileXRType::ALL_GATHER; + request.sendBuf = reinterpret_cast(0x1000); + request.recvBuf = reinterpret_cast(0x2000); + request.count = 1; + request.dataType = TileXR::TILEXR_DATA_TYPE_INT32; + request.comm = reinterpret_cast(0x3000); + request.stream = nullptr; + int sendValue = 1; + int recvValue = 0; + TileXRCollectiveOptions options {}; + options.backend = TILEXR_COLLECTIVE_BACKEND_AUTO; + + BackendTestState state {}; + state.aivReturn = TileXR::TILEXR_SUCCESS; + state.udmaInitialized = false; + state.ccuInitialized = false; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_AUTO) != TileXR::TILEXR_SUCCESS) { + return 2; + } + + state.udmaInitialized = true; + state.udmaSupported = true; + state.udmaReturn = TileXR::TILEXR_SUCCESS; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_UDMA) != TileXR::TILEXR_SUCCESS) { + return 3; + } + + state.udmaInitialized = false; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_UDMA) != TileXR::TILEXR_ERROR_NOT_INITIALIZED) { + return 4; + } + + state.udmaInitialized = true; + state.udmaSupported = false; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_UDMA) != TileXR::TILEXR_ERROR_NOT_SUPPORT) { + return 5; + } + + state.ccuInitialized = false; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_CCU) != TileXR::TILEXR_ERROR_NOT_INITIALIZED) { + return 6; + } + + state.ccuInitialized = true; + state.ccuSupported = false; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_CCU) != TileXR::TILEXR_ERROR_NOT_SUPPORT) { + return 7; + } + + state.ccuSupported = true; + state.ccuReturn = TileXR::TILEXR_SUCCESS; + SetBackendTestState(state); + if (DispatchCollective(request, TILEXR_COLLECTIVE_BACKEND_CCU) != TileXR::TILEXR_SUCCESS) { + return 8; + } + + options.backend = TILEXR_COLLECTIVE_BACKEND_UDMA; + state.udmaInitialized = false; + state.udmaSupported = false; + SetBackendTestState(state); + if (TileXRAllGatherEx(&sendValue, &recvValue, 1, TileXR::TILEXR_DATA_TYPE_INT32, request.comm, nullptr, &options) != + TileXR::TILEXR_ERROR_NOT_INITIALIZED) { + return 9; + } + + options.backend = TILEXR_COLLECTIVE_BACKEND_CCU; + state.ccuInitialized = true; + state.ccuSupported = false; + SetBackendTestState(state); + if (TileXRAllGatherEx(&sendValue, &recvValue, 1, TileXR::TILEXR_DATA_TYPE_INT32, request.comm, nullptr, &options) != + TileXR::TILEXR_ERROR_NOT_SUPPORT) { + return 10; + } + + ResetBackendTestState(); + return 0; +} + +} // namespace + +int main() +{ + const int pointerRet = CheckFunctionPointers(); + if (pointerRet != 0) { + return pointerRet; + } + return CheckBackendDispatch(); +} diff --git a/tests/comm/unit/test_tilexr_source_guards.cpp b/tests/comm/unit/test_tilexr_source_guards.cpp index 4c7e70e0..84f9896b 100644 --- a/tests/comm/unit/test_tilexr_source_guards.cpp +++ b/tests/comm/unit/test_tilexr_source_guards.cpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace { @@ -70,6 +71,53 @@ std::string RunCommand(const std::string& command) return output; } +std::string ShellQuote(const std::string& value) +{ + std::string quoted = "'"; + for (const char ch : value) { + if (ch == '\'') { + quoted += "'\\''"; + } else { + quoted += ch; + } + } + quoted += "'"; + return quoted; +} + +std::vector SplitPathspec(const std::string& pathspec) +{ + std::vector parts; + std::istringstream input(pathspec); + std::string part; + while (input >> part) { + parts.push_back(part); + } + return parts; +} + +std::string StripTrailingDot(const std::string& path) +{ + if (path.size() >= 2U && path.substr(path.size() - 2U) == "/.") { + return path.substr(0, path.size() - 2U); + } + return path; +} + +std::string ListFilesCommand(const std::string& pathspec) +{ + const std::string root = StripTrailingDot(RepoPath(".")); + std::string command = "if git -C " + ShellQuote(root) + + " rev-parse --is-inside-work-tree >/dev/null 2>&1; then git -C " + + ShellQuote(root) + " ls-files --cached --others --exclude-standard -- " + pathspec + "; else "; + for (const auto& part : SplitPathspec(pathspec)) { + command += "find " + ShellQuote(root + "/" + part) + + " -type f 2>/dev/null | sed " + ShellQuote("s#^" + root + "/##") + "; "; + } + command += "true; fi"; + return command; +} + void CheckNoLineContains(const std::string& description, const std::string& text, const std::string& needle) { std::istringstream lines(text); @@ -82,10 +130,72 @@ void CheckNoLineContains(const std::string& description, const std::string& text } } +void CheckTrackedFilesDoNotContain( + const std::string& description, + const std::string& gitPathspec, + const std::vector& forbiddenNeedles) +{ + const auto trackedFiles = RunCommand(ListFilesCommand(gitPathspec)); + + std::istringstream paths(trackedFiles); + std::string path; + while (std::getline(paths, path)) { + if (path.empty()) { + continue; + } + const auto text = ReadFile(path); + for (const auto& needle : forbiddenNeedles) { + const auto pos = text.find(needle); + if (pos != std::string::npos) { + std::cerr << "unexpected " << description << " in " << path + << ": " << needle << " at byte " << pos << std::endl; + ++g_failures; + } + } + } +} + +bool ContainsPath(const std::vector& paths, const std::string& path) +{ + for (const auto& item : paths) { + if (item == path) { + return true; + } + } + return false; +} + +void CheckTrackedFilesContainNeedleOnly( + const std::string& description, + const std::string& gitPathspec, + const std::string& needle, + const std::vector& allowedPaths) +{ + const auto trackedFiles = RunCommand(ListFilesCommand(gitPathspec)); + + std::istringstream paths(trackedFiles); + std::string path; + while (std::getline(paths, path)) { + if (path.empty()) { + continue; + } + const auto text = ReadFile(path); + const auto pos = text.find(needle); + if (pos != std::string::npos && !ContainsPath(allowedPaths, path)) { + std::cerr << "unexpected " << description << " in " << path + << ": " << needle << " at byte " << pos << std::endl; + ++g_failures; + } + } + + for (const auto& allowedPath : allowedPaths) { + CheckContains(allowedPath, ReadFile(allowedPath), needle); + } +} + void TestOpenSourceTarballsAreNotTracked() { - const std::string command = "git -C " + RepoPath(".") + " ls-files 3rdparty/open_source"; - const auto trackedFiles = RunCommand(command); + const auto trackedFiles = RunCommand(ListFilesCommand("3rdparty/open_source")); CheckNoLineContains("tracked open-source dependency archive", trackedFiles, ".tar.gz"); CheckNoLineContains("tracked open-source dependency archive", trackedFiles, ".tar.xz"); @@ -183,14 +293,713 @@ void TestCommBuildIncludesProfilingHeaders() CheckContains(commPath, commText, "${ASCEND_HOME_PATH}/${ARCH}-linux/pkg_inc/profiling/"); } -void TestChipMapCoversObservedAscend950Variants() +void TestChipNameResolverRecognizesAscend950PrVariants() { const std::string path = "src/comm/tilexr_internal.cpp"; const auto text = ReadFile(path); + CheckContains(path, text, "ChipName ResolveChipNameFromSocVersion"); CheckContains(path, text, "{\"Ascend950PR\", ChipName::CHIP_950PR}"); CheckContains(path, text, "{\"Ascend950PR_9589\", ChipName::CHIP_950PR}"); CheckContains(path, text, "{\"Ascend950PR_9599\", ChipName::CHIP_950PR}"); + CheckContains(path, text, "{\"Ascend950PR_\", ChipName::CHIP_950PR}"); + CheckContains(path, text, "{\"Ascend950DT_\", ChipName::CHIP_950}"); + CheckContains(path, text, "ResolveChipNameFromSocVersion(chipName)"); +} + +void TestCommRuntimeDoesNotUseHcommOrHcclV2() +{ + const std::string path = "src/comm/CMakeLists.txt"; + const auto text = ReadFile(path); + + CheckNotContains(path, text, "hcomm"); + CheckNotContains(path, text, "hccl"); + CheckNotContains(path, text, "libhccl_v2"); + CheckNotContains(path, text, "libhccl_fwk"); + CheckNotContains(path, text, "libmc2_client"); + + CheckTrackedFilesDoNotContain("hcomm or HCCL CCU runtime dependency", "src/comm src/include", { + "#include ", + "#include \"hccl.h\"", + "pkg_inc/hcomm", + "pkg_inc/hccl", + "include/hccl", + "${ARCH}-linux/include/hccl", + "${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "HcclAllocComResourceByTiling", + "HcclCreateOpResCtx", + "HcclEngineCtx", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + "HcclChannelAcquire", + "HcclGetChannelForCcu", + "HcclAllocAlgResourceCcu", + "HcclCcuKernel", + "HcommChannelNotify", + "HcommChannelFence", + "rtGetNotifyAddress", + "HrtCcuLaunch", + "HrtGetDevResAddress", + "HrtReleaseDevResAddress", + "HrtNotifyGetAddr", + "HrtRaCustomChannel", + "HrtCntNotify", + "CcuResBatchAllocator", + "CcuResRepository", + "CcuResReq", + "CcuDeviceManager", + "CcuDevMgrImp", + "CcuRepContext", + "CcuKernelMgr", + "CtxMgrImp", + "CcuTaskParam", + "CcuTaskArg", + "GeneTaskParam", + "GetMissionKey", + "SetMissionId", + "SetMissionKey", + "SetInstrId", + "SetCcuInstrInfo", + "LoadInstruction", + "AllocIns", + "AllocCke", + "AllocXn", + "COMM_ENGINE_CCU", + "COMM_PROTOCOL_UBC_CTP", + "RT_RES_TYPE_CCU_CKE", + "RT_RES_TYPE_CCU_XN", + "HCCL_SERVER_TYPE_CCU", + }); +} + +void TestRootCMakeHcclIncludesAreNotTileCommSurface() +{ + const std::string rootPath = "CMakeLists.txt"; + const std::string commPath = "src/comm/CMakeLists.txt"; + const auto rootText = ReadFile(rootPath); + const auto commText = ReadFile(commPath); + + for (const auto& privateInclude : { + "${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl", + "${ARCH}-linux/include/hccl", + "pkg_inc/hccl", + "include/hccl", + "hccl/", + }) { + CheckNotContains(rootPath, rootText, privateInclude); + CheckNotContains(commPath, commText, privateInclude); + } +} + +void TestCommDirectCcuInstallAttemptDoesNotSubmit() +{ + const std::string commHeaderPath = "src/comm/tilexr_comm.h"; + const std::string commSourcePath = "src/comm/tilexr_comm.cpp"; + const std::string ccuBackendHeaderPath = "src/comm/ccu/tilexr_ccu_backend.h"; + const std::string ccuBackendSourcePath = "src/comm/ccu/tilexr_ccu_backend.cpp"; + const std::string ccuRuntimeSessionHeaderPath = "src/comm/ccu/tilexr_ccu_runtime_session.h"; + const std::string ccuRuntimeSessionSourcePath = "src/comm/ccu/tilexr_ccu_runtime_session.cpp"; + const std::string ccuPlannerHeaderPath = "src/comm/ccu/tilexr_ccu_collective_planner.h"; + const std::string ccuPlannerSourcePath = "src/comm/ccu/tilexr_ccu_collective_planner.cpp"; + const std::string ccuExecutorHeaderPath = "src/comm/ccu/tilexr_ccu_executor.h"; + const std::string ccuExecutorSourcePath = "src/comm/ccu/tilexr_ccu_executor.cpp"; + const std::string ccuRuntimeHeaderPath = "src/comm/ccu/tilexr_ccu_direct_runtime.h"; + const std::string ccuRuntimeSourcePath = "src/comm/ccu/tilexr_ccu_direct_runtime.cpp"; + const auto commHeaderText = ReadFile(commHeaderPath); + const auto commSourceText = ReadFile(commSourcePath); + const auto ccuBackendHeaderText = ReadFile(ccuBackendHeaderPath); + const auto ccuBackendSourceText = ReadFile(ccuBackendSourcePath); + const auto ccuRuntimeSessionHeaderText = ReadFile(ccuRuntimeSessionHeaderPath); + const auto ccuRuntimeSessionSourceText = ReadFile(ccuRuntimeSessionSourcePath); + const auto ccuPlannerHeaderText = ReadFile(ccuPlannerHeaderPath); + const auto ccuPlannerSourceText = ReadFile(ccuPlannerSourcePath); + const auto ccuExecutorHeaderText = ReadFile(ccuExecutorHeaderPath); + const auto ccuExecutorSourceText = ReadFile(ccuExecutorSourcePath); + const auto ccuRuntimeHeaderText = ReadFile(ccuRuntimeHeaderPath); + const auto ccuRuntimeSourceText = ReadFile(ccuRuntimeSourcePath); + + CheckContains(commHeaderPath, commHeaderText, "class TileXRCcuBackend;"); + CheckContains(commHeaderPath, commHeaderText, "std::unique_ptr ccuBackend_"); + for (const auto& forbiddenCommDetail : { + "tilexr_ccu_direct_runtime.h", + "tilexr_ccu_lower_layer_plan_builder.h", + "TileXRCcuDirectRuntime", + "directCcuBasicInfo_", + "directCcuLowerLayerPlan_", + "directCcuVerifiedEndpointRoutes_", + "PrepareDirectCcuInstallAttempt", + "PrepareDirectCcuLowerLayerPlanCallback", + }) { + CheckNotContains(commHeaderPath, commHeaderText, forbiddenCommDetail); + } + + CheckContains(ccuBackendHeaderPath, ccuBackendHeaderText, "class TileXRCcuBackend"); + CheckContains(ccuBackendHeaderPath, ccuBackendHeaderText, "TileXRSockExchange *exchange"); + CheckContains(ccuBackendHeaderPath, ccuBackendHeaderText, "std::unique_ptr impl_"); + CheckContains(ccuBackendSourcePath, ccuBackendSourceText, "#include \"ccu/tilexr_ccu_runtime_session.h\""); + CheckContains(ccuBackendSourcePath, ccuBackendSourceText, "#include \"ccu/tilexr_ccu_collective_planner.h\""); + CheckContains(ccuBackendSourcePath, ccuBackendSourceText, "#include \"ccu/tilexr_ccu_executor.h\""); + CheckNotContains(ccuBackendSourcePath, ccuBackendSourceText, "#include \"ccu/tilexr_ccu_direct_runtime.h\""); + CheckNotContains(ccuBackendSourcePath, ccuBackendSourceText, "#include \"ccu/tilexr_ccu_repository.h\""); + CheckNotContains(ccuBackendSourcePath, ccuBackendSourceText, "TileXRCcuDirectRuntime"); + CheckContains(ccuBackendSourcePath, ccuBackendSourceText, "TileXRCcuBackend::Impl::Init"); + CheckContains(ccuRuntimeSessionHeaderPath, ccuRuntimeSessionHeaderText, "TileXRCcuDirectRuntime"); + CheckContains(ccuRuntimeSessionSourcePath, ccuRuntimeSessionSourceText, "ccuDirectRuntime_->CreateDriverAdapter"); + CheckContains(ccuPlannerHeaderPath, ccuPlannerHeaderText, "class TileXRCcuRuntimeSession"); + CheckContains(ccuPlannerHeaderPath, ccuPlannerHeaderText, "#ifdef TILEXR_CCU_TESTING"); + CheckContains(ccuPlannerHeaderPath, ccuPlannerHeaderText, "PrepareDirectCcuMemoryCopyInstallAttempt"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "#include \"ccu/tilexr_ccu_repository.h\""); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "#ifdef TILEXR_CCU_TESTING"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "TileXRCcuCollectivePlanner::PrepareDirectCcuInstallAttempt"); + CheckContains( + ccuPlannerSourcePath, + ccuPlannerSourceText, + "TileXRCcuCollectivePlanner::PrepareDirectCcuMemoryCopyInstallAttempt"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerPlanCallback"); + CheckContains( + ccuPlannerSourcePath, + ccuPlannerSourceText, + "TileXRCcuMakeRepositoryDeviceMemoryOps(next.repositoryMemoryAllocMode)"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "next.lowerLayerPlan = nullptr"); + CheckContains( + ccuPlannerSourcePath, + ccuPlannerSourceText, + "next.prepareLowerLayerPlan = &TileXRCcuCollectivePlanner::PrepareDirectCcuLowerLayerPlanCallback"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "LowerLayerPlanCallbackContext callbackContext"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "next.lowerLayerPlanUserData = &callbackContext"); + CheckContains(ccuPlannerSourcePath, ccuPlannerSourceText, "TileXRCcuRunDirectInstallAttempt(next, attempt, report)"); + CheckContains(ccuExecutorHeaderPath, ccuExecutorHeaderText, "#ifdef TILEXR_CCU_TESTING"); + CheckContains(ccuExecutorHeaderPath, ccuExecutorHeaderText, "ReadDirectCcuInstructionsForDebug"); + CheckContains(ccuExecutorSourcePath, ccuExecutorSourceText, "#ifdef TILEXR_CCU_TESTING"); + CheckContains(ccuExecutorSourcePath, ccuExecutorSourceText, "ReadDirectCcuInstructionsForDebug"); + CheckContains(ccuRuntimeHeaderPath, ccuRuntimeHeaderText, "int CreateDriverAdapter("); + CheckContains(ccuRuntimeSourcePath, ccuRuntimeSourceText, "int TileXRCcuDirectRuntime::CreateDriverAdapter"); + CheckContains(ccuRuntimeHeaderPath, ccuRuntimeHeaderText, "TileXRCcuHccpLoader"); + for (const auto& forbiddenUdmaCcuCall : { + std::string("udmaTransport_->") + "CreateCcuDriverAdapter", + std::string("udmaTransport_->") + "QueryCcuBasicInfo", + std::string("udmaTransport_->") + "RegisterCcuResourceRmaBuffer", + std::string("udmaTransport_->") + "ExportLocalCcuRmaBuffer", + std::string("udmaTransport_->") + "ExportRemoteCcuRmaBuffers", + std::string("udmaTransport_->") + "ExportLowerLayerTransportSnapshot", + }) { + CheckNotContains(commSourcePath, commSourceText, forbiddenUdmaCcuCall); + } + + const auto initUdmaBegin = commSourceText.find("int TileXRComm::InitUDMA"); + const auto initCcuBackendBegin = commSourceText.find("int TileXRComm::InitCcuBackend"); + if (initUdmaBegin == std::string::npos || initCcuBackendBegin == std::string::npos || + initUdmaBegin >= initCcuBackendBegin) { + std::cerr << commSourcePath << ": cannot isolate InitUDMA body" << std::endl; + ++g_failures; + } else { + const auto initUdmaBody = commSourceText.substr(initUdmaBegin, initCcuBackendBegin - initUdmaBegin); + CheckNotContains(commSourcePath, initUdmaBody, "RefreshDirectCcuBasicInfo"); + CheckNotContains(commSourcePath, initUdmaBody, "ResetDirectCcuBasicInfo"); + } + + const auto registerUdmaBegin = commSourceText.find("int TileXRComm::RegisterUDMAMemory"); + const auto unregisterUdmaBegin = commSourceText.find("int TileXRComm::UnregisterUDMAMemory"); + const auto getUdmaRegistryBegin = commSourceText.find("GM_ADDR TileXRComm::GetUDMARegistryPtr"); + if (registerUdmaBegin == std::string::npos || unregisterUdmaBegin == std::string::npos || + getUdmaRegistryBegin == std::string::npos || registerUdmaBegin >= unregisterUdmaBegin || + unregisterUdmaBegin >= getUdmaRegistryBegin) { + std::cerr << commSourcePath << ": cannot isolate UDMA memory registration bodies" << std::endl; + ++g_failures; + } else { + const auto registerUdmaBody = commSourceText.substr( + registerUdmaBegin, unregisterUdmaBegin - registerUdmaBegin); + const auto unregisterUdmaBody = commSourceText.substr( + unregisterUdmaBegin, getUdmaRegistryBegin - unregisterUdmaBegin); + CheckNotContains(commSourcePath, registerUdmaBody, "ResetDirectCcuLowerLayerPlan"); + CheckNotContains(commSourcePath, unregisterUdmaBody, "ResetDirectCcuLowerLayerPlan"); + } + + for (const auto& forbidden : { + "TileXRCcuPrepareSubmitTasks", + "TileXRCcuSubmitTask", + "rtCCULaunch", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + "libhcomm", + "libhccl_v2", + }) { + CheckNotContains(commHeaderPath, commHeaderText, forbidden); + CheckNotContains(commSourcePath, commSourceText, forbidden); + CheckNotContains(ccuBackendHeaderPath, ccuBackendHeaderText, forbidden); + CheckNotContains(ccuBackendSourcePath, ccuBackendSourceText, forbidden); + CheckNotContains(ccuRuntimeSessionHeaderPath, ccuRuntimeSessionHeaderText, forbidden); + CheckNotContains(ccuRuntimeSessionSourcePath, ccuRuntimeSessionSourceText, forbidden); + CheckNotContains(ccuPlannerHeaderPath, ccuPlannerHeaderText, forbidden); + CheckNotContains(ccuPlannerSourcePath, ccuPlannerSourceText, forbidden); + CheckNotContains(ccuExecutorHeaderPath, ccuExecutorHeaderText, forbidden); + CheckNotContains(ccuExecutorSourcePath, ccuExecutorSourceText, forbidden); + CheckNotContains(ccuRuntimeHeaderPath, ccuRuntimeHeaderText, forbidden); + CheckNotContains(ccuRuntimeSourcePath, ccuRuntimeSourceText, forbidden); + } +} + +void TestCcuRuntimeSubmitBoundaryUsesPublicRuntimeOnly() +{ + const std::string cmakePath = "src/comm/CMakeLists.txt"; + const std::string abiConstantsHeaderPath = "src/comm/ccu/tilexr_ccu_abi_constants.h"; + const std::string barrierHeaderPath = "src/comm/ccu/tilexr_ccu_barrier_program.h"; + const std::string barrierSourcePath = "src/comm/ccu/tilexr_ccu_barrier_program.cpp"; + const std::string directHeaderPath = "src/comm/ccu/tilexr_ccu_direct_orchestrator.h"; + const std::string directSourcePath = "src/comm/ccu/tilexr_ccu_direct_orchestrator.cpp"; + const std::string directRuntimeHeaderPath = "src/comm/ccu/tilexr_ccu_direct_runtime.h"; + const std::string directRuntimeSourcePath = "src/comm/ccu/tilexr_ccu_direct_runtime.cpp"; + const std::string driverHeaderPath = "src/comm/ccu/tilexr_ccu_driver_adapter.h"; + const std::string driverSourcePath = "src/comm/ccu/tilexr_ccu_driver_adapter.cpp"; + const std::string hccpTypesHeaderPath = "src/comm/ccu/tilexr_ccu_hccp_types.h"; + const std::string hccpLoaderHeaderPath = "src/comm/ccu/tilexr_ccu_hccp_loader.h"; + const std::string hccpLoaderSourcePath = "src/comm/ccu/tilexr_ccu_hccp_loader.cpp"; + const std::string installHeaderPath = "src/comm/ccu/tilexr_ccu_install_provider.h"; + const std::string installSourcePath = "src/comm/ccu/tilexr_ccu_install_provider.cpp"; + const std::string lowerLayerPlanHeaderPath = "src/comm/ccu/tilexr_ccu_lower_layer_plan_builder.h"; + const std::string lowerLayerPlanSourcePath = "src/comm/ccu/tilexr_ccu_lower_layer_plan_builder.cpp"; + const std::string packageHeaderPath = "src/comm/ccu/tilexr_ccu_launch_package.h"; + const std::string packageSourcePath = "src/comm/ccu/tilexr_ccu_launch_package.cpp"; + const std::string microcodeHeaderPath = "src/comm/ccu/tilexr_ccu_microcode.h"; + const std::string microcodeSourcePath = "src/comm/ccu/tilexr_ccu_microcode.cpp"; + const std::string planHeaderPath = "src/comm/ccu/tilexr_ccu_producer_plan.h"; + const std::string planSourcePath = "src/comm/ccu/tilexr_ccu_producer_plan.cpp"; + const std::string providerHeaderPath = "src/comm/ccu/tilexr_ccu_provider.h"; + const std::string providerSourcePath = "src/comm/ccu/tilexr_ccu_provider.cpp"; + const std::string raProviderHeaderPath = "src/comm/ccu/tilexr_ccu_ra_custom_channel_provider.h"; + const std::string raProviderSourcePath = "src/comm/ccu/tilexr_ccu_ra_custom_channel_provider.cpp"; + const std::string repositoryHeaderPath = "src/comm/ccu/tilexr_ccu_repository.h"; + const std::string repositorySourcePath = "src/comm/ccu/tilexr_ccu_repository.cpp"; + const std::string allocatorHeaderPath = "src/comm/ccu/tilexr_ccu_resource_allocator.h"; + const std::string allocatorSourcePath = "src/comm/ccu/tilexr_ccu_resource_allocator.cpp"; + const std::string specsHeaderPath = "src/comm/ccu/tilexr_ccu_specs.h"; + const std::string specsSourcePath = "src/comm/ccu/tilexr_ccu_specs.cpp"; + const std::string headerPath = "src/comm/ccu/tilexr_ccu_runtime.h"; + const std::string sourcePath = "src/comm/ccu/tilexr_ccu_runtime.cpp"; + const auto cmakeText = ReadFile(cmakePath); + const auto abiConstantsHeaderText = ReadFile(abiConstantsHeaderPath); + const auto barrierHeaderText = ReadFile(barrierHeaderPath); + const auto barrierSourceText = ReadFile(barrierSourcePath); + const auto directHeaderText = ReadFile(directHeaderPath); + const auto directSourceText = ReadFile(directSourcePath); + const auto directRuntimeHeaderText = ReadFile(directRuntimeHeaderPath); + const auto directRuntimeSourceText = ReadFile(directRuntimeSourcePath); + const auto driverHeaderText = ReadFile(driverHeaderPath); + const auto driverSourceText = ReadFile(driverSourcePath); + const auto hccpTypesHeaderText = ReadFile(hccpTypesHeaderPath); + const auto hccpLoaderHeaderText = ReadFile(hccpLoaderHeaderPath); + const auto hccpLoaderSourceText = ReadFile(hccpLoaderSourcePath); + const auto installHeaderText = ReadFile(installHeaderPath); + const auto installSourceText = ReadFile(installSourcePath); + const auto lowerLayerPlanHeaderText = ReadFile(lowerLayerPlanHeaderPath); + const auto lowerLayerPlanSourceText = ReadFile(lowerLayerPlanSourcePath); + const auto packageHeaderText = ReadFile(packageHeaderPath); + const auto packageSourceText = ReadFile(packageSourcePath); + const auto microcodeHeaderText = ReadFile(microcodeHeaderPath); + const auto microcodeSourceText = ReadFile(microcodeSourcePath); + const auto planHeaderText = ReadFile(planHeaderPath); + const auto planSourceText = ReadFile(planSourcePath); + const auto providerHeaderText = ReadFile(providerHeaderPath); + const auto providerSourceText = ReadFile(providerSourcePath); + const auto raProviderHeaderText = ReadFile(raProviderHeaderPath); + const auto raProviderSourceText = ReadFile(raProviderSourcePath); + const auto repositoryHeaderText = ReadFile(repositoryHeaderPath); + const auto repositorySourceText = ReadFile(repositorySourcePath); + const auto allocatorHeaderText = ReadFile(allocatorHeaderPath); + const auto allocatorSourceText = ReadFile(allocatorSourcePath); + const auto specsHeaderText = ReadFile(specsHeaderPath); + const auto specsSourceText = ReadFile(specsSourcePath); + const auto headerText = ReadFile(headerPath); + const auto sourceText = ReadFile(sourcePath); + + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_abi_constants.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_barrier_program.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_barrier_program.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_driver_adapter.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_direct_orchestrator.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_direct_orchestrator.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_direct_runtime.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_direct_runtime.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_driver_adapter.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_hccp_types.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_hccp_loader.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_hccp_loader.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_launch_package.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_launch_package.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_install_provider.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_install_provider.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_lower_layer_plan_builder.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_lower_layer_plan_builder.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_microcode.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_microcode.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_producer_plan.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_producer_plan.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_provider.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_provider.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_ra_custom_channel_provider.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_ra_custom_channel_provider.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_repository.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_repository.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_resource_allocator.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_resource_allocator.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_runtime.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_runtime.cpp"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_specs.h"); + CheckContains(cmakePath, cmakeText, "ccu/tilexr_ccu_specs.cpp"); + + CheckContains(abiConstantsHeaderPath, abiConstantsHeaderText, "TILEXR_CCU_EID_BYTES"); + CheckContains(abiConstantsHeaderPath, abiConstantsHeaderText, "TILEXR_CCU_REMOTE_CCU_VA_SHIFT"); + CheckNotContains(abiConstantsHeaderPath, abiConstantsHeaderText, "runtime/kernel.h"); + CheckNotContains(abiConstantsHeaderPath, abiConstantsHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(directHeaderPath, directHeaderText, "TileXRCcuDirectInstallOptions"); + CheckContains(directHeaderPath, directHeaderText, "TileXRCcuDirectInstallAttempt"); + CheckContains(directHeaderPath, directHeaderText, "TileXRCcuDirectInstallReport"); + CheckContains(directHeaderPath, directHeaderText, "TileXRCcuRunDirectInstallAttempt"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuDecodeBasicInfo"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuBuildResourceSpec"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuResourceAllocator"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuBuildLaunchPackage"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuBindLaunchPackageInstallScope"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuBuildInstallManifest"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuInstallHardware"); + CheckContains(directSourcePath, directSourceText, "TileXRCcuPrepareSubmitTasks"); + CheckNotContains(directHeaderPath, directHeaderText, "runtime/kernel.h"); + CheckNotContains(directHeaderPath, directHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(directRuntimeHeaderPath, directRuntimeHeaderText, "TileXRCcuDirectRuntime"); + CheckContains(directRuntimeHeaderPath, directRuntimeHeaderText, "QueryBasicInfo"); + CheckContains(directRuntimeHeaderPath, directRuntimeHeaderText, "CreateDriverAdapter"); + CheckContains(directRuntimeHeaderPath, directRuntimeHeaderText, "RegisterCcuResourceRmaBuffer"); + CheckContains(directRuntimeSourcePath, directRuntimeSourceText, "TileXRCcuRaCustomChannelProvider"); + CheckContains(directRuntimeSourcePath, directRuntimeSourceText, "loader_.Load"); + CheckContains(directRuntimeSourcePath, directRuntimeSourceText, "loader_.ResolveDevicePhyId"); + CheckContains(directRuntimeSourcePath, directRuntimeSourceText, "loader_.RaCustomChannel"); + CheckNotContains(directRuntimeHeaderPath, directRuntimeHeaderText, "udma/"); + CheckNotContains(directRuntimeSourcePath, directRuntimeSourceText, "udma/"); + + CheckContains(driverHeaderPath, driverHeaderText, "TileXRCcuDriverAdapter"); + CheckContains(driverHeaderPath, driverHeaderText, "TileXRCcuCustomChannelIn"); + CheckContains(driverHeaderPath, driverHeaderText, "TILEXR_CCU_U_OP_GET_BASIC_INFO"); + CheckContains(driverHeaderPath, driverHeaderText, "TILEXR_CCU_U_OP_GET_DIE_WORKING"); + CheckContains(driverHeaderPath, driverHeaderText, "GetBasicInfo"); + CheckContains(driverHeaderPath, driverHeaderText, "GetDieEnabled"); + CheckNotContains(driverHeaderPath, driverHeaderText, "runtime/kernel.h"); + CheckNotContains(driverHeaderPath, driverHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallRequest"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallManifest"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallManifestReport"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallRequirement"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallRequirementKind"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuBuildInstallManifest"); + CheckContains(installHeaderPath, installHeaderText, "provider"); + CheckContains(installHeaderPath, installHeaderText, "manifest"); + CheckContains(installHeaderPath, installHeaderText, "installAttemptReceiptRequired"); + CheckContains(installHeaderPath, installHeaderText, "requiredEvidenceKind"); + CheckContains(installHeaderPath, installHeaderText, "requiredEvidenceSurface"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallStepEvidence"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallProviderReport"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuBuildInstallEvidence"); + CheckContains(installHeaderPath, installHeaderText, "TileXRCcuInstallHardware"); + CheckContains(installHeaderPath, installHeaderText, "installAttemptReceiptId"); + CheckContains(installSourcePath, installSourceText, "ValidateInstallRequestScope"); + CheckContains(installSourcePath, installSourceText, "ValidateInstallManifestScope"); + CheckContains(installSourcePath, installSourceText, "ValidateInstallRequestManifest"); + CheckContains(installSourcePath, installSourceText, "ValidatePublicVerifiedStepScope"); + CheckContains(installHeaderPath, installHeaderText, "requiredInstallSurfaceCount"); + CheckContains(installHeaderPath, installHeaderText, "publicVerifiedInstallSurfaceCount"); + CheckContains(installHeaderPath, installHeaderText, "missingInstallSurfaceCount"); + CheckContains(installSourcePath, installSourceText, "FillManifestInstallSurfaceCounts"); + CheckContains(installSourcePath, installSourceText, "launch install scope is stale"); + CheckContains(installSourcePath, installSourceText, "install manifest requirement kind mismatch"); + CheckContains(installSourcePath, installSourceText, "install manifest hardware requirement mismatch"); + CheckContains(installSourcePath, installSourceText, "install manifest mission requirement mismatch"); + CheckContains(installSourcePath, installSourceText, "install manifest channel requirement mismatch"); + CheckContains(installSourcePath, installSourceText, "public verified evidence scope is incomplete"); + CheckContains(installSourcePath, installSourceText, "missing CCU repository image for install manifest"); + CheckContains(installSourcePath, installSourceText, "install generated CCU repository image"); + CheckContains(installSourcePath, installSourceText, "bind CCU channel routes for sync resources"); + CheckContains(installHeaderPath, installHeaderText, "localWaitCke"); + CheckContains(installSourcePath, installSourceText, "local wait CKE"); + CheckContains(installSourcePath, installSourceText, "remote notify CKE"); + CheckContains(installSourcePath, installSourceText, "ValidateInstallReceipt"); + CheckContains(installSourcePath, installSourceText, "install attempt did not succeed"); + CheckContains(installSourcePath, installSourceText, "install attempt receipt mismatch"); + CheckContains(installSourcePath, installSourceText, "device scope mismatch"); + CheckContains(installSourcePath, installSourceText, "rank scope mismatch"); + CheckContains(installSourcePath, installSourceText, "provider scope mismatch"); + CheckContains(installHeaderPath, installHeaderText, "tilexr_ccu_provider.h"); + CheckNotContains(installHeaderPath, installHeaderText, "runtime/kernel.h"); + CheckNotContains(installHeaderPath, installHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(lowerLayerPlanHeaderPath, lowerLayerPlanHeaderText, "TileXRCcuLowerLayerPlanSpec"); + CheckContains(lowerLayerPlanHeaderPath, lowerLayerPlanHeaderText, "TileXRCcuBuildLowerLayerInstallPlan"); + CheckContains(lowerLayerPlanHeaderPath, lowerLayerPlanHeaderText, "remoteNotifyCke"); + CheckContains(lowerLayerPlanSourcePath, lowerLayerPlanSourceText, "TileXRCcuBuildPfeCtx"); + CheckContains(lowerLayerPlanSourcePath, lowerLayerPlanSourceText, "TileXRCcuBuildLocalJettyCtx"); + CheckContains(lowerLayerPlanSourcePath, lowerLayerPlanSourceText, "TileXRCcuBuildChannelCtxV1"); + CheckContains(lowerLayerPlanSourcePath, lowerLayerPlanSourceText, "localWaitCke"); + CheckNotContains(lowerLayerPlanHeaderPath, lowerLayerPlanHeaderText, "runtime/kernel.h"); + CheckNotContains(lowerLayerPlanHeaderPath, lowerLayerPlanHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuLaunchPackage"); + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuLaunchPackageReport"); + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuBuildLaunchPackage"); + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuComputeLaunchPackageFingerprint"); + CheckContains(packageSourcePath, packageSourceText, "TileXRCcuComputeLaunchPackageFingerprint"); + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuLaunchInstallScope"); + CheckContains(packageHeaderPath, packageHeaderText, "installScope"); + CheckContains(packageHeaderPath, packageHeaderText, "TileXRCcuBindLaunchPackageInstallScope"); + CheckContains(packageSourcePath, packageSourceText, "TileXRCcuBindLaunchPackageInstallScope"); + CheckContains(packageHeaderPath, packageHeaderText, "requiresHardwareInstall"); + CheckContains(packageHeaderPath, packageHeaderText, "tilexr_ccu_repository.h"); + CheckNotContains(packageHeaderPath, packageHeaderText, "runtime/kernel.h"); + CheckNotContains(packageHeaderPath, packageHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(microcodeHeaderPath, microcodeHeaderText, "struct TileXRCcuInstr"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "struct TileXRCcuSyncXnSpec"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "struct TileXRCcuCkeSpec"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "TileXRCcuEncodeLoadSqeArgsToX"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "TileXRCcuEncodeSyncXn"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "TileXRCcuEncodeSetCke"); + CheckContains(microcodeHeaderPath, microcodeHeaderText, "TileXRCcuEncodeClearCke"); + CheckContains(microcodeSourcePath, microcodeSourceText, "0x0001U"); + CheckContains(microcodeSourcePath, microcodeSourceText, "0x0802U"); + CheckContains(microcodeSourcePath, microcodeSourceText, "0x0804U"); + CheckContains(microcodeSourcePath, microcodeSourceText, "0x100dU"); + CheckNotContains(microcodeHeaderPath, microcodeHeaderText, "runtime/kernel.h"); + CheckNotContains(microcodeHeaderPath, microcodeHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(barrierHeaderPath, barrierHeaderText, "TileXRCcuBarrierSyncSpec"); + CheckContains(barrierHeaderPath, barrierHeaderText, "TileXRCcuBarrierProgramReport"); + CheckContains(barrierHeaderPath, barrierHeaderText, "TileXRCcuBuildBarrierProgram"); + CheckContains(barrierSourcePath, barrierSourceText, "TileXRCcuEncodeSyncXn"); + CheckContains(barrierSourcePath, barrierSourceText, "TileXRCcuEncodeClearCke"); + CheckNotContains(barrierHeaderPath, barrierHeaderText, "runtime/kernel.h"); + CheckNotContains(barrierHeaderPath, barrierHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuProducerPlan"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuValidateProducerPlan"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuBuildTasks"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuBuildMicrocode"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuSyncResource"); + CheckContains(planHeaderPath, planHeaderText, "localWaitCke"); + CheckContains(planHeaderPath, planHeaderText, "localWaitMask"); + CheckContains(planHeaderPath, planHeaderText, "remoteNotifyMask"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuInstructionWindow"); + CheckContains(planHeaderPath, planHeaderText, "TileXRCcuProgram"); + CheckContains(planHeaderPath, planHeaderText, "tilexr_ccu_barrier_program.h"); + CheckContains(planSourcePath, planSourceText, "TileXRCcuBuildBarrierProgram"); + CheckContains(planSourcePath, planSourceText, "spec.localWaitCke"); + CheckNotContains(planHeaderPath, planHeaderText, "runtime/kernel.h"); + CheckNotContains(planHeaderPath, planHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(providerHeaderPath, providerHeaderText, "TileXRCcuHardwareInstallEvidence"); + CheckContains(providerHeaderPath, providerHeaderText, "TileXRCcuValidateHardwareInstall"); + CheckContains(providerHeaderPath, providerHeaderText, "TileXRCcuPrepareSubmitTasks"); + CheckContains(providerHeaderPath, providerHeaderText, "submitReady"); + CheckContains(providerHeaderPath, providerHeaderText, "packageFingerprint"); + CheckContains(providerHeaderPath, providerHeaderText, "deviceId"); + CheckContains(providerHeaderPath, providerHeaderText, "rank"); + CheckContains(providerHeaderPath, providerHeaderText, "provider"); + CheckContains(providerHeaderPath, providerHeaderText, "installAttemptReceiptId"); + CheckContains(providerSourcePath, providerSourceText, "package fingerprint mismatch"); + CheckContains(providerSourcePath, providerSourceText, "launch install scope is not bound"); + CheckContains(providerSourcePath, providerSourceText, "device scope mismatch"); + CheckContains(providerSourcePath, providerSourceText, "rank scope mismatch"); + CheckContains(providerSourcePath, providerSourceText, "provider scope mismatch"); + CheckContains(providerSourcePath, providerSourceText, "install attempt receipt is missing"); + CheckContains(providerSourcePath, providerSourceText, "install attempt receipt mismatch"); + CheckContains(providerHeaderPath, providerHeaderText, "tilexr_ccu_launch_package.h"); + CheckNotContains(providerHeaderPath, providerHeaderText, "runtime/kernel.h"); + CheckNotContains(providerHeaderPath, providerHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(raProviderHeaderPath, raProviderHeaderText, "TileXRCcuRaCustomChannelProvider"); + CheckContains(raProviderHeaderPath, raProviderHeaderText, "CreateAdapter"); + CheckContains(raProviderHeaderPath, raProviderHeaderText, "TileXRCcuRaCustomChannelFunc"); + CheckContains(raProviderSourcePath, raProviderSourceText, "TILEXR_CCU_NETWORK_OFFLINE"); + CheckNotContains(raProviderHeaderPath, raProviderHeaderText, "udma/"); + CheckNotContains(raProviderHeaderPath, raProviderHeaderText, "runtime/kernel.h"); + CheckNotContains(raProviderHeaderPath, raProviderHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(hccpTypesHeaderPath, hccpTypesHeaderText, "TileXRCcuRaInfo"); + CheckContains(hccpTypesHeaderPath, hccpTypesHeaderText, "TileXRCcuRaCustomChannelFunc"); + CheckContains(hccpLoaderHeaderPath, hccpLoaderHeaderText, "TileXRCcuHccpLoader"); + CheckContains(hccpLoaderSourcePath, hccpLoaderSourceText, "dlopen(\"libra.so\", RTLD_NOW)"); + CheckContains(hccpLoaderSourcePath, hccpLoaderSourceText, "RaCustomChannel"); + CheckContains(hccpLoaderSourcePath, hccpLoaderSourceText, "rtGetDevicePhyIdByIndex"); + + CheckContains(repositoryHeaderPath, repositoryHeaderText, "TileXRCcuRepositoryImage"); + CheckContains(repositoryHeaderPath, repositoryHeaderText, "TileXRCcuRepositoryReport"); + CheckContains(repositoryHeaderPath, repositoryHeaderText, "TileXRCcuBuildRepositoryImage"); + CheckContains(repositoryHeaderPath, repositoryHeaderText, "missionOffset"); + CheckContains(repositoryHeaderPath, repositoryHeaderText, "sqeLoadOffset"); + CheckContains(repositoryHeaderPath, repositoryHeaderText, "syncOffset"); + CheckNotContains(repositoryHeaderPath, repositoryHeaderText, "runtime/kernel.h"); + CheckNotContains(repositoryHeaderPath, repositoryHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(allocatorHeaderPath, allocatorHeaderText, "TileXRCcuResourceAllocator"); + CheckContains(allocatorHeaderPath, allocatorHeaderText, "TileXRCcuResourceSpec"); + CheckContains(allocatorHeaderPath, allocatorHeaderText, "TileXRCcuResourceRequest"); + CheckContains(allocatorSourcePath, allocatorSourceText, "TileXRCcuValidateProducerPlan"); + CheckNotContains(allocatorHeaderPath, allocatorHeaderText, "runtime/kernel.h"); + CheckNotContains(allocatorHeaderPath, allocatorHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(specsHeaderPath, specsHeaderText, "TileXRCcuBasicInfo"); + CheckContains(specsHeaderPath, specsHeaderText, "TileXRCcuDecodeBasicInfo"); + CheckContains(specsHeaderPath, specsHeaderText, "TileXRCcuBuildResourceSpec"); + CheckContains(specsSourcePath, specsSourceText, "TILEXR_CCU_V1_XN_RESOURCE_OFFSET"); + CheckNotContains(specsHeaderPath, specsHeaderText, "runtime/kernel.h"); + CheckNotContains(specsHeaderPath, specsHeaderText, "rtCcuTaskInfo_t"); + + CheckContains(headerPath, headerText, "TILEXR_CCU_SQE_ARGS_LEN"); + CheckContains(headerPath, headerText, "struct TileXRCcuTask"); + CheckContains(headerPath, headerText, "TileXRCcuValidateTask"); + CheckContains(headerPath, headerText, "TileXRCcuSubmitTask"); + CheckNotContains(headerPath, headerText, "runtime/kernel.h"); + CheckNotContains(headerPath, headerText, "rtCcuTaskInfo_t"); + + CheckContains(sourcePath, sourceText, "#include "); + CheckContains(sourcePath, sourceText, "rtCcuTaskInfo_t runtimeTask"); + CheckContains(sourcePath, sourceText, "rtCCULaunch(&runtimeTask, stream)"); + CheckContains(sourcePath, sourceText, "RT_CCU_INST_CNT_INVALID"); + CheckContains(sourcePath, sourceText, "RT_CCU_INST_START_MAX"); + CheckContains(sourcePath, sourceText, "task.argSize != 1 && task.argSize != TILEXR_CCU_SQE_ARGS_LEN"); + CheckContains(sourcePath, sourceText, "TILEXR_ERROR_MKIRT"); + + for (const auto& privateNeedle : { + "#include ", + "#include \"hccl.h\"", + "pkg_inc/hcomm", + "pkg_inc/hccl", + "include/hccl", + "${ARCH}-linux/include/hccl", + "${ASCEND_HOME_PATH}/${ARCH}-linux/include/hccl", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "HcclCcuKernel", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + "HcclChannelAcquire", + "HcclGetChannelForCcu", + "CcuResBatchAllocator", + "CcuResRepository", + "GetMissionKey", + "SetMissionId", + "SetMissionKey", + "SetInstrId", + "SetCcuInstrInfo", + "LoadInstruction", + "AllocIns", + "AllocXn", + "AllocCke", + "RT_RES_TYPE_CCU_CKE", + "RT_RES_TYPE_CCU_XN", + "dlopen", + "dlsym", + }) { + CheckNotContains(directSourcePath, directSourceText, privateNeedle); + CheckNotContains(abiConstantsHeaderPath, abiConstantsHeaderText, privateNeedle); + CheckNotContains(directHeaderPath, directHeaderText, privateNeedle); + CheckNotContains(directRuntimeSourcePath, directRuntimeSourceText, privateNeedle); + CheckNotContains(directRuntimeHeaderPath, directRuntimeHeaderText, privateNeedle); + CheckNotContains(driverSourcePath, driverSourceText, privateNeedle); + CheckNotContains(driverHeaderPath, driverHeaderText, privateNeedle); + CheckNotContains(barrierSourcePath, barrierSourceText, privateNeedle); + CheckNotContains(barrierHeaderPath, barrierHeaderText, privateNeedle); + CheckNotContains(installSourcePath, installSourceText, privateNeedle); + CheckNotContains(installHeaderPath, installHeaderText, privateNeedle); + CheckNotContains(packageSourcePath, packageSourceText, privateNeedle); + CheckNotContains(packageHeaderPath, packageHeaderText, privateNeedle); + CheckNotContains(microcodeSourcePath, microcodeSourceText, privateNeedle); + CheckNotContains(microcodeHeaderPath, microcodeHeaderText, privateNeedle); + CheckNotContains(planSourcePath, planSourceText, privateNeedle); + CheckNotContains(planHeaderPath, planHeaderText, privateNeedle); + CheckNotContains(providerSourcePath, providerSourceText, privateNeedle); + CheckNotContains(providerHeaderPath, providerHeaderText, privateNeedle); + CheckNotContains(raProviderSourcePath, raProviderSourceText, privateNeedle); + CheckNotContains(raProviderHeaderPath, raProviderHeaderText, privateNeedle); + CheckNotContains(repositorySourcePath, repositorySourceText, privateNeedle); + CheckNotContains(repositoryHeaderPath, repositoryHeaderText, privateNeedle); + CheckNotContains(allocatorSourcePath, allocatorSourceText, privateNeedle); + CheckNotContains(allocatorHeaderPath, allocatorHeaderText, privateNeedle); + CheckNotContains(specsSourcePath, specsSourceText, privateNeedle); + CheckNotContains(specsHeaderPath, specsHeaderText, privateNeedle); + CheckNotContains(sourcePath, sourceText, privateNeedle); + CheckNotContains(headerPath, headerText, privateNeedle); + } + + for (const auto& loaderPrivateNeedle : { + "#include ", + "#include \"hccl.h\"", + "pkg_inc/hcomm", + "pkg_inc/hccl", + "include/hccl", + "libhcomm", + "libhccl_v2", + "libhccl_fwk", + "libmc2_client", + "HcclGetCcuTaskInfo", + "HcomGetCcuTaskInfo", + }) { + CheckNotContains(hccpTypesHeaderPath, hccpTypesHeaderText, loaderPrivateNeedle); + CheckNotContains(hccpLoaderHeaderPath, hccpLoaderHeaderText, loaderPrivateNeedle); + CheckNotContains(hccpLoaderSourcePath, hccpLoaderSourceText, loaderPrivateNeedle); + } + + CheckTrackedFilesContainNeedleOnly( + "public CCU runtime launch ABI", + "src/comm src/include", + "rtCCULaunch", + {sourcePath}); + CheckTrackedFilesContainNeedleOnly( + "public CCU runtime kernel header", + "src/comm src/include", + "runtime/kernel.h", + {sourcePath}); +} + +void TestDirectCcuHeadersOwnStandardDependencies() +{ + const std::string commHeaderPath = "src/comm/tilexr_comm.h"; + const std::string abiConstantsPath = "src/comm/ccu/tilexr_ccu_abi_constants.h"; + const std::string hccpTypesPath = "src/comm/ccu/tilexr_ccu_hccp_types.h"; + const auto commHeaderText = ReadFile(commHeaderPath); + const auto abiConstantsText = ReadFile(abiConstantsPath); + const auto hccpTypesText = ReadFile(hccpTypesPath); + + CheckContains(commHeaderPath, commHeaderText, "#include "); + CheckContains(abiConstantsPath, abiConstantsText, "#include "); + CheckContains(hccpTypesPath, hccpTypesText, "#include "); + CheckContains(hccpTypesPath, hccpTypesText, "tilexr_ccu_abi_constants.h"); + CheckContains(hccpTypesPath, hccpTypesText, "TileXRCcuEndpointRouteProviderFunc"); + CheckNotContains(hccpTypesPath, hccpTypesText, "tilexr_ccu_driver_adapter.h"); + CheckNotContains(hccpTypesPath, hccpTypesText, "tilexr_ccu_lower_layer_payloads.h"); + CheckNotContains(abiConstantsPath, abiConstantsText, "udma/"); + CheckNotContains(hccpTypesPath, hccpTypesText, "udma/"); + CheckNotContains(hccpTypesPath, hccpTypesText, ""); + CheckNotContains(hccpTypesPath, hccpTypesText, "dlopen"); + CheckNotContains(hccpTypesPath, hccpTypesText, "dlsym"); + CheckNotContains(hccpTypesPath, hccpTypesText, "std::string"); } } // namespace @@ -205,7 +1014,12 @@ int main() TestRuntimeEnvDoesNotPrependCannDevlib(); TestRootCMakeRespectsAscendDriverOverride(); TestCommBuildIncludesProfilingHeaders(); - TestChipMapCoversObservedAscend950Variants(); + TestChipNameResolverRecognizesAscend950PrVariants(); + TestCommRuntimeDoesNotUseHcommOrHcclV2(); + TestRootCMakeHcclIncludesAreNotTileCommSurface(); + TestCommDirectCcuInstallAttemptDoesNotSubmit(); + TestCcuRuntimeSubmitBoundaryUsesPublicRuntimeOnly(); + TestDirectCcuHeadersOwnStandardDependencies(); if (g_failures != 0) { std::cerr << g_failures << " TileXR source guard checks failed" << std::endl;