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

Generated by: LCOV version 2.0-1