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-04 10:52:23 Functions: 100.0 % 15 15

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

Generated by: LCOV version 2.0-1