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

Generated by: LCOV version 2.0-1