LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_kernel - ccu_kernel.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.4 % 1913 1500
Test Date: 2026-08-25 19:18:03 Functions: 85.6 % 208 178

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "ccu_kernel.h"
      12              : 
      13              : #include <algorithm>
      14              : 
      15              : #include "ccu_rep_v1.h"
      16              : #include "ccu_kernel_resource.h"
      17              : #include "ccu_microcode_v1.h"
      18              : 
      19              : #include "ccu_types.h"
      20              : #include "exception_util.h"
      21              : #include "ccu_api_exception.h"
      22              : #include "ccu_dev_mgr_imp.h"
      23              : #include "env_config.h"
      24              : #include "ccu_rep_type_v1.h"
      25              : 
      26              : #include "hcomm_c_adpt.h"
      27              : 
      28              : #include "ccu_rep_context_v1.h"
      29              : #include "ccu_rep_funccall_v1.h"
      30              : #include "../../endpoint_pairs/channels/ccu/ccu_urma_channel.h"
      31              : #include "../ccu_instance/ccu_var_event_res_mgr.h"
      32              : 
      33              : #include "ccu_log.h"
      34              : 
      35              : #include "hcom_common.h"
      36              : 
      37              : // todo: 引入头文件需要检查
      38              : #include "ccu_assist_v1.h"
      39              : #include "hccl_comm_pub.h"
      40              : #include "hcclCommDfx.h"
      41              : #include "task_info.h"
      42              : #include "task_param.h"
      43              : 
      44              : #include "ccu_ins_generator_base.h"
      45              : #include "ccu_ins_generator_v1.h"
      46              : #include "unified_platform/pub_inc/config_plf_log.h"
      47              : 
      48              : namespace hcomm {
      49              : 
      50              : using Hccl::PLF_DATA_OP;
      51              : 
      52              : constexpr uint32_t TOKEN_VALUE_INDEX = 2;
      53              : constexpr uint16_t INVALID_U16 = 65535;
      54              : 
      55              : using CcuRep::CcuInsGeneratorBase;
      56              : using CcuRep::CcuInsGeneratorV1;
      57              : 
      58              : template <typename T>
      59          217 : T CcuKernel::CreateResAssist(std::array<std::vector<T>, CCU_MAX_IODIE_NUM>& resRecord)
      60              : {
      61              :     // kernel确认die之前默认为0,需要刷新资源
      62              :     // 确认die之后按实际使用die分配资源
      63          217 :     const uint32_t dieId = GetDieId();
      64          217 :     resRecord[dieId].emplace_back(this);
      65          217 :     auto& item = resRecord[dieId].back();
      66          217 :     item.Reset(resRecord[dieId].size(), dieId);
      67          217 :     return item;
      68              : }
      69              : 
      70              : template <typename T>
      71              : std::vector<T>
      72          892 : CcuKernel::CreateBlockResAssist(const uint32_t count, std::array<std::vector<T>, CCU_MAX_IODIE_NUM>& resRecord)
      73              : {
      74          892 :     constexpr uint16_t CCU_BLOCK_RES_ID_BASE = 0x1000; // block 批量分配资源 id 基址,与单资源 id 区间隔离便于 DFX 定位
      75          892 :     std::vector<T> block;
      76          892 :     block.reserve(count);
      77          892 :     const uint32_t dieId = GetDieId();
      78         2160 :     for (size_t i = 0; i < count; i++) {
      79         1268 :         block.emplace_back(this);
      80         1268 :         block.back().Reset(static_cast<uint16_t>(CCU_BLOCK_RES_ID_BASE + resRecord[dieId].size() + i), dieId);
      81              :     }
      82          892 :     resRecord[dieId].insert(resRecord[dieId].end(), block.begin(), block.end());
      83          892 :     return block;
      84            0 : }
      85              : 
      86          172 : CcuKernel::~CcuKernel() {}
      87              : 
      88           11 : static HcclResult GetDieIdByChannel(const ChannelHandle channel, uint32_t& dieId)
      89              : {
      90           11 :     void* channelPtr{nullptr};
      91           11 :     CHK_RET(static_cast<HcclResult>(HcommChannelGet(channel, &channelPtr)));
      92           11 :     auto* channelImpl = dynamic_cast<CcuUrmaChannel*>(static_cast<Channel*>(channelPtr));
      93           11 :     if (channelImpl == nullptr) {
      94            0 :         HCCL_ERROR("[%s] failed to cast channel[0x%llx] to CcuUrmaChannel", __func__, channel);
      95            0 :         return HcclResult::HCCL_E_PTR;
      96              :     }
      97           11 :     dieId = channelImpl->GetDieId();
      98           11 :     HCCL_INFO("[%s], channelHandle[0x%llx], dieId[%u]", __func__, channel, dieId);
      99           11 :     return HcclResult::HCCL_SUCCESS;
     100              : }
     101              : 
     102            1 : static HcclResult GetDieIdByChannels(const std::unordered_set<ChannelHandle>& channels, uint32_t& dieId)
     103              : {
     104            1 :     if (channels.empty()) {
     105            1 :         int32_t devLogicId = HcclGetThreadDeviceId();
     106            1 :         for (uint32_t die = 0; die < CCU_MAX_IODIE_NUM; die++) {
     107            1 :             bool enableFlag = false;
     108            2 :             CHK_RET(static_cast<HcclResult>(CcuGetDieEnableInfo(devLogicId, die, enableFlag)));
     109            1 :             if (enableFlag) {
     110            1 :                 dieId = die;
     111            1 :                 return HcclResult::HCCL_SUCCESS;
     112              :             }
     113              :         }
     114              : 
     115            0 :         HCCL_ERROR("[CcuKernel][%s] failed, all dies are disable, devLogicId[%d].", __func__, devLogicId);
     116            0 :         return HcclResult::HCCL_E_INTERNAL;
     117              :     }
     118              : 
     119            0 :     uint32_t firstDieId = 0;
     120            0 :     CHK_RET(GetDieIdByChannel(*channels.begin(), firstDieId));
     121            0 :     for (const auto channel : channels) {
     122            0 :         uint32_t nextDieId = 0;
     123            0 :         CHK_RET(GetDieIdByChannel(channel, nextDieId));
     124            0 :         if (firstDieId != nextDieId) {
     125            0 :             HCCL_ERROR("[%s] failed, the dies of channels are not same.", __func__);
     126            0 :             return HcclResult::HCCL_E_PARA;
     127              :         }
     128              :     }
     129              : 
     130            0 :     dieId = firstDieId;
     131            0 :     return HcclResult::HCCL_SUCCESS;
     132              : }
     133              : 
     134           58 : static HcclResult CheckChannelsDie(const std::unordered_set<ChannelHandle>& channels, const uint32_t targetDieId)
     135              : {
     136           66 :     for (const auto channel : channels) {
     137           11 :         uint32_t channelDieId = 0;
     138           14 :         CHK_RET(GetDieIdByChannel(channel, channelDieId));
     139           11 :         if (channelDieId != targetDieId) {
     140            3 :             HCCL_ERROR(
     141              :                 "[%s] failed, channel[0x%llx] dieId[%u] differs from target dieId[%u].", __func__, channel,
     142              :                 channelDieId, targetDieId);
     143            3 :             return HcclResult::HCCL_E_PARA;
     144              :         }
     145              :     }
     146           55 :     return HcclResult::HCCL_SUCCESS;
     147              : }
     148              : 
     149           56 : static void MoveResourcesToDie(CcuRepResource& res, uint32_t targetDieId)
     150              : {
     151           56 :     if (targetDieId == 0)
     152           55 :         return; // 初始资源位于die0,不用设置
     153              : 
     154           11 :     auto moveAndSet = [&](auto& arr) {
     155           11 :         arr[targetDieId] = std::move(arr[0]);
     156           11 :         for (auto& item : arr[targetDieId])
     157            0 :             item.SetDieId(targetDieId);
     158           12 :     };
     159              : 
     160            1 :     moveAndSet(res.ccubufs);
     161            1 :     moveAndSet(res.blockCcubufs);
     162            1 :     moveAndSet(res.executor);
     163            1 :     moveAndSet(res.blockExecutor);
     164            1 :     moveAndSet(res.completedEvent);
     165            1 :     moveAndSet(res.blockCompletedEvent);
     166            1 :     moveAndSet(res.address);
     167            1 :     moveAndSet(res.blockAddress);
     168            1 :     moveAndSet(res.continuousVariable);
     169            1 :     moveAndSet(res.variable);
     170            1 :     moveAndSet(res.localNotify);
     171              : }
     172              : 
     173           72 : HcclResult CcuKernel::SetupProfilingInfo(const char* kernelFuncName)
     174              : {
     175           72 :     if (kernelFuncName == nullptr || strlen(kernelFuncName) == 0) {
     176            0 :         name_ = std::string("CCU_KERNEL"); // 默认名称
     177            0 :         AddSqeProfiling(name_);
     178            0 :         return HcclResult::HCCL_SUCCESS;
     179              :     }
     180              : 
     181           72 :     constexpr size_t MAX_KERNEL_FUNC_NAME_LEN = 128;
     182           72 :     const auto nameLen = strlen(kernelFuncName);
     183           72 :     if (nameLen > MAX_KERNEL_FUNC_NAME_LEN) {
     184            0 :         name_ = std::string(kernelFuncName, MAX_KERNEL_FUNC_NAME_LEN);
     185            0 :         HCCL_WARNING("[CcuKernel][%s] kernelFuncName is too long, reset to %s.", __func__, name_.c_str());
     186              :     }
     187              : 
     188              :     // 生成SQE粒度profiling信息,此时未选择die,默认die 0
     189           72 :     AddSqeProfiling(name_);
     190           72 :     return HcclResult::HCCL_SUCCESS;
     191              : }
     192              : 
     193              : static HcclResult
     194           56 : UpdateProfilingInfo(std::vector<CcuProfilingInfo>& profilingInfos, uint32_t dieId, const std::string& kernelName)
     195              : {
     196           56 :     if (dieId == 0) {
     197              :         // 与默认dieId相同,不需要修改
     198           55 :         return HcclResult::HCCL_SUCCESS;
     199              :     }
     200              : 
     201              :     // 正常情况仅首个info包含die信息,仅应为CCU_TASK_PROFILING类型
     202            1 :     if (UNLIKELY(profilingInfos.empty())) {
     203              :         // profiling不属于主流程,不打断算子业务
     204            0 :         HCCL_INFO("[%s] passed, profiling infos are empty, ccu kernel func[%s].", __func__, kernelName.c_str());
     205            0 :         return HcclResult::HCCL_SUCCESS;
     206              :     }
     207              : 
     208              :     // 根据选择的die跟新profiling信息
     209            2 :     for (auto& info : profilingInfos) {
     210            1 :         info.dieId = dieId;
     211              :     }
     212              : 
     213            1 :     HCCL_INFO("[%s] reset profiling info dieId to [%u], ccu kernel func[%s].", __func__, dieId, kernelName.c_str());
     214            1 :     return HcclResult::HCCL_SUCCESS;
     215              : }
     216              : 
     217            1 : HcclResult CcuKernel::ApplyDieFromChannels()
     218              : {
     219            1 :     uint32_t dieId{0};
     220            1 :     CHK_RET(GetDieIdByChannels(channels_, dieId));
     221            1 :     CHK_PRT_RET(
     222              :         dieId >= CCU_MAX_IODIE_NUM,
     223              :         HCCL_ERROR("[CcuKernel][%s] failed, dieId[%u] should be less than [%u].", __func__, dieId, CCU_MAX_IODIE_NUM),
     224              :         HcclResult::HCCL_E_PARA);
     225            1 :     SetDieId(dieId);
     226            1 :     MoveResourcesToDie(res_, dieId);
     227            1 :     (void)UpdateProfilingInfo(profilingInfo, dieId, name_);
     228              : 
     229            1 :     return HcclResult::HCCL_SUCCESS;
     230              : }
     231              : 
     232           58 : HcclResult CcuKernel::ValidateAndApplyDie(const uint32_t targetDieId)
     233              : {
     234           58 :     CHK_PRT_RET(
     235              :         targetDieId >= CCU_MAX_IODIE_NUM,
     236              :         HCCL_ERROR(
     237              :             "[CcuKernel][%s] failed, dieId[%u] should be less than [%u].", __func__, targetDieId, CCU_MAX_IODIE_NUM),
     238              :         HcclResult::HCCL_E_PARA);
     239              : 
     240           58 :     const int32_t devLogicId = HcclGetThreadDeviceId();
     241           58 :     bool enableFlag = false;
     242           58 :     CHK_RET(static_cast<HcclResult>(CcuGetDieEnableInfo(devLogicId, static_cast<uint8_t>(targetDieId), enableFlag)));
     243           58 :     CHK_PRT_RET(
     244              :         !enableFlag,
     245              :         HCCL_ERROR(
     246              :             "[CcuKernel][%s] failed, target dieId[%u] is disabled, devLogicId[%d].", __func__, targetDieId, devLogicId),
     247              :         HcclResult::HCCL_E_PARA);
     248           58 :     CHK_RET(CheckChannelsDie(channels_, targetDieId));
     249              : 
     250           55 :     SetDieId(targetDieId);
     251           55 :     MoveResourcesToDie(res_, targetDieId);
     252           55 :     (void)UpdateProfilingInfo(profilingInfo, targetDieId, name_);
     253              : 
     254           55 :     return HcclResult::HCCL_SUCCESS;
     255              : }
     256              : 
     257           75 : void CcuKernel::SetInsGenerater(CcuInsGeneratorBase* insGeneratorBase) { insGenerator = insGeneratorBase; }
     258              : 
     259            5 : CcuResult CcuKernel::ValidateTaskArgs(const uint64_t* taskArgs, uint32_t argsNum) const
     260              : {
     261            5 :     if (loadArgUsedSet_.size() != argsNum) {
     262            0 :         HCCL_ERROR(
     263              :             "[CcuKernel][%s] failed, args number does not match the Load instruction, "
     264              :             "argsNum = %u, loaded = %zu",
     265              :             __func__, argsNum, loadArgUsedSet_.size());
     266            0 :         return CcuResult::CCU_E_INTERNAL;
     267              :     }
     268           50 :     for (uint32_t i = 0; i < argsNum; ++i) {
     269           45 :         if (loadArgUsedSet_.count(i) == 0) {
     270            0 :             HCCL_ERROR("[CcuKernel][%s] failed, argId %u not loaded (argsNum=%u)", __func__, i, argsNum);
     271            0 :             return CcuResult::CCU_E_INTERNAL;
     272              :         }
     273              :     }
     274            5 :     if (argsNum != 0) {
     275            3 :         CCU_CHK_PTR_NULL(taskArgs);
     276              :     }
     277            5 :     if (instrInfo_.missionInstrCount == 0 || instrInfo_.instrVec.empty()) {
     278            0 :         HCCL_ERROR(
     279              :             "[CcuKernel][%s] failed, mission instructions are empty, "
     280              :             "the kernel is not been translated yet.",
     281              :             __func__);
     282            0 :         return CcuResult::CCU_E_INTERNAL;
     283              :     }
     284            5 :     return CcuResult::CCU_SUCCESS;
     285              : }
     286              : 
     287            8 : void CcuKernel::FillTaskParam(
     288              :     CcuTaskParam& param, uint32_t index, uint32_t seqNum, const uint64_t* taskArgs, uint32_t argsNum) const
     289              : {
     290            8 :     param.dieId = GetDieId();
     291            8 :     param.missionId = GetMissionId();
     292            8 :     param.instStartId = instrInfo_.missionStartInstrId + index * CCU_SQE_ARGS_LEN;
     293            8 :     param.key = GetMissionKey();
     294            8 :     param.argSize = CCU_SQE_ARGS_LEN;
     295              : 
     296            8 :     const uint32_t preMissionInsCnt = index * CCU_SQE_ARGS_LEN;
     297            8 :     const bool isLast = (index == seqNum - 1);
     298            8 :     param.instCnt = isLast ? (instrInfo_.missionInstrCount - preMissionInsCnt) : CCU_SQE_ARGS_LEN;
     299              : 
     300            8 :     if (argsNum > preMissionInsCnt) {
     301            6 :         const uint32_t argsToCopy = isLast ? std::min(argsNum - preMissionInsCnt, CCU_SQE_ARGS_LEN) : CCU_SQE_ARGS_LEN;
     302           12 :         std::copy(taskArgs + preMissionInsCnt, taskArgs + preMissionInsCnt + argsToCopy, std::begin(param.args));
     303              :     }
     304              : 
     305            8 :     HCCL_INFO(
     306              :         "[GeneTaskParam]task Param, dieId[%u] missionId[%u] instStartId[%u] instCnt[%u], argSize[%u]", param.dieId,
     307              :         param.missionId, param.instStartId, param.instCnt, param.argSize);
     308            8 : }
     309              : 
     310            5 : CcuResult CcuKernel::GeneTaskParams(const uint64_t* taskArgs, uint32_t argsNum, std::vector<CcuTaskParam>& taskParams)
     311              : {
     312            5 :     CCU_CHK_RET(ValidateTaskArgs(taskArgs, argsNum));
     313              : 
     314              :     // 如果agrs数量超过sqe arg的最大数量,则返回多个TaskParam,前面几个只从sqe中加载args;
     315              :     // args数量大于等于0、小于等于最大值时,返回1个TaskParam
     316            5 :     const uint32_t seqNum
     317            5 :         = (argsNum / CCU_SQE_ARGS_LEN) + ((argsNum % CCU_SQE_ARGS_LEN) == 0 ? 0 : 1) + (argsNum == 0 ? 1 : 0);
     318              : 
     319            5 :     const uint32_t preMissonSqeInsCnt = (seqNum - 1) * CCU_SQE_ARGS_LEN;
     320            5 :     if (instrInfo_.missionInstrCount < preMissonSqeInsCnt) {
     321            0 :         HCCL_ERROR(
     322              :             "[CcuKernel][%s] failed, missionInstrCount[%u] should be greater "
     323              :             "than preMissonSqeInsCnt[%u].",
     324              :             __func__, instrInfo_.missionInstrCount, preMissonSqeInsCnt);
     325            0 :         return CcuResult::CCU_E_INTERNAL;
     326              :     }
     327              : 
     328            5 :     taskParams.resize(seqNum);
     329           13 :     for (uint32_t index = 0; index < seqNum; index++) {
     330            8 :         FillTaskParam(taskParams[index], index, seqNum, taskArgs, argsNum);
     331              :     }
     332              : 
     333            5 :     return CcuResult::CCU_SUCCESS;
     334              : }
     335              : 
     336           21 : HcclResult CcuKernel::CreateVariable(const ChannelHandle channel, uint32_t varIndex, CcuRep::Variable* var)
     337              : {
     338           21 :     channels_.insert(channel);
     339              : 
     340           21 :     void* channelPtr{nullptr};
     341           21 :     CHK_RET(static_cast<HcclResult>(HcommChannelGet(channel, &channelPtr)));
     342           21 :     auto* channelImpl = dynamic_cast<CcuUrmaChannel*>(static_cast<Channel*>(channelPtr));
     343           21 :     if (channelImpl == nullptr) {
     344            0 :         HCCL_ERROR("[%s] failed to cast channel[0x%llx] to CcuUrmaChannel", __func__, channel);
     345            0 :         return HcclResult::HCCL_E_PTR;
     346              :     }
     347           21 :     uint32_t locXnId{0};
     348           21 :     CHK_RET(channelImpl->GetLocXnByIndex(varIndex, locXnId));
     349           20 :     var->Reset(locXnId, channelImpl->GetDieId());
     350           20 :     return HcclResult::HCCL_SUCCESS;
     351              : }
     352              : 
     353            9 : void CcuKernel::AddPinnedRegGroup(const CcuRep::Variable& baseVar, uint16_t count)
     354              : {
     355            9 :     if (count == 0) {
     356            0 :         return;
     357              :     }
     358            9 :     const uint16_t baseId = baseVar.Id();
     359           11 :     for (const auto& g : pinnedRegGroups_) {
     360            5 :         if (g.baseVar.Id() == baseId && g.count == count) {
     361            3 :             return;
     362              :         }
     363              :     }
     364            6 :     pinnedRegGroups_.push_back({baseVar, count});
     365            6 : }
     366              : 
     367           46 : CcuRepResource& CcuKernel::GetResource() { return res_; }
     368              : 
     369           95 : CcuResReq CcuKernel::GetResourceRequest()
     370              : {
     371           95 :     CcuResReq req;
     372           95 :     uint32_t dieId = GetDieId();
     373           95 :     req.msReq[dieId] = res_.ccubufs[dieId].size();
     374           95 :     req.blockMsReq[dieId] = res_.blockCcubufs[dieId].size();
     375           95 :     req.ckeReq[dieId] = res_.completedEvent[dieId].size();
     376           95 :     req.blockCkeReq[dieId] = res_.blockCompletedEvent[dieId].size() + res_.localNotify[dieId].size();
     377           95 :     req.loopEngineReq[dieId] = res_.executor[dieId].size();
     378           95 :     req.blockLoopEngineReq[dieId] = res_.blockExecutor[dieId].size();
     379           95 :     req.gsaReq[dieId] = res_.address[dieId].size();
     380           95 :     req.blockGsaReq[dieId] = res_.blockAddress[dieId].size();
     381           95 :     req.xnReq[dieId] = res_.variable[dieId].size();
     382           95 :     req.blockXnReq[dieId] = res_.continuousVariable[dieId].size();
     383              : 
     384           95 :     req.missionReq.reqType = MissionReqType::FUSION_MULTIPLE_DIE;
     385           95 :     req.missionReq.req[dieId] = 1;
     386              : 
     387              :     auto info = Hccl::StringFormat(
     388              :         "resource request: dieId[%u], ms[%u], blockMs[%u], cke[%u], blockCke[%u], "
     389              :         "loopEngine[%u], blockLoopEngine[%u], gsa[%u], blockGsa[%u], xn[%u], blockXn[%u], "
     390              :         "missionId[%u]",
     391          380 :         dieId, req.msReq[dieId], req.blockMsReq[dieId], req.ckeReq[dieId], req.blockCkeReq[dieId],
     392          380 :         req.loopEngineReq[dieId], req.blockLoopEngineReq[dieId], req.gsaReq[dieId], req.blockGsaReq[dieId],
     393           95 :         req.xnReq[dieId], req.blockXnReq[dieId], req.missionReq.req[dieId]);
     394              : 
     395           95 :     HCCL_INFO("%s", info.c_str());
     396              : 
     397          190 :     return req;
     398           95 : }
     399              : 
     400              : template <typename HandleType, typename ResourceType>
     401         1704 : static CcuResult GetResourceByHandle(
     402              :     std::unordered_map<HandleType, ResourceType>& resourceMap, HandleType handle, ResourceType** resource,
     403              :     const char* resourceType)
     404              : {
     405         1704 :     auto iter = resourceMap.find(handle);
     406         1704 :     if (iter == resourceMap.end()) {
     407            0 :         HCCL_ERROR("[%s] failed to find %s by handle: 0x%llx", __func__, resourceType, handle);
     408            0 :         return CcuResult::CCU_E_NOT_FOUND;
     409              :     }
     410              : 
     411              :     // ccu资源本身可能重载=,对象赋值会被转换成指令,导致流程失败
     412         1704 :     *resource = &(iter->second);
     413         1704 :     return CcuResult::CCU_SUCCESS;
     414              : }
     415              : 
     416         1370 : CcuResult CcuKernel::GetVariableByHandle(CcuVariableHandle varHandle, CcuRep::Variable** variable)
     417              : {
     418         1370 :     return GetResourceByHandle(ccuVarMap_, varHandle, variable, "variable");
     419              : }
     420              : // Alloc 相关接口
     421          495 : CcuResult CcuKernel::VariableAlloc(CcuVariableHandle* varHandle)
     422              : {
     423          495 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[VariableAlloc]");
     424          495 :     const auto& var = CreateBlockResAssist(1, res_.continuousVariable);
     425          495 :     CcuVariableHandle handle = ccuVarMap_.size();
     426          495 :     ccuVarMap_.emplace(handle, var[0]);
     427              : 
     428          495 :     *varHandle = handle;
     429          495 :     return CcuResult::CCU_SUCCESS;
     430          495 : }
     431           10 : CcuResult CcuKernel::AddressAlloc(CcuAddressHandle* addrHandle)
     432              : {
     433           10 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[AddressAlloc]");
     434           10 :     const auto addr = CreateAddress();
     435           10 :     CcuAddressHandle handle = ccuAddrMap_.size();
     436           10 :     ccuAddrMap_.emplace(handle, addr);
     437           10 :     *addrHandle = handle;
     438           10 :     return CcuResult::CCU_SUCCESS;
     439           10 : }
     440           14 : CcuResult CcuKernel::EventAlloc(CcuEventHandle* eventHandle)
     441              : {
     442           14 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[EventAlloc]");
     443           14 :     const auto& event = CreateResAssist(res_.blockCompletedEvent);
     444           14 :     CcuEventHandle handle = ccuEventMap_.size();
     445           14 :     ccuEventMap_.emplace(handle, event);
     446           14 :     *eventHandle = handle;
     447           14 :     return CcuResult::CCU_SUCCESS;
     448           14 : }
     449            2 : CcuResult CcuKernel::BufferAlloc(CcuBufferHandle* bufHandle)
     450              : {
     451            2 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[BufferAlloc]");
     452            2 :     const auto& buffer = CreateBlockResAssist(1, res_.blockCcubufs);
     453            2 :     CcuBufferHandle handle = ccuBufferMap_.size();
     454            2 :     ccuBufferMap_.emplace(handle, buffer[0]);
     455            2 :     *bufHandle = handle;
     456            2 :     return CcuResult::CCU_SUCCESS;
     457            2 : }
     458          156 : CcuResult CcuKernel::LocalAddrAlloc(
     459              :     CcuLocalAddrHandle* localAddrHandle, CcuAddressHandle* addrHandle, CcuVariableHandle* tokenHandle)
     460              : {
     461          156 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LocalAddrAlloc]");
     462          156 :     auto localAddr = CreateLocalAddr();
     463              : 
     464          156 :     CcuAddressHandle aHandle = ccuAddrMap_.size();
     465          156 :     ccuAddrMap_.emplace(aHandle, localAddr.addr);
     466              : 
     467          156 :     CcuVariableHandle tHandle = ccuVarMap_.size();
     468          156 :     ccuVarMap_.emplace(tHandle, localAddr.token);
     469              : 
     470          156 :     CcuLocalAddrHandle laHandle = ccuLocalAddrMap_.size();
     471          156 :     ccuLocalAddrMap_.emplace(laHandle, localAddr);
     472              : 
     473          156 :     *localAddrHandle = laHandle;
     474          156 :     *addrHandle = aHandle;
     475          156 :     *tokenHandle = tHandle;
     476          156 :     return CcuResult::CCU_SUCCESS;
     477          156 : }
     478           37 : CcuResult CcuKernel::RemoteAddrAlloc(
     479              :     CcuRemoteAddrHandle* remoteAddrHandle, CcuAddressHandle* addrHandle, CcuVariableHandle* tokenHandle)
     480              : {
     481           37 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[RemoteAddrAlloc]");
     482           37 :     auto remoteAddr = CreateRemoteAddr();
     483              : 
     484           37 :     CcuAddressHandle aHandle = ccuAddrMap_.size();
     485           37 :     ccuAddrMap_.emplace(aHandle, remoteAddr.addr);
     486              : 
     487           37 :     CcuVariableHandle tHandle = ccuVarMap_.size();
     488           37 :     ccuVarMap_.emplace(tHandle, remoteAddr.token);
     489              : 
     490           37 :     CcuRemoteAddrHandle raHandle = ccuRemoteAddrMap_.size();
     491           37 :     ccuRemoteAddrMap_.emplace(raHandle, remoteAddr);
     492              : 
     493           37 :     *remoteAddrHandle = raHandle;
     494           37 :     *addrHandle = aHandle;
     495           37 :     *tokenHandle = tHandle;
     496           37 :     return CcuResult::CCU_SUCCESS;
     497           37 : }
     498              : 
     499            6 : CcuResult CcuKernel::BlockVariableAlloc(CcuVariableHandle* varHandles, uint32_t count)
     500              : {
     501            6 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[BlockVariableAlloc] count=%u", count);
     502            6 :     const auto& var = CreateBlockResAssist(count, res_.continuousVariable);
     503           18 :     for (uint32_t i = 0; i < count; i++) {
     504           12 :         CcuVariableHandle handle = ccuVarMap_.size();
     505           12 :         ccuVarMap_.emplace(handle, var[i]);
     506           12 :         varHandles[i] = handle;
     507              :     }
     508            6 :     return CcuResult::CCU_SUCCESS;
     509            6 : }
     510              : 
     511            6 : CcuResult CcuKernel::BlockEventAlloc(CcuEventHandle* eventHandles, uint32_t count)
     512              : {
     513            6 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[BlockEventAlloc] count=%u", count);
     514            6 :     const auto& event = CreateBlockResAssist(count, res_.blockCompletedEvent);
     515           52 :     for (uint32_t i = 0; i < count; i++) {
     516           46 :         CcuEventHandle handle = ccuEventMap_.size();
     517           46 :         ccuEventMap_.emplace(handle, event[i]);
     518           46 :         eventHandles[i] = handle;
     519              :     }
     520            6 :     return CcuResult::CCU_SUCCESS;
     521            6 : }
     522              : 
     523            7 : CcuResult CcuKernel::BlockBufferAlloc(CcuBufferHandle* bufHandles, uint32_t count)
     524              : {
     525            7 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[BlockBufferAlloc] count=%u", count);
     526            7 :     const auto& buffer = CreateBlockResAssist(count, res_.blockCcubufs);
     527          332 :     for (uint32_t i = 0; i < count; i++) {
     528          325 :         CcuBufferHandle handle = ccuBufferMap_.size();
     529          325 :         ccuBufferMap_.emplace(handle, buffer[i]);
     530          325 :         bufHandles[i] = handle;
     531              :     }
     532            7 :     return CcuResult::CCU_SUCCESS;
     533            7 : }
     534              : 
     535           21 : CcuResult CcuKernel::VariableCreateByChannel(ChannelHandle channel, uint32_t varIndex, CcuVariableHandle* varHandle)
     536              : {
     537           21 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[VariableCreateByChannel] channel=%llu, varIndex=%u", channel, varIndex);
     538           21 :     channels_.insert(channel);
     539           21 :     CcuRep::Variable var(this);
     540           21 :     CCU_CHK_RET(CreateVariable(channel, varIndex, &var));
     541           20 :     CcuVariableHandle handle = ccuVarMap_.size();
     542           20 :     ccuVarMap_.emplace(handle, var);
     543           20 :     *varHandle = handle;
     544           20 :     declaredLocXns_.insert(var.Id());
     545           20 :     return CcuResult::CCU_SUCCESS;
     546           21 : }
     547              : 
     548           10 : CcuResult CcuKernel::VariableCreateByAcquire(CcuVariableHandle acqHandle, uint32_t index, CcuVariableHandle* varHandle)
     549              : {
     550           10 :     uint8_t dieId = 0;
     551           10 :     uint32_t xnId = 0;
     552           10 :     CCU_CHK_RET(CcuVarEventResMgr::GetInstance(HcclGetThreadDeviceId()).GetVariableXnId(acqHandle, index, dieId, xnId));
     553              : 
     554           10 :     CcuRep::Variable var(this);
     555           10 :     var.Reset(static_cast<uint16_t>(xnId), static_cast<uint16_t>(dieId));
     556           10 :     CcuVariableHandle handle = ccuVarMap_.size();
     557           10 :     ccuVarMap_.emplace(handle, var);
     558           10 :     *varHandle = handle;
     559           10 :     return CcuResult::CCU_SUCCESS;
     560           10 : }
     561              : 
     562            4 : CcuResult CcuKernel::EventCreateByAcquire(CcuEventHandle acqHandle, uint32_t index, CcuEventHandle* eventHandle)
     563              : {
     564            4 :     uint8_t dieId = 0;
     565            4 :     uint32_t ckeId = 0;
     566            4 :     CCU_CHK_RET(CcuVarEventResMgr::GetInstance(HcclGetThreadDeviceId()).GetEventCkeId(acqHandle, index, dieId, ckeId));
     567              : 
     568            4 :     CcuRep::CompletedEvent event(this);
     569            4 :     event.Reset(static_cast<uint16_t>(ckeId), static_cast<uint16_t>(dieId));
     570            4 :     CcuEventHandle handle = ccuEventMap_.size();
     571            4 :     ccuEventMap_.emplace(handle, event);
     572            4 :     *eventHandle = handle;
     573            4 :     return CcuResult::CCU_SUCCESS;
     574            4 : }
     575              : 
     576          280 : CcuResult CcuKernel::VariableAssignImm(CcuVariableHandle varHandle, uint64_t immediate)
     577              : {
     578          280 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[VariableAssignImm] varHandle=%llu, immediate=%llu", varHandle, immediate);
     579          280 :     CcuRep::Variable* variable{nullptr};
     580          280 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
     581              :     // 通过符号重载实现,内部记录rep;异常由入口 HcommCcuKernelRegister 的
     582              :     // CCU_EXCEPTION_HANDLE_BEGIN/END 统一接住,无需在此局部 try/catch。
     583          280 :     (*variable) = immediate;
     584          280 :     return CcuResult::CCU_SUCCESS;
     585              : }
     586              : 
     587          158 : CcuResult CcuKernel::VariableAssignVar(CcuVariableHandle varHandle, CcuVariableHandle varA)
     588              : {
     589          158 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[VariableAssignVar] varHandle=%llu, varA=%llu", varHandle, varA);
     590          158 :     CcuRep::Variable* variable{nullptr};
     591          158 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
     592          158 :     CcuRep::Variable* variableA{nullptr};
     593          158 :     CCU_CHK_RET(GetVariableByHandle(varA, &variableA));
     594              :     // 通过符号重载实现,内部记录rep;异常由入口统一 catch。
     595          158 :     (*variable) = (*variableA);
     596          158 :     return CcuResult::CCU_SUCCESS;
     597              : }
     598              : 
     599              : CcuResult
     600          109 : CcuKernel::VariableAddVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     601              : {
     602          109 :     PLF_CONFIG_INFO(
     603              :         PLF_DATA_OP, "[VariableAddVarToVar] varHandle=%llu, varAHandle=%llu, varBHandle=%llu", varHandle, varAHandle,
     604              :         varBHandle);
     605          109 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     606          109 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     607          109 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     608          109 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     609              : 
     610              :     // 通过符号重载实现,内部记录rep;异常由入口统一 catch。
     611          109 :     *resVar = *leftVar + *rightVar;
     612          109 :     return CcuResult::CCU_SUCCESS;
     613              : }
     614              : 
     615              : CcuResult
     616            2 : CcuKernel::VariableSubVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     617              : {
     618            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     619            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     620            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     621            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     622              : 
     623            2 :     *resVar = *leftVar - *rightVar;
     624            2 :     return CcuResult::CCU_SUCCESS;
     625              : }
     626              : 
     627              : CcuResult
     628            2 : CcuKernel::VariableMulVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     629              : {
     630            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     631            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     632            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     633            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     634              : 
     635            2 :     *resVar = *leftVar * *rightVar;
     636            2 :     return CcuResult::CCU_SUCCESS;
     637              : }
     638              : 
     639            1 : CcuResult CcuKernel::VariableAddImmToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, uint16_t immediate)
     640              : {
     641            1 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr};
     642            1 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     643            1 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     644              : 
     645            1 :     *resVar = *leftVar + immediate;
     646            1 :     return CcuResult::CCU_SUCCESS;
     647              : }
     648              : 
     649            2 : CcuResult CcuKernel::VariableSubImmToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, uint16_t immediate)
     650              : {
     651            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr};
     652            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     653            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     654              : 
     655            2 :     *resVar = *leftVar - immediate;
     656            2 :     return CcuResult::CCU_SUCCESS;
     657              : }
     658              : 
     659            2 : CcuResult CcuKernel::VariableMulImmToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, uint16_t immediate)
     660              : {
     661            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr};
     662            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     663            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     664              : 
     665            2 :     *resVar = *leftVar * immediate;
     666            2 :     return CcuResult::CCU_SUCCESS;
     667              : }
     668              : 
     669              : CcuResult
     670            2 : CcuKernel::VariableAndVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     671              : {
     672            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     673            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     674            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     675            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     676              : 
     677            2 :     *resVar = *leftVar & *rightVar;
     678            2 :     return CcuResult::CCU_SUCCESS;
     679              : }
     680              : 
     681              : CcuResult
     682            2 : CcuKernel::VariableOrVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     683              : {
     684            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     685            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     686            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     687            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     688              : 
     689            2 :     *resVar = *leftVar | *rightVar;
     690            2 :     return CcuResult::CCU_SUCCESS;
     691              : }
     692              : 
     693              : CcuResult
     694            2 : CcuKernel::VariableXorVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     695              : {
     696            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     697            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     698            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     699            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     700              : 
     701            2 :     *resVar = *leftVar ^ *rightVar;
     702            2 :     return CcuResult::CCU_SUCCESS;
     703              : }
     704              : 
     705            1 : CcuResult CcuKernel::VariableNotVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle)
     706              : {
     707            1 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr};
     708            1 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     709            1 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     710              : 
     711            1 :     *resVar = ~(*leftVar);
     712            1 :     return CcuResult::CCU_SUCCESS;
     713              : }
     714              : 
     715              : CcuResult
     716            2 : CcuKernel::VariableShlVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     717              : {
     718            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     719            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     720            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     721            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     722              : 
     723            2 :     *resVar = *leftVar << *rightVar;
     724            2 :     return CcuResult::CCU_SUCCESS;
     725              : }
     726              : 
     727              : CcuResult
     728            2 : CcuKernel::VariableShrVarToVar(CcuVariableHandle varHandle, CcuVariableHandle varAHandle, CcuVariableHandle varBHandle)
     729              : {
     730            2 :     CcuRep::Variable *resVar{nullptr}, *leftVar{nullptr}, *rightVar{nullptr};
     731            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &resVar));
     732            2 :     CCU_CHK_RET(GetVariableByHandle(varAHandle, &leftVar));
     733            2 :     CCU_CHK_RET(GetVariableByHandle(varBHandle, &rightVar));
     734              : 
     735            2 :     *resVar = *leftVar >> *rightVar;
     736            2 :     return CcuResult::CCU_SUCCESS;
     737              : }
     738              : 
     739              : /*========== Event信号同步类 相关接口 ==========*/
     740           18 : CcuResult CcuKernel::EventRecord(CcuEventHandle eventHandle, uint32_t mask)
     741              : {
     742           18 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[EventRecord] eventHandle=%llu, mask=%u", eventHandle, mask);
     743           18 :     CcuRep::CompletedEvent* event{nullptr};
     744           18 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
     745              :     // 复用已有的 RecordEvent 实现(内部 Append CcuRepLocRecordEvent)
     746           18 :     CCU_CHK_RET(RecordEvent(*event, mask));
     747           17 :     return CcuResult::CCU_SUCCESS;
     748              : }
     749              : 
     750           44 : CcuResult CcuKernel::EventWait(CcuEventHandle eventHandle, uint32_t mask)
     751              : {
     752           44 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[EventWait] eventHandle=%llu, mask=%u", eventHandle, mask);
     753           44 :     CcuRep::CompletedEvent* event{nullptr};
     754           44 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
     755              :     // 复用已有的 WaitEvent 实现(内部 Append CcuRepLocWaitEvent)
     756           44 :     CCU_CHK_RET(WaitEvent(*event, mask));
     757           44 :     return CcuResult::CCU_SUCCESS;
     758              : }
     759              : 
     760            1 : CcuResult CcuKernel::LocalNotifyRecord(const char* notifyTag, const uint32_t mask)
     761              : {
     762            1 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LocalNotifyRecord] tag=%s, mask=%u", (notifyTag ? notifyTag : "null"), mask);
     763            1 :     if (notifyTag == nullptr) {
     764            0 :         HCCL_ERROR("[CcuKernel][%s] notifyTag is nullptr, please check.", __func__);
     765            0 :         return CcuResult::CCU_E_PTR;
     766              :     }
     767            1 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
     768            1 :         HCCL_ERROR("[CcuKernel][%s] is not supported in loop block, please check.", __func__);
     769            1 :         return LatchBodyError(CcuResult::CCU_E_NOT_SUPPORT);
     770              :     }
     771              : 
     772            0 :     const std::string tagKey(notifyTag);
     773              : 
     774            0 :     auto& sharedNotifies = importedRes_.sharedNotifies;
     775            0 :     if (sharedNotifies.find(tagKey) == sharedNotifies.end()) {
     776            0 :         CcuRep::LocalNotify localNotify;
     777            0 :         sharedNotifies.insert({tagKey, localNotify});
     778            0 :     }
     779              : 
     780            0 :     Append(std::make_shared<CcuRep::CcuRepRecordSharedNotify>(insGenerator, sharedNotifies.at(tagKey), mask));
     781              : 
     782            0 :     return CcuResult::CCU_SUCCESS;
     783            0 : }
     784              : 
     785            0 : CcuResult CcuKernel::LocalNotifyWait(const char* notifyTag, const uint32_t mask)
     786              : {
     787            0 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LocalNotifyWait] tag=%s, mask=%u", (notifyTag ? notifyTag : "null"), mask);
     788            0 :     if (notifyTag == nullptr) {
     789            0 :         HCCL_ERROR("[CcuKernel][%s] notifyTag is nullptr, please check.", __func__);
     790            0 :         return CcuResult::CCU_E_PTR;
     791              :     }
     792              : 
     793            0 :     const std::string tagKey(notifyTag);
     794              : 
     795            0 :     auto& sharedNotifies = exportedRes_.sharedNotifies;
     796            0 :     if (sharedNotifies.find(tagKey) == sharedNotifies.end()) {
     797            0 :         CcuRep::LocalNotify notify = CreateLocalNotify();
     798            0 :         exportedRes_.sharedNotifies.insert({tagKey, notify});
     799            0 :     }
     800              : 
     801            0 :     bool isProfiling = CurrentBlock()->Type() != CcuRep::CcuRepType::LOOP_BLOCK;
     802            0 :     Append(std::make_shared<CcuRep::CcuRepLocWaitNotify>(
     803            0 :         insGenerator, exportedRes_.sharedNotifies.at(tagKey), mask, isProfiling));
     804            0 :     return CcuResult::CCU_SUCCESS;
     805            0 : }
     806              : 
     807            6 : CcuResult CcuKernel::NotifyRecord(const ChannelHandle channel, uint32_t remoteNotifyIdx, uint32_t mask)
     808              : {
     809            6 :     PLF_CONFIG_INFO(
     810              :         PLF_DATA_OP, "[NotifyRecord] channel=%llu, remoteNotifyIdx=%u, mask=%u", channel, remoteNotifyIdx, mask);
     811            6 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
     812            1 :         HCCL_ERROR("[%s] NotifyRecord is not allowed inside a ccu::Loop body", __func__);
     813            1 :         return LatchBodyError(CcuResult::CCU_E_NOT_SUPPORT);
     814              :     }
     815            5 :     channels_.insert(channel);
     816            5 :     Append(std::make_shared<CcuRep::CcuRepRemPostSem>(insGenerator, channel, remoteNotifyIdx, mask));
     817            5 :     return CCU_SUCCESS;
     818              : }
     819              : 
     820           11 : CcuResult CcuKernel::NotifyWait(const ChannelHandle channel, uint32_t localNotifyIdx, uint32_t mask)
     821              : {
     822           11 :     PLF_CONFIG_INFO(
     823              :         PLF_DATA_OP, "[NotifyWait] channel=%llu, localNotifyIdx=%u, mask=%u", channel, localNotifyIdx, mask);
     824           11 :     channels_.insert(channel);
     825           11 :     bool isProfiling = CurrentBlock()->Type() != CcuRep::CcuRepType::LOOP_BLOCK;
     826           11 :     if (isProfiling) {
     827           33 :         CCU_CHK_RET(static_cast<HcclResult>(AddProfiling(channel, "NotifyWait", localNotifyIdx, mask)));
     828              :     }
     829           10 :     Append(std::make_shared<CcuRep::CcuRepRemWaitSem>(insGenerator, channel, localNotifyIdx, mask, isProfiling));
     830           10 :     return CcuResult::CCU_SUCCESS;
     831              : }
     832              : 
     833           10 : CcuResult CcuKernel::WriteVariableWithNotify(
     834              :     const ChannelHandle channel, CcuVariableHandle varHandle, uint32_t remoteVarIdx, uint32_t remoteNotifyIdx,
     835              :     uint32_t mask)
     836              : {
     837           10 :     PLF_CONFIG_INFO(
     838              :         PLF_DATA_OP,
     839              :         "[WriteVariableWithNotify] channel=%llu, varHandle=%llu, remoteVarIdx=%u,"
     840              :         " remoteNotifyIdx=%u, mask=%u",
     841              :         channel, varHandle, remoteVarIdx, remoteNotifyIdx, mask);
     842           10 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
     843            1 :         HCCL_ERROR("[%s] WriteVariableWithNotify is not allowed inside a ccu::Loop body", __func__);
     844            1 :         return LatchBodyError(CcuResult::CCU_E_NOT_SUPPORT);
     845              :     }
     846            9 :     channels_.insert(channel);
     847            9 :     CcuRep::Variable* var{nullptr};
     848            9 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     849            9 :     Append(
     850           18 :         std::make_shared<CcuRep::CcuRepRemPostVar>(insGenerator, *var, channel, remoteVarIdx, remoteNotifyIdx, mask));
     851            9 :     return CcuResult::CCU_SUCCESS;
     852              : }
     853              : 
     854              : // 加载类 相关接口
     855           49 : CcuResult CcuKernel::LoadArg(CcuVariableHandle varHandle, uint32_t argId)
     856              : {
     857           49 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoadArg] varHandle=%llu, argId=%u", varHandle, argId);
     858           49 :     loadArgUsedSet_.insert(argId);
     859           49 :     CcuRep::Variable* var{nullptr};
     860           49 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     861              :     auto loadArgRep = std::make_shared<CcuRep::CcuRepLoadArg>(
     862           49 :         insGenerator, *var, argId % CCU_SQE_ARGS_LEN, static_cast<uint16_t>(argId));
     863           49 :     Append(loadArgRep);
     864           49 :     return CcuResult::CCU_SUCCESS;
     865           49 : }
     866              : 
     867            3 : CcuResult CcuKernel::GetCcuKernelInfo(CcuKernelInfo& info) const
     868              : {
     869            3 :     uint32_t maxTaskArgsNum = 0;
     870              :     // 如果没有LoadArg指令,则说明不需要传入参数,直接返回0
     871            3 :     if (loadArgUsedSet_.empty()) {
     872            1 :         info.maxTaskArgsNum = 0;
     873            1 :         return CcuResult::CCU_SUCCESS;
     874              :     }
     875              :     // 遍历loadArgUsedSet_,获取最大的argId,加1得到最大任务参数数量(argId从0连续)
     876            7 :     for (const auto& argId : loadArgUsedSet_) {
     877            5 :         maxTaskArgsNum = std::max(maxTaskArgsNum, argId);
     878              :     }
     879            2 :     maxTaskArgsNum += 1;
     880            2 :     info.maxTaskArgsNum = maxTaskArgsNum;
     881            2 :     return CcuResult::CCU_SUCCESS;
     882              : }
     883              : 
     884           13 : CcuResult CcuKernel::CheckContinuousVariables(
     885              :     CcuVariableHandle varHandle, uint32_t num, const CcuRep::Variable& baseVar, const char* tag)
     886              : {
     887           13 :     if (num <= 1) {
     888            4 :         return CcuResult::CCU_SUCCESS;
     889              :     }
     890           18 :     for (uint32_t i = 1; i < num; i++) {
     891            9 :         CcuRep::Variable* nextVar{nullptr};
     892            9 :         CCU_CHK_RET(GetVariableByHandle(varHandle + i, &nextVar));
     893            9 :         if (nextVar->Id() != baseVar.Id() + i) {
     894            0 :             HCCL_ERROR(
     895              :                 "[CcuKernel][%s] variables not continuous at index %u, "
     896              :                 "expected Id %u but got %u",
     897              :                 tag, i, baseVar.Id() + i, nextVar->Id());
     898            0 :             return HCCL_TO_CCU_RET(HCCL_E_PARA);
     899              :         }
     900              :     }
     901            9 :     return CcuResult::CCU_SUCCESS;
     902              : }
     903              : 
     904            6 : CcuResult CcuKernel::LoadVar(uint64_t addr, CcuVariableHandle varHandle, uint32_t num)
     905              : {
     906            6 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoadVar] addr=0x%llx, varHandle=%llu, num=%u", addr, varHandle, num);
     907            6 :     CcuRep::Variable* var{nullptr};
     908            6 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     909            6 :     CCU_CHK_RET(CheckContinuousVariables(varHandle, num, *var, "LoadVariable"));
     910            6 :     Append(std::make_shared<CcuRep::CcuRepLoad>(insGenerator, addr, *var, num));
     911              :     // 数据面 num>=2 走 Array<Variable>: microcode 会用到 [baseVReg, baseVReg+num)
     912              :     // 这段连续 Xn 且组内相对偏移固定, 交给 microcode 后端优化 Pass 2 作为 pinned 组.
     913            6 :     if (num >= 2) {
     914            5 :         AddPinnedRegGroup(*var, static_cast<uint16_t>(num));
     915              :     }
     916            6 :     return CcuResult::CCU_SUCCESS;
     917              : }
     918              : 
     919            2 : CcuResult CcuKernel::CcuLoadVarFromVarAddr(CcuVariableHandle addrHandle, CcuVariableHandle varHandle, uint32_t num)
     920              : {
     921            2 :     PLF_CONFIG_INFO(
     922              :         PLF_DATA_OP,
     923              :         "[CcuLoadVarFromVarAddr] addrHandle=%llu, varHandle=%llu,"
     924              :         " num=%u",
     925              :         addrHandle, varHandle, num);
     926            2 :     CcuRep::Variable* addrVar{nullptr};
     927            2 :     CCU_CHK_RET(GetVariableByHandle(addrHandle, &addrVar));
     928            2 :     CcuRep::Variable* var{nullptr};
     929            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     930            2 :     CCU_CHK_RET(CheckContinuousVariables(varHandle, num, *var, "LoadVar dst"));
     931            2 :     Append(std::make_shared<CcuRep::CcuRepLoadVar>(insGenerator, *addrVar, *var, num));
     932            2 :     if (num >= 2) {
     933            1 :         AddPinnedRegGroup(*var, static_cast<uint16_t>(num));
     934              :     }
     935            2 :     return CcuResult::CCU_SUCCESS;
     936              : }
     937              : 
     938            3 : CcuResult CcuKernel::StoreVar(uint64_t addr, CcuVariableHandle varHandle, uint32_t num)
     939              : {
     940            3 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[StoreVar] addr=0x%llx, varHandle=%llu, num=%u", addr, varHandle, num);
     941            3 :     CcuRep::Variable* var{nullptr};
     942            3 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     943            3 :     CCU_CHK_RET(CheckContinuousVariables(varHandle, num, *var, "StoreVariable"));
     944            3 :     Append(std::make_shared<CcuRep::CcuRepStore>(insGenerator, *var, addr, num));
     945            3 :     if (num >= 2) {
     946            2 :         AddPinnedRegGroup(*var, static_cast<uint16_t>(num));
     947              :     }
     948            3 :     return CcuResult::CCU_SUCCESS;
     949              : }
     950              : 
     951            2 : CcuResult CcuKernel::CcuStoreVarToVarAddr(CcuVariableHandle addrHandle, CcuVariableHandle varHandle, uint32_t num)
     952              : {
     953            2 :     PLF_CONFIG_INFO(
     954              :         PLF_DATA_OP,
     955              :         "[CcuStoreVarToVarAddr] addrHandle=%llu, varHandle=%llu,"
     956              :         " num=%u",
     957              :         addrHandle, varHandle, num);
     958            2 :     CcuRep::Variable* addrVar{nullptr};
     959            2 :     CCU_CHK_RET(GetVariableByHandle(addrHandle, &addrVar));
     960            2 :     CcuRep::Variable* var{nullptr};
     961            2 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &var));
     962            2 :     CCU_CHK_RET(CheckContinuousVariables(varHandle, num, *var, "StoreVar src"));
     963            2 :     Append(std::make_shared<CcuRep::CcuRepStoreVar>(insGenerator, *var, *addrVar, num));
     964            2 :     if (num >= 2) {
     965            1 :         AddPinnedRegGroup(*var, static_cast<uint16_t>(num));
     966              :     }
     967            2 :     return CcuResult::CCU_SUCCESS;
     968              : }
     969              : 
     970              : // 本地数据拷贝 相关实现
     971           12 : CcuResult CcuKernel::LocalCopyMemToBuffer(
     972              :     CcuBufferHandle dstHandle, CcuLocalAddrHandle srcHandle, CcuVariableHandle lenHandle, CcuEventHandle eventHandle,
     973              :     uint32_t mask)
     974              : {
     975           12 :     PLF_CONFIG_INFO(
     976              :         PLF_DATA_OP,
     977              :         "[LocalCopyMemToBuffer] dstHandle=%llu, srcHandle=%llu, lenHandle=%llu,"
     978              :         " eventHandle=%llu, mask=%u",
     979              :         dstHandle, srcHandle, lenHandle, eventHandle, mask);
     980           12 :     CcuRep::CcuBuf* dst{nullptr};
     981           12 :     CCU_CHK_RET(GetBufferByHandle(dstHandle, &dst));
     982           12 :     CcuRep::LocalAddr* src{nullptr};
     983           12 :     CCU_CHK_RET(GetLocalAddrByHandle(srcHandle, &src));
     984           12 :     CcuRep::Variable* len{nullptr};
     985           12 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, &len));
     986           12 :     CcuRep::CompletedEvent* event{nullptr};
     987           12 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
     988           12 :     auto ret = LocalCopyNb(*dst, *src, *len, *event, mask); // 复用 protected
     989           12 :     return HCCL_TO_CCU_RET(ret);
     990              : }
     991              : 
     992            8 : CcuResult CcuKernel::LocalCopyBufferToMem(
     993              :     CcuLocalAddrHandle dstHandle, CcuBufferHandle srcHandle, CcuVariableHandle lenHandle, CcuEventHandle eventHandle,
     994              :     uint32_t mask)
     995              : {
     996            8 :     PLF_CONFIG_INFO(
     997              :         PLF_DATA_OP,
     998              :         "[LocalCopyBufferToMem] dstHandle=%llu, srcHandle=%llu, lenHandle=%llu,"
     999              :         " eventHandle=%llu, mask=%u",
    1000              :         dstHandle, srcHandle, lenHandle, eventHandle, mask);
    1001            8 :     CcuRep::LocalAddr* dst{nullptr};
    1002            8 :     CCU_CHK_RET(GetLocalAddrByHandle(dstHandle, &dst));
    1003            8 :     CcuRep::CcuBuf* src{nullptr};
    1004            8 :     CCU_CHK_RET(GetBufferByHandle(srcHandle, &src));
    1005            8 :     CcuRep::Variable* len{nullptr};
    1006            8 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, &len));
    1007            8 :     CcuRep::CompletedEvent* event{nullptr};
    1008            8 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
    1009            8 :     auto ret = LocalCopyNb(*dst, *src, *len, *event, mask);
    1010            8 :     return HCCL_TO_CCU_RET(ret);
    1011              : }
    1012              : 
    1013            1 : CcuResult CcuKernel::LocalCopyMemToMem(
    1014              :     CcuLocalAddrHandle dstHandle, CcuLocalAddrHandle srcHandle, CcuVariableHandle lenHandle, CcuEventHandle eventHandle,
    1015              :     uint32_t mask)
    1016              : {
    1017            1 :     PLF_CONFIG_INFO(
    1018              :         PLF_DATA_OP,
    1019              :         "[LocalCopyMemToMem] dstHandle=%llu, srcHandle=%llu, lenHandle=%llu,"
    1020              :         " eventHandle=%llu, mask=%u",
    1021              :         dstHandle, srcHandle, lenHandle, eventHandle, mask);
    1022            1 :     CcuRep::LocalAddr* dst{nullptr};
    1023            1 :     CCU_CHK_RET(GetLocalAddrByHandle(dstHandle, &dst));
    1024            1 :     CcuRep::LocalAddr* src{nullptr};
    1025            1 :     CCU_CHK_RET(GetLocalAddrByHandle(srcHandle, &src));
    1026            1 :     CcuRep::Variable* len{nullptr};
    1027            1 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, &len));
    1028            1 :     CcuRep::CompletedEvent* event{nullptr};
    1029            1 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
    1030            1 :     auto ret = LocalCopyNb(*dst, *src, *len, *event, mask);
    1031            1 :     return HCCL_TO_CCU_RET(ret);
    1032              : }
    1033              : 
    1034              : // 本地reduce 相关实现
    1035            0 : CcuResult CcuKernel::LocalMemReduce(
    1036              :     CcuLocalAddrHandle dstHandle, CcuLocalAddrHandle srcHandle, CcuVariableHandle lenHandle, HcclDataType dataType,
    1037              :     HcclReduceOp opType, CcuEventHandle eventHandle, uint32_t mask)
    1038              : {
    1039            0 :     PLF_CONFIG_INFO(
    1040              :         PLF_DATA_OP,
    1041              :         "[LocalMemReduce] dstHandle=%llu, srcHandle=%llu, lenHandle=%llu, dataType=%d,"
    1042              :         " op=%d, eventHandle=%llu, mask=%u",
    1043              :         dstHandle, srcHandle, lenHandle, dataType, opType, eventHandle, mask);
    1044            0 :     CcuRep::LocalAddr* dst{nullptr};
    1045            0 :     CCU_CHK_RET(GetLocalAddrByHandle(dstHandle, &dst));
    1046            0 :     CcuRep::LocalAddr* src{nullptr};
    1047            0 :     CCU_CHK_RET(GetLocalAddrByHandle(srcHandle, &src));
    1048            0 :     CcuRep::Variable* len{nullptr};
    1049            0 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, &len));
    1050            0 :     CcuRep::CompletedEvent* event{nullptr};
    1051            0 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
    1052            0 :     auto ret = LocalReduceNb(*dst, *src, *len, dataType, opType, *event, mask);
    1053            0 :     return HCCL_TO_CCU_RET(ret);
    1054              : }
    1055              : 
    1056            4 : CcuResult CcuKernel::LocalBufferReduce(
    1057              :     CcuBufferHandle* bufHandles, uint32_t count, HcclDataType dataType, HcclDataType outputDataType,
    1058              :     HcclReduceOp opType, CcuVariableHandle lenHandle, CcuEventHandle eventHandle, uint32_t mask)
    1059              : {
    1060            4 :     PLF_CONFIG_INFO(
    1061              :         PLF_DATA_OP,
    1062              :         "[LocalBufferReduce] count=%u, dataType=%d, outDataType=%d,"
    1063              :         " op=%d, lenHandle=%llu, eventHandle=%llu, mask=%u",
    1064              :         count, dataType, outputDataType, opType, lenHandle, eventHandle, mask);
    1065            4 :     CcuRep::Variable* len{nullptr};
    1066            4 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, &len));
    1067            4 :     CcuRep::CompletedEvent* event{nullptr};
    1068            4 :     CCU_CHK_RET(GetEventByHandle(eventHandle, &event));
    1069            4 :     std::vector<CcuRep::CcuBuf> bufs(count);
    1070           12 :     for (uint32_t i = 0; i < count; i++) {
    1071            8 :         CcuRep::CcuBuf* buf{nullptr};
    1072            8 :         CCU_CHK_RET(GetBufferByHandle(bufHandles[i], &buf));
    1073            8 :         bufs[i] = *buf;
    1074              :     }
    1075            4 :     auto ret = LocalReduceNb(bufs.data(), count, dataType, outputDataType, opType, *len, *event, mask);
    1076            4 :     return HCCL_TO_CCU_RET(ret);
    1077            4 : }
    1078              : 
    1079              : /*========== 远端数据传输操作 ==========*/
    1080              : 
    1081            4 : CcuResult CcuKernel::ResolveBufRemoteLenEvent(
    1082              :     CcuBufferHandle bufHandle, CcuRemoteAddrHandle remoteHandle, CcuVariableHandle lenHandle,
    1083              :     CcuEventHandle eventHandle, CcuRep::CcuBuf** buf, CcuRep::RemoteAddr** remote, CcuRep::Variable** len,
    1084              :     CcuRep::CompletedEvent** event)
    1085              : {
    1086            4 :     CCU_CHK_RET(GetBufferByHandle(bufHandle, buf));
    1087            4 :     CCU_CHK_RET(GetRemoteAddrByHandle(remoteHandle, remote));
    1088            4 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, len));
    1089            4 :     CCU_CHK_RET(GetEventByHandle(eventHandle, event));
    1090            4 :     return CcuResult::CCU_SUCCESS;
    1091              : }
    1092              : 
    1093            6 : CcuResult CcuKernel::ResolveLocalRemoteLenEvent(
    1094              :     CcuLocalAddrHandle localHandle, CcuRemoteAddrHandle remoteHandle, CcuVariableHandle lenHandle,
    1095              :     CcuEventHandle eventHandle, CcuRep::LocalAddr** local, CcuRep::RemoteAddr** remote, CcuRep::Variable** len,
    1096              :     CcuRep::CompletedEvent** event)
    1097              : {
    1098            6 :     CCU_CHK_RET(GetLocalAddrByHandle(localHandle, local));
    1099            6 :     CCU_CHK_RET(GetRemoteAddrByHandle(remoteHandle, remote));
    1100            6 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, len));
    1101            6 :     CCU_CHK_RET(GetEventByHandle(eventHandle, event));
    1102            6 :     return CcuResult::CCU_SUCCESS;
    1103              : }
    1104              : 
    1105            5 : CcuResult CcuKernel::ResolveRemoteLocalLenEvent(
    1106              :     CcuRemoteAddrHandle remoteHandle, CcuLocalAddrHandle localHandle, CcuVariableHandle lenHandle,
    1107              :     CcuEventHandle eventHandle, CcuRep::RemoteAddr** remote, CcuRep::LocalAddr** local, CcuRep::Variable** len,
    1108              :     CcuRep::CompletedEvent** event)
    1109              : {
    1110            5 :     CCU_CHK_RET(GetRemoteAddrByHandle(remoteHandle, remote));
    1111            5 :     CCU_CHK_RET(GetLocalAddrByHandle(localHandle, local));
    1112            5 :     CCU_CHK_RET(GetVariableByHandle(lenHandle, len));
    1113            5 :     CCU_CHK_RET(GetEventByHandle(eventHandle, event));
    1114            5 :     return CcuResult::CCU_SUCCESS;
    1115              : }
    1116              : 
    1117            4 : CcuResult CcuKernel::ReadMemToMem(
    1118              :     ChannelHandle channel, CcuLocalAddrHandle localHandle, CcuRemoteAddrHandle remoteHandle,
    1119              :     CcuVariableHandle lenHandle, CcuEventHandle eventHandle, uint32_t mask)
    1120              : {
    1121            4 :     PLF_CONFIG_INFO(
    1122              :         PLF_DATA_OP,
    1123              :         "[ReadMemToMem] channel=%llu, localHandle=%llu, remoteHandle=%llu,"
    1124              :         " lenHandle=%llu, eventHandle=%llu, mask=%u",
    1125              :         channel, localHandle, remoteHandle, lenHandle, eventHandle, mask);
    1126            4 :     channels_.insert(channel);
    1127            4 :     CcuRep::LocalAddr* local{nullptr};
    1128            4 :     CcuRep::RemoteAddr* remote{nullptr};
    1129            4 :     CcuRep::Variable* len{nullptr};
    1130            4 :     CcuRep::CompletedEvent* event{nullptr};
    1131            4 :     CCU_CHK_RET(
    1132              :         ResolveLocalRemoteLenEvent(localHandle, remoteHandle, lenHandle, eventHandle, &local, &remote, &len, &event));
    1133            4 :     auto ret = ReadNb(channel, *local, *remote, *len, *event, mask);
    1134            4 :     return HCCL_TO_CCU_RET(ret);
    1135              : }
    1136              : 
    1137            2 : CcuResult CcuKernel::ReadMemToBuffer(
    1138              :     ChannelHandle channel, CcuBufferHandle localHandle, CcuRemoteAddrHandle remoteHandle, CcuVariableHandle lenHandle,
    1139              :     CcuEventHandle eventHandle, uint32_t mask)
    1140              : {
    1141            2 :     PLF_CONFIG_INFO(
    1142              :         PLF_DATA_OP,
    1143              :         "[ReadMemToBuffer] channel=%llu, bufHandle=%llu, remoteHandle=%llu,"
    1144              :         " lenHandle=%llu, eventHandle=%llu, mask=%u",
    1145              :         channel, localHandle, remoteHandle, lenHandle, eventHandle, mask);
    1146            2 :     channels_.insert(channel);
    1147            2 :     CcuRep::CcuBuf* local{nullptr};
    1148            2 :     CcuRep::RemoteAddr* remote{nullptr};
    1149            2 :     CcuRep::Variable* len{nullptr};
    1150            2 :     CcuRep::CompletedEvent* event{nullptr};
    1151            2 :     CCU_CHK_RET(
    1152              :         ResolveBufRemoteLenEvent(localHandle, remoteHandle, lenHandle, eventHandle, &local, &remote, &len, &event));
    1153            2 :     auto ret = ReadNb(channel, *local, *remote, *len, *event, mask);
    1154            2 :     return HCCL_TO_CCU_RET(ret);
    1155              : }
    1156              : 
    1157            2 : CcuResult CcuKernel::ReadMemToMemReduce(
    1158              :     ChannelHandle channel, CcuLocalAddrHandle localHandle, CcuRemoteAddrHandle remoteHandle,
    1159              :     CcuVariableHandle lenHandle, HcclDataType dataType, HcclReduceOp opType, CcuEventHandle eventHandle, uint32_t mask)
    1160              : {
    1161            2 :     PLF_CONFIG_INFO(
    1162              :         PLF_DATA_OP,
    1163              :         "[ReadMemToMemReduce] channel=%llu, lenHandle=%llu, dataType=%d, op=%d,"
    1164              :         " eventHandle=%llu, mask=%u",
    1165              :         channel, lenHandle, dataType, opType, eventHandle, mask);
    1166            2 :     channels_.insert(channel);
    1167            2 :     CcuRep::LocalAddr* local{nullptr};
    1168            2 :     CcuRep::RemoteAddr* remote{nullptr};
    1169            2 :     CcuRep::Variable* len{nullptr};
    1170            2 :     CcuRep::CompletedEvent* event{nullptr};
    1171            2 :     CCU_CHK_RET(
    1172              :         ResolveLocalRemoteLenEvent(localHandle, remoteHandle, lenHandle, eventHandle, &local, &remote, &len, &event));
    1173            2 :     auto ret = ReadReduceNb(channel, *local, *remote, *len, dataType, opType, *event, mask);
    1174            2 :     return HCCL_TO_CCU_RET(ret);
    1175              : }
    1176              : 
    1177            3 : CcuResult CcuKernel::WriteMemToMem(
    1178              :     ChannelHandle channel, CcuRemoteAddrHandle remoteHandle, CcuLocalAddrHandle localHandle,
    1179              :     CcuVariableHandle lenHandle, CcuEventHandle eventHandle, uint32_t mask)
    1180              : {
    1181            3 :     PLF_CONFIG_INFO(
    1182              :         PLF_DATA_OP,
    1183              :         "[WriteMemToMem] channel=%llu, remoteHandle=%llu, localHandle=%llu,"
    1184              :         " lenHandle=%llu, eventHandle=%llu, mask=%u",
    1185              :         channel, remoteHandle, localHandle, lenHandle, eventHandle, mask);
    1186            3 :     channels_.insert(channel);
    1187            3 :     CcuRep::RemoteAddr* remote{nullptr};
    1188            3 :     CcuRep::LocalAddr* local{nullptr};
    1189            3 :     CcuRep::Variable* len{nullptr};
    1190            3 :     CcuRep::CompletedEvent* event{nullptr};
    1191            3 :     CCU_CHK_RET(
    1192              :         ResolveRemoteLocalLenEvent(remoteHandle, localHandle, lenHandle, eventHandle, &remote, &local, &len, &event));
    1193            3 :     auto ret = WriteNb(channel, *remote, *local, *len, *event, mask);
    1194            3 :     return HCCL_TO_CCU_RET(ret);
    1195              : }
    1196              : 
    1197            2 : CcuResult CcuKernel::WriteBufferToMem(
    1198              :     ChannelHandle channel, CcuRemoteAddrHandle remoteHandle, CcuBufferHandle localHandle, CcuVariableHandle lenHandle,
    1199              :     CcuEventHandle eventHandle, uint32_t mask)
    1200              : {
    1201            2 :     PLF_CONFIG_INFO(
    1202              :         PLF_DATA_OP,
    1203              :         "[WriteBufferToMem] channel=%llu, remoteHandle=%llu, bufHandle=%llu,"
    1204              :         " lenHandle=%llu, eventHandle=%llu, mask=%u",
    1205              :         channel, remoteHandle, localHandle, lenHandle, eventHandle, mask);
    1206            2 :     channels_.insert(channel);
    1207            2 :     CcuRep::CcuBuf* local{nullptr};
    1208            2 :     CcuRep::RemoteAddr* remote{nullptr};
    1209            2 :     CcuRep::Variable* len{nullptr};
    1210            2 :     CcuRep::CompletedEvent* event{nullptr};
    1211            2 :     CCU_CHK_RET(
    1212              :         ResolveBufRemoteLenEvent(localHandle, remoteHandle, lenHandle, eventHandle, &local, &remote, &len, &event));
    1213            2 :     auto ret = WriteNb(channel, *remote, *local, *len, *event, mask);
    1214            2 :     return HCCL_TO_CCU_RET(ret);
    1215              : }
    1216              : 
    1217            2 : CcuResult CcuKernel::WriteMemToMemReduce(
    1218              :     ChannelHandle channel, CcuRemoteAddrHandle remoteHandle, CcuLocalAddrHandle localHandle,
    1219              :     CcuVariableHandle lenHandle, HcclDataType dataType, HcclReduceOp opType, CcuEventHandle eventHandle, uint32_t mask)
    1220              : {
    1221            2 :     PLF_CONFIG_INFO(
    1222              :         PLF_DATA_OP,
    1223              :         "[WriteMemToMemReduce] channel=%llu, lenHandle=%llu, dataType=%d, op=%d,"
    1224              :         " eventHandle=%llu, mask=%u",
    1225              :         channel, lenHandle, dataType, opType, eventHandle, mask);
    1226            2 :     channels_.insert(channel);
    1227            2 :     CcuRep::RemoteAddr* remote{nullptr};
    1228            2 :     CcuRep::LocalAddr* local{nullptr};
    1229            2 :     CcuRep::Variable* len{nullptr};
    1230            2 :     CcuRep::CompletedEvent* event{nullptr};
    1231            2 :     CCU_CHK_RET(
    1232              :         ResolveRemoteLocalLenEvent(remoteHandle, localHandle, lenHandle, eventHandle, &remote, &local, &len, &event));
    1233            2 :     auto ret = WriteReduceNb(channel, *remote, *local, *len, dataType, opType, *event, mask);
    1234            2 :     return HCCL_TO_CCU_RET(ret);
    1235              : }
    1236              : 
    1237         1502 : void CcuKernel::FlushClosablePendingIfs()
    1238              : {
    1239         1502 :     if (isFlushing_) {
    1240           82 :         return;
    1241              :     }
    1242         1420 :     isFlushing_ = true;
    1243         2922 :     while (IfLabelStackTopIsClosable()) {
    1244           82 :         const char* lbl = IfLabelStackPop();
    1245           82 :         if (lbl != nullptr) {
    1246           82 :             IfEnd(lbl);
    1247              :         }
    1248              :     }
    1249         1420 :     isFlushing_ = false;
    1250              : }
    1251              : 
    1252         1235 : void CcuKernel::Append(std::shared_ptr<CcuRep::CcuRepBase> rep)
    1253              : {
    1254         1235 :     FlushClosablePendingIfs();
    1255         1235 :     CcuRep::CcuRepContext::Append(rep);
    1256         1235 : }
    1257              : 
    1258              : namespace {
    1259          104 :     std::shared_ptr<CcuRep::CcuRepJumpBase> MakeInvertedCondJumpImm(
    1260              :         CcuInsGeneratorBase* insGenerator, const std::string& destLabelStr, const CcuRep::Variable& targetVar,
    1261              :         const CcuRep::Variable& expectVar, const CcuRep::Variable& variable, uint64_t immediate,
    1262              :         CcuConditionType condType, const char* funcName)
    1263              :     {
    1264          104 :         switch (condType) {
    1265           82 :             case CCU_CONDITION_EQ:
    1266          164 :                 return std::make_shared<CcuRep::CcuRepJumpNE>(
    1267           82 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1268           12 :             case CCU_CONDITION_NE:
    1269           24 :                 return std::make_shared<CcuRep::CcuRepJumpEQ>(
    1270           12 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1271            3 :             case CCU_CONDITION_LT:
    1272            6 :                 return std::make_shared<CcuRep::CcuRepJumpGE>(
    1273            3 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1274            2 :             case CCU_CONDITION_LE:
    1275            4 :                 return std::make_shared<CcuRep::CcuRepJumpGT>(
    1276            2 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1277            2 :             case CCU_CONDITION_GT:
    1278            4 :                 return std::make_shared<CcuRep::CcuRepJumpLE>(
    1279            2 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1280            3 :             case CCU_CONDITION_GE:
    1281            6 :                 return std::make_shared<CcuRep::CcuRepJumpLT>(
    1282            3 :                     insGenerator, destLabelStr, targetVar, expectVar, variable, immediate);
    1283            0 :             default:
    1284            0 :                 HCCL_ERROR("[%s] unsupported condition type: %d", funcName, condType);
    1285            0 :                 return nullptr;
    1286              :         }
    1287              :     }
    1288              : 
    1289              :     // 双变量版本:当 (lhsVar OP rhsVar) 为假时跳转到 destLabelStr。
    1290            4 :     std::shared_ptr<CcuRep::CcuRepJumpBase> MakeInvertedCondJumpVar(
    1291              :         CcuInsGeneratorBase* insGenerator, const std::string& destLabelStr, const CcuRep::Variable& targetVar,
    1292              :         const CcuRep::Variable& lhsVar, const CcuRep::Variable& rhsVar, CcuConditionType condType, const char* funcName)
    1293              :     {
    1294            4 :         switch (condType) {
    1295            1 :             case CCU_CONDITION_EQ:
    1296            1 :                 return std::make_shared<CcuRep::CcuRepJumpNE>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1297            0 :             case CCU_CONDITION_NE:
    1298            0 :                 return std::make_shared<CcuRep::CcuRepJumpEQ>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1299            2 :             case CCU_CONDITION_LT:
    1300            2 :                 return std::make_shared<CcuRep::CcuRepJumpGE>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1301            0 :             case CCU_CONDITION_LE:
    1302            0 :                 return std::make_shared<CcuRep::CcuRepJumpGT>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1303            0 :             case CCU_CONDITION_GT:
    1304            0 :                 return std::make_shared<CcuRep::CcuRepJumpLE>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1305            1 :             case CCU_CONDITION_GE:
    1306            1 :                 return std::make_shared<CcuRep::CcuRepJumpLT>(insGenerator, destLabelStr, targetVar, lhsVar, rhsVar);
    1307            0 :             default:
    1308            0 :                 HCCL_ERROR("[%s] unsupported condition type: %d", funcName, condType);
    1309            0 :                 return nullptr;
    1310              :         }
    1311              :     }
    1312              : } // namespace
    1313              : 
    1314              : CcuResult
    1315          102 : CcuKernel::IfBegin(CcuVariableHandle varHandle, uint64_t immediate, CcuConditionType condType, const char* label)
    1316              : {
    1317          102 :     PLF_CONFIG_INFO(
    1318              :         PLF_DATA_OP, "[IfBegin] varHandle=%llu, immediate=%llu, condType=%d, label=%s", varHandle, immediate, condType,
    1319              :         (label ? label : "null"));
    1320          102 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1321            1 :         HCCL_ERROR(
    1322              :             "[%s] CCU_IF is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1323              :             label != nullptr ? label : "(null)");
    1324            1 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1325              :     }
    1326          101 :     CcuRep::Variable* variable{nullptr};
    1327          101 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
    1328              : 
    1329          101 :     FlushClosablePendingIfs();
    1330              : 
    1331          101 :     std::string labelStr(label);
    1332          101 :     if (pendingIfCtx_.find(labelStr) != pendingIfCtx_.end()) {
    1333            0 :         HCCL_ERROR("[%s] label '%s' already has a pending IfBegin without IfEnd", __func__, label);
    1334            0 :         return CcuResult::CCU_E_PARA;
    1335              :     }
    1336              : 
    1337          101 :     std::string elseLabelStr = labelStr + "_else";
    1338          101 :     std::string endLabelStr = labelStr + "_end";
    1339          101 :     auto elseLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, elseLabelStr);
    1340          101 :     auto endLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, endLabelStr);
    1341          101 :     auto targetVar = CreateJumpTargetVar();
    1342          101 :     auto expectVar = CreateExpectVar();
    1343              : 
    1344              :     // 反转条件:"if <cond>, 执行块" 等价于 "!<cond> 时跳过块"。
    1345              :     auto jump = MakeInvertedCondJumpImm(
    1346          101 :         insGenerator, elseLabelStr, targetVar, expectVar, *variable, immediate, condType, __func__);
    1347          101 :     if (jump == nullptr) {
    1348            0 :         return CcuResult::CCU_E_PARA;
    1349              :     }
    1350          101 :     jump->Reference(elseLabel);
    1351          101 :     Append(jump);
    1352              : 
    1353          101 :     PendingIfContext ctx;
    1354          101 :     ctx.elseLabel = elseLabel;
    1355          101 :     ctx.endLabel = endLabel;
    1356          101 :     ctx.hasElse = false;
    1357          101 :     pendingIfCtx_.emplace(labelStr, std::move(ctx));
    1358              : 
    1359          101 :     return CcuResult::CCU_SUCCESS;
    1360          101 : }
    1361              : 
    1362            3 : CcuResult CcuKernel::IfBeginVar(
    1363              :     CcuVariableHandle lhsHandle, CcuVariableHandle rhsHandle, CcuConditionType condType, const char* label)
    1364              : {
    1365            3 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1366            0 :         HCCL_ERROR(
    1367              :             "[%s] CCU_IF is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1368              :             label != nullptr ? label : "(null)");
    1369            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1370              :     }
    1371            3 :     CcuRep::Variable* lhsVar{nullptr};
    1372            3 :     CcuRep::Variable* rhsVar{nullptr};
    1373            3 :     CCU_CHK_RET(GetVariableByHandle(lhsHandle, &lhsVar));
    1374            3 :     CCU_CHK_RET(GetVariableByHandle(rhsHandle, &rhsVar));
    1375              : 
    1376            3 :     FlushClosablePendingIfs();
    1377              : 
    1378            3 :     std::string labelStr(label);
    1379            3 :     if (pendingIfCtx_.find(labelStr) != pendingIfCtx_.end()) {
    1380            0 :         HCCL_ERROR("[%s] label '%s' already has a pending IfBegin without IfEnd", __func__, label);
    1381            0 :         return CcuResult::CCU_E_PARA;
    1382              :     }
    1383              : 
    1384            3 :     std::string endLabelStr = labelStr + "_end";
    1385            3 :     std::string elseLabelStr = labelStr + "_else";
    1386            3 :     auto endLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, endLabelStr);
    1387            3 :     auto elseLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, elseLabelStr);
    1388            3 :     auto targetVar = CreateJumpTargetVar();
    1389              : 
    1390            3 :     auto jump = MakeInvertedCondJumpVar(insGenerator, elseLabelStr, targetVar, *lhsVar, *rhsVar, condType, __func__);
    1391            3 :     if (jump == nullptr) {
    1392            0 :         return CcuResult::CCU_E_PARA;
    1393              :     }
    1394            3 :     jump->Reference(elseLabel);
    1395            3 :     Append(jump);
    1396              : 
    1397            3 :     PendingIfContext ctx;
    1398            3 :     ctx.hasElse = false;
    1399            3 :     ctx.endLabel = endLabel;
    1400            3 :     ctx.elseLabel = elseLabel;
    1401            3 :     pendingIfCtx_.emplace(labelStr, std::move(ctx));
    1402              : 
    1403            3 :     return CcuResult::CCU_SUCCESS;
    1404            3 : }
    1405              : 
    1406           22 : CcuResult CcuKernel::IfElse(const char* label)
    1407              : {
    1408           22 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[IfElse] label=%s", (label ? label : "null"));
    1409           22 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1410            0 :         HCCL_ERROR(
    1411              :             "[%s] CCU_ELSE is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1412              :             label != nullptr ? label : "(null)");
    1413            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1414              :     }
    1415              : 
    1416           22 :     std::string labelStr(label);
    1417           22 :     auto iter = pendingIfCtx_.find(labelStr);
    1418           22 :     if (iter == pendingIfCtx_.end()) {
    1419            0 :         HCCL_ERROR("[%s] no matching IfBegin for label '%s'", __func__, label);
    1420            0 :         return CcuResult::CCU_E_NOT_FOUND;
    1421              :     }
    1422              : 
    1423           22 :     if (iter->second.hasElse) {
    1424            0 :         HCCL_ERROR("[%s] label '%s' already has an IfElse", __func__, label);
    1425            0 :         return CcuResult::CCU_E_PARA;
    1426              :     }
    1427              : 
    1428              :     // At end of then-block: unconditional jump past else-block to endLabel
    1429           22 :     std::string endLabelStr = labelStr + "_end";
    1430           22 :     auto skipElseVar = CreateJumpTargetVar();
    1431           22 :     auto skipElseJump = std::make_shared<CcuRep::CcuRepJump>(insGenerator, endLabelStr, skipElseVar);
    1432           22 :     skipElseJump->Reference(iter->second.endLabel);
    1433           22 :     Append(skipElseJump);
    1434              : 
    1435              :     // Place the else label (entry point of else-block)
    1436           22 :     Append(iter->second.elseLabel);
    1437              : 
    1438           22 :     iter->second.hasElse = true;
    1439              : 
    1440           22 :     return CcuResult::CCU_SUCCESS;
    1441           22 : }
    1442              : 
    1443          104 : CcuResult CcuKernel::IfEnd(const char* label)
    1444              : {
    1445          104 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[IfEnd] label=%s", (label ? label : "null"));
    1446          104 :     std::string labelStr(label);
    1447          104 :     auto iter = pendingIfCtx_.find(labelStr);
    1448          104 :     if (iter == pendingIfCtx_.end()) {
    1449            0 :         HCCL_ERROR("[%s] no matching IfBegin for label '%s'", __func__, label);
    1450            0 :         return CcuResult::CCU_E_NOT_FOUND;
    1451              :     }
    1452              : 
    1453          104 :     if (iter->second.hasElse) {
    1454              :         // Had else-block: place endLabel after else-block
    1455           22 :         Append(iter->second.endLabel);
    1456              :     } else {
    1457              :         // No else-block: place elseLabel as the skip target
    1458           82 :         Append(iter->second.elseLabel);
    1459              :     }
    1460              : 
    1461          104 :     pendingIfCtx_.erase(iter);
    1462              : 
    1463          104 :     return CcuResult::CCU_SUCCESS;
    1464          104 : }
    1465              : 
    1466              : CcuResult
    1467            3 : CcuKernel::WhileBegin(CcuVariableHandle varHandle, uint64_t immediate, CcuConditionType condType, const char* label)
    1468              : {
    1469            3 :     PLF_CONFIG_INFO(
    1470              :         PLF_DATA_OP, "[WhileBegin] varHandle=%llu, immediate=%llu, condType=%d, label=%s", varHandle, immediate,
    1471              :         condType, (label ? label : "null"));
    1472            3 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1473            0 :         HCCL_ERROR(
    1474              :             "[%s] CCU_WHILE is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1475              :             label != nullptr ? label : "(null)");
    1476            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1477              :     }
    1478              : 
    1479            3 :     CcuRep::Variable* variable{nullptr};
    1480            3 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
    1481              : 
    1482            3 :     std::string labelStr(label);
    1483            3 :     if (pendingWhileCtx_.find(labelStr) != pendingWhileCtx_.end()) {
    1484            0 :         HCCL_ERROR("[%s] label '%s' already has a pending WhileBegin without WhileEnd", __func__, label);
    1485            0 :         return CcuResult::CCU_E_PARA;
    1486              :     }
    1487              : 
    1488            3 :     std::string beginLabelStr = labelStr + "_begin";
    1489            3 :     std::string endLabelStr = labelStr + "_end";
    1490            3 :     auto beginLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, beginLabelStr);
    1491            3 :     auto endLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, endLabelStr);
    1492              : 
    1493            3 :     Append(beginLabel);
    1494              : 
    1495            3 :     auto targetVar = CcuRep::CreateVariable(this);
    1496            3 :     auto expectVar = CreateExpectVar();
    1497              :     auto jump = MakeInvertedCondJumpImm(
    1498            3 :         insGenerator, endLabelStr, targetVar, expectVar, *variable, immediate, condType, __func__);
    1499            3 :     if (jump == nullptr) {
    1500            0 :         return CcuResult::CCU_E_PARA;
    1501              :     }
    1502            3 :     jump->Reference(endLabel);
    1503            3 :     Append(jump);
    1504              : 
    1505            3 :     PendingWhileContext ctx;
    1506            3 :     ctx.beginLabel = beginLabel;
    1507            3 :     ctx.endLabel = endLabel;
    1508            3 :     ctx.varHandle = varHandle;
    1509            3 :     ctx.immediate = immediate;
    1510            3 :     ctx.condType = condType;
    1511            3 :     pendingWhileCtx_.emplace(labelStr, std::move(ctx));
    1512              : 
    1513            3 :     return CcuResult::CCU_SUCCESS;
    1514            3 : }
    1515              : 
    1516            1 : CcuResult CcuKernel::WhileBeginVar(
    1517              :     CcuVariableHandle lhsHandle, CcuVariableHandle rhsHandle, CcuConditionType condType, const char* label)
    1518              : {
    1519            1 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1520            0 :         HCCL_ERROR(
    1521              :             "[%s] CCU_WHILE is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1522              :             label != nullptr ? label : "(null)");
    1523            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1524              :     }
    1525              : 
    1526            1 :     CcuRep::Variable* lhsVar{nullptr};
    1527            1 :     CcuRep::Variable* rhsVar{nullptr};
    1528            1 :     CCU_CHK_RET(GetVariableByHandle(lhsHandle, &lhsVar));
    1529            1 :     CCU_CHK_RET(GetVariableByHandle(rhsHandle, &rhsVar));
    1530              : 
    1531            1 :     std::string labelStr(label);
    1532            1 :     if (pendingWhileCtx_.find(labelStr) != pendingWhileCtx_.end()) {
    1533            0 :         HCCL_ERROR("[%s] label '%s' already has a pending WhileBegin without WhileEnd", __func__, label);
    1534            0 :         return CcuResult::CCU_E_PARA;
    1535              :     }
    1536              : 
    1537            1 :     std::string endLabelStr = labelStr + "_end";
    1538            1 :     std::string beginLabelStr = labelStr + "_begin";
    1539            1 :     auto endLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, endLabelStr);
    1540            1 :     auto beginLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, beginLabelStr);
    1541              : 
    1542            1 :     Append(beginLabel);
    1543              : 
    1544            1 :     auto targetVar = CcuRep::CreateVariable(this);
    1545            1 :     auto jump = MakeInvertedCondJumpVar(insGenerator, endLabelStr, targetVar, *lhsVar, *rhsVar, condType, __func__);
    1546            1 :     if (jump == nullptr) {
    1547            0 :         return CcuResult::CCU_E_PARA;
    1548              :     }
    1549            1 :     jump->Reference(endLabel);
    1550            1 :     Append(jump);
    1551              : 
    1552            1 :     PendingWhileContext ctx;
    1553            1 :     ctx.beginLabel = beginLabel;
    1554            1 :     ctx.endLabel = endLabel;
    1555            1 :     ctx.varHandle = lhsHandle;
    1556            1 :     ctx.immediate = 0;
    1557            1 :     ctx.condType = condType;
    1558            1 :     pendingWhileCtx_.emplace(labelStr, std::move(ctx));
    1559              : 
    1560            1 :     return CcuResult::CCU_SUCCESS;
    1561            1 : }
    1562              : 
    1563            4 : CcuResult CcuKernel::WhileEnd(const char* label)
    1564              : {
    1565            4 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[WhileEnd] label=%s", (label ? label : "null"));
    1566            4 :     std::string labelStr(label);
    1567            4 :     auto iter = pendingWhileCtx_.find(labelStr);
    1568            4 :     if (iter == pendingWhileCtx_.end()) {
    1569            0 :         HCCL_ERROR("[%s] no matching WhileBegin for label '%s'", __func__, label);
    1570            0 :         return CcuResult::CCU_E_NOT_FOUND;
    1571              :     }
    1572              : 
    1573            4 :     std::string beginLabelStr = labelStr + "_begin";
    1574            4 :     auto loopBackVar = CcuRep::CreateVariable(this);
    1575            4 :     auto loopBackJump = std::make_shared<CcuRep::CcuRepJump>(insGenerator, beginLabelStr, loopBackVar);
    1576            4 :     loopBackJump->Reference(iter->second.beginLabel);
    1577            4 :     Append(loopBackJump);
    1578              : 
    1579            4 :     Append(iter->second.endLabel);
    1580              : 
    1581            4 :     pendingWhileCtx_.erase(iter);
    1582              : 
    1583            4 :     return CcuResult::CCU_SUCCESS;
    1584            4 : }
    1585              : 
    1586            9 : CcuResult CcuKernel::DoWhileBegin(const char* label)
    1587              : {
    1588            9 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[DoWhileBegin] label=%s", (label ? label : "null"));
    1589            9 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1590            0 :         HCCL_ERROR(
    1591              :             "[%s] CCU_DO is not allowed inside a ccu::Loop body (label='%s')", __func__,
    1592              :             label != nullptr ? label : "(null)");
    1593            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    1594              :     }
    1595              : 
    1596            9 :     std::string labelStr(label);
    1597            9 :     if (pendingDoWhileCtx_.find(labelStr) != pendingDoWhileCtx_.end()) {
    1598            0 :         HCCL_ERROR("[%s] label '%s' already has a pending DoWhileBegin without DoWhileEnd", __func__, label);
    1599            0 :         return CcuResult::CCU_E_PARA;
    1600              :     }
    1601              : 
    1602            9 :     std::string beginLabelStr = labelStr + "_begin";
    1603            9 :     auto beginLabel = std::make_shared<CcuRep::CcuRepJumpLabel>(insGenerator, beginLabelStr);
    1604            9 :     Append(beginLabel);
    1605              : 
    1606            9 :     PendingDoWhileContext ctx;
    1607            9 :     ctx.beginLabel = beginLabel;
    1608            9 :     pendingDoWhileCtx_.emplace(labelStr, std::move(ctx));
    1609              : 
    1610            9 :     return CcuResult::CCU_SUCCESS;
    1611            9 : }
    1612              : 
    1613              : CcuResult
    1614            5 : CcuKernel::DoWhileEnd(CcuVariableHandle varHandle, uint64_t immediate, CcuConditionType condType, const char* label)
    1615              : {
    1616            5 :     PLF_CONFIG_INFO(
    1617              :         PLF_DATA_OP, "[DoWhileEnd] varHandle=%llu, immediate=%llu, condType=%d, label=%s", varHandle, immediate,
    1618              :         condType, (label ? label : "null"));
    1619            5 :     CcuRep::Variable* variable{nullptr};
    1620            5 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
    1621              : 
    1622            5 :     std::string labelStr(label);
    1623            5 :     auto iter = pendingDoWhileCtx_.find(labelStr);
    1624            5 :     if (iter == pendingDoWhileCtx_.end()) {
    1625            0 :         HCCL_ERROR("[%s] no matching DoWhileBegin for label '%s'", __func__, label);
    1626            0 :         return CcuResult::CCU_E_NOT_FOUND;
    1627              :     }
    1628              : 
    1629            5 :     std::string beginLabelStr = labelStr + "_begin";
    1630            5 :     auto targetVar = CcuRep::CreateVariable(this);
    1631            5 :     auto expectVar = CreateExpectVar();
    1632            5 :     std::shared_ptr<CcuRep::CcuRepJumpBase> jump{nullptr};
    1633              : 
    1634              :     // "condition true => continue looping" means jump back to begin when condition holds
    1635            5 :     if (condType == CCU_CONDITION_EQ) {
    1636            0 :         jump = std::make_shared<CcuRep::CcuRepJumpEQ>(
    1637            0 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1638            5 :     } else if (condType == CCU_CONDITION_NE) {
    1639            4 :         jump = std::make_shared<CcuRep::CcuRepJumpNE>(
    1640            4 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1641            1 :     } else if (condType == CCU_CONDITION_LT) {
    1642            0 :         jump = std::make_shared<CcuRep::CcuRepJumpLT>(
    1643            0 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1644            1 :     } else if (condType == CCU_CONDITION_LE) {
    1645            1 :         jump = std::make_shared<CcuRep::CcuRepJumpLE>(
    1646            1 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1647            0 :     } else if (condType == CCU_CONDITION_GT) {
    1648            0 :         jump = std::make_shared<CcuRep::CcuRepJumpGT>(
    1649            0 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1650            0 :     } else if (condType == CCU_CONDITION_GE) {
    1651            0 :         jump = std::make_shared<CcuRep::CcuRepJumpGE>(
    1652            0 :             insGenerator, beginLabelStr, targetVar, expectVar, *variable, immediate);
    1653              :     } else {
    1654            0 :         HCCL_ERROR("[%s] unsupported condition type: %d", __func__, condType);
    1655            0 :         return CcuResult::CCU_E_PARA;
    1656              :     }
    1657              : 
    1658            5 :     jump->Reference(iter->second.beginLabel);
    1659            5 :     Append(jump);
    1660              : 
    1661            5 :     pendingDoWhileCtx_.erase(iter);
    1662              : 
    1663            5 :     return CcuResult::CCU_SUCCESS;
    1664            5 : }
    1665              : 
    1666            1 : CcuResult CcuKernel::DoWhileEndVar(
    1667              :     CcuVariableHandle lhsHandle, CcuVariableHandle rhsHandle, CcuConditionType condType, const char* label)
    1668              : {
    1669            1 :     CcuRep::Variable* lhsVar{nullptr};
    1670            1 :     CcuRep::Variable* rhsVar{nullptr};
    1671            1 :     CCU_CHK_RET(GetVariableByHandle(lhsHandle, &lhsVar));
    1672            1 :     CCU_CHK_RET(GetVariableByHandle(rhsHandle, &rhsVar));
    1673              : 
    1674            1 :     std::string labelStr(label);
    1675            1 :     auto iter = pendingDoWhileCtx_.find(labelStr);
    1676            1 :     if (iter == pendingDoWhileCtx_.end()) {
    1677            0 :         HCCL_ERROR("[%s] no matching DoWhileBegin for label '%s'", __func__, label);
    1678            0 :         return CcuResult::CCU_E_NOT_FOUND;
    1679              :     }
    1680              : 
    1681            1 :     std::string beginLabelStr = labelStr + "_begin";
    1682            1 :     auto targetVar = CcuRep::CreateVariable(this);
    1683            1 :     std::shared_ptr<CcuRep::CcuRepJumpBase> jump{nullptr};
    1684              : 
    1685            1 :     if (condType == CCU_CONDITION_EQ) {
    1686            0 :         jump = std::make_shared<CcuRep::CcuRepJumpEQ>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1687            1 :     } else if (condType == CCU_CONDITION_NE) {
    1688            1 :         jump = std::make_shared<CcuRep::CcuRepJumpNE>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1689            0 :     } else if (condType == CCU_CONDITION_LT) {
    1690            0 :         jump = std::make_shared<CcuRep::CcuRepJumpLT>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1691            0 :     } else if (condType == CCU_CONDITION_LE) {
    1692            0 :         jump = std::make_shared<CcuRep::CcuRepJumpLE>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1693            0 :     } else if (condType == CCU_CONDITION_GT) {
    1694            0 :         jump = std::make_shared<CcuRep::CcuRepJumpGT>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1695            0 :     } else if (condType == CCU_CONDITION_GE) {
    1696            0 :         jump = std::make_shared<CcuRep::CcuRepJumpGE>(insGenerator, beginLabelStr, targetVar, *lhsVar, *rhsVar);
    1697              :     } else {
    1698            0 :         HCCL_ERROR("[%s] unsupported condition type: %d", __func__, condType);
    1699            0 :         return CcuResult::CCU_E_PARA;
    1700              :     }
    1701              : 
    1702            1 :     jump->Reference(iter->second.beginLabel);
    1703            1 :     Append(jump);
    1704              : 
    1705            1 :     pendingDoWhileCtx_.erase(iter);
    1706              : 
    1707            1 :     return CcuResult::CCU_SUCCESS;
    1708            1 : }
    1709              : 
    1710              : // 控制流标签栈实体
    1711          104 : void CcuKernel::IfLabelStackPush(const char* label) { iflabelStack_.push_back({label, false}); }
    1712          104 : void CcuKernel::IfLabelStackMarkBodyDone()
    1713              : {
    1714          104 :     if (iflabelStack_.empty()) {
    1715            0 :         HCCL_ERROR("[CcuKernel::IfLabelStack][MarkBodyDone] stack is empty");
    1716            0 :         return;
    1717              :     }
    1718          104 :     iflabelStack_.back().bodyDone = true;
    1719              : }
    1720           22 : const char* CcuKernel::IfLabelStackPopForElse()
    1721              : {
    1722           22 :     if (iflabelStack_.empty()) {
    1723            0 :         HCCL_ERROR("[CcuKernel::IfLabelStack][PopForElse] orphan CCU_ELSE: "
    1724              :                    "no matching CCU_IF on the stack");
    1725            0 :         return nullptr;
    1726              :     }
    1727           22 :     if (!iflabelStack_.back().bodyDone) {
    1728            0 :         HCCL_ERROR(
    1729              :             "[CcuKernel::IfLabelStack][PopForElse] CCU_ELSE called while "
    1730              :             "top if-body is still InBody (label='%s')",
    1731              :             iflabelStack_.back().label != nullptr ? iflabelStack_.back().label : "(null)");
    1732            0 :         return nullptr;
    1733              :     }
    1734           22 :     const char* label = iflabelStack_.back().label;
    1735           22 :     iflabelStack_.pop_back();
    1736           22 :     return label;
    1737              : }
    1738         1502 : bool CcuKernel::IfLabelStackTopIsClosable() { return !iflabelStack_.empty() && iflabelStack_.back().bodyDone; }
    1739              : 
    1740           82 : const char* CcuKernel::IfLabelStackPop()
    1741              : {
    1742           82 :     if (iflabelStack_.empty()) {
    1743            0 :         return nullptr;
    1744              :     }
    1745           82 :     const char* label = iflabelStack_.back().label;
    1746           82 :     iflabelStack_.pop_back();
    1747           82 :     return label;
    1748              : }
    1749              : 
    1750            9 : void CcuKernel::DoWhileLabelStackPush(const char* label)
    1751              : {
    1752            9 :     DoWhileLabelEntry entry;
    1753            9 :     entry.label = label;
    1754            9 :     entry.snapshotBlock = CurrentBlock();
    1755            9 :     entry.snapshotRepCount = (entry.snapshotBlock != nullptr) ? entry.snapshotBlock->GetReps().size() : 0;
    1756            9 :     doWhileLabelStack_.push_back(std::move(entry));
    1757            9 : }
    1758              : 
    1759           13 : const char* CcuKernel::DoWhileLabelStackPopForWhile()
    1760              : {
    1761           13 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1762            1 :         return nullptr;
    1763              :     }
    1764           12 :     if (doWhileLabelStack_.empty()) {
    1765            4 :         return nullptr;
    1766              :     }
    1767            8 :     DoWhileLabelEntry entry = doWhileLabelStack_.back();
    1768            8 :     doWhileLabelStack_.pop_back();
    1769              : 
    1770            8 :     auto currentBlock = CurrentBlock();
    1771            8 :     size_t currentRepCount = (currentBlock != nullptr) ? currentBlock->GetReps().size() : 0;
    1772            8 :     if (currentBlock != entry.snapshotBlock || currentRepCount != entry.snapshotRepCount) {
    1773            1 :         HCCL_ERROR(
    1774              :             "[CcuKernel::DoWhileLabelStackPopForWhile] dangling CCU calls between CCU_DO end "
    1775              :             "and CCU_WHILE (label='%s', snapRep=%zu, curRep=%zu, blockChanged=%d); they must "
    1776              :             "be syntactically adjacent, otherwise the code in between is pulled into the body.",
    1777              :             entry.label != nullptr ? entry.label : "(null)", entry.snapshotRepCount, currentRepCount,
    1778              :             currentBlock != entry.snapshotBlock ? 1 : 0);
    1779            1 :         return nullptr;
    1780              :     }
    1781            7 :     return entry.label;
    1782            8 : }
    1783              : 
    1784          152 : CcuResult CcuKernel::GetAddressByHandle(CcuAddressHandle addrHandle, CcuRep::Address** address)
    1785              : {
    1786          152 :     return GetResourceByHandle(ccuAddrMap_, addrHandle, address, "address");
    1787              : }
    1788              : 
    1789              : // addr = 立即数 → CcuRepAssign(Address, uint64_t)
    1790           13 : CcuResult CcuKernel::AddressAssignImm(CcuAddressHandle addrHandle, uint64_t immediate)
    1791              : {
    1792           13 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[AddressAssignImm] addrHandle=%llu, immediate=%llu", addrHandle, immediate);
    1793           13 :     CcuRep::Address* address{nullptr};
    1794           13 :     CCU_CHK_RET(GetAddressByHandle(addrHandle, &address));
    1795           13 :     (*address) = immediate;
    1796           13 :     return CcuResult::CCU_SUCCESS;
    1797              : }
    1798              : 
    1799              : // addr = variable → CcuRepAssign(Address, Variable)
    1800           14 : CcuResult CcuKernel::AddressAssignVar(CcuAddressHandle addrHandle, CcuVariableHandle varHandle)
    1801              : {
    1802           14 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[AddressAssignVar] addrHandle=%llu, varHandle=%llu", addrHandle, varHandle);
    1803           14 :     CcuRep::Address* address{nullptr};
    1804           14 :     CCU_CHK_RET(GetAddressByHandle(addrHandle, &address));
    1805              : 
    1806           14 :     CcuRep::Variable* variable{nullptr};
    1807           14 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
    1808              : 
    1809           14 :     (*address) = (*variable);
    1810           14 :     return CcuResult::CCU_SUCCESS;
    1811              : }
    1812              : // addr = addr → CcuRepAssign(Address, Address)
    1813           38 : CcuResult CcuKernel::AddressAssignAddr(CcuAddressHandle dstAddrHandle, CcuAddressHandle srcAddrHandle)
    1814              : {
    1815           38 :     PLF_CONFIG_INFO(
    1816              :         PLF_DATA_OP, "[AddressAssignAddr] dstAddrHandle=%llu, srcAddrHandle=%llu", dstAddrHandle, srcAddrHandle);
    1817           38 :     CcuRep::Address* dstAddress{nullptr};
    1818           38 :     CCU_CHK_RET(GetAddressByHandle(dstAddrHandle, &dstAddress));
    1819              : 
    1820           38 :     CcuRep::Address* srcAddress{nullptr};
    1821           38 :     CCU_CHK_RET(GetAddressByHandle(srcAddrHandle, &srcAddress));
    1822              : 
    1823           38 :     (*dstAddress) = (*srcAddress);
    1824           38 :     return CcuResult::CCU_SUCCESS;
    1825              : }
    1826              : 
    1827              : // resAddr = lhsAddr + rhsVar → CcuRepAdd(Address, Address, Variable)
    1828            0 : CcuResult CcuKernel::AddressAddVarToAddr(
    1829              :     CcuAddressHandle resAddrHandle, CcuAddressHandle lhsAddrHandle, CcuVariableHandle rhsVarHandle)
    1830              : {
    1831            0 :     PLF_CONFIG_INFO(
    1832              :         PLF_DATA_OP, "[AddressAddVarToAddr] resAddrHandle=%llu, lhsAddrHandle=%llu, rhsVarHandle=%llu", resAddrHandle,
    1833              :         lhsAddrHandle, rhsVarHandle);
    1834            0 :     CcuRep::Address *resAddr{nullptr}, *lhsAddr{nullptr};
    1835            0 :     CCU_CHK_RET(GetAddressByHandle(resAddrHandle, &resAddr));
    1836            0 :     CCU_CHK_RET(GetAddressByHandle(lhsAddrHandle, &lhsAddr));
    1837              : 
    1838            0 :     CcuRep::Variable* rhsVar{nullptr};
    1839            0 :     CCU_CHK_RET(GetVariableByHandle(rhsVarHandle, &rhsVar));
    1840              : 
    1841            0 :     *resAddr = *lhsAddr + *rhsVar;
    1842            0 :     return CcuResult::CCU_SUCCESS;
    1843              : }
    1844              : 
    1845              : // resAddr = addrA + addrB → CcuRepAdd(Address, Address, Address)
    1846            2 : CcuResult CcuKernel::AddressAddAddrToAddr(
    1847              :     CcuAddressHandle resAddrHandle, CcuAddressHandle addrAHandle, CcuAddressHandle addrBHandle)
    1848              : {
    1849            2 :     PLF_CONFIG_INFO(
    1850              :         PLF_DATA_OP, "[AddressAddAddrToAddr] resAddrHandle=%llu, addrAHandle=%llu, addrBHandle=%llu", resAddrHandle,
    1851              :         addrAHandle, addrBHandle);
    1852            2 :     CcuRep::Address *resAddr{nullptr}, *addrA{nullptr}, *addrB{nullptr};
    1853            2 :     CCU_CHK_RET(GetAddressByHandle(resAddrHandle, &resAddr));
    1854            2 :     CCU_CHK_RET(GetAddressByHandle(addrAHandle, &addrA));
    1855            2 :     CCU_CHK_RET(GetAddressByHandle(addrBHandle, &addrB));
    1856              : 
    1857            2 :     *resAddr = *addrA + *addrB;
    1858            2 :     return CcuResult::CCU_SUCCESS;
    1859              : }
    1860              : 
    1861              : // addr += variable → CcuRepAdd(Address, Variable) 就地加
    1862           41 : CcuResult CcuKernel::AddressAddAssignVar(CcuAddressHandle addrHandle, CcuVariableHandle varHandle)
    1863              : {
    1864           41 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[AddressAddAssignVar] addrHandle=%llu, varHandle=%llu", addrHandle, varHandle);
    1865           41 :     CcuRep::Address* address{nullptr};
    1866           41 :     CCU_CHK_RET(GetAddressByHandle(addrHandle, &address));
    1867              : 
    1868           41 :     CcuRep::Variable* variable{nullptr};
    1869           41 :     CCU_CHK_RET(GetVariableByHandle(varHandle, &variable));
    1870              : 
    1871           41 :     (*address) += (*variable);
    1872           41 :     return CcuResult::CCU_SUCCESS;
    1873              : }
    1874              : 
    1875              : // addr += addr → 等价于 addr = addr + otherAddr
    1876            0 : CcuResult CcuKernel::AddressAddAssignAddr(CcuAddressHandle addrHandle, CcuAddressHandle otherHandle)
    1877              : {
    1878            0 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[AddressAddAssignAddr] addrHandle=%llu, otherHandle=%llu", addrHandle, otherHandle);
    1879            0 :     CcuRep::Address* address{nullptr};
    1880            0 :     CCU_CHK_RET(GetAddressByHandle(addrHandle, &address));
    1881              : 
    1882            0 :     CcuRep::Address* other{nullptr};
    1883            0 :     CCU_CHK_RET(GetAddressByHandle(otherHandle, &other));
    1884              : 
    1885            0 :     (*address) = (*address) + (*other);
    1886            0 :     return CcuResult::CCU_SUCCESS;
    1887              : }
    1888              : 
    1889            1 : CcuResult CcuKernel::AddressAddImmToAddr(CcuAddressHandle resAddrHandle, CcuAddressHandle addrAHandle, uint16_t imm)
    1890              : {
    1891            1 :     CcuRep::Address *resAddr{nullptr}, *addrA{nullptr};
    1892            1 :     CCU_CHK_RET(GetAddressByHandle(resAddrHandle, &resAddr));
    1893            1 :     CCU_CHK_RET(GetAddressByHandle(addrAHandle, &addrA));
    1894              : 
    1895            1 :     *resAddr = *addrA + imm;
    1896            1 :     return CcuResult::CCU_SUCCESS;
    1897              : }
    1898              : 
    1899            0 : void CcuKernel::Load(const CcuRep::Variable& var)
    1900              : {
    1901              :     auto loadArgRep = std::make_shared<CcuRep::CcuRepLoadArg>(
    1902            0 :         insGenerator, var, loadArgIndex_ % CCU_SQE_ARGS_LEN, static_cast<uint16_t>(loadArgIndex_));
    1903            0 :     GetLGProfilingInfo().loadRep2ArgIdxMap[loadArgRep] = loadArgIndex_;
    1904            0 :     Append(loadArgRep);
    1905            0 :     loadArgIndex_++;
    1906            0 : }
    1907              : 
    1908            0 : void CcuKernel::StoreVariable(const CcuRep::Variable& var, uint64_t addr)
    1909              : {
    1910            0 :     Append(std::make_shared<CcuRep::CcuRepStore>(insGenerator, var, addr));
    1911            0 : }
    1912              : 
    1913            0 : void CcuKernel::LoadVariable(const CcuRep::Variable& src, const CcuRep::Variable& var)
    1914              : {
    1915            0 :     Append(std::make_shared<CcuRep::CcuRepLoadVar>(insGenerator, src, var));
    1916            0 : }
    1917              : 
    1918           18 : HcclResult CcuKernel::RecordEvent(CcuRep::CompletedEvent event, uint32_t mask)
    1919              : {
    1920           18 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    1921            1 :         HCCL_ERROR("[CcuKernel][%s] is not supported in loop block, please check.", __func__);
    1922            1 :         LatchBodyError(HCCL_TO_CCU_RET(HcclResult::HCCL_E_NOT_SUPPORT));
    1923            1 :         return HcclResult::HCCL_E_NOT_SUPPORT;
    1924              :     }
    1925              : 
    1926           17 :     auto rep = std::make_shared<CcuRep::CcuRepLocRecordEvent>(insGenerator, event, mask);
    1927           17 :     Append(rep);
    1928           17 :     SetDependencyInfo(event.Id(), mask, rep);
    1929           17 :     return HCCL_SUCCESS;
    1930           17 : }
    1931              : 
    1932           44 : HcclResult CcuKernel::WaitEvent(CcuRep::CompletedEvent event, uint32_t mask)
    1933              : {
    1934           44 :     bool isProfiling = CurrentBlock()->Type() != CcuRep::CcuRepType::LOOP_BLOCK;
    1935           44 :     auto rep = std::make_shared<CcuRep::CcuRepLocWaitEvent>(insGenerator, event, mask, isProfiling);
    1936           44 :     if (isProfiling) {
    1937           84 :         CHK_RET(static_cast<HcclResult>(AddProfiling("WaitEvent", rep->GetMask())));
    1938              :     }
    1939           44 :     rep->SetDependencyInfo(GetDependencyInfo(event.Id()));
    1940           44 :     EraseDependencyInfo(event.Id());
    1941           44 :     Append(rep);
    1942           44 :     return HCCL_SUCCESS;
    1943           44 : }
    1944              : 
    1945          102 : CcuResult CcuKernel::GetEventByHandle(CcuEventHandle eventHandle, CcuRep::CompletedEvent** event)
    1946              : {
    1947          102 :     return GetResourceByHandle(ccuEventMap_, eventHandle, event, "completedEvent");
    1948              : }
    1949              : 
    1950              : /*
    1951              : LocalAddr / RemoteAddr 相关接口
    1952              : */
    1953           33 : CcuResult CcuKernel::GetLocalAddrByHandle(CcuLocalAddrHandle handle, CcuRep::LocalAddr** localAddr)
    1954              : {
    1955           33 :     return GetResourceByHandle(ccuLocalAddrMap_, handle, localAddr, "localAddr");
    1956              : }
    1957              : 
    1958           15 : CcuResult CcuKernel::GetRemoteAddrByHandle(CcuRemoteAddrHandle handle, CcuRep::RemoteAddr** remoteAddr)
    1959              : {
    1960           15 :     return GetResourceByHandle(ccuRemoteAddrMap_, handle, remoteAddr, "remoteAddr");
    1961              : }
    1962              : 
    1963              : /*Read新接口*/
    1964            2 : HcclResult CcuKernel::ReadNb(
    1965              :     const ChannelHandle channel, const CcuRep::CcuBuf& loc, const CcuRep::RemoteAddr& rem, const CcuRep::Variable& len,
    1966              :     CcuRep::CompletedEvent event, uint32_t mask)
    1967              : {
    1968            2 :     channels_.insert(channel);
    1969            2 :     auto rep = std::make_shared<CcuRep::CcuRepBufRead>(insGenerator, channel, rem, loc, len, event, mask);
    1970            2 :     Append(rep);
    1971            2 :     SetDependencyInfo(event.Id(), mask, rep);
    1972            2 :     return HCCL_SUCCESS;
    1973            2 : }
    1974              : 
    1975              : /*Write新接口*/
    1976            2 : HcclResult CcuKernel::WriteNb(
    1977              :     const ChannelHandle channel, const CcuRep::RemoteAddr& rem, const CcuRep::CcuBuf& loc, const CcuRep::Variable& len,
    1978              :     CcuRep::CompletedEvent event, uint32_t mask)
    1979              : {
    1980            2 :     channels_.insert(channel);
    1981            2 :     auto rep = std::make_shared<CcuRep::CcuRepBufWrite>(insGenerator, channel, loc, rem, len, event, mask);
    1982            2 :     Append(rep);
    1983            2 :     SetDependencyInfo(event.Id(), mask, rep);
    1984            2 :     return HCCL_SUCCESS;
    1985            2 : }
    1986              : 
    1987            8 : static bool isLowPrecisionIn(Hccl::DataType dataType)
    1988              : {
    1989           16 :     return dataType == Hccl::DataType::INT8 || dataType == Hccl::DataType::HIF8 || dataType == Hccl::DataType::FP8E4M3
    1990           16 :            || dataType == Hccl::DataType::FP8E5M2;
    1991              : }
    1992              : 
    1993            0 : static bool isLowPrecisionOut(Hccl::DataType dataType)
    1994              : {
    1995            0 :     return dataType == Hccl::DataType::FP16 || dataType == Hccl::DataType::BFP16 || dataType == Hccl::DataType::FP32;
    1996              : }
    1997              : 
    1998              : constexpr uint32_t MAX_DATA_TYPE = 17;
    1999              : 
    2000              : const Hccl::DataType orionDataTypes[]
    2001              :     = {Hccl::DataType::INT8,   Hccl::DataType::INT16,   Hccl::DataType::INT32,
    2002              :        Hccl::DataType::FP16,   Hccl::DataType::FP32,    Hccl::DataType::INT64,
    2003              :        Hccl::DataType::UINT64, Hccl::DataType::UINT8,   Hccl::DataType::UINT16,
    2004              :        Hccl::DataType::UINT32, Hccl::DataType::FP64,    Hccl::DataType::BFP16,
    2005              :        Hccl::DataType::INT128,
    2006              : #if !defined(OPEN_BUILD_PROJECT) || defined(ORION_MODE)
    2007              :        Hccl::DataType::HIF8,   Hccl::DataType::FP8E4M3, Hccl::DataType::FP8E5M2,
    2008              :        Hccl::DataType::FP8E8M0
    2009              : #endif
    2010              : };
    2011              : 
    2012           12 : static Hccl::DataType HcommDataTypeToHcclDataType(const HcclDataType dataType)
    2013              : {
    2014           12 :     const auto dataTypeNum = static_cast<uint32_t>(dataType);
    2015           12 :     if (dataTypeNum > MAX_DATA_TYPE) {
    2016            0 :         return Hccl::DataType::INVALID;
    2017              :     }
    2018              : 
    2019           12 :     return orionDataTypes[dataTypeNum];
    2020              : }
    2021              : 
    2022              : constexpr uint32_t MAX_REDUCE_TYPE = 4;
    2023              : const Hccl::ReduceOp orionReduceOps[] = {
    2024              :     Hccl::ReduceOp::SUM,
    2025              :     Hccl::ReduceOp::PROD,
    2026              :     Hccl::ReduceOp::MAX,
    2027              :     Hccl::ReduceOp::MIN,
    2028              : };
    2029              : 
    2030            8 : static Hccl::ReduceOp HcommReduceOpToHcclReduceOp(const HcclReduceOp reduceOp)
    2031              : {
    2032            8 :     const auto reduceOpNum = static_cast<uint32_t>(reduceOp);
    2033            8 :     if (reduceOpNum > MAX_REDUCE_TYPE) {
    2034            0 :         return Hccl::ReduceOp::INVALID;
    2035              :     }
    2036              : 
    2037            8 :     return orionReduceOps[reduceOpNum];
    2038              : }
    2039              : 
    2040            4 : HcclResult CcuKernel::LocalReduceNb(
    2041              :     const CcuRep::CcuBuf* bufs, uint32_t count, HcclDataType dataType, HcclDataType outputDataType, HcclReduceOp opType,
    2042              :     const CcuRep::Variable& len, CcuRep::CompletedEvent event, uint32_t mask)
    2043              : {
    2044            4 :     auto opType_ = HcommReduceOpToHcclReduceOp(opType);
    2045            4 :     auto dataType_ = HcommDataTypeToHcclDataType(dataType);
    2046            4 :     auto outputDataType_ = HcommDataTypeToHcclDataType(outputDataType);
    2047              : 
    2048            8 :     if ((opType_ == Hccl::ReduceOp::SUM && isLowPrecisionIn(dataType_) && !isLowPrecisionOut(outputDataType_))
    2049            4 :         || (opType_ == Hccl::ReduceOp::SUM && !isLowPrecisionIn(dataType_) && dataType_ != outputDataType_)
    2050            8 :         || (opType_ != Hccl::ReduceOp::SUM && dataType_ != outputDataType_)) {
    2051            0 :         return HCCL_E_NOT_SUPPORT;
    2052              :     }
    2053              : 
    2054            4 :     std::vector<CcuRep::CcuBuf> ccuBufs(count);
    2055           12 :     for (uint32_t i = 0; i < count; i++) {
    2056            8 :         ccuBufs[i] = bufs[i];
    2057              :     }
    2058              : 
    2059              :     auto rep = std::make_shared<CcuRep::CcuRepBufReduce>(
    2060            0 :         insGenerator, ccuBufs, count, CcuRep::GetCcuDataType(dataType_, opType_),
    2061            4 :         CcuRep::GetCcuDataType(outputDataType_, opType_), CcuRep::GetCcuReduceType(opType_), event, len, mask);
    2062            4 :     Append(rep);
    2063            4 :     SetDependencyInfo(event.Id(), mask, rep);
    2064            4 :     return HCCL_SUCCESS;
    2065            4 : }
    2066              : 
    2067              : /*Read新接口*/
    2068            4 : HcclResult CcuKernel::ReadNb(
    2069              :     const ChannelHandle channel, const CcuRep::LocalAddr& loc, const CcuRep::RemoteAddr& rem,
    2070              :     const CcuRep::Variable& len, CcuRep::CompletedEvent event, uint32_t mask)
    2071              : {
    2072            4 :     channels_.insert(channel);
    2073            4 :     auto rep = std::make_shared<CcuRep::CcuRepRead>(insGenerator, channel, loc, rem, len, event, mask);
    2074            4 :     Append(rep);
    2075            4 :     SetDependencyInfo(event.Id(), mask, rep);
    2076            4 :     return HCCL_SUCCESS;
    2077            4 : }
    2078              : 
    2079              : /*ReadReduce新接口*/
    2080            2 : HcclResult CcuKernel::ReadReduceNb(
    2081              :     const ChannelHandle channel, const CcuRep::LocalAddr& loc, const CcuRep::RemoteAddr& rem,
    2082              :     const CcuRep::Variable& len, HcclDataType dataType, HcclReduceOp opType, CcuRep::CompletedEvent event,
    2083              :     uint32_t mask)
    2084              : {
    2085            2 :     channels_.insert(channel);
    2086            2 :     auto opType_ = HcommReduceOpToHcclReduceOp(opType);
    2087            2 :     auto dataType_ = HcommDataTypeToHcclDataType(dataType);
    2088              : 
    2089              :     auto rep = std::make_shared<CcuRep::CcuRepRead>(
    2090            2 :         insGenerator, channel, loc, rem, len, CcuRep::GetUBDataType(dataType_), CcuRep::GetUBReduceType(opType_), event,
    2091            2 :         mask);
    2092            2 :     Append(rep);
    2093            2 :     SetDependencyInfo(event.Id(), mask, rep);
    2094            2 :     return HCCL_SUCCESS;
    2095            2 : }
    2096              : 
    2097              : /*Write新接口*/
    2098            3 : HcclResult CcuKernel::WriteNb(
    2099              :     const ChannelHandle channel, const CcuRep::RemoteAddr& rem, const CcuRep::LocalAddr& loc,
    2100              :     const CcuRep::Variable& len, CcuRep::CompletedEvent event, uint32_t mask)
    2101              : {
    2102            3 :     channels_.insert(channel);
    2103            3 :     auto rep = std::make_shared<CcuRep::CcuRepWrite>(insGenerator, channel, rem, loc, len, event, mask);
    2104            3 :     Append(rep);
    2105            3 :     SetDependencyInfo(event.Id(), mask, rep);
    2106            3 :     return HCCL_SUCCESS;
    2107            3 : }
    2108              : 
    2109            2 : HcclResult CcuKernel::WriteReduceNb(
    2110              :     const ChannelHandle channel, const CcuRep::RemoteAddr& rem, const CcuRep::LocalAddr& loc,
    2111              :     const CcuRep::Variable& len, HcclDataType dataType, HcclReduceOp opType, CcuRep::CompletedEvent event,
    2112              :     uint32_t mask)
    2113              : {
    2114            2 :     channels_.insert(channel);
    2115            2 :     auto opType_ = HcommReduceOpToHcclReduceOp(opType);
    2116            2 :     auto dataType_ = HcommDataTypeToHcclDataType(dataType);
    2117              : 
    2118              :     auto rep = std::make_shared<CcuRep::CcuRepWrite>(
    2119            2 :         insGenerator, channel, rem, loc, len, CcuRep::GetUBDataType(dataType_), CcuRep::GetUBReduceType(opType_), event,
    2120            2 :         mask);
    2121            2 :     Append(rep);
    2122            2 :     SetDependencyInfo(event.Id(), mask, rep);
    2123            2 :     return HCCL_SUCCESS;
    2124            2 : }
    2125              : 
    2126           32 : CcuResult CcuKernel::GetBufferByHandle(CcuBufferHandle bufferHandle, CcuRep::CcuBuf** buffer)
    2127              : {
    2128           32 :     return GetResourceByHandle(ccuBufferMap_, bufferHandle, buffer, "buffer");
    2129              : }
    2130              : 
    2131            1 : HcclResult CcuKernel::LocalCopyNb(
    2132              :     const CcuRep::LocalAddr& dst, const CcuRep::LocalAddr& src, const CcuRep::Variable& len,
    2133              :     CcuRep::CompletedEvent event, uint32_t mask)
    2134              : {
    2135            1 :     auto rep = std::make_shared<CcuRep::CcuRepLocCpy>(insGenerator, dst, src, len, event, mask);
    2136            1 :     Append(rep);
    2137            1 :     SetDependencyInfo(event.Id(), mask, rep);
    2138            1 :     return HCCL_SUCCESS;
    2139            1 : }
    2140              : 
    2141           12 : HcclResult CcuKernel::LocalCopyNb(
    2142              :     const CcuRep::CcuBuf& dst, const CcuRep::LocalAddr& src, const CcuRep::Variable& len, CcuRep::CompletedEvent event,
    2143              :     uint32_t mask)
    2144              : {
    2145           12 :     auto rep = std::make_shared<CcuRep::CcuRepBufLocRead>(insGenerator, src, dst, len, event, mask);
    2146           12 :     Append(rep);
    2147           12 :     SetDependencyInfo(event.Id(), mask, rep);
    2148           12 :     return HCCL_SUCCESS;
    2149           12 : }
    2150              : 
    2151            8 : HcclResult CcuKernel::LocalCopyNb(
    2152              :     const CcuRep::LocalAddr& dst, const CcuRep::CcuBuf& src, const CcuRep::Variable& len, CcuRep::CompletedEvent event,
    2153              :     uint32_t mask)
    2154              : {
    2155            8 :     auto rep = std::make_shared<CcuRep::CcuRepBufLocWrite>(insGenerator, src, dst, len, event, mask);
    2156            8 :     Append(rep);
    2157            8 :     SetDependencyInfo(event.Id(), mask, rep);
    2158            8 :     return HCCL_SUCCESS;
    2159            8 : }
    2160              : 
    2161            0 : HcclResult CcuKernel::LocalReduceNb(
    2162              :     const CcuRep::LocalAddr& dst, const CcuRep::LocalAddr& src, const CcuRep::Variable& len, HcclDataType dataType,
    2163              :     HcclReduceOp opType, CcuRep::CompletedEvent event, uint32_t mask)
    2164              : {
    2165            0 :     auto opType_ = HcommReduceOpToHcclReduceOp(opType);
    2166            0 :     auto dataType_ = HcommDataTypeToHcclDataType(dataType);
    2167              : 
    2168              :     auto rep = std::make_shared<CcuRep::CcuRepLocCpy>(
    2169            0 :         insGenerator, dst, src, len, CcuRep::GetUBDataType(dataType_), CcuRep::GetUBReduceType(opType_), event, mask);
    2170            0 :     Append(rep);
    2171            0 :     SetDependencyInfo(event.Id(), mask, rep);
    2172            0 :     return HCCL_SUCCESS;
    2173            0 : }
    2174              : 
    2175            0 : CcuRep::FuncCall CcuKernel::Func(const std::string& label) { return CcuRep::FuncCall(this, label); }
    2176              : 
    2177            0 : CcuRep::FuncCall CcuKernel::Func(const CcuRep::Variable& funcAddr) { return CcuRep::FuncCall(this, funcAddr); }
    2178              : 
    2179            0 : CcuRep::LoopCall CcuKernel::Loop(const std::string& label) { return CcuRep::LoopCall(this, label); }
    2180              : 
    2181           52 : CcuResult CcuKernel::LoopCreate(CcuLoop* loop)
    2182              : {
    2183           52 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoopCreate]");
    2184           52 :     if (loop == nullptr) {
    2185            0 :         HCCL_ERROR("[CcuKernel::LoopCreate] null pointer");
    2186            0 :         return CcuResult::CCU_E_PTR;
    2187              :     }
    2188           52 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    2189            0 :         HCCL_ERROR("[CcuKernel::LoopCreate] cannot create loop inside a loop body");
    2190            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2191              :     }
    2192           52 :     if (inFuncBody_) {
    2193            0 :         HCCL_ERROR("[CcuKernel::LoopCreate] cannot create loop inside a func body");
    2194            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2195              :     }
    2196              : 
    2197           52 :     CcuLoop handle = ++loopHandleCounter_;
    2198           52 :     std::string label = "loop_" + std::to_string(handle);
    2199              : 
    2200           52 :     LoopDescriptor desc;
    2201           52 :     desc.label = label;
    2202           52 :     desc.repLoopBlock = std::make_shared<CcuRep::CcuRepLoopBlock>(insGenerator, label);
    2203              : 
    2204           52 :     loopMap_[handle] = std::move(desc);
    2205           52 :     *loop = handle;
    2206           52 :     return CcuResult::CCU_SUCCESS;
    2207           52 : }
    2208              : 
    2209            7 : CcuResult CcuKernel::LatchBodyError(CcuResult err)
    2210              : {
    2211           15 :     if ((CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK || inFuncBody_)
    2212           15 :         && bodyError_ == CcuResult::CCU_SUCCESS) {
    2213            7 :         bodyError_ = err;
    2214              :     }
    2215            7 :     return err;
    2216              : }
    2217              : 
    2218           52 : CcuResult CcuKernel::LoopBodyEnter(CcuLoop loop)
    2219              : {
    2220           52 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoopBodyEnter] loop=%llu", loop);
    2221           52 :     auto it = loopMap_.find(loop);
    2222           52 :     if (it == loopMap_.end()) {
    2223            0 :         HCCL_ERROR("[CcuKernel::LoopBodyEnter] invalid loop handle %lu", loop);
    2224            0 :         return CcuResult::CCU_E_PARA;
    2225              :     }
    2226           52 :     auto& desc = it->second;
    2227           52 :     if (desc.bodyDefined) {
    2228            0 :         HCCL_ERROR("[CcuKernel::LoopBodyEnter] loop %lu body already defined", loop);
    2229            0 :         return CcuResult::CCU_E_INTERNAL;
    2230              :     }
    2231              : 
    2232           52 :     Append(desc.repLoopBlock);
    2233           52 :     desc.prevActiveBlock = CurrentBlock();
    2234           52 :     SetCurrentBlock(desc.repLoopBlock);
    2235           52 :     ++loopBodyDepth_;
    2236           52 :     bodyError_ = CcuResult::CCU_SUCCESS;
    2237              : 
    2238           52 :     return CcuResult::CCU_SUCCESS;
    2239              : }
    2240              : 
    2241           52 : CcuResult CcuKernel::LoopBodyExit(CcuLoop loop)
    2242              : {
    2243           52 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoopBodyExit] loop=%llu", loop);
    2244           52 :     auto it = loopMap_.find(loop);
    2245           52 :     if (it == loopMap_.end()) {
    2246            0 :         HCCL_ERROR("[CcuKernel::LoopBodyExit] invalid loop handle %lu", loop);
    2247            0 :         return CcuResult::CCU_E_PARA;
    2248              :     }
    2249           52 :     auto& desc = it->second;
    2250              : 
    2251           52 :     SetCurrentBlock(desc.prevActiveBlock);
    2252           52 :     desc.bodyDefined = true;
    2253           52 :     --loopBodyDepth_;
    2254              : 
    2255           52 :     if (bodyError_ != CcuResult::CCU_SUCCESS) {
    2256            6 :         const CcuResult err = bodyError_;
    2257            6 :         HCCL_ERROR("[CcuKernel::LoopBodyExit] illegal operation inside loop body, err=%d", err);
    2258            6 :         bodyError_ = CcuResult::CCU_SUCCESS;
    2259            6 :         return err;
    2260              :     }
    2261              : 
    2262           46 :     return CcuResult::CCU_SUCCESS;
    2263              : }
    2264              : 
    2265            8 : CcuResult CcuKernel::FuncBlockLookup(const void* funcPtr, uint64_t* outHandle)
    2266              : {
    2267            8 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[FuncBlockLookup] funcPtr=%p", funcPtr);
    2268            8 :     if (funcPtr == nullptr || outHandle == nullptr) {
    2269            0 :         HCCL_ERROR("[CcuKernel::FuncBlockLookup] null pointer");
    2270            0 :         return CcuResult::CCU_E_PTR;
    2271              :     }
    2272            8 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK || inFuncBody_) {
    2273            2 :         HCCL_ERROR("[CcuKernel::FuncBlockLookup] ccu::CallFunc only allowed at top level");
    2274            2 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2275              :     }
    2276              : 
    2277            6 :     auto it = funcInstanceMap_.find(funcPtr);
    2278            6 :     *outHandle = (it == funcInstanceMap_.end()) ? 0 : it->second;
    2279            6 :     return CcuResult::CCU_SUCCESS;
    2280              : }
    2281              : 
    2282            5 : CcuResult CcuKernel::FuncBlockBegin(const void* funcPtr, uint64_t* outHandle)
    2283              : {
    2284            5 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[FuncBlockBegin] funcPtr=%p", funcPtr);
    2285            5 :     if (funcPtr == nullptr || outHandle == nullptr) {
    2286            0 :         HCCL_ERROR("[CcuKernel::FuncBlockBegin] null pointer");
    2287            0 :         return CcuResult::CCU_E_PTR;
    2288              :     }
    2289            5 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK || inFuncBody_) {
    2290            0 :         HCCL_ERROR("[CcuKernel::FuncBlockBegin] ccu::CallFunc only allowed at top level");
    2291            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2292              :     }
    2293              : 
    2294            5 :     auto exist = funcInstanceMap_.find(funcPtr);
    2295            5 :     if (exist != funcInstanceMap_.end()) {
    2296            0 :         *outHandle = exist->second;
    2297            0 :         return CcuResult::CCU_SUCCESS;
    2298              :     }
    2299              : 
    2300            5 :     const uint64_t handle = ++funcHandleCounter_;
    2301            5 :     std::string label = "func_" + std::to_string(handle);
    2302              : 
    2303            5 :     FuncDescriptor desc;
    2304            5 :     desc.funcPtr = funcPtr;
    2305            5 :     desc.label = label;
    2306            5 :     desc.repFuncBlock = std::make_shared<CcuRep::CcuRepFuncBlock>(insGenerator, label);
    2307            5 :     desc.prevActiveBlock = CurrentBlock();
    2308              : 
    2309            5 :     funcMap_[handle] = desc;
    2310            5 :     SetCurrentBlock(desc.repFuncBlock);
    2311            5 :     inFuncBody_ = true;
    2312            5 :     bodyError_ = CcuResult::CCU_SUCCESS;
    2313            5 :     *outHandle = handle;
    2314            5 :     return CcuResult::CCU_SUCCESS;
    2315            5 : }
    2316              : 
    2317            4 : CcuResult CcuKernel::FuncBlockEnd(uint64_t handle)
    2318              : {
    2319            4 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[FuncBlockEnd] handle=%llu", handle);
    2320            4 :     auto it = funcMap_.find(handle);
    2321            4 :     if (it == funcMap_.end()) {
    2322            0 :         HCCL_ERROR("[CcuKernel::FuncBlockEnd] invalid func handle %lu", handle);
    2323            0 :         return CcuResult::CCU_E_PARA;
    2324              :     }
    2325            4 :     auto& desc = it->second;
    2326              : 
    2327            4 :     SetCurrentBlock(desc.prevActiveBlock);
    2328            4 :     inFuncBody_ = false;
    2329              : 
    2330            4 :     if (bodyError_ != CcuResult::CCU_SUCCESS) {
    2331            0 :         const CcuResult err = bodyError_;
    2332            0 :         HCCL_ERROR("[CcuKernel::FuncBlockEnd] illegal operation inside func body, err=%d", err);
    2333            0 :         bodyError_ = CcuResult::CCU_SUCCESS;
    2334            0 :         funcMap_.erase(it);
    2335            0 :         return err;
    2336              :     }
    2337              : 
    2338            4 :     Append(desc.repFuncBlock);
    2339            4 :     desc.bodyDefined = true;
    2340            4 :     funcInstanceMap_[desc.funcPtr] = handle;
    2341            4 :     return CcuResult::CCU_SUCCESS;
    2342              : }
    2343              : 
    2344            7 : CcuResult CcuKernel::FuncDefineInArg(uint64_t handle, CcuVariableHandle formal)
    2345              : {
    2346            7 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[FuncDefineInArg] handle=%llu, formal=%llu", handle, formal);
    2347            7 :     auto it = funcMap_.find(handle);
    2348            7 :     if (it == funcMap_.end()) {
    2349            0 :         HCCL_ERROR("[CcuKernel::FuncDefineInArg] invalid func handle %lu", handle);
    2350            0 :         return CcuResult::CCU_E_PARA;
    2351              :     }
    2352              : 
    2353            7 :     CcuRep::Variable* formalVar = nullptr;
    2354            7 :     CCU_CHK_RET(GetVariableByHandle(formal, &formalVar));
    2355            7 :     it->second.repFuncBlock->DefineInArg(*formalVar);
    2356            7 :     return CcuResult::CCU_SUCCESS;
    2357              : }
    2358              : 
    2359            5 : CcuResult CcuKernel::FuncCall(uint64_t handle, const CcuVariableHandle* inArgs, uint32_t numIn)
    2360              : {
    2361            5 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[FuncCall] handle=%llu, numIn=%u", handle, numIn);
    2362            5 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK || inFuncBody_) {
    2363            0 :         HCCL_ERROR("[CcuKernel::FuncCall] ccu::CallFunc only allowed at top level");
    2364            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2365              :     }
    2366            5 :     if (numIn > 0 && inArgs == nullptr) {
    2367            0 :         HCCL_ERROR("[CcuKernel::FuncCall] null input args");
    2368            0 :         return CcuResult::CCU_E_PTR;
    2369              :     }
    2370              : 
    2371            5 :     auto it = funcMap_.find(handle);
    2372            5 :     if (it == funcMap_.end() || !it->second.bodyDefined) {
    2373            0 :         HCCL_ERROR("[CcuKernel::FuncCall] invalid func handle %lu", handle);
    2374            0 :         return CcuResult::CCU_E_PARA;
    2375              :     }
    2376              : 
    2377            5 :     auto repFuncCall = std::make_shared<CcuRep::CcuRepFuncCall>(insGenerator, it->second.label);
    2378           12 :     for (uint32_t i = 0; i < numIn; i++) {
    2379            7 :         CcuRep::Variable* actual = nullptr;
    2380            7 :         CCU_CHK_RET(GetVariableByHandle(inArgs[i], &actual));
    2381            7 :         repFuncCall->SetInArg(*actual);
    2382              :     }
    2383            5 :     Append(repFuncCall);
    2384            5 :     return CcuResult::CCU_SUCCESS;
    2385            5 : }
    2386              : 
    2387              : // 按 maxLoopNum 把 res_.blockExecutor[0] 扩容到至少 maxLoopNum 个 LoopEngine。
    2388              : // 与 CreateBlockResAssist 对齐:所有 LoopEngine 资源先落在 die0 池,待实际 die 确定后
    2389              : // 再由 MoveResourcesToDie 迁移到目标 die。
    2390              : // 不同 LoopGroup 通过 local loopIdx 复用同一池低位 executorId,所以这里只
    2391              : // "补足"而不是"累加"。
    2392           28 : CcuResult CcuKernel::EnsureLoopEnginePool(uint32_t maxLoopNum)
    2393              : {
    2394           28 :     if (maxLoopNum == 0) {
    2395            0 :         HCCL_ERROR("[CcuKernel::EnsureLoopEnginePool] maxLoopNum must be > 0");
    2396            0 :         return CcuResult::CCU_E_PARA;
    2397              :     }
    2398           28 :     constexpr uint32_t poolDieId = 0;
    2399           28 :     auto& loopEnginePool = res_.blockExecutor[poolDieId];
    2400           28 :     if (maxLoopNum <= loopEnginePool.size()) {
    2401           10 :         return CcuResult::CCU_SUCCESS;
    2402              :     }
    2403           18 :     const uint32_t deficit = maxLoopNum - static_cast<uint32_t>(loopEnginePool.size());
    2404           18 :     std::vector<CcuRep::Executor> tmp(deficit, CcuRep::Executor(this));
    2405           18 :     (void)CreateBlockExecutor(deficit, tmp.data());
    2406           18 :     return CcuResult::CCU_SUCCESS;
    2407           18 : }
    2408              : 
    2409           13 : CcuResult CcuKernel::LoopGroupCreate(CcuLoopGroup* group, uint32_t maxLoopNum, const CcuLoopGroupCfg* cfg)
    2410              : {
    2411           13 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoopGroupCreate] maxLoopNum=%u", maxLoopNum);
    2412           13 :     if (group == nullptr || cfg == nullptr) {
    2413            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreate] null pointer");
    2414            0 :         return CcuResult::CCU_E_PTR;
    2415              :     }
    2416           13 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    2417            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreate] cannot create loop group inside a loop body");
    2418            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2419              :     }
    2420           13 :     if (inFuncBody_) {
    2421            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreate] cannot create loop group inside a func body");
    2422            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2423              :     }
    2424              : 
    2425              :     // 按需扩 LoopEngine 池;池足够则复用低位 executorId,跨组共享。
    2426           13 :     CCU_CHK_RET(EnsureLoopEnginePool(maxLoopNum));
    2427              : 
    2428           13 :     CcuLoopGroup handle = ++loopGroupHandleCounter_;
    2429              : 
    2430           13 :     LoopGroupDescriptor desc;
    2431           13 :     desc.config = *cfg;
    2432           13 :     desc.parallelVar = CreateVariable();
    2433           13 :     desc.offsetVar = CreateVariable();
    2434           13 :     desc.isVarBased = false;
    2435              : 
    2436           13 :     auto bundle = std::make_shared<CcuRep::CcuRepLoopGroupBundle>(insGenerator, *cfg, desc.parallelVar, desc.offsetVar);
    2437           13 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2438            4 :         bundle->SetXnOffsetVar(CreateVariable());
    2439              :     }
    2440           13 :     desc.bundleRep = bundle;
    2441           13 :     Append(bundle);
    2442              : 
    2443           13 :     loopGroupMap_[handle] = std::move(desc);
    2444           13 :     *group = handle;
    2445           13 :     return CcuResult::CCU_SUCCESS;
    2446           13 : }
    2447              : 
    2448           11 : CcuResult CcuKernel::LoopGroupCreateFromVar(
    2449              :     CcuLoopGroup* group, uint32_t maxLoopNum, CcuVariableHandle parallelVarHandle, CcuVariableHandle offsetVarHandle)
    2450              : {
    2451           11 :     PLF_CONFIG_INFO(
    2452              :         PLF_DATA_OP, "[LoopGroupCreateFromVar] maxLoopNum=%u, parallelVarHandle=%llu, offsetVarHandle=%llu", maxLoopNum,
    2453              :         parallelVarHandle, offsetVarHandle);
    2454           11 :     if (group == nullptr) {
    2455            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVar] null pointer for group");
    2456            0 :         return CcuResult::CCU_E_PTR;
    2457              :     }
    2458           11 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    2459            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVar] cannot create loop group inside a loop body");
    2460            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2461              :     }
    2462           11 :     if (inFuncBody_) {
    2463            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVar] cannot create loop group inside a func body");
    2464            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2465              :     }
    2466              : 
    2467           11 :     CCU_CHK_RET(EnsureLoopEnginePool(maxLoopNum));
    2468              : 
    2469           11 :     CcuRep::Variable* parallelVarPtr = nullptr;
    2470           11 :     CcuRep::Variable* offsetVarPtr = nullptr;
    2471           11 :     CCU_CHK_RET(GetVariableByHandle(parallelVarHandle, &parallelVarPtr));
    2472           11 :     CCU_CHK_RET(GetVariableByHandle(offsetVarHandle, &offsetVarPtr));
    2473              : 
    2474           11 :     CcuLoopGroup handle = ++loopGroupHandleCounter_;
    2475              : 
    2476           11 :     LoopGroupDescriptor desc;
    2477           11 :     desc.parallelVar = CcuRep::Variable(*parallelVarPtr);
    2478           11 :     desc.offsetVar = CcuRep::Variable(*offsetVarPtr);
    2479           11 :     desc.isVarBased = true;
    2480              : 
    2481           11 :     auto bundle = std::make_shared<CcuRep::CcuRepLoopGroupBundle>(insGenerator, desc.parallelVar, desc.offsetVar);
    2482           11 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2483            1 :         bundle->SetCompatRemapVars(CreateVariable(), CreateVariable());
    2484              :     }
    2485           11 :     desc.bundleRep = bundle;
    2486           11 :     Append(bundle);
    2487              : 
    2488           11 :     loopGroupMap_[handle] = std::move(desc);
    2489           11 :     *group = handle;
    2490           11 :     return CcuResult::CCU_SUCCESS;
    2491           11 : }
    2492              : 
    2493            5 : CcuResult CcuKernel::LoopGroupCreateFromVarV2(
    2494              :     CcuLoopGroup* group, uint32_t maxLoopNum, CcuVariableHandle parallelVarV2Handle,
    2495              :     CcuVariableHandle offsetVarV2Handle, CcuVariableHandle varOffsetVarHandle)
    2496              : {
    2497            5 :     if (ccuVersion_ != CcuVersion::CCU_V2) {
    2498            1 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVarV2] only supported on V2");
    2499            1 :         return CcuResult::CCU_E_NOT_SUPPORT;
    2500              :     }
    2501            4 :     if (group == nullptr) {
    2502            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVarV2] null pointer for group");
    2503            0 :         return CcuResult::CCU_E_PTR;
    2504              :     }
    2505            4 :     if (CurrentBlock()->Type() == CcuRep::CcuRepType::LOOP_BLOCK) {
    2506            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVarV2] cannot create loop group inside a loop body");
    2507            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2508              :     }
    2509            4 :     if (inFuncBody_) {
    2510            0 :         HCCL_ERROR("[CcuKernel::LoopGroupCreateFromVarV2] cannot create loop group inside a func body");
    2511            0 :         return LatchBodyError(CcuResult::CCU_E_INTERNAL);
    2512              :     }
    2513              : 
    2514            4 :     CCU_CHK_RET(EnsureLoopEnginePool(maxLoopNum));
    2515              : 
    2516            4 :     CcuRep::Variable* parallelVarPtr = nullptr;
    2517            4 :     CcuRep::Variable* offsetVarPtr = nullptr;
    2518            4 :     CcuRep::Variable* xnOffsetVarPtr = nullptr;
    2519            4 :     CCU_CHK_RET(GetVariableByHandle(parallelVarV2Handle, &parallelVarPtr));
    2520            4 :     CCU_CHK_RET(GetVariableByHandle(offsetVarV2Handle, &offsetVarPtr));
    2521            4 :     CCU_CHK_RET(GetVariableByHandle(varOffsetVarHandle, &xnOffsetVarPtr));
    2522              : 
    2523            4 :     CcuLoopGroup handle = ++loopGroupHandleCounter_;
    2524              : 
    2525            4 :     LoopGroupDescriptor desc;
    2526            4 :     desc.parallelVar = CcuRep::Variable(*parallelVarPtr);
    2527            4 :     desc.offsetVar = CcuRep::Variable(*offsetVarPtr);
    2528            4 :     desc.xnOffsetVar = CcuRep::Variable(*xnOffsetVarPtr);
    2529            4 :     desc.isVarBased = true;
    2530            4 :     desc.isVersionV2 = true;
    2531              : 
    2532            4 :     auto bundle = std::make_shared<CcuRep::CcuRepLoopGroupBundle>(insGenerator, desc.parallelVar, desc.offsetVar);
    2533            4 :     bundle->SetLayout(CcuRep::CcuRepLoopGroupBundle::Layout::VersionV2);
    2534            4 :     bundle->SetXnOffsetVar(desc.xnOffsetVar);
    2535            4 :     desc.bundleRep = bundle;
    2536            4 :     Append(bundle);
    2537              : 
    2538            4 :     loopGroupMap_[handle] = std::move(desc);
    2539            4 :     *group = handle;
    2540            4 :     return CcuResult::CCU_SUCCESS;
    2541            4 : }
    2542              : 
    2543           56 : CcuResult CcuKernel::LookupLoopGroupAndLoop(
    2544              :     CcuLoopGroup group, CcuLoop loop, const char* fnName, const char* createFnName, LoopGroupDescriptor*& grpDesc,
    2545              :     LoopDescriptor*& loopDesc, uint32_t& loopIdx)
    2546              : {
    2547           56 :     auto grpIt = loopGroupMap_.find(group);
    2548           56 :     if (grpIt == loopGroupMap_.end()) {
    2549            0 :         HCCL_ERROR("[CcuKernel::%s] invalid group handle %lu", fnName, group);
    2550            0 :         return CcuResult::CCU_E_PARA;
    2551              :     }
    2552           56 :     grpDesc = &grpIt->second;
    2553              : 
    2554           56 :     auto loopIt = loopMap_.find(loop);
    2555           56 :     if (loopIt == loopMap_.end()) {
    2556            0 :         HCCL_ERROR("[CcuKernel::%s] invalid loop handle %lu", fnName, loop);
    2557            0 :         return CcuResult::CCU_E_PARA;
    2558              :     }
    2559           56 :     loopDesc = &loopIt->second;
    2560              : 
    2561           56 :     if (!loopDesc->bodyDefined) {
    2562            0 :         HCCL_ERROR("[CcuKernel::%s] loop %lu body not defined", fnName, loop);
    2563            0 :         return CcuResult::CCU_E_INTERNAL; // CCU_E_LOOP_BODY_UNDEFINED
    2564              :     }
    2565              : 
    2566           56 :     auto& loopEnginePool = res_.blockExecutor[0];
    2567           56 :     loopIdx = grpDesc->loopCount;
    2568           56 :     if (loopIdx >= loopEnginePool.size()) {
    2569            0 :         HCCL_ERROR(
    2570              :             "[CcuKernel::%s] loopEngine pool exhausted (pool size %zu, loopIdx %u). "
    2571              :             "Pass a larger maxLoopNum to %s so the pool can be extended at create time.",
    2572              :             fnName, loopEnginePool.size(), loopIdx, createFnName);
    2573            0 :         return CcuResult::CCU_E_PARA;
    2574              :     }
    2575           56 :     return CcuResult::CCU_SUCCESS;
    2576              : }
    2577              : 
    2578           25 : CcuResult CcuKernel::LoopGroupAddLoop(CcuLoopGroup group, CcuLoop loop, const CcuLoopCfg* cfg)
    2579              : {
    2580           25 :     PLF_CONFIG_INFO(PLF_DATA_OP, "[LoopGroupAddLoop] group=%llu, loop=%llu", group, loop);
    2581           25 :     if (cfg == nullptr) {
    2582            0 :         HCCL_ERROR("[CcuKernel::LoopGroupAddLoop] null pointer for cfg");
    2583            0 :         return CcuResult::CCU_E_PTR;
    2584              :     }
    2585           25 :     LoopGroupDescriptor* grpDesc = nullptr;
    2586           25 :     LoopDescriptor* loopDesc = nullptr;
    2587           25 :     uint32_t loopIdx = 0;
    2588           25 :     CCU_CHK_RET(
    2589              :         LookupLoopGroupAndLoop(group, loop, "LoopGroupAddLoop", "CcuLoopGroupCreate", grpDesc, loopDesc, loopIdx));
    2590           25 :     auto& loopEnginePool = res_.blockExecutor[0];
    2591              : 
    2592           25 :     grpDesc->loopCount++;
    2593           25 :     grpDesc->totalLoopNum = grpDesc->loopCount;
    2594              : 
    2595           25 :     CcuRep::CcuRepLoopGroupBundle::LoopEntry entry;
    2596           25 :     entry.config = *cfg;
    2597           25 :     entry.executor = loopEnginePool[loopIdx];
    2598           25 :     entry.repLoopBlock = loopDesc->repLoopBlock;
    2599           25 :     entry.loopParamVar = CreateVariable();
    2600           25 :     entry.layout = CcuRep::CcuRepLoopGroupBundle::Layout::Config;
    2601           25 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2602            7 :         entry.iterNumVar = CreateVariable();
    2603            7 :         entry.addrOffsetVar = CreateVariable();
    2604            7 :         entry.ctxIdVar = CreateVariable();
    2605              :     }
    2606              : 
    2607           25 :     auto bundle = std::static_pointer_cast<CcuRep::CcuRepLoopGroupBundle>(grpDesc->bundleRep);
    2608           25 :     bundle->AddLoop(entry);
    2609              : 
    2610           25 :     if (!grpDesc->isVarBased) {
    2611           19 :         bundle->SetRepeatLoopIdx(grpDesc->config.cloneLoopOffset);
    2612           19 :         bundle->SetTotalLoopNum(grpDesc->totalLoopNum);
    2613              :     }
    2614              : 
    2615           25 :     return CcuResult::CCU_SUCCESS;
    2616           25 : }
    2617              : 
    2618           23 : CcuResult CcuKernel::LoopGroupAddLoopFromVar(CcuLoopGroup group, CcuLoop loop, CcuVariableHandle loopParamVarHandle)
    2619              : {
    2620           23 :     PLF_CONFIG_INFO(
    2621              :         PLF_DATA_OP, "[LoopGroupAddLoopFromVar] group=%llu, loop=%llu, loopParamVarHandle=%llu", group, loop,
    2622              :         loopParamVarHandle);
    2623           23 :     LoopGroupDescriptor* grpDesc = nullptr;
    2624           23 :     LoopDescriptor* loopDesc = nullptr;
    2625           23 :     uint32_t loopIdx = 0;
    2626           23 :     CCU_CHK_RET(LookupLoopGroupAndLoop(
    2627              :         group, loop, "LoopGroupAddLoopFromVar", "CcuLoopGroupCreateFromVar", grpDesc, loopDesc, loopIdx));
    2628           23 :     auto& loopEnginePool = res_.blockExecutor[0];
    2629              : 
    2630           23 :     CcuRep::Variable* loopParamVarPtr = nullptr;
    2631           23 :     CCU_CHK_RET(GetVariableByHandle(loopParamVarHandle, &loopParamVarPtr));
    2632              : 
    2633           23 :     CcuRep::CcuRepLoopGroupBundle::LoopEntry entry;
    2634           23 :     entry.executor = loopEnginePool[loopIdx];
    2635           23 :     entry.repLoopBlock = loopDesc->repLoopBlock;
    2636           23 :     entry.loopParamVar = CcuRep::Variable(*loopParamVarPtr);
    2637           23 :     entry.layout = CcuRep::CcuRepLoopGroupBundle::Layout::PackedVar;
    2638           23 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2639            4 :         entry.iterNumVar = CreateVariable();
    2640            4 :         entry.addrOffsetVar = CreateVariable();
    2641            4 :         entry.ctxIdVar = CreateVariable();
    2642              :     }
    2643              : 
    2644           23 :     auto bundle = std::static_pointer_cast<CcuRep::CcuRepLoopGroupBundle>(grpDesc->bundleRep);
    2645           23 :     bundle->AddLoop(entry);
    2646              : 
    2647              :     // 计数放在入 bundle 之后统一更新:totalLoopNum 仅供 config 组同步编码使用,与 AddLoop 无先后依赖。
    2648           23 :     grpDesc->loopCount++;
    2649           23 :     grpDesc->totalLoopNum = grpDesc->loopCount;
    2650           23 :     if (!grpDesc->isVarBased) {
    2651            7 :         bundle->SetRepeatLoopIdx(grpDesc->config.cloneLoopOffset);
    2652            7 :         bundle->SetTotalLoopNum(grpDesc->totalLoopNum);
    2653              :     }
    2654              : 
    2655           23 :     return CcuResult::CCU_SUCCESS;
    2656           23 : }
    2657              : 
    2658            8 : CcuResult CcuKernel::LoopGroupAddLoopFromVarV2(
    2659              :     CcuLoopGroup group, CcuLoop loop, CcuVariableHandle iterNumVarHandle, CcuVariableHandle addrOffsetVarHandle,
    2660              :     CcuVariableHandle ctxIdVarHandle)
    2661              : {
    2662            8 :     if (ccuVersion_ != CcuVersion::CCU_V2) {
    2663            0 :         HCCL_ERROR("[CcuKernel::LoopGroupAddLoopFromVarV2] only supported on V2");
    2664            0 :         return CcuResult::CCU_E_NOT_SUPPORT;
    2665              :     }
    2666              : 
    2667            8 :     LoopGroupDescriptor* grpDesc = nullptr;
    2668            8 :     LoopDescriptor* loopDesc = nullptr;
    2669            8 :     uint32_t loopIdx = 0;
    2670            8 :     CCU_CHK_RET(LookupLoopGroupAndLoop(
    2671              :         group, loop, "LoopGroupAddLoopFromVarV2", "CcuLoopGroupCreateFromVarV2", grpDesc, loopDesc, loopIdx));
    2672            8 :     auto& loopEnginePool = res_.blockExecutor[0];
    2673              : 
    2674            8 :     CcuRep::Variable* iterNumVarPtr = nullptr;
    2675            8 :     CcuRep::Variable* addrOffsetVarPtr = nullptr;
    2676            8 :     CcuRep::Variable* ctxIdVarPtr = nullptr;
    2677            8 :     CCU_CHK_RET(GetVariableByHandle(iterNumVarHandle, &iterNumVarPtr));
    2678            8 :     CCU_CHK_RET(GetVariableByHandle(addrOffsetVarHandle, &addrOffsetVarPtr));
    2679            8 :     CCU_CHK_RET(GetVariableByHandle(ctxIdVarHandle, &ctxIdVarPtr));
    2680              : 
    2681            8 :     grpDesc->loopCount++;
    2682            8 :     grpDesc->totalLoopNum = grpDesc->loopCount;
    2683              : 
    2684            8 :     VersionV2LoopRecord record;
    2685            8 :     record.iterNumVar = CcuRep::Variable(*iterNumVarPtr);
    2686            8 :     record.addrOffsetVar = CcuRep::Variable(*addrOffsetVarPtr);
    2687            8 :     record.ctxIdVar = CcuRep::Variable(*ctxIdVarPtr);
    2688            8 :     grpDesc->versionV2Loops.push_back(record);
    2689              : 
    2690            8 :     CcuRep::CcuRepLoopGroupBundle::LoopEntry entry;
    2691            8 :     entry.executor = loopEnginePool[loopIdx];
    2692            8 :     entry.repLoopBlock = loopDesc->repLoopBlock;
    2693            8 :     entry.iterNumVar = CcuRep::Variable(*iterNumVarPtr);
    2694            8 :     entry.addrOffsetVar = CcuRep::Variable(*addrOffsetVarPtr);
    2695            8 :     entry.ctxIdVar = CcuRep::Variable(*ctxIdVarPtr);
    2696            8 :     entry.layout = CcuRep::CcuRepLoopGroupBundle::Layout::VersionV2;
    2697              : 
    2698            8 :     auto bundle = std::static_pointer_cast<CcuRep::CcuRepLoopGroupBundle>(grpDesc->bundleRep);
    2699            8 :     bundle->AddLoop(entry);
    2700              : 
    2701            8 :     if (!grpDesc->isVarBased) {
    2702            2 :         bundle->SetRepeatLoopIdx(grpDesc->config.cloneLoopOffset);
    2703            2 :         bundle->SetTotalLoopNum(grpDesc->totalLoopNum);
    2704              :     }
    2705              : 
    2706            8 :     return CcuResult::CCU_SUCCESS;
    2707            8 : }
    2708              : 
    2709           46 : void CcuKernel::SetInstrId(uint32_t instrId) { instrInfo_.startInstrId = instrId; }
    2710              : 
    2711           92 : uint32_t CcuKernel::GetInstrId() const { return instrInfo_.startInstrId; }
    2712              : 
    2713          143 : uint32_t CcuKernel::GetInstrCount()
    2714              : {
    2715          143 :     uint32_t instrCount = 0;
    2716         3435 :     for (const auto& rep : GetRepSequence()) {
    2717         3292 :         instrCount += rep->InstrCount();
    2718              :     }
    2719          143 :     instrInfo_.instrCount = instrCount;
    2720          143 :     HCCL_INFO("Kernel inst %u", instrCount);
    2721          143 :     return instrCount;
    2722              : }
    2723              : 
    2724              : namespace {
    2725              :     // 识别三种 wait 类 rep: 无论 profiling 与否都会翻译出一条"既 wait 又 set/clear 同一 CKE 位"的
    2726              :     // CTRL 指令 (profiling 分支 -> setcke, 非 profiling 分支 -> clearcke, 二者都是 CKE 写者),
    2727              :     // 后端优化可能为其后续读者补 NOP, 因此都要按 CCU_CKE_RAW_LATENCY 预留指令空间.
    2728         1089 :     bool IsCkeWaitRep(const std::shared_ptr<CcuRep::CcuRepBase>& rep)
    2729              :     {
    2730         1089 :         if (rep == nullptr) {
    2731            0 :             return false;
    2732              :         }
    2733         1089 :         switch (rep->Type()) {
    2734           36 :             case CcuRep::CcuRepType::LOC_WAIT_EVENT:
    2735              :             case CcuRep::CcuRepType::LOC_WAIT_NOTIFY:
    2736              :             case CcuRep::CcuRepType::REM_WAIT_SEM:
    2737           36 :                 return true;
    2738         1053 :             default:
    2739         1053 :                 return false;
    2740              :         }
    2741              :     }
    2742              : 
    2743              :     // 与 CcuKernelMgr::PrepareConstValueResources 一致地下钻 block 子 rep, 统计其中会翻译出
    2744              :     // setcke / clearcke (CKE 写者) 的 wait 类 rep 个数.
    2745              :     // 只下钻一层是充分的: 表示层禁止 block 嵌套 —— CcuKernel::LoopCreate / FuncBlockBegin /
    2746              :     // FuncBlockLookup 在 CurrentBlock() 为 LOOP_BLOCK 或 inFuncBody_ 时直接报错 (见 ccu_kernel.cc),
    2747              :     // 故 LOOP_BLOCK / FUNC_BLOCK 内不可能再出现 block 类型子 rep, 无需递归下钻.
    2748              :     // 若后续放开 block 嵌套, 此处 (与 PrepareConstValueResources) 需同步改为递归统计, 否则会漏计.
    2749          999 :     uint32_t CountCkeWaitRepInBlock(const std::shared_ptr<CcuRep::CcuRepBase>& rep)
    2750              :     {
    2751          999 :         const auto repType = rep->Type();
    2752          999 :         if (repType != CcuRep::CcuRepType::BLOCK && repType != CcuRep::CcuRepType::FUNC_BLOCK
    2753          999 :             && repType != CcuRep::CcuRepType::LOOP_BLOCK) {
    2754          945 :             return 0;
    2755              :         }
    2756           54 :         auto* blockPtr = static_cast<CcuRep::CcuRepBlock*>(rep.get());
    2757           54 :         if (blockPtr == nullptr) {
    2758            0 :             return 0;
    2759              :         }
    2760           54 :         uint32_t count = 0;
    2761          144 :         for (const auto& child : blockPtr->GetReps()) {
    2762           90 :             if (IsCkeWaitRep(child)) {
    2763           18 :                 count++;
    2764              :             }
    2765              :         }
    2766           54 :         return count;
    2767              :     }
    2768              : } // namespace
    2769              : 
    2770              : // 统计当前 kernel 中"需要按 cke 写后读 latency 补 NOP"的 rep 个数 (含 block 子 rep).
    2771              : // 三种 wait 类 rep 无论 profiling 与否都翻译出一条 CKE 写者微码 (profiling -> setcke, 非 profiling
    2772              : // -> clearcke), 后端优化最多为其后续读者补 (CCU_CKE_RAW_LATENCY - 1) 条 NOP, 上层据此为每个此类 rep
    2773              : // 预留同等指令空间, 保证优化后指令数不越界.
    2774          157 : uint32_t CcuKernel::GetRepNeedToAddLatency() const
    2775              : {
    2776              :     // cke 写后读补 NOP 与指令空间预留只属于 A6(CCU_V2) 后端优化; A5(CCU_V1) 不跑后端优化,
    2777              :     // 不做任何预留, 直接返回 0, 避免影响 A5 的申请/释放口径.
    2778          157 :     if (ccuVersion_ != CcuVersion::CCU_V2) {
    2779          106 :         return 0;
    2780              :     }
    2781           51 :     uint32_t count = 0;
    2782              :     // GetRepSequence() 语义纯读但尚未标 const, 此处仅遍历不修改, 去 const 调用以保持本方法 const 契约.
    2783         1050 :     for (const auto& rep : const_cast<CcuKernel*>(this)->GetRepSequence()) {
    2784          999 :         if (rep == nullptr) {
    2785            0 :             continue;
    2786              :         }
    2787          999 :         if (IsCkeWaitRep(rep)) {
    2788           18 :             count++;
    2789              :         }
    2790          999 :         count += CountCkeWaitRepInBlock(rep);
    2791              :     }
    2792           51 :     HCCL_INFO("[CcuKernel] cke wait rep count %u (reserve %u instrs)", count, count * CcuRep::CCU_CKE_RAW_LATENCY);
    2793           51 :     return count;
    2794              : }
    2795              : 
    2796           45 : void CcuKernel::SetCcuInstrInfo(const CcuRep::CcuInstrInfo& instrInfo) { this->instrInfo_ = instrInfo; }
    2797              : 
    2798          358 : CcuRep::Variable CcuKernel::CreateVariable()
    2799              : {
    2800          358 :     const auto& var = CreateBlockResAssist(1, res_.continuousVariable);
    2801          716 :     return var[0];
    2802          358 : }
    2803              : 
    2804          109 : CcuRep::Variable CcuKernel::CreateExpectVar()
    2805              : {
    2806              :     // v2(A6) 的 jump 只支持 var-var 比较,需要真实 XN 承载立即数;
    2807              :     // v1(A5) 的 jump 直接支持 var-imm,expectVar 不参与翻译,
    2808              :     // 用不进 res_ 账本的壳 Variable 即可,避免 v1 资源虚高。
    2809          109 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2810           20 :         return CreateVariable();
    2811              :     }
    2812           89 :     return CcuRep::Variable(this);
    2813              : }
    2814              : 
    2815          126 : CcuRep::Variable CcuKernel::CreateJumpTargetVar()
    2816              : {
    2817          126 :     if (ccuVersion_ == CcuVersion::CCU_V1) {
    2818              :         // A5(CCU_V1): 没有指令重排,可复用同一个 Xn 存放跳转目标地址。targetVar 仅用于 LoadImdToXn + 紧接 Jump。
    2819          102 :         if (!sharedJumpTargetVar_) {
    2820           14 :             sharedJumpTargetVar_ = std::make_unique<CcuRep::Variable>(CreateVariable());
    2821              :         }
    2822          102 :         return *sharedJumpTargetVar_;
    2823              :     }
    2824           24 :     return CcuRep::CreateVariable(this);
    2825              : }
    2826              : 
    2827          203 : CcuRep::Address CcuKernel::CreateAddress()
    2828              : {
    2829          203 :     if (ccuVersion_ == CcuVersion::CCU_V2) {
    2830              :         // A6创建Address时,需要添加到Variable的列表中,但是仍以Address返回
    2831           91 :         return CcuRep::Address(CreateResAssist(res_.continuousVariable));
    2832              :     }
    2833          112 :     return CreateResAssist(res_.blockAddress);
    2834              : }
    2835              : 
    2836            0 : CcuRep::LocalNotify CcuKernel::CreateLocalNotify() { return CreateResAssist(res_.localNotify); }
    2837              : 
    2838            0 : CcuRep::CompletedEvent CcuKernel::CreateCompletedEvent() { return CreateResAssist(res_.blockCompletedEvent); }
    2839              : 
    2840            0 : CcuRep::CcuBuf CcuKernel::CreateCcuBuf()
    2841              : {
    2842            0 :     const auto& buffer = CreateBlockResAssist(1, res_.blockCcubufs);
    2843            0 :     return buffer[0];
    2844            0 : }
    2845              : 
    2846            0 : CcuRep::Executor CcuKernel::CreateExecutor() { return CreateResAssist(res_.blockExecutor); }
    2847              : 
    2848          156 : CcuRep::LocalAddr CcuKernel::CreateLocalAddr() { return CcuRep::LocalAddr(CreateAddress(), CreateVariable()); }
    2849              : 
    2850           37 : CcuRep::RemoteAddr CcuKernel::CreateRemoteAddr() { return CcuRep::RemoteAddr(CreateAddress(), CreateVariable()); }
    2851              : 
    2852            0 : CcuRep::RemoteAddr CcuKernel::GetRemoteAddr(const ChannelHandle channel, uint32_t index)
    2853              : {
    2854              :     (void)index;
    2855            0 :     channels_.insert(channel);
    2856            0 :     auto mem = CcuRep::RemoteAddr(CreateAddress(), CreateVariable());
    2857            0 :     Append(std::make_shared<CcuRep::CcuRepRemMem>(insGenerator, channel, mem));
    2858            0 :     return mem;
    2859            0 : }
    2860              : 
    2861            0 : CcuRep::LocalAddr CcuKernel::CreateLocalAddr(const CcuRep::Variable& token)
    2862              : {
    2863            0 :     return CcuRep::LocalAddr(CreateAddress(), token);
    2864              : }
    2865              : 
    2866            0 : HcclResult CcuKernel::CreateBlockCcuBuf(const uint32_t count, CcuRep::CcuBuf* ccuBufs)
    2867              : {
    2868            0 :     CHK_PTR_NULL(ccuBufs);
    2869            0 :     auto resources = CreateBlockResAssist(count, res_.blockCcubufs);
    2870              : 
    2871            0 :     for (uint32_t i = 0; i < count; i++) {
    2872            0 :         ccuBufs[i] = resources[i]; // 拷贝虚拟资源,通过shared_ptr链接到物理资源
    2873              :     }
    2874              : 
    2875            0 :     return HcclResult::HCCL_SUCCESS;
    2876            0 : }
    2877              : 
    2878           18 : HcclResult CcuKernel::CreateBlockExecutor(const uint32_t count, CcuRep::Executor* ccuExes)
    2879              : {
    2880           18 :     CHK_PTR_NULL(ccuExes);
    2881           18 :     auto resources = CreateBlockResAssist(count, res_.blockExecutor);
    2882              : 
    2883           48 :     for (uint32_t i = 0; i < count; i++) {
    2884           30 :         ccuExes[i] = resources[i]; // 拷贝虚拟资源,通过shared_ptr链接到物理资源
    2885              :     }
    2886              : 
    2887           18 :     return HcclResult::HCCL_SUCCESS;
    2888           18 : }
    2889              : 
    2890            0 : HcclResult CcuKernel::CreateBlockCompletedEvent(const uint32_t count, CcuRep::CompletedEvent* ccuEvents)
    2891              : {
    2892            0 :     CHK_PTR_NULL(ccuEvents);
    2893            0 :     auto resources = CreateBlockResAssist(count, res_.blockCompletedEvent);
    2894              : 
    2895            0 :     for (uint32_t i = 0; i < count; i++) {
    2896            0 :         ccuEvents[i] = resources[i]; // 拷贝虚拟资源,通过shared_ptr链接到物理资源
    2897              :     }
    2898              : 
    2899            0 :     return HcclResult::HCCL_SUCCESS;
    2900            0 : }
    2901              : 
    2902           46 : void CcuKernel::SetResRepository(const CcuResRepository& resRepo) { resRepo_ = resRepo; }
    2903              : 
    2904           46 : CcuResRepository& CcuKernel::GetResRepository() { return resRepo_; }
    2905              : 
    2906           46 : CcuSharedResource& CcuKernel::GetExportedRes() { return exportedRes_; }
    2907              : 
    2908           46 : CcuSharedResource& CcuKernel::GetImportedRes() { return importedRes_; }
    2909              : 
    2910           10 : static HcclResult GetArgIndex(
    2911              :     const std::unordered_map<uint16_t, uint16_t>& varId2VarIdMap,
    2912              :     const std::unordered_map<uint16_t, uint32_t>& varId2ArgIndexMap, const uint64_t* taskArgs, uint32_t argSize,
    2913              :     uint16_t varId, uint64_t& argIndex)
    2914              : {
    2915           10 :     HCCL_INFO("[GetArgIndex] Enter varId(%u)", varId);
    2916           10 :     auto item = varId2ArgIndexMap.find(varId);
    2917           10 :     if (item == varId2ArgIndexMap.end()) {
    2918            0 :         uint16_t oriVarId = varId;
    2919            0 :         auto iter = varId2VarIdMap.find(varId);
    2920            0 :         while (iter != varId2VarIdMap.end()) { // 循环查找中间assign Rep,找到起始varId
    2921            0 :             oriVarId = iter->second;
    2922            0 :             iter = varId2VarIdMap.find(oriVarId);
    2923              :         }
    2924            0 :         if (oriVarId != varId) { // 起始varId预期通过LoadArg赋值
    2925            0 :             item = varId2ArgIndexMap.find(oriVarId);
    2926            0 :             if (item == varId2ArgIndexMap.end()) {
    2927            0 :                 HCCL_ERROR("[%s]fail, Invalid goSize variable id(%u), oriVarId = %u", __func__, varId, oriVarId);
    2928            0 :                 return HCCL_E_PARA;
    2929              :             }
    2930              :         } else {
    2931            0 :             HCCL_ERROR("[%s]fail, Invalid goSize variable id(%u)", __func__, varId);
    2932            0 :             return HCCL_E_PARA;
    2933              :         }
    2934              :     }
    2935           10 :     HCCL_INFO("[GetArgIndex] find end");
    2936           10 :     if (item->second >= argSize) {
    2937            0 :         HCCL_ERROR("Invalid goSize variable index(%u).", item->second);
    2938            0 :         return HCCL_E_PARA;
    2939              :     }
    2940           10 :     HCCL_INFO(
    2941              :         "GetArgIndex success: varId(%u) varId2VarIdMapSize(%u) varId2ArgIndexMapSize(%u) taskArgsSize(%u)", varId,
    2942              :         varId2VarIdMap.size(), varId2ArgIndexMap.size(), argSize);
    2943           10 :     argIndex = taskArgs[item->second];
    2944           10 :     return HCCL_SUCCESS;
    2945              : }
    2946              : 
    2947            0 : void DumpCcuProfilingInfo(const std::vector<CcuProfilingInfo>& ccuProfilingInfo)
    2948              : {
    2949            0 :     auto dumpLinkInfo = [](const CcuProfilingInfo& info) -> void {
    2950            0 :         for (int i = 0; i < CCU_MAX_CHANNEL_NUM; i++) {
    2951            0 :             if (info.channelId[i] == INVALID_VALUE_CHANNELID) {
    2952            0 :                 continue;
    2953              :             }
    2954            0 :             HCCL_INFO("channelId(%u), remoteRankId(%u).", info.channelId[i], info.remoteRankId[i]);
    2955              :         }
    2956            0 :     };
    2957              : 
    2958            0 :     for (const auto& profInfo : ccuProfilingInfo) {
    2959            0 :         if (profInfo.type == static_cast<uint8_t>(CcuProfilinType::CCU_TASK_PROFILING)) {
    2960            0 :             HCCL_INFO(
    2961              :                 "Dump CCU Profiling Info:SQE Profiling Info: ctxSignautre(%s), "
    2962              :                 "dieId(%d), missionId(%d), instrId(%d).",
    2963              :                 profInfo.name.c_str(), static_cast<int>(profInfo.dieId), static_cast<int>(profInfo.missionId),
    2964              :                 static_cast<int>(profInfo.instrId));
    2965            0 :         } else if (profInfo.type == static_cast<uint8_t>(CcuProfilinType::CCU_WAITCKE_PROFILING)) {
    2966            0 :             HCCL_INFO(
    2967              :                 "Microcode WaitCKE Profiling Info: name(%s), "
    2968              :                 "dieId(%d), missionId(%d), instrId(%d), ckeId(%u), mask(%u).",
    2969              :                 profInfo.name.c_str(), static_cast<int>(profInfo.dieId), static_cast<int>(profInfo.missionId),
    2970              :                 static_cast<int>(profInfo.instrId), profInfo.ckeId, profInfo.mask);
    2971            0 :             dumpLinkInfo(profInfo);
    2972            0 :         } else if (profInfo.type == static_cast<uint8_t>(CcuProfilinType::CCU_LOOPGROUP_PROFILING)) {
    2973            0 :             HCCL_INFO(
    2974              :                 "Microcode LoopGroup Profiling Info: name(%s), "
    2975              :                 "dieId(%d), missionId(%d), instrId(%d), reduceOpType(%d), inputDataType(%d), "
    2976              :                 "outputDataType(%d), dataSize(%llu).",
    2977              :                 profInfo.name.c_str(), static_cast<int>(profInfo.dieId), static_cast<int>(profInfo.missionId),
    2978              :                 static_cast<int>(profInfo.instrId), static_cast<int>(profInfo.reduceOpType),
    2979              :                 static_cast<int>(profInfo.inputDataType), static_cast<int>(profInfo.outputDataType), profInfo.dataSize);
    2980            0 :             dumpLinkInfo(profInfo);
    2981              :         }
    2982              :     }
    2983            0 : }
    2984              : 
    2985            2 : constexpr uint64_t SetBits(uint16_t end) { return ((uint64_t(1) << (end + 1)) - uint64_t(1)); }
    2986              : 
    2987            2 : static uint16_t ParseRepeatNumFromParallelParam(uint64_t parallelParam)
    2988              : {
    2989            2 :     constexpr uint16_t repeatBitNum = 7;       // 7: repeat num 占 7 bits
    2990            2 :     constexpr uint16_t repeatNumShiftBit = 55; // 55: repeat num占[61:55]位置
    2991            2 :     return (parallelParam >> repeatNumShiftBit) & SetBits(repeatBitNum);
    2992              : }
    2993              : 
    2994            0 : HcclResult CcuKernel::CollectSqeAndWaitCkeProfilingInfo()
    2995              : {
    2996            0 :     auto& ccuProfilingCache = GetProfilingInfo();
    2997            0 :     uint32_t count{0};
    2998            0 :     HCCL_INFO("[GetCcuProfilingInfo] Process sqe&waitcke profiling info start.");
    2999            0 :     for (auto& profInfo : ccuProfilingCache) {
    3000            0 :         profInfo.missionId = GetMissionId();
    3001            0 :         if (profInfo.type == static_cast<uint8_t>(hcomm::CcuProfilinType::CCU_TASK_PROFILING)) {
    3002            0 :             profInfo.instrId = GetInstrId();
    3003            0 :             allCcuProfilingInfos_.push_back(profInfo);
    3004            0 :             continue;
    3005              :         }
    3006            0 :         if (count >= GetWaiteCkeProfilingReps().size()) {
    3007            0 :             HCCL_ERROR(
    3008              :                 "count[%u] out of range[0, %u], cache size(%u).", count, GetWaiteCkeProfilingReps().size(),
    3009              :                 ccuProfilingCache.size());
    3010            0 :             return HCCL_E_INTERNAL;
    3011              :         }
    3012            0 :         auto waitCkeRep = GetWaiteCkeProfilingReps()[count];
    3013            0 :         profInfo.instrId = waitCkeRep->StartInstrId();
    3014            0 :         if (profInfo.ckeId == INVALID_CKE_ID) { // localWait Rep
    3015            0 :             if (waitCkeRep.get() == nullptr) {
    3016            0 :                 HCCL_ERROR("[GetCcuProfilingInfo] localWaitRep is nullptr.");
    3017            0 :                 return HCCL_E_PTR;
    3018              :             }
    3019            0 :             profInfo.ckeId = waitCkeRep->GetId();
    3020            0 :             HCCL_INFO("[CcuKernel][GetCcuProfilingInfo] waitcke[%u]", profInfo.ckeId);
    3021              :         }
    3022            0 :         allCcuProfilingInfos_.push_back(profInfo);
    3023            0 :         count++;
    3024            0 :     }
    3025            0 :     return HCCL_SUCCESS;
    3026              : }
    3027              : 
    3028            0 : HcclResult CcuKernel::BuildLoopGroupVarIdMaps(
    3029              :     std::unordered_map<uint16_t, uint32_t>& varId2ArgIndexMap, std::unordered_map<uint16_t, uint16_t>& varId2VarIdMap)
    3030              : {
    3031            0 :     auto& lgProfInfo = GetLGProfilingInfo();
    3032            0 :     HCCL_INFO("[GetCcuProfilingInfo] create varId2ArgIndexMap start. size=%lu", lgProfInfo.loadRep2ArgIdxMap.size());
    3033            0 :     for (auto& iter : lgProfInfo.loadRep2ArgIdxMap) {
    3034            0 :         if (iter.first.get() == nullptr) {
    3035            0 :             HCCL_ERROR("[GetCcuProfilingInfo] loadRep is nullptr.");
    3036            0 :             return HCCL_E_PTR;
    3037              :         }
    3038            0 :         auto loadRep = dynamic_cast<CcuRep::CcuRepLoadArg*>(iter.first.get());
    3039            0 :         varId2ArgIndexMap[loadRep->GetVarId()] = iter.second;
    3040              :     }
    3041              : 
    3042            0 :     HCCL_INFO("[GetCcuProfilingInfo] create varId2VarIdMap start. size=%lu", lgProfInfo.assignProfilingReps.size());
    3043            0 :     for (auto& iter : lgProfInfo.assignProfilingReps) {
    3044            0 :         if (iter.get() == nullptr) {
    3045            0 :             HCCL_ERROR("[GetCcuProfilingInfo] assignRep is nullptr.");
    3046            0 :             return HCCL_E_PTR;
    3047              :         }
    3048            0 :         auto assignRep = dynamic_cast<CcuRep::CcuRepAssign*>(iter.get());
    3049            0 :         varId2VarIdMap[assignRep->GetVarB().Id()] = assignRep->GetVarA().Id();
    3050              :     }
    3051            0 :     return HCCL_SUCCESS;
    3052              : }
    3053              : 
    3054            8 : HcclResult CcuKernel::CollectLoopGroupProfilingInfo(
    3055              :     const uint64_t* taskArgs, uint32_t argSize, const std::unordered_map<uint16_t, uint32_t>& varId2ArgIndexMap,
    3056              :     const std::unordered_map<uint16_t, uint16_t>& varId2VarIdMap)
    3057              : {
    3058            8 :     auto& lgProfInfo = GetLGProfilingInfo();
    3059            8 :     HCCL_INFO(
    3060              :         "[GetCcuProfilingInfo] process loop group profiling start: "
    3061              :         "lgsize(%lu), goSize(%lu)",
    3062              :         lgProfInfo.lgProfilingReps.size(), groupOpSizeInfo_.size());
    3063              :     // lgProfilingReps、groupOpSizeInfo_、ccuProfilingInfos 设计上同步 push;
    3064              :     // 但 CcuRepContext::AddProfiling 可能只 push ccuProfilingInfos 而不 push lgProfilingReps,
    3065              :     // 取三者最小值作为循环安全上界,防止任一容器较短时下标越界。
    3066            8 :     size_t repSize = lgProfInfo.lgProfilingReps.size();
    3067            8 :     size_t goSizeNum = groupOpSizeInfo_.size();
    3068            8 :     size_t profSize = lgProfInfo.ccuProfilingInfos.size();
    3069            8 :     size_t safeSize = (repSize < goSizeNum) ? repSize : goSizeNum;
    3070            8 :     safeSize = (profSize < safeSize) ? profSize : safeSize;
    3071            8 :     if (safeSize != repSize) {
    3072            1 :         HCCL_WARNING(
    3073              :             "[CollectLoopGroupProfilingInfo] size mismatch: lgReps[%zu], goSize[%zu], ccuProf[%zu],"
    3074              :             " use safeSize[%zu].",
    3075              :             repSize, goSizeNum, profSize, safeSize);
    3076              :     }
    3077           15 :     for (uint32_t i = 0; i < safeSize; i += 2) { // 2: 一个goSize对应一个CcuProfilingInfo,对应1个loopGroup Rep
    3078            7 :         CHK_RET(CollectSingleLoopGroupProfiling(i, repSize, taskArgs, argSize, varId2ArgIndexMap, varId2VarIdMap));
    3079              :     }
    3080            8 :     return HCCL_SUCCESS;
    3081              : }
    3082              : 
    3083            7 : HcclResult CcuKernel::CollectSingleLoopGroupProfiling(
    3084              :     uint32_t i, size_t repSize, const uint64_t* taskArgs, uint32_t argSize,
    3085              :     const std::unordered_map<uint16_t, uint32_t>& varId2ArgIndexMap,
    3086              :     const std::unordered_map<uint16_t, uint16_t>& varId2VarIdMap)
    3087              : {
    3088            7 :     if (argSize == 0 || varId2ArgIndexMap.empty()) {
    3089            3 :         return HCCL_SUCCESS;
    3090              :     }
    3091            4 :     auto& lgProfInfo = GetLGProfilingInfo();
    3092            4 :     uint64_t loopParam{0};
    3093            4 :     CHK_RET(
    3094              :         GetArgIndex(varId2VarIdMap, varId2ArgIndexMap, taskArgs, argSize, groupOpSizeInfo_[i].loopParamId, loopParam));
    3095            4 :     uint64_t parallelParam{0};
    3096            4 :     CHK_RET(GetArgIndex(
    3097              :         varId2VarIdMap, varId2ArgIndexMap, taskArgs, argSize, groupOpSizeInfo_[i].parallelParamId, parallelParam));
    3098            4 :     HCCL_INFO(
    3099              :         "Collect loopgroup profiling info: repSize[%u], index[%u],"
    3100              :         "loopParam[%llu], parallelParam[%llu].",
    3101              :         lgProfInfo.lgProfilingReps.size(), i, loopParam, parallelParam);
    3102              : 
    3103            4 :     if (loopParam != 0) {
    3104            1 :         lgProfInfo.ccuProfilingInfos[i].dataSize = loopParam * moConfig_.loopCount * moConfig_.memSlice;
    3105            1 :         lgProfInfo.ccuProfilingInfos[i].instrId
    3106            1 :             = dynamic_cast<CcuRep::CcuRepLoopGroupBundle*>(lgProfInfo.lgProfilingReps[i].get())->StartInstrId();
    3107            1 :         allCcuProfilingInfos_.push_back(lgProfInfo.ccuProfilingInfos[i]);
    3108              :     }
    3109              : 
    3110            4 :     if (parallelParam != 0) {
    3111            2 :         HCCL_INFO("[GetCcuProfilingInfo] collect lg, residual start i=%lu", i);
    3112            2 :         uint64_t residual{0};
    3113            3 :         CHK_RET(GetArgIndex(
    3114              :             varId2VarIdMap, varId2ArgIndexMap, taskArgs, argSize, groupOpSizeInfo_[i].residualId, residual));
    3115            2 :         uint64_t repeatNum = ParseRepeatNumFromParallelParam(parallelParam);
    3116            2 :         lgProfInfo.ccuProfilingInfos[i].dataSize = repeatNum * moConfig_.memSlice + residual;
    3117              :         // rep[i] 对应 loopParam 分支,rep[i+1] 对应 parallelParam 分支;尾项无配对 rep 时跳过避免越界
    3118            2 :         if (i + 1 >= repSize) {
    3119            1 :             HCCL_WARNING(
    3120              :                 "[CollectLoopGroupProfilingInfo] parallelParam != 0 but no paired rep,"
    3121              :                 " index(%u), repSize(%zu), skip parallelParam profiling.",
    3122              :                 i, repSize);
    3123            1 :             return HCCL_SUCCESS;
    3124              :         }
    3125            1 :         lgProfInfo.ccuProfilingInfos[i].instrId
    3126            1 :             = dynamic_cast<CcuRep::CcuRepLoopGroupBundle*>(lgProfInfo.lgProfilingReps[i + 1].get())->StartInstrId();
    3127            1 :         allCcuProfilingInfos_.push_back(lgProfInfo.ccuProfilingInfos[i]);
    3128              :     }
    3129            3 :     return HCCL_SUCCESS;
    3130              : }
    3131              : 
    3132              : /*
    3133              :  * variable/maskSignal等资源变量Id,一定要在获取ccu profiling时才获取;
    3134              :  * 原因:在创建context Rep时,其资源Id属于虚拟资源;翻译时,才会绑定固定的物理资源。
    3135              :  */
    3136            0 : HcclResult CcuKernel::GetCcuProfilingInfo(
    3137              :     const uint64_t* taskArgs, uint32_t argSize, std::vector<CcuProfilingInfo>& allCcuProfilingInfo)
    3138              : {
    3139            0 :     HCCL_INFO("[GetCcuProfilingInfo] Enter.");
    3140            0 :     allCcuProfilingInfos_.clear();
    3141              : 
    3142            0 :     CHK_RET(CollectSqeAndWaitCkeProfilingInfo());
    3143              : 
    3144            0 :     std::unordered_map<uint16_t, uint32_t> varId2ArgIndexMap;
    3145            0 :     std::unordered_map<uint16_t, uint16_t> varId2VarIdMap;
    3146            0 :     CHK_RET(BuildLoopGroupVarIdMaps(varId2ArgIndexMap, varId2VarIdMap));
    3147              : 
    3148            0 :     CHK_RET(CollectLoopGroupProfilingInfo(taskArgs, argSize, varId2ArgIndexMap, varId2VarIdMap));
    3149              : 
    3150            0 :     DumpCcuProfilingInfo(allCcuProfilingInfos_);
    3151            0 :     allCcuProfilingInfo = allCcuProfilingInfos_;
    3152            0 :     return HCCL_SUCCESS;
    3153            0 : }
    3154              : 
    3155            0 : HcclResult CcuKernel::AddProfilingInfo(
    3156              :     const ChannelHandle* channels, uint32_t channelNum, HcclDataType dataType, HcclDataType outputDataType,
    3157              :     HcclReduceOp opType, const std::string& opName)
    3158              : {
    3159            0 :     CHK_PTR_NULL(channels);
    3160            0 :     ccuProfilingInfoCache.type = (uint8_t)CcuProfilinType::CCU_LOOPGROUP_PROFILING;
    3161            0 :     ccuProfilingInfoCache.name = opName;
    3162            0 :     ccuProfilingInfoCache.reduceOpType = opType;
    3163            0 :     ccuProfilingInfoCache.inputDataType = dataType;
    3164            0 :     ccuProfilingInfoCache.outputDataType = outputDataType;
    3165            0 :     ccuProfilingInfoCache.missionId = GetMissionId();
    3166              : 
    3167            0 :     CHK_SAFETY_FUNC_RET(memset_s(
    3168              :         ccuProfilingInfoCache.channelId, sizeof(ccuProfilingInfoCache.channelId), INVALID_VALUE_CHANNELID,
    3169              :         sizeof(ccuProfilingInfoCache.channelId)));
    3170            0 :     for (uint32_t i = 0; i < channelNum; i++) {
    3171            0 :         void* channelPtr{nullptr};
    3172            0 :         CHK_RET(static_cast<HcclResult>(HcommChannelGet(channels[i], &channelPtr)));
    3173            0 :         auto* channelImpl = dynamic_cast<CcuUrmaChannel*>(static_cast<Channel*>(channelPtr));
    3174            0 :         CHK_PTR_NULL(channelImpl);
    3175            0 :         ccuProfilingInfoCache.channelId[i] = channelImpl->GetChannelId();
    3176            0 :         ccuProfilingInfoCache.channelHandle[i] = channels[i];
    3177            0 :         HCCL_INFO(
    3178              :             "[%s]type[%d], name[%s], opType[%d], dataType[%d], outputDataType[%d], missionId[%u], "
    3179              :             "channelHandle[0x%llx], channelId[%u]",
    3180              :             __func__, ccuProfilingInfoCache.type, ccuProfilingInfoCache.name.c_str(), opType, dataType, outputDataType,
    3181              :             ccuProfilingInfoCache.missionId, ccuProfilingInfoCache.channelHandle[i],
    3182              :             ccuProfilingInfoCache.channelId[i]);
    3183              :     }
    3184            0 :     lgProfilingInfo.ccuProfilingInfos.push_back(ccuProfilingInfoCache);
    3185            0 :     lgProfilingInfo.lgProfilingReps.push_back(allLgProfilingReps.back());
    3186            0 :     return HCCL_SUCCESS;
    3187              : }
    3188              : 
    3189            0 : HcclResult CcuKernel::AddCcuProfiling(
    3190              :     GroupInfo groupInfo, const std::vector<ChannelHandle> channelHandle, HcclDataType dataType,
    3191              :     HcclDataType outputDataType, HcclReduceOp opType, const std::string& opName)
    3192              : {
    3193            0 :     CHK_RET(AddCcuProfiling(channelHandle.data(), channelHandle.size(), dataType, outputDataType, opType, opName));
    3194            0 :     groupOpSizeInfo_.push_back(groupInfo);
    3195            0 :     return HCCL_SUCCESS;
    3196              : }
    3197              : 
    3198            0 : HcclResult CcuKernel::AddCcuProfiling(
    3199              :     const ChannelHandle* channels, uint32_t channelNum, HcclDataType dataType, HcclDataType outputDataType,
    3200              :     HcclReduceOp opType, const std::string& opName)
    3201              : {
    3202            0 :     CHK_PTR_NULL(channels);
    3203            0 :     CHK_RET(AddProfilingInfo(channels, channelNum, dataType, outputDataType, opType, opName));
    3204            0 :     return HCCL_SUCCESS;
    3205              : }
    3206              : 
    3207            5 : HcclResult CcuKernel::Add2ConstValue2VarMap(std::vector<uint64_t>& values)
    3208              : {
    3209              :     // 记录当前context所需的常量,仅A6场景适用
    3210           21 :     for (uint64_t value : values) {
    3211           16 :         if (constValue2VarMap.find(value) == constValue2VarMap.end()) {
    3212            3 :             constValue2VarMap[value] = CreateVariable();
    3213              :         }
    3214              :     }
    3215            5 :     return HCCL_SUCCESS;
    3216              : }
    3217              : 
    3218              : }; // namespace hcomm
        

Generated by: LCOV version 2.0-1