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

Generated by: LCOV version 2.0-1