LCOV - code coverage report
Current view: top level - legacy/ascend950/unified_platform/ccu/ccu_representation/reps/translator - ccu_rep_translator.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.7 % 164 152
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 22 22

            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_rep_translator.h"
      12              : #include "exception_util.h"
      13              : #include "ccu_api_exception.h"
      14              : #include "ccu_rep_loopcall.h"
      15              : #include "ccu_rep_funccall.h"
      16              : #include "ccu_rep_type.h"
      17              : #include "ccu_rep_loop.h"
      18              : #include "ccu_assist.h"
      19              : 
      20              : namespace Hccl {
      21              : namespace CcuRep {
      22              : 
      23              : template <typename T> bool CheckType(const std::shared_ptr<CcuRepBlock> &refer)
      24              : {
      25              :     HCCL_INFO("[CheckType] refer->Type() = %d", refer->Type());
      26              :     return false;
      27              : }
      28              : 
      29            2 : template <> bool CheckType<CcuRepFuncBlock>(const std::shared_ptr<CcuRepBlock> &refer)
      30              : {
      31            2 :     return refer->Type() == CcuRepType::FUNC_BLOCK ? true : false;
      32              : }
      33              : 
      34           21 : template <> bool CheckType<CcuRepLoopBlock>(const std::shared_ptr<CcuRepBlock> &refer)
      35              : {
      36           21 :     return refer->Type() == CcuRepType::LOOP_BLOCK ? true : false;
      37              : }
      38              : 
      39           26 : template <typename T1, typename T2> void CcuRepTranslator::BuildReference(const std::shared_ptr<CcuRepBase> &rep)
      40              : {
      41           26 :     auto caller = std::static_pointer_cast<T1>(rep);
      42           26 :     auto label  = caller->GetLabel();
      43              :     // 特例:针对函数地址调用,不需要依靠函数名索引
      44           26 :     if (label == "") {
      45            2 :         return;
      46              :     }
      47           24 :     auto refer = refManager->GetRefBlock(label);
      48           23 :     if (CheckType<T2>(refer)) {
      49           23 :         caller->Reference(std::static_pointer_cast<T2>(refer));
      50              :     } else {
      51            0 :         THROW<CcuApiException>("Invalid Reference: %s", label.c_str());
      52              :     }
      53           29 : }
      54              : 
      55           64 : CcuRepTranslator::CcuRepTranslator(int32_t deviceLogicId, uint8_t dieId,
      56              :                                    std::shared_ptr<CcuRepReferenceManager> refManager,
      57              :                                    std::array<uint16_t, MAX_CCU_IODIE_NUM>& reserverChannalId,
      58           64 :                                    std::pair<uint64_t, uint64_t>& ccuTokenInfo, uint64_t hbmTokenInfo)
      59          640 :     : refManager(refManager)
      60              : {
      61           64 :     transDep.logicalId = deviceLogicId;
      62           64 :     transDep.dieId     = dieId;
      63           64 :     s32 result = memcpy_s(transDep.reserveChannalId, sizeof(transDep.reserveChannalId), reserverChannalId.data(), sizeof(reserverChannalId));
      64           64 :     if (result != 0) {
      65            0 :         THROW<InternalException>(StringFormat("[NsRecovery] CcuRepTranslator::CcuRepTranslator: memcpy_s failed, ret = %d", result));
      66              :     }
      67              :     // 获取xn起始地址
      68           64 :     HcclResult ret = CcuDeviceManager::GetXnBaseAddr(deviceLogicId, dieId, transDep.xnBaseAddr);
      69           64 :     if (ret != HcclResult::HCCL_SUCCESS) {
      70            0 :         THROW<CcuApiException>("Failed to get xn base address. deviceLogicId = %d, dieId = %u, ret = %d",
      71              :                                deviceLogicId, dieId, ret);
      72              :     }
      73           64 :     transDep.ccuResSpaceTokenInfo = CcuRep::GetToken(ccuTokenInfo.first, ccuTokenInfo.second, 1);
      74              :     // 获取hbm token信息
      75           64 :     transDep.memTokenInfo = hbmTokenInfo;
      76           64 : }
      77              : 
      78            2 : CcuRepTranslator::CcuRepTranslator(std::shared_ptr<CcuRepReferenceManager> refManager, const TransDep &transDep)
      79           20 :     : refManager(refManager), transDep(transDep)
      80              : {
      81            2 : }
      82              : 
      83           10 : uint32_t CcuRepTranslator::GetInstrNum()
      84              : {
      85           10 :     return 4; // 4:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令)
      86              : }
      87              : 
      88           49 : CcuResReq CcuRepTranslator::GetResReq(uint8_t dieId)
      89              : {
      90              :     // 需要申请若干xn、gsa、cke设置为固定值用于通用操作
      91           49 :     CcuResReq resReq;
      92           49 :     resReq.xnReq[dieId]  = XN_NUM; // 4个Xn资源
      93           49 :     resReq.gsaReq[dieId] = GSA_NUM; // 3个GSA资源
      94           49 :     resReq.ckeReq[dieId] = CKE_NUM; // 2个CKE资源
      95           49 :     return resReq;
      96              : }
      97              : 
      98           53 : void CcuRepTranslator::GetRes(CcuRepResource &res)
      99              : {
     100          265 :     for (int i = 0; i < XN_NUM; i++) {
     101          212 :         res.variable[transDep.dieId].push_back(var[i]);
     102              :     }
     103          212 :     for (int i = 0; i < GSA_NUM; i++) {
     104          159 :         res.address[transDep.dieId].push_back(addr[i]);
     105              :     }
     106          159 :     for (int i = 0; i < CKE_NUM; i++) {
     107          106 :         res.maskSignal[transDep.dieId].push_back(signal[i]);
     108              :     }
     109           53 : }
     110              : 
     111          664 : void CcuRepTranslator::PreProcess(std::shared_ptr<CcuRepBase> rep)
     112              : {
     113          664 :     auto repType = rep->Type();
     114          664 :     if (repType == CcuRepType::FUNC_BLOCK) {
     115            2 :         auto funcBlock = std::static_pointer_cast<CcuRepFuncBlock>(rep);
     116            2 :         refManager->SetRefBlock(funcBlock->GetLabel(), funcBlock);
     117            2 :         funcBlock->SetFuncManager(refManager.get());
     118          664 :     } else if (repType == CcuRepType::LOOP_BLOCK) {
     119           11 :         auto loopBlock = std::static_pointer_cast<CcuRepLoopBlock>(rep);
     120           12 :         refManager->SetRefBlock(loopBlock->GetLabel(), loopBlock);
     121          662 :     } else if (repType == CcuRepType::FUNC_CALL) {
     122            4 :         BuildReference<CcuRepFuncCall, CcuRepFuncBlock>(rep);
     123            4 :         auto funcCall = std::static_pointer_cast<CcuRepFuncCall>(rep);
     124            4 :         funcCall->SetFuncManager(refManager.get());
     125          651 :     } else if (repType == CcuRepType::LOOP_CALL) {
     126           13 :         BuildReference<CcuRepLoopCall, CcuRepLoopBlock>(rep);
     127          634 :     } else if (repType == CcuRepType::LOOP) {
     128            9 :         BuildReference<CcuRepLoop, CcuRepLoopBlock>(rep);
     129              :     }
     130          662 : }
     131              : 
     132           91 : void CcuRepTranslator::Translate(const std::vector<std::shared_ptr<CcuRepBase>> &repVec, CcuInstr *&instr,
     133              :                                  uint16_t &instrId, std::function<bool(std::shared_ptr<CcuRepBase>)> filter)
     134              : {
     135           91 :     constexpr uint32_t maxTryCount = 10; // 最大尝试次数10
     136           91 :     uint32_t           tryCount    = 0;
     137           91 :     uint32_t           restCount   = 0;
     138              : 
     139           91 :     auto funcInVar = refManager.get()->GetFuncIn();
     140           91 :     int funcArgIndex = 0;
     141              : 
     142              :     do {
     143          101 :         restCount = 0;
     144         3143 :         for (uint32_t index = 0; index < repVec.size(); index++) {
     145         3044 :             if (!filter(repVec[index])) {
     146         1737 :                 continue;
     147              :             }
     148              : 
     149         1307 :             if (repVec[index]->Translated()) {
     150          643 :                 continue;
     151              :             }
     152              : 
     153          664 :             if (repVec[index]->Type() == CcuRepType::LOAD_ARG && transDep.isFuncBlock) {
     154            0 :                 transDep.loadXnId = funcInVar[funcArgIndex++].Id();
     155              :             }
     156              : 
     157          666 :             PreProcess(repVec[index]);
     158          662 :             bool flag = repVec[index]->Translate(instr, instrId, transDep);
     159          662 :             if (!flag) {
     160           36 :                 restCount++;
     161              :             }
     162         1986 :             HCCL_DEBUG("index[%u], Try to translate: %s", index, flag ? "OK" : "Skip");
     163              :         }
     164           99 :         tryCount++;
     165          297 :         HCCL_INFO("tryCount = %u, remaining representation = %u", tryCount, restCount);
     166           99 :     } while (restCount > 0 && tryCount < maxTryCount);
     167              : 
     168           89 :     if (tryCount == maxTryCount && restCount > 0) {
     169            0 :         HCCL_ERROR("After translation, remaining representation: tryCount = %u, restCount = %u ", tryCount, restCount);
     170            0 :         for (uint32_t index = 0; index < repVec.size(); index++) {
     171            0 :             if (!repVec[index]->Translated()) {
     172            0 :                 HCCL_ERROR("index[%u], %s", index, repVec[index]->Describe().c_str());
     173              :             }
     174              :         }
     175            0 :         THROW<CcuApiException>("Translation Failed");
     176              :     }
     177           91 : }
     178              : 
     179           23 : CcuInstrInfo CcuRepTranslator::Translate(const std::vector<std::shared_ptr<CcuRepBase>> &repVec, uint16_t startInstrId, bool isFuncBlock)
     180              : {
     181           23 :     constexpr uint32_t defaultInstrCapacity = 32 * 1024; // 默认最大容量32 * 1024条
     182           23 :     CcuInstrInfo       instrInfo;
     183           23 :     instrInfo.instrVec.resize(defaultInstrCapacity);
     184           23 :     CcuInstr *instr      = instrInfo.instrVec.data();
     185           23 :     uint16_t  curInstrId = startInstrId;
     186              : 
     187           23 :     BindResource(isFuncBlock);
     188              : 
     189              :     // 翻译LoopBlock
     190           24 :     Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     191          615 :         return rep->Type() == CcuRepType::LOOP_BLOCK;
     192              :     });
     193              : 
     194              :     // 翻译funcBlock
     195           22 :     Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     196          612 :         return rep->Type() == CcuRepType::FUNC_BLOCK;
     197              :     });
     198              : 
     199           22 :     uint16_t missionStartInstrId = curInstrId;
     200              : 
     201              :     // 翻译Load
     202           22 :     Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     203          612 :         return rep->Type() == CcuRepType::LOAD_ARG;
     204              :     });
     205              : 
     206              :     // 插入通用操作
     207           22 :     CommonProcess(instr, curInstrId);
     208              : 
     209              :     // 翻译主体
     210           23 :     Translate(repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     211         1177 :         return true;
     212              :     });
     213              : 
     214           21 :     FinishMainBlock(instr, curInstrId);
     215              : 
     216           21 :     instrInfo.startInstrId        = startInstrId;
     217           21 :     instrInfo.instrCount          = curInstrId - startInstrId;
     218           21 :     instrInfo.missionStartInstrId = missionStartInstrId;
     219           21 :     instrInfo.missionInstrCount   = curInstrId - missionStartInstrId;
     220           21 :     instrInfo.instrVec.resize(instrInfo.instrCount);
     221              : 
     222           21 :     DumpInstruction(instrInfo);
     223           21 :     DumpRep(repVec, instrInfo);
     224              : 
     225           21 :     return instrInfo;
     226            2 : }
     227              : 
     228           22 : void CcuRepTranslator::CommonProcess(CcuInstr *&instr, uint16_t &instrId)
     229              : {
     230           22 :     LoadImdToXnInstr(instr++, var[0].Id(), 0);
     231           22 :     LoadImdToGSAInstr(instr++, addr[0].Id(), 0);
     232           22 :     SetCKEInstr(instr++, signal[0].Id(), 0xffff, 0, 0, 1);
     233           22 :     u32 instrNum = 3;
     234           22 :     if (instrId > UINT16_MAX - instrNum) {
     235            0 :         THROW<InternalException>("integer overflow occurs");
     236              :     }
     237           22 :     instrId += instrNum;  // 插入3条指令
     238           22 : }
     239              : 
     240           21 : void CcuRepTranslator::FinishMainBlock(CcuInstr *&instr, uint16_t &instrId)
     241              : {
     242           21 :     if (transDep.isFuncBlock) {
     243            0 :         JumpInstr(instr++, refManager.get()->GetFuncRet(FUNC_NEST_MAX).Id(), transDep.reserveXnId, 1);
     244              :     } else {
     245           21 :         LoadImdToXnInstr(instr++, var[0].Id(), 0);
     246              :     }
     247           21 :     if (instrId > UINT16_MAX - 1) {
     248            0 :         THROW<InternalException>("integer overflow occurs");
     249              :     }
     250           21 :     instrId++;
     251           21 : }
     252              : 
     253           21 : void CcuRepTranslator::DumpInstruction(const CcuInstrInfo &instrInfo) const
     254              : {
     255           63 :     HCCL_INFO("CcuInstrInfo: startInstrId = %u, instrCount = %u, missionStartInstrId = %u, missionInstrCount = %u",
     256              :               instrInfo.startInstrId, instrInfo.instrCount, instrInfo.missionStartInstrId, instrInfo.missionInstrCount);
     257         1066 :     for (uint16_t index = 0; index < instrInfo.instrVec.size(); index++) {
     258         3135 :         HCCL_INFO("%d: %s", instrInfo.startInstrId + index, ParseInstr(instrInfo.instrVec.data() + index).c_str());
     259              :     }
     260           21 : }
     261              : 
     262           21 : void CcuRepTranslator::DumpRep(const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
     263              :                                const CcuInstrInfo                             &instrInfo) const
     264              : {
     265           63 :     HCCL_INFO("Translated Ccu Rep:");
     266          631 :     for (uint32_t index = 0; index < repVec.size(); index++) {
     267         1830 :         HCCL_INFO("rep[%u]: %s", index, repVec[index]->Describe().c_str());
     268          610 :         uint16_t startInstrId = repVec[index]->StartInstrId();
     269          610 :         uint16_t endInstrId   = startInstrId + repVec[index]->InstrCount();
     270         1571 :         for (uint16_t instrId = startInstrId; instrId < endInstrId; instrId++) {
     271         2883 :             HCCL_INFO("microcode[%u]: %s", instrId,
     272              :                       ParseInstr(instrInfo.instrVec.data() + (instrId - instrInfo.startInstrId)).c_str());
     273              :         }
     274              :     }
     275           21 : }
     276              : 
     277           23 : void CcuRepTranslator::BindResource(bool isFuncBlock)
     278              : {
     279           23 :     transDep.reserveXnId  = var[0].Id();
     280           23 :     transDep.reserveGsaId = addr[0].Id();
     281           23 :     transDep.reserveCkeId = signal[0].Id();
     282           92 :     for (int i = 0; i < XN_NUM - 1; i++) {
     283           69 :         transDep.commXn[i] = var[i + 1].Id();
     284              :     }
     285           69 :     for (int i = 0; i < GSA_NUM - 1; i++) {
     286           46 :         transDep.commGsa[i] = addr[i + 1].Id();
     287              :     }
     288           23 :     transDep.commSignal = signal[1].Id();
     289           23 :     transDep.isFuncBlock = isFuncBlock;
     290           69 :     HCCL_INFO("TransDep info: logicalId = %d, dieId = %u, reserveXnId = %u, reserveGsaId = %u, reserveCkeId = %u, "
     291              :               "innerDieChannelId = %u, interDieChannelId = %u",
     292              :               transDep.logicalId, transDep.dieId, transDep.reserveXnId, transDep.reserveGsaId, transDep.reserveCkeId,
     293              :               transDep.reserveChannalId[0], transDep.reserveChannalId[1]);
     294           23 : }
     295              : }; // namespace CcuRep
     296              : }; // namespace Hccl
        

Generated by: LCOV version 2.0-1