LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_instance - ccu_instance.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.6 % 139 119
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 16 16

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 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_instance.h"
      12              : 
      13              : #include <algorithm>
      14              : 
      15              : #include "log.h"
      16              : #include "ccu_log.h"
      17              : 
      18              : #include "hcom_common.h"
      19              : 
      20              : #include "ccu_res_pack.h"
      21              : #include "ccu_kernel_mgr.h"
      22              : #include "ccu_var_event_res_mgr.h"
      23              : #include "ccu_res_specs.h"
      24              : #include "ccu_dev_mgr_imp.h"
      25              : 
      26              : namespace hcomm {
      27              : 
      28           76 : CcuInstance::~CcuInstance()
      29              : {
      30              :     // 主动释放资源保证时序,不得随意调整顺序
      31          120 :     for (auto& kernelHandle : kernelHandles_) {
      32           44 :         if (kernelHandle != 0) {
      33           44 :             (void)CcuKernelMgr::GetInstance(devLogicId_).UnRegister(kernelHandle);
      34           44 :             kernelHandle = 0;
      35              :         }
      36              :     }
      37           76 :     kernelHandles_.clear();
      38              : 
      39           76 :     (void)CcuVarEventResMgr::GetInstance(devLogicId_).ReleaseByInstance(insHandle_);
      40              : 
      41           76 :     resPack_ = nullptr; // 释放instance持有的CCU资源
      42           76 :     if (ccuDrvHandle_) {
      43           68 :         ccuDrvHandle_ = nullptr; // 先减少引用计数,再尝试关闭
      44           68 :         (void)CcuDeinitFeature(devLogicId_);
      45              :         // 尝试关闭CCU功能,最后一个调用时会关闭CCU驱动
      46              :     }
      47           76 : }
      48              : 
      49            6 : CcuResult CcuInstance::InitByInsType(const CcuInstanceType insType)
      50              : {
      51            6 :     if (insType >= CcuInstanceType::CCU_UNUSED) {
      52            0 :         HCCL_ERROR("[CcuInstance][%s] failed, CcuInstanceType[%d] is invalid.", __func__, insType);
      53            0 :         return CcuResult::CCU_E_PARA;
      54              :     }
      55              : 
      56            6 :     devLogicId_ = HcclGetThreadDeviceId();
      57              : 
      58            6 :     if (!ccuDrvHandle_) {
      59            6 :         CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
      60              :     }
      61              : 
      62            6 :     if (!resPack_) {
      63            6 :         resPack_.reset(new (std::nothrow) CcuResPack());
      64            6 :         CCU_CHK_PTR_NULL(resPack_);
      65            6 :         CCU_CHK_RET(resPack_->InitByInsType(insType));
      66            6 :         CCU_CHK_RET(FillTotalResDescs());
      67              :     }
      68              : 
      69            6 :     return CcuResult::CCU_SUCCESS;
      70              : }
      71              : 
      72           62 : CcuResult CcuInstance::InitByResDescs(const CcuResDesc* descs[], uint32_t descNum)
      73              : {
      74           62 :     if (descs == nullptr || descNum == 0 || descNum > hcomm::CCU_MAX_IODIE_NUM) {
      75            0 :         HCCL_ERROR("[CcuInstance][%s] failed, invalid descs[%p] descNum[%u].", __func__, descs, descNum);
      76            0 :         return CcuResult::CCU_E_PARA;
      77              :     }
      78              : 
      79           62 :     devLogicId_ = HcclGetThreadDeviceId();
      80              : 
      81           62 :     if (!ccuDrvHandle_) {
      82           62 :         CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
      83              :     }
      84              : 
      85           61 :     if (!resPack_) {
      86           61 :         resPack_.reset(new (std::nothrow) CcuResPack());
      87           61 :         CCU_CHK_PTR_NULL(resPack_);
      88           61 :         CCU_CHK_RET(resPack_->InitByResDescs(descs, descNum));
      89           60 :         CCU_CHK_RET(FillTotalResDescs());
      90              :     }
      91              : 
      92           60 :     return CcuResult::CCU_SUCCESS;
      93              : }
      94              : 
      95            2 : CcuResult CcuInstance::InitByAllRes()
      96              : {
      97            2 :     devLogicId_ = HcclGetThreadDeviceId();
      98              : 
      99            2 :     if (!ccuDrvHandle_) {
     100            2 :         CCU_CHK_RET(CcuInitFeature(devLogicId_, ccuDrvHandle_));
     101              :     }
     102              : 
     103              :     // 申请当前 Device 上所有已使能 ioDie 的全部资源:
     104              :     // 先查询各 die 是否启用,仅对已使能的 die 调用 CcuGetXXXNum 获取资源总量,
     105              :     // 未启用的 die 其 resNum 保持 0(resNum 默认初始化为 0)
     106            2 :     std::array<hcomm::CcuResDesc, hcomm::CCU_MAX_IODIE_NUM> descs{};
     107            1 :     std::array<const hcomm::CcuResDesc*, hcomm::CCU_MAX_IODIE_NUM> descPtrs{};
     108            3 :     for (uint8_t i = 0; i < hcomm::CCU_MAX_IODIE_NUM; i++) {
     109            2 :         descs[i].dieId = i;
     110            2 :         descPtrs[i] = &descs[i];
     111              :     }
     112              : 
     113            3 :     for (uint8_t dieId = 0; dieId < hcomm::CCU_MAX_IODIE_NUM; dieId++) {
     114            2 :         bool dieEnable = false;
     115            2 :         CCU_CHK_RET(CcuGetDieEnableInfo(devLogicId_, dieId, dieEnable));
     116            2 :         if (!dieEnable) {
     117            0 :             continue; // 未启用的 die,resNum 保持 0
     118              :         }
     119              : 
     120            2 :         uint32_t num = 0;
     121              :         // 各资源类型总量查询(per-die),按块分的资源查的是块大小*块总数
     122            2 :         CCU_CHK_RET(CcuGetLoopEngineNum(devLogicId_, dieId, num));
     123            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::LOOP, num));
     124            2 :         CCU_CHK_RET(CcuGetMsNum(devLogicId_, dieId, num));
     125            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::MS, num));
     126            2 :         CCU_CHK_RET(CcuGetCkeNum(devLogicId_, dieId, num));
     127            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::CKE, num));
     128            2 :         CCU_CHK_RET(CcuGetXnNum(devLogicId_, dieId, num));
     129            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::XN, num));
     130            2 :         CCU_CHK_RET(CcuGetGsaNum(devLogicId_, dieId, num));
     131            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::GSA, num));
     132            2 :         CCU_CHK_RET(CcuGetInstructionNum(devLogicId_, dieId, num));
     133            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::INS, num));
     134            2 :         CCU_CHK_RET(CcuGetMissionNum(devLogicId_, dieId, num));
     135            2 :         CCU_CHK_RET(descs[dieId].SetResNum(ResType::MISSION, num));
     136              :     }
     137              : 
     138            1 :     if (!resPack_) {
     139            1 :         resPack_.reset(new (std::nothrow) CcuResPack());
     140            1 :         CCU_CHK_PTR_NULL(resPack_);
     141            2 :         CCU_CHK_RET(resPack_->InitByResDescs(descPtrs.data(), hcomm::CCU_MAX_IODIE_NUM));
     142            1 :         CCU_CHK_RET(FillTotalResDescs());
     143              :     }
     144              : 
     145            1 :     return CcuResult::CCU_SUCCESS;
     146              : }
     147              : 
     148           55 : CcuResult CcuInstance::Reset()
     149              : {
     150           55 :     if (!resPack_) {
     151            0 :         return CcuResult::CCU_SUCCESS;
     152              :     }
     153              : 
     154           55 :     untranslatedKernelHandles_.clear();
     155           55 :     CCU_CHK_RET(resPack_->Reset());
     156              : 
     157           55 :     CCU_CHK_RET(CcuVarEventResMgr::GetInstance(devLogicId_).ExcludeAllocatedFromRepo(insHandle_));
     158           55 :     return CcuResult::CCU_SUCCESS;
     159              : }
     160              : 
     161           70 : CcuResPack* CcuInstance::GetResPack() { return resPack_.get(); }
     162              : 
     163           67 : void CcuInstance::SetHandle(CcuInsHandle insHandle) { insHandle_ = insHandle; }
     164              : 
     165              : // 累加某 die 上某资源 vector 中各 ResInfo::num,得到该 die 该资源的占用数量
     166         1474 : static uint32_t SumResNum(const std::vector<ResInfo>& resInfos, std::string resName)
     167              : {
     168         1474 :     uint32_t total = 0;
     169         2248 :     for (const auto& info : resInfos) {
     170          774 :         total += info.num;
     171              :     }
     172         1474 :     HCCL_INFO("[CcuInstance][FillTotalResDescs] resType: %s, resNum: %u", resName.c_str(), total);
     173         1474 :     return total;
     174              : }
     175              : 
     176           67 : CcuResult CcuInstance::FillTotalResDescs()
     177              : {
     178           67 :     if (resPack_ == nullptr) {
     179            0 :         HCCL_ERROR("[CcuInstance][%s] failed, resPack_ is nullptr.", __func__);
     180            0 :         return CcuResult::CCU_E_INTERNAL;
     181              :     }
     182           67 :     const auto& resRepo = resPack_->GetCcuResRepo();
     183              : 
     184          201 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     185          134 :         totalResDescs_[dieId].dieId = dieId;
     186              :         // 各资源类型占用数量 = block 路径 + 非 block 连续路径之和
     187          670 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(
     188              :             ResType::LOOP, SumResNum(resRepo.blockLoopEngine[dieId], "blockLoopEngine")
     189              :                                + SumResNum(resRepo.loopEngine[dieId], "loopEngine")));
     190          670 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(
     191              :             ResType::MS, SumResNum(resRepo.blockMs[dieId], "blockMs") + SumResNum(resRepo.ms[dieId], "ms")));
     192          670 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(
     193              :             ResType::CKE, SumResNum(resRepo.blockCke[dieId], "blockCke") + SumResNum(resRepo.cke[dieId], "cke")));
     194          670 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(
     195              :             ResType::XN, SumResNum(resRepo.blockXn[dieId], "blockXn") + SumResNum(resRepo.xn[dieId], "xn")));
     196          670 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(
     197              :             ResType::GSA, SumResNum(resRepo.blockGsa[dieId], "blockGsa") + SumResNum(resRepo.gsa[dieId], "gsa")));
     198          402 :         CCU_CHK_RET(
     199              :             totalResDescs_[dieId].SetResNum(ResType::MISSION, SumResNum(resRepo.mission.mission[dieId], "mission")));
     200              :         // INS 当前无对应占用资源项,写 0
     201          134 :         CCU_CHK_RET(totalResDescs_[dieId].SetResNum(ResType::INS, 0));
     202              :     }
     203           67 :     return CcuResult::CCU_SUCCESS;
     204              : }
     205              : 
     206            2 : const CcuResDesc& CcuInstance::GetTotalResDescs(uint8_t dieId) const { return totalResDescs_[dieId]; }
     207              : 
     208           44 : CcuResult CcuInstance::SaveKernel(const CcuKernelHandle kernelHandle)
     209              : {
     210           44 :     kernelHandles_.push_back(kernelHandle);
     211           44 :     untranslatedKernelHandles_.push_back(kernelHandle);
     212           44 :     return CcuResult::CCU_SUCCESS;
     213              : }
     214              : 
     215           45 : const std::vector<CcuKernelHandle>& CcuInstance::GetUntranslatedKernels() { return untranslatedKernelHandles_; }
     216              : 
     217           55 : CcuResult CcuInstance::BeginRegister()
     218              : {
     219           55 :     if (registerState_ == RegisterState::REGISTERING) {
     220            0 :         HCCL_ERROR(
     221              :             "[CcuInstance][%s] failed, previous register round is not ended, "
     222              :             "HcommCcuKernelRegisterEnd is missing before a new HcommCcuKernelRegisterStart.",
     223              :             __func__);
     224            0 :         return CcuResult::CCU_E_INTERNAL;
     225              :     }
     226           55 :     registerState_ = RegisterState::REGISTERING;
     227           55 :     return CcuResult::CCU_SUCCESS;
     228              : }
     229              : 
     230           55 : CcuResult CcuInstance::CheckRegistering() const
     231              : {
     232           55 :     if (registerState_ != RegisterState::REGISTERING) {
     233            0 :         HCCL_ERROR(
     234              :             "[CcuInstance][%s] failed, HcommCcuKernelRegister must be called between "
     235              :             "HcommCcuKernelRegisterStart and HcommCcuKernelRegisterEnd.",
     236              :             __func__);
     237            0 :         return CcuResult::CCU_E_INTERNAL;
     238              :     }
     239           55 :     return CcuResult::CCU_SUCCESS;
     240              : }
     241              : 
     242           45 : CcuResult CcuInstance::EndRegister()
     243              : {
     244           45 :     if (registerState_ == RegisterState::IDLE) {
     245            0 :         HCCL_ERROR(
     246              :             "[CcuInstance][%s] failed, HcommCcuKernelRegisterEnd is called without a matching "
     247              :             "HcommCcuKernelRegisterStart.",
     248              :             __func__);
     249            0 :         return CcuResult::CCU_E_INTERNAL;
     250              :     }
     251           45 :     if (registerState_ == RegisterState::REGISTER_ABORTED) {
     252            1 :         HCCL_WARNING(
     253              :             "[CcuInstance][%s] previous register round was aborted due to error, "
     254              :             "close it to keep Start/End paired, no kernel will be translated.",
     255              :             __func__);
     256              :     }
     257           45 :     registerState_ = RegisterState::IDLE;
     258           45 :     return CcuResult::CCU_SUCCESS;
     259              : }
     260              : 
     261           11 : void CcuInstance::AbortRegister()
     262              : {
     263           11 :     for (auto kernelHandle : untranslatedKernelHandles_) {
     264            0 :         if (kernelHandle == 0) {
     265            0 :             continue;
     266              :         }
     267            0 :         (void)CcuKernelMgr::GetInstance(devLogicId_).UnRegister(kernelHandle);
     268            0 :         auto it = std::find(kernelHandles_.begin(), kernelHandles_.end(), kernelHandle);
     269            0 :         if (it != kernelHandles_.end()) {
     270            0 :             kernelHandles_.erase(it);
     271              :         }
     272              :     }
     273           11 :     untranslatedKernelHandles_.clear();
     274           11 :     registerState_ = RegisterState::REGISTER_ABORTED;
     275           11 : }
     276              : 
     277              : } // namespace hcomm
        

Generated by: LCOV version 2.0-1