LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_device - ccu_res_batch_allocator.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.2 % 504 394
Test Date: 2026-08-18 17:47:01 Functions: 93.5 % 31 29

            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_res_batch_allocator.h"
      12              : 
      13              : #include <array>
      14              : #include <memory>
      15              : #include <utility>
      16              : #include <iterator>
      17              : #include <algorithm>
      18              : 
      19              : #include "hccl_common.h"
      20              : 
      21              : #include "ccu_comp.h"
      22              : #include "ccu_res_specs.h"
      23              : #include "ccu_res_type_converter.h"
      24              : #include "ccu_device_res.h"
      25              : #include "ccu_rep_reference_manager_v1.h"
      26              : #include "ccu_rep_reference_manager.h"
      27              : 
      28              : namespace hcomm {
      29              : 
      30              : constexpr uint32_t REQ_RES_TYPE_NUM = 11;
      31              : constexpr uint32_t BLOCK_RES_TYPE_NUM = 5;
      32              : constexpr uint32_t CONS_RES_TYPE_NUM = 1;
      33              : constexpr uint32_t DISCRETE_RES_TYPE_NUM = 4;
      34              : constexpr uint32_t NON_BLOCK_TYPE_NUM = CONS_RES_TYPE_NUM + DISCRETE_RES_TYPE_NUM;
      35              : constexpr uint32_t BLOCK_SIZE_MS_AX_DIE0 = 128;
      36              : constexpr uint32_t CCUA_NUM = 4;
      37              : 
      38              : constexpr uint32_t CCU_REPREFMGR_NEW_XN_NUM
      39              :     = hcomm::CcuRep::FUNC_ARG_MAX + hcomm::CcuRep::FUNC_ARG_MAX + 1 + hcomm::CcuRep::FUNC_NEST_MAX + 1;
      40              : constexpr uint32_t CCU_REPREFMGR_LEGACY_XN_NUM
      41              :     = Hccl::CcuRep::FUNC_IN_MAX + Hccl::CcuRep::FUNC_OUT_MAX + 1 + Hccl::CcuRep::FUNC_NEST_MAX + 1;
      42              : constexpr uint32_t CCU_REP_TRANSLATOR_GSA_NUM = 3;
      43              : constexpr uint32_t CCU_REP_TRANSLATOR_CKE_NUM = 2;
      44              : constexpr uint32_t CCU_REP_TRANSLATOR_XN_NUM = 4;
      45              : // 建链预留数量 + 开源+legacy的CcuRepTranslator预留数量
      46              : constexpr uint32_t RESERVED_DISCRETE_CKE_NUM = 4 * 128 + (CCU_REP_TRANSLATOR_CKE_NUM * 16) * 2;
      47              : // 建链预留数量 + 开源+legacy的CcuRepReferenceManager预留数量 + 开源+legacy的CcuRepTranslator预留数量
      48              : constexpr uint32_t RESERVED_DISCRETE_XN_NUM
      49              :     = 4 * 128 + CCU_REPREFMGR_LEGACY_XN_NUM * 16 + CCU_REPREFMGR_NEW_XN_NUM * 16 + (CCU_REP_TRANSLATOR_XN_NUM * 16) * 2;
      50              : // 开源+legacy的CcuRepTranslator预留数量
      51              : constexpr uint32_t RESERVED_DISCRETE_GSA_NUM = (CCU_REP_TRANSLATOR_GSA_NUM * 16) * 2;
      52              : 
      53         1073 : CcuResBatchAllocator& CcuResBatchAllocator::GetInstance(const int32_t deviceLogicId)
      54              : {
      55         1205 :     static CcuResBatchAllocator ccuResBatchAllocator[MAX_MODULE_DEVICE_NUM + 1];
      56         1073 :     int32_t devLogicId = deviceLogicId;
      57         1073 :     if (devLogicId < 0 || static_cast<uint32_t>(devLogicId) >= MAX_MODULE_DEVICE_NUM) {
      58            0 :         HCCL_WARNING(
      59              :             "[CcuResBatchAllocator][%s] use the backup device, devLogicId[%d] "
      60              :             "should be less than %u.",
      61              :             __func__, devLogicId, MAX_MODULE_DEVICE_NUM);
      62            0 :         devLogicId = MAX_MODULE_DEVICE_NUM; // 使用备份设备
      63              :     }
      64         1073 :     ccuResBatchAllocator[devLogicId].devLogicId_ = devLogicId;
      65         1073 :     return ccuResBatchAllocator[devLogicId];
      66              : }
      67              : 
      68          173 : HcclResult CcuResBatchAllocator::Init()
      69              : {
      70          173 :     if (initFlag_) {
      71           77 :         return HcclResult::HCCL_SUCCESS;
      72              :     }
      73              : 
      74           96 :     dieEnableFlags_ = CcuComponent::GetInstance(devLogicId_).GetDieEnableFlags();
      75           96 :     if (!dieEnableFlags_[0] && !dieEnableFlags_[1]) {
      76            0 :         HCCL_WARNING(
      77              :             "[CcuResBatchAllocator][%s] failed but passed, "
      78              :             "devLogicId[%d] no usable die.",
      79              :             __func__, devLogicId_);
      80            0 :         return HcclResult::HCCL_E_UNAVAIL;
      81              :     }
      82              : 
      83           96 :     auto ret = PreAllocBlockRes();
      84           96 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
      85            0 :         HCCL_WARNING(
      86              :             "[CcuResBatchAllocator][%s] pre alloc block res failed but passed, "
      87              :             "some sources are not enough, devLogicId[%d].",
      88              :             __func__, devLogicId_);
      89            0 :         return ret;
      90              :     }
      91           96 :     CHK_RET(ret);
      92              : 
      93           96 :     ret = missionMgr_.PreAlloc(devLogicId_, resStrategies_[0].missionNum, dieEnableFlags_);
      94           96 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
      95            0 :         HCCL_WARNING(
      96              :             "[CcuResBatchAllocator][%s] pre alloc mission res failed but passed, "
      97              :             "some sources are not enough, devLogicId[%d].",
      98              :             __func__, devLogicId_);
      99            0 :         return ret;
     100              :     }
     101           96 :     CHK_RET(ret);
     102              : 
     103           96 :     initFlag_ = true;
     104           96 :     return HcclResult::HCCL_SUCCESS;
     105              : }
     106              : 
     107          173 : HcclResult CcuResBatchAllocator::Deinit()
     108              : {
     109          173 :     missionMgr_.Reset();
     110          519 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     111          346 :         resBlocks_[dieId].clear();
     112              :     }
     113              : 
     114          173 :     handleMap_.clear();
     115          173 :     initFlag_ = false;
     116          173 :     return HcclResult::HCCL_SUCCESS;
     117              : }
     118              : 
     119          192 : static CcuResBlockNums GetPreAllocatedMaxBlockNums(
     120              :     const uint32_t devLogicId, const uint8_t dieId,
     121              :     const std::array<CcuBlockResStrategy, CCU_MAX_IODIE_NUM>& resStrategies)
     122              : {
     123          192 :     CcuResBlockNums blockNums{};
     124              : 
     125          192 :     CcuResSpecifications& ccuResSepcs = CcuResSpecifications::GetInstance(devLogicId);
     126              : 
     127          192 :     uint32_t loopNum = 0;
     128          192 :     (void)ccuResSepcs.GetLoopEngineNum(dieId, loopNum);
     129          192 :     blockNums.loopNum = loopNum / resStrategies[dieId].loopNum;
     130              : 
     131          192 :     uint32_t msNum = 0;
     132          192 :     (void)ccuResSepcs.GetMsNum(dieId, msNum);
     133          192 :     blockNums.msNum = msNum / resStrategies[dieId].msNum;
     134              : 
     135          192 :     uint32_t ckeNum = 0;
     136          192 :     (void)ccuResSepcs.GetCkeNum(dieId, ckeNum);
     137          192 :     if (ckeNum > RESERVED_DISCRETE_CKE_NUM) {
     138          192 :         blockNums.ckeNum = (ckeNum - RESERVED_DISCRETE_CKE_NUM) / resStrategies[dieId].ckeNum;
     139              :     } else {
     140            0 :         blockNums.ckeNum = 0;
     141              :     }
     142              : 
     143          192 :     uint32_t xnNum = 0;
     144          192 :     (void)ccuResSepcs.GetXnNum(dieId, xnNum);
     145          192 :     if (xnNum > RESERVED_DISCRETE_XN_NUM) {
     146          192 :         blockNums.xnNum = (xnNum - RESERVED_DISCRETE_XN_NUM) / resStrategies[dieId].xnNum;
     147              :     } else {
     148            0 :         blockNums.xnNum = 0;
     149              :     }
     150              : 
     151          192 :     if (ccuResSepcs.GetCcuVersion() == CcuVersion::CCU_V1) {
     152          162 :         uint32_t gsaNum = 0;
     153          162 :         (void)ccuResSepcs.GetGsaNum(dieId, gsaNum);
     154          162 :         if (gsaNum > RESERVED_DISCRETE_GSA_NUM) {
     155          162 :             blockNums.gsaNum = (gsaNum - RESERVED_DISCRETE_GSA_NUM) / resStrategies[dieId].gsaNum;
     156              :         } else {
     157            0 :             blockNums.gsaNum = 0;
     158              :         }
     159              :     } else {
     160           30 :         blockNums.gsaNum = 0;
     161              :     }
     162              : 
     163          192 :     HCCL_INFO(
     164              :         "[CcuResBatchAllocator][%s] batch allocator will alloc blocks resources: loop blocks[%u] "
     165              :         "ms blocks[%u] cke blocks[%u] xn blocks[%u] gsa blocks[%u], devLogicId[%d] dieId[%u].",
     166              :         __func__, blockNums.loopNum, blockNums.msNum, blockNums.ckeNum, blockNums.xnNum, blockNums.gsaNum, devLogicId,
     167              :         dieId);
     168          384 :     return blockNums;
     169              : }
     170              : 
     171           16 : HcclResult CcuResBatchAllocator::GetAllocatableMaxBlockResNum(ResType resType, uint8_t dieId, uint32_t& num) const
     172              : {
     173           16 :     switch (resType) {
     174            7 :         case ResType::LOOP:
     175            7 :             num = maxResBlockNums_.loopNum * resStrategies_[dieId].loopNum;
     176            7 :             break;
     177            3 :         case ResType::MS:
     178            3 :             num = maxResBlockNums_.msNum * resStrategies_[dieId].msNum;
     179            3 :             break;
     180            2 :         case ResType::CKE:
     181            2 :             num = maxResBlockNums_.ckeNum * resStrategies_[dieId].ckeNum;
     182            2 :             break;
     183            2 :         case ResType::XN:
     184            2 :             num = maxResBlockNums_.xnNum * resStrategies_[dieId].xnNum;
     185            2 :             break;
     186            2 :         case ResType::GSA:
     187            2 :             num = maxResBlockNums_.gsaNum * resStrategies_[dieId].gsaNum;
     188            2 :             break;
     189            0 :         default:
     190            0 :             HCCL_ERROR(
     191              :                 "[CcuResBatchAllocator][%s] unsupported block res type[%s], devLogicId[%d] dieId[%u].", __func__,
     192              :                 resType.Describe().c_str(), devLogicId_, dieId);
     193            0 :             return HcclResult::HCCL_E_PARA;
     194              :     }
     195           16 :     return HcclResult::HCCL_SUCCESS;
     196              : }
     197              : 
     198           96 : HcclResult CcuResBatchAllocator::PreAllocBlockRes()
     199              : {
     200           96 :     CcuComponent& ccuComponent = CcuComponent::GetInstance(devLogicId_);
     201           96 :     const auto serveMode = CcuResSpecifications::GetInstance(devLogicId_).GetServeMode();
     202          288 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     203          192 :         if (!dieEnableFlags_[dieId]) {
     204            0 :             HCCL_WARNING(
     205              :                 "[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     206              :                 "will not pre-allocate block resource.",
     207              :                 __func__, devLogicId_, dieId);
     208            0 :             continue;
     209              :         }
     210              : 
     211          192 :         maxResBlockNums_ = GetPreAllocatedMaxBlockNums(devLogicId_, dieId, resStrategies_);
     212              :         const std::array<std::tuple<ResType, uint32_t, uint32_t>, BLOCK_RES_TYPE_NUM> blockResReqs = {
     213          192 :             std::make_tuple(ResType::LOOP, maxResBlockNums_.loopNum, resStrategies_[dieId].loopNum),
     214          192 :             std::make_tuple(ResType::MS, maxResBlockNums_.msNum, resStrategies_[dieId].msNum),
     215          192 :             std::make_tuple(ResType::CKE, maxResBlockNums_.ckeNum, resStrategies_[dieId].ckeNum),
     216          192 :             std::make_tuple(ResType::XN, maxResBlockNums_.xnNum, resStrategies_[dieId].xnNum),
     217          192 :             std::make_tuple(ResType::GSA, maxResBlockNums_.gsaNum, resStrategies_[dieId].gsaNum),
     218          960 :         };
     219              : 
     220         1152 :         for (auto& resReq : blockResReqs) {
     221          960 :             const ResType resType = std::get<0>(resReq);
     222          960 :             const uint32_t blockNum = std::get<1>(resReq);
     223          960 :             const uint32_t blockSize = std::get<2>(resReq);
     224          960 :             const uint32_t reqNum = blockNum * blockSize; // 生成时已保证不会溢出
     225          960 :             if (reqNum == 0) {
     226           30 :                 HCCL_WARNING(
     227              :                     "[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u], "
     228              :                     "resType[%s], request num is 0, passed.",
     229              :                     __func__, devLogicId_, dieId, resType.Describe().c_str());
     230           30 :                 continue;
     231              :             }
     232              : 
     233          930 :             std::vector<ResInfo> tempResInfos;
     234          930 :             auto ret = ccuComponent.AllocRes(dieId, resType, reqNum, true, tempResInfos);
     235          930 :             if (ret == HcclResult::HCCL_E_UNAVAIL) {
     236            0 :                 HCCL_WARNING(
     237              :                     "[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     238              :                     "failed to pre allocate block type resource, resType[%s], num[%u].",
     239              :                     __func__, devLogicId_, dieId, resType.Describe().c_str(), reqNum);
     240            0 :                 return ret;
     241              :             }
     242          930 :             CHK_RET(ret);
     243              : 
     244          930 :             const bool avoidCcu0Flag = (serveMode == ServeMode::ARMX86 && dieId == 0 && resType == ResType::MS);
     245          930 :             std::vector<BlockInfo> tempBlocks;
     246          930 :             const uint32_t startId = tempResInfos[0].startId;
     247        62358 :             for (uint32_t k = 0; k < blockNum; k++) {
     248        61428 :                 BlockInfo blockInfo;
     249        61428 :                 blockInfo.id = k;
     250        61428 :                 blockInfo.startId = startId + k * blockSize;
     251        61428 :                 blockInfo.num = blockSize;
     252              :                 // A+X形态,PCIE连接到IOdie0,导致IOdie0上连接PCIE的CCUA0无法使用,分配MS资源时需要跳过CCUA0
     253              :                 // 给要分给CCUA0的块,设置成已分配过,防止后续分给算法使用
     254        61428 :                 blockInfo.allocated = avoidCcu0Flag ? k % CCUA_NUM == 0 : false;
     255        61428 :                 blockInfo.handle = 0;
     256        61428 :                 tempBlocks.emplace_back(blockInfo);
     257              :             }
     258          930 :             resBlocks_[dieId][resType] = std::move(tempBlocks);
     259          930 :         }
     260              :     }
     261              : 
     262           96 :     return HcclResult::HCCL_SUCCESS;
     263              : }
     264              : 
     265          251 : static bool CheckReqValid(const CcuResReq& req, int32_t devLogicId, std::array<bool, CCU_MAX_IODIE_NUM>& dieEnableFlags)
     266              : {
     267          251 :     bool ifValid = false;
     268          753 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     269              :         const std::array<uint32_t, REQ_RES_TYPE_NUM> reqs
     270          502 :             = {req.loopEngineReq[i], req.blockLoopEngineReq[i], req.msReq[i],         req.blockMsReq[i],
     271         2008 :                req.ckeReq[i],        req.blockCkeReq[i],        req.xnReq[i],         req.blockXnReq[i],
     272          502 :                req.gsaReq[i],        req.blockGsaReq[i],        req.missionReq.req[i]};
     273              : 
     274         1004 :         const bool ifReqEmpty = std::all_of(std::begin(reqs), std::end(reqs), [](uint32_t x) {
     275         3212 :             return x == 0;
     276              :         });
     277          502 :         if (!dieEnableFlags[i] && !ifReqEmpty) { // 当前die未使能,但请求资源
     278            0 :             HCCL_ERROR(
     279              :                 "[CcuResBatchAllocator][%s] failed, dieId[%u] is not enable, "
     280              :                 "but resource request is not empty, devLogicId[%d].",
     281              :                 __func__, i, devLogicId);
     282            0 :             return false;
     283              :         }
     284              : 
     285              :         // 当前die使能,并且请求资源即合法
     286          502 :         if (dieEnableFlags[i] && !ifReqEmpty) {
     287          318 :             ifValid = true;
     288              :         }
     289              :     }
     290              : 
     291          251 :     if (!ifValid) {
     292            0 :         HCCL_ERROR(
     293              :             "[CcuResBatchAllocator][%s] all dies resource request is empty, "
     294              :             "devLogicId[%d].",
     295              :             __func__, devLogicId);
     296              :     }
     297              : 
     298          251 :     return ifValid;
     299              : }
     300              : 
     301          251 : HcclResult CcuResBatchAllocator::AllocResHandle(const CcuResReq& resReq, CcuResHandle& resHandle)
     302              : {
     303          251 :     if (!CheckReqValid(resReq, devLogicId_, dieEnableFlags_)) {
     304            0 :         resHandle = nullptr;
     305            0 :         HCCL_ERROR(
     306              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], invalid resource "
     307              :             "request, all resource request is empty.",
     308              :             __func__, devLogicId_);
     309            0 :         return HcclResult::HCCL_E_PARA;
     310              :     }
     311              : 
     312          251 :     std::unique_ptr<CcuResRepository> resRepoPtr = nullptr;
     313          251 :     resRepoPtr.reset(new (std::nothrow) CcuResRepository());
     314          251 :     CHK_PTR_NULL(resRepoPtr);
     315          251 :     const uintptr_t handleKey = reinterpret_cast<uintptr_t>(resRepoPtr.get());
     316              :     // 申请分配临时资源
     317          251 :     HcclResult ret = TryAllocResHandle(handleKey, resReq, resRepoPtr);
     318          251 :     if (ret != HcclResult::HCCL_SUCCESS) {
     319            0 :         resHandle = nullptr;
     320            0 :         HCCL_WARNING(
     321              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], failed to "
     322              :             "allocate resource handle, release temporary resources of this request.",
     323              :             __func__, devLogicId_);
     324              : 
     325              :         // 释放申请的临时资源,由CcuResRepo对象对应的智能指针管理
     326            0 :         HcclResult releaseRet = ReleaseResource(resRepoPtr);
     327            0 :         if (releaseRet != HcclResult::HCCL_SUCCESS) {
     328            0 :             HCCL_ERROR(
     329              :                 "[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     330              :                 "failed to release temporary resources of this request.",
     331              :                 __func__, devLogicId_);
     332            0 :             return releaseRet;
     333              :         }
     334              : 
     335            0 :         HCCL_INFO(
     336              :             "[CcuResBatchAllocator][%s] devLogicId[%d], "
     337              :             "temporary resources released.",
     338              :             __func__, devLogicId_);
     339            0 :         return ret;
     340              :     }
     341              :     // 保存资源信息
     342          251 :     resHandle = reinterpret_cast<CcuResHandle>(resRepoPtr.get());
     343          251 :     handleMap_[handleKey] = std::move(resRepoPtr);
     344              : 
     345          251 :     return HcclResult::HCCL_SUCCESS;
     346          251 : }
     347              : 
     348          707 : static HcclResult HandleBlockRes(
     349              :     const uintptr_t handleKey, const uint32_t num, const uint32_t blockSize, std::vector<BlockInfo>& blocks,
     350              :     std::vector<ResInfo>& resInfos)
     351              : {
     352          707 :     uint32_t blockNum = 1 + (num - 1) / blockSize;
     353          707 :     uint32_t blockMaxSize = blocks.size();
     354          707 :     uint32_t blockStartId = blockMaxSize;
     355          707 :     uint32_t freeNum = 0;
     356          707 :     bool allocatable = false;
     357        10720 :     for (size_t k = 0; k < blockMaxSize; k++) {
     358              :         // 如果当前块已分配,说明当前分配不够,重置分配数量与起始id
     359        10720 :         if (blocks[k].allocated) {
     360            0 :             blockStartId = blockMaxSize;
     361            0 :             freeNum = 0;
     362            0 :             continue;
     363              :         }
     364              :         // 如果是首个可分配块,记录起始id
     365        10720 :         if (blockStartId == blockMaxSize) {
     366          707 :             blockStartId = k;
     367              :         }
     368              :         // 当前块未分配,更新可分配数量
     369        10720 :         freeNum++;
     370              :         // 可分配数量足够则分配成功
     371        10720 :         if (freeNum >= blockNum) {
     372          707 :             allocatable = true;
     373          707 :             break;
     374              :         }
     375              :     }
     376          707 :     if (!allocatable) {
     377            0 :         return HcclResult::HCCL_E_UNAVAIL;
     378              :     }
     379              :     // 更新所有新分配的块的信息
     380        11427 :     for (size_t k = blockStartId; k < blockStartId + blockNum; k++) {
     381        10720 :         blocks[k].handle = handleKey;
     382        10720 :         blocks[k].allocated = true;
     383              :     }
     384          707 :     resInfos.emplace_back(ResInfo{blocks[blockStartId].startId, blockNum * blockSize});
     385          707 :     return HcclResult::HCCL_SUCCESS;
     386              : }
     387              : 
     388            0 : static void DumpBlockResInfo(ResType resType, const std::vector<BlockInfo>& blocks)
     389              : {
     390            0 :     HCCL_INFO("Dump ResType[%s] block resources info: ", resType.Describe().c_str());
     391            0 :     uint32_t blockNum = blocks.size();
     392            0 :     for (size_t k = 0; k < blockNum; k++) {
     393            0 :         HCCL_INFO(
     394              :             "Block[id[%u], startId[%u], num[%u], handle(uintptr_t)[%llu], allocated[%d]]", blocks[k].id,
     395              :             blocks[k].startId, blocks[k].num, static_cast<unsigned long long>(blocks[k].handle),
     396              :             static_cast<int>(blocks[k].allocated));
     397              :     }
     398            0 : }
     399              : 
     400          251 : HcclResult CcuResBatchAllocator::AllocBlockRes(
     401              :     const uintptr_t handleKey, const CcuResReq& resReq, std::unique_ptr<CcuResRepository>& resRepoPtr)
     402              : {
     403              :     using ResTypeReqNumBlockNumFunc = std::tuple<ResType::Value, uint32_t, uint32_t, std::vector<ResInfo>&>;
     404              : 
     405          753 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     406          502 :         if (!dieEnableFlags_[dieId]) {
     407            0 :             HCCL_WARNING(
     408              :                 "[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     409              :                 "will not allocate block resource.",
     410              :                 __func__, devLogicId_, dieId);
     411            0 :             continue;
     412              :         }
     413              : 
     414              :         std::array<ResTypeReqNumBlockNumFunc, BLOCK_RES_TYPE_NUM> blockReqParas
     415              :             = {std::make_tuple(
     416          502 :                    ResType::LOOP, resReq.blockLoopEngineReq[dieId], resStrategies_[dieId].loopNum,
     417          502 :                    std::ref(resRepoPtr->blockLoopEngine[dieId])),
     418              :                std::make_tuple(
     419          502 :                    ResType::MS, resReq.blockMsReq[dieId], resStrategies_[dieId].msNum,
     420          502 :                    std::ref(resRepoPtr->blockMs[dieId])),
     421              :                std::make_tuple(
     422          502 :                    ResType::CKE, resReq.blockCkeReq[dieId], resStrategies_[dieId].ckeNum,
     423          502 :                    std::ref(resRepoPtr->blockCke[dieId])),
     424              :                std::make_tuple(
     425          502 :                    ResType::XN, resReq.blockXnReq[dieId], resStrategies_[dieId].xnNum,
     426          502 :                    std::ref(resRepoPtr->blockXn[dieId])),
     427              :                std::make_tuple(
     428          502 :                    ResType::GSA, resReq.blockGsaReq[dieId], resStrategies_[dieId].gsaNum,
     429         2510 :                    std::ref(resRepoPtr->blockGsa[dieId]))};
     430              : 
     431         3012 :         for (uint32_t blockType = 0; blockType < BLOCK_RES_TYPE_NUM; blockType++) {
     432         2510 :             const auto& req = blockReqParas[blockType];
     433         2510 :             const uint32_t num = std::get<1>(req);
     434         2510 :             if (num == 0) {
     435         1870 :                 continue;
     436              :             }
     437              : 
     438          640 :             const ResType resType = std::get<0>(req);
     439          640 :             const uint32_t blockSize = std::get<2>(req);
     440          640 :             auto& blocks = resBlocks_[dieId][resType];
     441          640 :             auto& resInfos = std::get<3>(req);
     442          640 :             auto ret = HandleBlockRes(handleKey, num, blockSize, blocks, resInfos);
     443          640 :             if (ret != HcclResult::HCCL_SUCCESS) {
     444            0 :                 HCCL_WARNING(
     445              :                     "[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     446              :                     "failed to allocate [%s] block resource, remaining block resources are "
     447              :                     "not enough, request num[%u].",
     448              :                     __func__, devLogicId_, dieId, resType.Describe().c_str(), num);
     449            0 :                 DumpBlockResInfo(resType, resBlocks_[dieId][resType]);
     450            0 :                 return ret;
     451              :             }
     452              :         }
     453              :     }
     454          251 :     return HcclResult::HCCL_SUCCESS;
     455              : }
     456              : 
     457              : HcclResult
     458          251 : CcuResBatchAllocator::AllocConsecutiveRes(const CcuResReq& resReq, std::unique_ptr<CcuResRepository>& resRepoPtr) const
     459              : {
     460              :     using ResTypeReqNumResInfoTuple = std::tuple<ResType, uint32_t, std::vector<ResInfo>&>;
     461              : 
     462          251 :     CcuComponent& ccuComponent = CcuComponent::GetInstance(devLogicId_);
     463          753 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     464          502 :         if (!dieEnableFlags_[dieId]) {
     465            0 :             HCCL_WARNING(
     466              :                 "[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     467              :                 "will not allocate consecutive resource.",
     468              :                 __func__, devLogicId_, dieId);
     469            0 :             continue;
     470              :         }
     471              : 
     472              :         std::array<ResTypeReqNumResInfoTuple, CONS_RES_TYPE_NUM> reqParas
     473          502 :             = {std::make_tuple(ResType::XN, resReq.xnReq[dieId], std::ref(resRepoPtr->xn[dieId]))};
     474              : 
     475         1004 :         for (const auto& req : reqParas) {
     476          502 :             if (std::get<1>(req) == 0) {
     477          318 :                 continue;
     478              :             }
     479              : 
     480          184 :             std::vector<ResInfo> resInfos;
     481          184 :             auto ret = ccuComponent.AllocRes(dieId, std::get<0>(req), std::get<1>(req), true, resInfos);
     482          184 :             if (ret == HcclResult::HCCL_E_UNAVAIL) {
     483            0 :                 HCCL_WARNING(
     484              :                     "[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     485              :                     "failed to allocate %s resource, num[%u].",
     486              :                     __func__, devLogicId_, dieId, std::get<0>(req).Describe().c_str(), std::get<1>(req));
     487            0 :                 return ret;
     488              :             }
     489          184 :             CHK_RET(ret);
     490              : 
     491          184 :             std::get<2>(req) = resInfos;
     492          184 :         }
     493              :     }
     494              : 
     495          251 :     return HcclResult::HCCL_SUCCESS;
     496              : }
     497              : 
     498              : HcclResult
     499          251 : CcuResBatchAllocator::AllocDiscreteRes(const CcuResReq& resReq, std::unique_ptr<CcuResRepository>& resRepoPtr) const
     500              : {
     501              :     using ResTypeReqNumResInfoTuple = std::tuple<ResType, uint32_t, std::vector<ResInfo>&>;
     502              : 
     503          251 :     CcuComponent& ccuComponent = CcuComponent::GetInstance(devLogicId_);
     504          753 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     505          502 :         if (!dieEnableFlags_[dieId]) {
     506            0 :             HCCL_WARNING(
     507              :                 "[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     508              :                 "will not allocate discrete resource.",
     509              :                 __func__, devLogicId_, dieId);
     510            0 :             continue;
     511              :         }
     512              : 
     513              :         std::array<ResTypeReqNumResInfoTuple, DISCRETE_RES_TYPE_NUM> reqParas
     514          502 :             = {std::make_tuple(ResType::LOOP, resReq.loopEngineReq[dieId], std::ref(resRepoPtr->loopEngine[dieId])),
     515          502 :                std::make_tuple(ResType::MS, resReq.msReq[dieId], std::ref(resRepoPtr->ms[dieId])),
     516          502 :                std::make_tuple(ResType::CKE, resReq.ckeReq[dieId], std::ref(resRepoPtr->cke[dieId])),
     517         1506 :                std::make_tuple(ResType::GSA, resReq.gsaReq[dieId], std::ref(resRepoPtr->gsa[dieId]))};
     518              : 
     519         2510 :         for (const auto& req : reqParas) {
     520         2008 :             if (std::get<1>(req) == 0) {
     521         1670 :                 continue;
     522              :             }
     523              : 
     524          338 :             std::vector<ResInfo> resInfos;
     525          338 :             auto ret = ccuComponent.AllocRes(dieId, std::get<0>(req), std::get<1>(req), false, resInfos);
     526          338 :             if (ret == HcclResult::HCCL_E_UNAVAIL) {
     527            0 :                 HCCL_WARNING(
     528              :                     "[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     529              :                     "failed to allocate %s resource, num[%u].",
     530              :                     __func__, devLogicId_, dieId, std::get<0>(req).Describe().c_str(), std::get<1>(req));
     531            0 :                 return ret;
     532              :             }
     533          338 :             CHK_RET(ret);
     534              : 
     535          338 :             std::get<2>(req) = resInfos; // 2: resRepotPtr to resource
     536          338 :         }
     537              :     }
     538              : 
     539          251 :     return HcclResult::HCCL_SUCCESS;
     540              : }
     541              : 
     542          251 : HcclResult CcuResBatchAllocator::TryAllocResHandle(
     543              :     const uintptr_t handleKey, const CcuResReq& resReq, std::unique_ptr<CcuResRepository>& resRepoPtr)
     544              : {
     545          251 :     std::unique_lock<std::mutex> lock(innerMutex_);
     546              : 
     547          251 :     HcclResult ret = AllocBlockRes(handleKey, resReq, resRepoPtr);
     548          251 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
     549            0 :         HCCL_WARNING(
     550              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     551              :             "failed to allocate block type resource.",
     552              :             __func__, devLogicId_);
     553            0 :         return ret;
     554              :     }
     555          251 :     CHK_RET(ret);
     556              : 
     557          251 :     ret = missionMgr_.Alloc(handleKey, resReq.missionReq, resRepoPtr->mission);
     558          251 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
     559            0 :         HCCL_WARNING(
     560              :             "[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     561              :             "mission resource, remaining block resources are not enough.",
     562              :             __func__, devLogicId_);
     563            0 :         return ret;
     564              :     }
     565          251 :     CHK_RET(ret);
     566              : 
     567          251 :     ret = AllocConsecutiveRes(resReq, resRepoPtr);
     568          251 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
     569            0 :         HCCL_WARNING(
     570              :             "[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     571              :             "consecutive resource.",
     572              :             __func__, devLogicId_);
     573            0 :         return ret;
     574              :     }
     575          251 :     CHK_RET(ret);
     576              : 
     577          251 :     ret = AllocDiscreteRes(resReq, resRepoPtr);
     578          251 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
     579            0 :         HCCL_WARNING(
     580              :             "[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     581              :             "discrete resource.",
     582              :             __func__, devLogicId_);
     583            0 :         return ret;
     584              :     }
     585          251 :     CHK_RET(ret);
     586              : 
     587          251 :     return HcclResult::HCCL_SUCCESS;
     588          251 : }
     589              : 
     590          707 : static void ReleaseBlockRes(const uint32_t blockSize, std::vector<BlockInfo>& blocks, std::vector<ResInfo>& resInfos)
     591              : {
     592          707 :     uint32_t startId = resInfos[0].startId;
     593          707 :     uint32_t num = resInfos[0].num;
     594          707 :     uint32_t startBlockId = (startId - blocks[0].startId) / blockSize;
     595          707 :     uint32_t blockNum = num / blockSize;
     596              : 
     597        11427 :     for (uint32_t k = startBlockId; k < startBlockId + blockNum; k++) {
     598        10720 :         blocks[k].handle = 0;
     599        10720 :         blocks[k].allocated = false;
     600              :     }
     601          707 :     resInfos.clear();
     602          707 : }
     603              : 
     604           67 : HcclResult CcuResBatchAllocator::ReleaseResHandle(const CcuResHandle& handle)
     605              : {
     606           67 :     std::unique_lock<std::mutex> lock(innerMutex_);
     607              : 
     608           67 :     uintptr_t handleKey = reinterpret_cast<uintptr_t>(handle);
     609           67 :     if (handleMap_.find(handleKey) == handleMap_.end()) {
     610            0 :         HCCL_ERROR(
     611              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     612              :             "failed to find resource repository, invalid resource handle(uintptr_t)[%llu]",
     613              :             __func__, devLogicId_, static_cast<unsigned long long>(handleKey));
     614            0 :         return HcclResult::HCCL_E_PARA;
     615              :     }
     616              : 
     617           67 :     std::unique_ptr<CcuResRepository>& resRepoPtr = handleMap_[handleKey];
     618              : 
     619           67 :     auto ret = ReleaseResource(resRepoPtr);
     620           67 :     if (ret != HcclResult::HCCL_SUCCESS) {
     621            0 :         HCCL_ERROR(
     622              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     623              :             "failed[%u] to release resource.",
     624              :             __func__, devLogicId_, ret);
     625            0 :         return ret;
     626              :     }
     627              : 
     628           67 :     handleMap_.erase(handleKey);
     629           67 :     return HcclResult::HCCL_SUCCESS;
     630           67 : }
     631              : 
     632           67 : HcclResult CcuResBatchAllocator::ReleaseResource(std::unique_ptr<CcuResRepository>& resRepoPtr)
     633              : {
     634           67 :     ReleaseBlockResource(resRepoPtr);
     635           67 :     missionMgr_.Release(resRepoPtr->mission);
     636           67 :     HcclResult ret = ReleaseNonBlockTypeRes(resRepoPtr);
     637           67 :     if (ret != HcclResult::HCCL_SUCCESS) {
     638            0 :         HCCL_ERROR(
     639              :             "[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     640              :             "failed[%u] to release discrete resource.",
     641              :             __func__, devLogicId_, ret);
     642            0 :         return ret;
     643              :     }
     644              : 
     645           67 :     return HcclResult::HCCL_SUCCESS;
     646              : }
     647              : 
     648           67 : void CcuResBatchAllocator::ReleaseBlockResource(std::unique_ptr<CcuResRepository>& resRepoPtr)
     649              : {
     650              :     using BlockSizeResNum = std::tuple<ResType, uint32_t, std::vector<ResInfo>&>;
     651              : 
     652          201 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     653          134 :         if (!dieEnableFlags_[i]) {
     654            0 :             continue;
     655              :         }
     656              : 
     657              :         const std::array<BlockSizeResNum, BLOCK_RES_TYPE_NUM> blockReqParas
     658          134 :             = {std::make_tuple(ResType::LOOP, resStrategies_[i].loopNum, std::ref(resRepoPtr->blockLoopEngine[i])),
     659          134 :                std::make_tuple(ResType::MS, resStrategies_[i].msNum, std::ref(resRepoPtr->blockMs[i])),
     660          134 :                std::make_tuple(ResType::CKE, resStrategies_[i].ckeNum, std::ref(resRepoPtr->blockCke[i])),
     661          134 :                std::make_tuple(ResType::XN, resStrategies_[i].xnNum, std::ref(resRepoPtr->blockXn[i])),
     662          536 :                std::make_tuple(ResType::GSA, resStrategies_[i].gsaNum, std::ref(resRepoPtr->blockGsa[i]))};
     663              : 
     664          804 :         for (uint32_t j = 0; j < BLOCK_RES_TYPE_NUM; j++) {
     665          670 :             auto req = blockReqParas[j];
     666          670 :             std::vector<ResInfo>& resInfos = std::get<2>(req);
     667          670 :             auto resType = std::get<0>(req);
     668          670 :             std::vector<BlockInfo>& blocks = resBlocks_[i][resType];
     669          670 :             if (resInfos.size() == 0 || blocks.size() == 0) {
     670           30 :                 continue;
     671              :             }
     672          640 :             ReleaseBlockRes(std::get<1>(req), blocks, resInfos);
     673              :         }
     674              :     }
     675           67 : }
     676              : 
     677              : using ResTypeResInfo = std::pair<ResType, std::vector<ResInfo>*>;
     678            0 : static auto EraseReverse(std::vector<ResInfo>& vec, std::vector<ResInfo>::reverse_iterator it)
     679              :     -> std::vector<ResInfo>::reverse_iterator
     680              : {
     681            0 :     return std::vector<ResInfo>::reverse_iterator(vec.erase(std::next(it).base()));
     682              : }
     683              : 
     684              : static HcclResult
     685          134 : DoReleaseNonBlockTypeRes(int32_t devLogicId, uint8_t dieId, std::array<ResTypeResInfo, NON_BLOCK_TYPE_NUM>& infoParas)
     686              : {
     687          134 :     CcuComponent& ccuComponent = CcuComponent::GetInstance(devLogicId);
     688              : 
     689          804 :     for (auto& infos : infoParas) {
     690          670 :         const ResType resType = infos.first;
     691          670 :         std::vector<ResInfo>* resInfosPtr = infos.second;
     692          670 :         if (resInfosPtr == nullptr || resInfosPtr->empty()) {
     693          670 :             continue;
     694              :         }
     695            0 :         std::vector<ResInfo>& resInfos = *resInfosPtr;
     696              :         // 倒序删除,减少vector元素移动
     697            0 :         for (auto it = resInfos.rbegin(); it != resInfos.rend();) {
     698            0 :             const uint32_t num = it->num;
     699            0 :             if (num == 0) {
     700            0 :                 it = EraseReverse(resInfos, it);
     701            0 :                 continue;
     702              :             }
     703              : 
     704            0 :             const uint32_t startId = it->startId;
     705            0 :             auto ret = ccuComponent.ReleaseRes(dieId, resType, startId, num);
     706            0 :             if (ret != HcclResult::HCCL_SUCCESS) {
     707            0 :                 HCCL_ERROR(
     708              :                     "[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     709              :                     "failed to release %s resource, startId[%u], num[%u].",
     710              :                     __func__, devLogicId, dieId, resType.Describe().c_str(), startId, num);
     711            0 :                 return ret;
     712              :             }
     713              : 
     714            0 :             it = EraseReverse(resInfos, it);
     715              :         }
     716              :     }
     717          134 :     return HcclResult::HCCL_SUCCESS;
     718              : }
     719              : 
     720           67 : HcclResult CcuResBatchAllocator::ReleaseNonBlockTypeRes(std::unique_ptr<CcuResRepository>& resRepoPtr) const
     721              : {
     722          201 :     for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
     723          134 :         if (!dieEnableFlags_[dieId]) {
     724            0 :             continue;
     725              :         }
     726              : 
     727              :         std::array<ResTypeResInfo, NON_BLOCK_TYPE_NUM> infoParas
     728          134 :             = {{{ResType::LOOP, &resRepoPtr->loopEngine[dieId]},
     729          134 :                 {ResType::MS, &resRepoPtr->ms[dieId]},
     730          134 :                 {ResType::CKE, &resRepoPtr->cke[dieId]},
     731          134 :                 {ResType::XN, &resRepoPtr->xn[dieId]},
     732          536 :                 {ResType::GSA, &resRepoPtr->gsa[dieId]}}};
     733              : 
     734          134 :         CHK_RET(DoReleaseNonBlockTypeRes(devLogicId_, dieId, infoParas));
     735              :     }
     736              : 
     737           67 :     return HcclResult::HCCL_SUCCESS;
     738              : }
     739              : 
     740          398 : HcclResult CcuResBatchAllocator::GetResource(const CcuResHandle& handle, CcuResRepository& ccuResRepo)
     741              : {
     742          398 :     std::unique_lock<std::mutex> lock(innerMutex_);
     743              : 
     744          398 :     uintptr_t handleKey = reinterpret_cast<uintptr_t>(handle);
     745          398 :     if (handleMap_.find(handleKey) == handleMap_.end()) {
     746            0 :         HCCL_ERROR(
     747              :             "[CcuResBatchAllocator][%s] devLogicId[%d], failed to find "
     748              :             "resource repository, invalid resource handle(uintptr_t)[%lu]",
     749              :             __func__, devLogicId_, handleKey);
     750            0 :         return HcclResult::HCCL_E_PARA;
     751              :     }
     752              : 
     753          398 :     ccuResRepo = *(handleMap_[handleKey].get());
     754          398 :     return HcclResult::HCCL_SUCCESS;
     755          398 : }
     756              : 
     757           96 : static HcclResult PreAllocMissionRes(
     758              :     int32_t devLogicId, std::array<bool, CCU_MAX_IODIE_NUM>& dieEnableFlags,
     759              :     std::array<uint32_t, CCU_MAX_IODIE_NUM>& missionNums, std::array<uint32_t, CCU_MAX_IODIE_NUM>& missionStartIds)
     760              : {
     761           96 :     auto& ccuResSepcs = CcuResSpecifications::GetInstance(devLogicId);
     762           96 :     auto& ccuComponent = CcuComponent::GetInstance(devLogicId);
     763          288 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     764          192 :         if (!dieEnableFlags[i]) {
     765            0 :             missionNums[i] = 0;
     766            0 :             missionStartIds[i] = 0;
     767            0 :             continue;
     768              :         }
     769              : 
     770          192 :         (void)ccuResSepcs.GetMissionNum(i, missionNums[i]);
     771          192 :         std::vector<ResInfo> tempResInfos;
     772          192 :         auto ret = ccuComponent.AllocRes(i, ResType::MISSION, missionNums[i], true, tempResInfos);
     773          192 :         if (ret == HcclResult::HCCL_E_UNAVAIL) {
     774            0 :             HCCL_WARNING(
     775              :                 "[CcuMissionMgr][%s] devLogicId[%d] dieId[%u], failed[%u] "
     776              :                 "to pre allocate mission resource, num[%u]",
     777              :                 __func__, devLogicId, i, ret, missionNums[i]);
     778            0 :             return ret;
     779              :         }
     780          192 :         CHK_RET(ret);
     781              : 
     782          192 :         missionStartIds[i] = tempResInfos[0].startId;
     783          192 :     }
     784              : 
     785           96 :     return HcclResult::HCCL_SUCCESS;
     786              : }
     787              : 
     788           96 : HcclResult CcuResBatchAllocator::CcuMissionMgr::PreAlloc(
     789              :     const int32_t devLogicId, const uint32_t blockSize, const std::array<bool, CCU_MAX_IODIE_NUM>& dieFlags)
     790              : {
     791           96 :     dieEnableFlags_ = dieFlags;
     792              :     std::array<uint32_t, CCU_MAX_IODIE_NUM> missionNums;
     793              :     std::array<uint32_t, CCU_MAX_IODIE_NUM> missionStartIds;
     794              : 
     795           96 :     auto ret = PreAllocMissionRes(devLogicId, dieEnableFlags_, missionNums, missionStartIds);
     796           96 :     if (ret != HcclResult::HCCL_SUCCESS) {
     797            0 :         return ret;
     798              :     }
     799              : 
     800           96 :     uint32_t missionNum = 0;
     801           96 :     if (dieEnableFlags_[0]) {
     802           96 :         missionNum = missionNums[0];
     803            0 :     } else if (dieEnableFlags_[1]) {
     804            0 :         missionNum = missionNums[1];
     805              :     }
     806              : 
     807           96 :     if (dieEnableFlags_[0] && dieEnableFlags_[1] && missionStartIds[0] != missionStartIds[1]) {
     808              :         // 当前 FUSION_MULTIPLE_DIE 要求多Die ID一致
     809            0 :         HCCL_ERROR(
     810              :             "[CcuMissionMgr][%s] devLogicId[%d] die 0 allocated missions "
     811              :             "start with id %u, die 1 allocated missions start with id %u, the start "
     812              :             "id should be same.",
     813              :             __func__, devLogicId, missionStartIds[0], missionStartIds[1]);
     814            0 :         return HcclResult::HCCL_E_INTERNAL;
     815              :     }
     816              : 
     817           96 :     stragtegy_ = blockSize;
     818           96 :     uint32_t blockNum = missionNum / stragtegy_;
     819          864 :     for (uint32_t i = 0; i < blockNum; i++) {
     820          768 :         BlockInfo blockInfo;
     821          768 :         blockInfo.id = i;
     822          768 :         blockInfo.startId = missionStartIds[0] + i * stragtegy_;
     823          768 :         blockInfo.num = stragtegy_;
     824          768 :         blockInfo.allocated = false;
     825          768 :         blockInfo.handle = 0;
     826          768 :         blocks_.emplace_back(blockInfo);
     827              :     }
     828              : 
     829           96 :     return HcclResult::HCCL_SUCCESS;
     830              : }
     831              : 
     832              : static uint32_t
     833          253 : Check2DieMissionReqNum(const MissionReq& missionReq, const std::array<bool, CCU_MAX_IODIE_NUM>& dieEnableFlags)
     834              : {
     835          253 :     uint32_t die0ReqNum = missionReq.req[0];
     836          253 :     uint32_t die1ReqNum = missionReq.req[1];
     837              : 
     838          253 :     if (dieEnableFlags[0] && dieEnableFlags[1]) {
     839          251 :         if (die0ReqNum != die1ReqNum) {
     840            0 :             HCCL_WARNING(
     841              :                 "[CcuMissionMgr][Alloc] die 0 request %u, die 1 request %u, "
     842              :                 "will choose the larger one.",
     843              :                 die0ReqNum, die1ReqNum);
     844            0 :             return std::max(die0ReqNum, die1ReqNum);
     845              :         }
     846              : 
     847          251 :         return die0ReqNum;
     848              :     }
     849              : 
     850            2 :     if (dieEnableFlags[0]) {
     851            0 :         return die0ReqNum;
     852              :     }
     853              : 
     854            2 :     if (dieEnableFlags[1]) {
     855            0 :         return die1ReqNum;
     856              :     }
     857              : 
     858            2 :     return 0;
     859              : }
     860              : 
     861          253 : HcclResult CcuResBatchAllocator::CcuMissionMgr::Alloc(
     862              :     const uintptr_t handleKey, const MissionReq& missionReq, MissionResInfo& missionInfos)
     863              : {
     864          253 :     MissionReqType reqType = missionReq.reqType;
     865          253 :     constexpr MissionReqType defaultReqType = MissionReqType::FUSION_MULTIPLE_DIE;
     866          253 :     if (missionReq.reqType != MissionReqType::FUSION_MULTIPLE_DIE) {
     867            1 :         HCCL_WARNING(
     868              :             "[CcuMissionMgr][%s] mission reqType[%d], mission resources "
     869              :             "now only support %d.",
     870              :             __func__, reqType, defaultReqType);
     871            1 :         reqType = MissionReqType::FUSION_MULTIPLE_DIE;
     872              :     }
     873              : 
     874          253 :     uint32_t reqNum = Check2DieMissionReqNum(missionReq, dieEnableFlags_);
     875          253 :     if (reqNum == 0) {
     876          186 :         HCCL_INFO(
     877              :             "[CcuMissionMgr][%s] passed, request mission num is 0, "
     878              :             "will not allocate mission resource.",
     879              :             __func__);
     880          186 :         return HcclResult::HCCL_SUCCESS;
     881              :     }
     882              : 
     883           67 :     std::vector<ResInfo> resInfos;
     884           67 :     auto ret = HandleBlockRes(handleKey, reqNum, stragtegy_, blocks_, resInfos);
     885           67 :     if (ret == HcclResult::HCCL_E_UNAVAIL) {
     886            0 :         HCCL_WARNING(
     887              :             "[CcuMissionMgr][%s] failed, mission block resources are unavailable, "
     888              :             "reqNum[%u], stragtegy[%u], reqType[%d].",
     889              :             __func__, reqNum, stragtegy_, reqType);
     890            0 :         DumpBlockResInfo(ResType::MISSION, blocks_);
     891            0 :         return ret;
     892              :     }
     893           67 :     CHK_RET(ret);
     894              : 
     895           67 :     missionInfos.reqType = reqType;
     896              : 
     897          201 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     898          134 :         if (dieEnableFlags_[i]) {
     899          134 :             missionInfos.mission[i] = resInfos;
     900              :         }
     901              :     }
     902              : 
     903           67 :     return HcclResult::HCCL_SUCCESS;
     904           67 : }
     905              : 
     906           67 : void CcuResBatchAllocator::CcuMissionMgr::Release(MissionResInfo& missionInfos)
     907              : {
     908              :     // 目前支持 FUSION_MULTIPLE_DIE 类型,故多die同步释放
     909           67 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     910           67 :         if (dieEnableFlags_[i] && missionInfos.mission[i].size() != 0) {
     911           67 :             ReleaseBlockRes(stragtegy_, blocks_, missionInfos.mission[i]);
     912           67 :             break;
     913              :         }
     914              :     }
     915              : 
     916          201 :     for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
     917          134 :         missionInfos.mission[i].clear();
     918              :     }
     919           67 : }
     920              : 
     921          173 : void CcuResBatchAllocator::CcuMissionMgr::Reset() { blocks_.clear(); }
     922              : 
     923              : // 根据 resType 解析对应的 blocks 指针,将 MISSION 与普通块类型的分支收敛至此
     924              : // GetAllocatableMaxBlockResNum 内部通过 switch 校验块类型,非法类型直接返回错误
     925              : HcclResult
     926            7 : CcuResBatchAllocator::ResolveBlocksPtr(uint8_t dieId, ResType resType, const std::vector<BlockInfo>*& blocksPtr) const
     927              : {
     928            7 :     if (resType == ResType::MISSION) {
     929            1 :         blocksPtr = &missionMgr_.GetBlocks();
     930            1 :         return HCCL_SUCCESS;
     931              :     }
     932              : 
     933            6 :     uint32_t poolSize = 0;
     934            6 :     CHK_RET(GetAllocatableMaxBlockResNum(resType, dieId, poolSize));
     935            6 :     if (poolSize == 0) {
     936            0 :         blocksPtr = nullptr;
     937            0 :         return HCCL_SUCCESS;
     938              :     }
     939              : 
     940            6 :     auto it = resBlocks_[dieId].find(resType);
     941            6 :     if (it == resBlocks_[dieId].end()) {
     942            0 :         blocksPtr = nullptr;
     943            0 :         return HCCL_SUCCESS;
     944              :     }
     945            6 :     blocksPtr = &it->second;
     946            6 :     return HCCL_SUCCESS;
     947              : }
     948              : 
     949              : // 直接扫描 resBlocks 的 allocated 标志计算最大连续空闲块数 × blockSize
     950              : // Block 分配时 HandleBlockRes 同步更新 allocated, 无需绕道 handleMap
     951            7 : HcclResult CcuResBatchAllocator::QueryRemainRes(uint8_t dieId, ResType resType, uint32_t& remainNum) const
     952              : {
     953            7 :     const std::vector<BlockInfo>* blocksPtr = nullptr;
     954            7 :     uint32_t blockSize = 0;
     955              : 
     956            7 :     CHK_RET(ResolveBlocksPtr(dieId, resType, blocksPtr));
     957            7 :     if (blocksPtr == nullptr || blocksPtr->empty()) {
     958            0 :         remainNum = 0;
     959            0 :         return HCCL_SUCCESS;
     960              :     }
     961              : 
     962            7 :     blockSize = blocksPtr->front().num;
     963            7 :     uint32_t maxFreeBlocks = 0;
     964            7 :     uint32_t curFreeBlocks = 0;
     965           43 :     for (const auto& block : *blocksPtr) {
     966           36 :         if (!block.allocated) {
     967           21 :             curFreeBlocks++;
     968           21 :             continue;
     969              :         }
     970           15 :         maxFreeBlocks = curFreeBlocks > maxFreeBlocks ? curFreeBlocks : maxFreeBlocks;
     971           15 :         curFreeBlocks = 0;
     972              :     }
     973            7 :     if (curFreeBlocks > maxFreeBlocks) {
     974            3 :         maxFreeBlocks = curFreeBlocks;
     975              :     }
     976              : 
     977            7 :     remainNum = maxFreeBlocks * blockSize;
     978            7 :     HCCL_INFO(
     979              :         "[CcuResBatchAllocator][%s] resType[%s] maxFreeBlocks[%u] blockSize[%u] remainNum[%u]", __func__,
     980              :         resType.Describe().c_str(), maxFreeBlocks, blockSize, remainNum);
     981            7 :     return HCCL_SUCCESS;
     982              : }
     983              : 
     984              : }; // namespace hcomm
        

Generated by: LCOV version 2.0-1