LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_representation/reps/translator - ccu_rep_translator.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 84.2 % 202 170
Test Date: 2026-07-28 12:11:00 Functions: 87.0 % 23 20

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
       3              :  * Description: ccu rep translator implement file
       4              :  * Create: 2025-02-20
       5              :  */
       6              : 
       7              : #include "ccu_rep_translator_v1.h"
       8              : 
       9              : #include <algorithm>
      10              : 
      11              : #include "exception_util.h"
      12              : #include "ccu_api_exception.h"
      13              : #include "ccu_rep_loopcall_v1.h"
      14              : #include "ccu_rep_funccall_v1.h"
      15              : #include "ccu_rep_type_v1.h"
      16              : #include "ccu_rep_loop_v1.h"
      17              : #include "ccu_rep_loadarg_v1.h"
      18              : #include "ccu_assist_v1.h"
      19              : 
      20              : #include "ccu_dev_mgr_imp.h"
      21              : #include "dtype_common.h"
      22              : 
      23              : #include "ccu_ins_generater_base.h"
      24              : #include "ccu_ins_generater_v1.h"
      25              : #include "../../../ccu_device/ccu_res_specs.h"
      26              : 
      27              : #include "unified_platform/pub_inc/config_plf_log.h"
      28              : 
      29              : namespace hcomm {
      30              : namespace CcuRep {
      31              : 
      32              : using Hccl::PLF_TASK;
      33              : 
      34              : CcuVersion CcuRepTranslator::ccuVersion = CcuVersion::CCU_INVALID;
      35              : 
      36              : template <typename T> bool CheckType(const std::shared_ptr<CcuRepBlock> &refer)
      37              : {
      38              :     if (refer == nullptr) {
      39              :         HCCL_ERROR("input refer is nullptr");
      40              :         return false;
      41              :     }
      42              :     HCCL_INFO("[CheckType] refer->Type() = %d", refer->Type());
      43              :     return false;
      44              : }
      45              : 
      46            5 : template <> bool CheckType<CcuRepFuncBlock>(const std::shared_ptr<CcuRepBlock> &refer)
      47              : {
      48            5 :     if (refer == nullptr) {
      49            0 :         HCCL_ERROR("input refer is nullptr");
      50            0 :         return false;
      51              :     }
      52            5 :     return refer->Type() == CcuRepType::FUNC_BLOCK ? true : false;
      53              : }
      54              : 
      55            0 : template <> bool CheckType<CcuRepLoopBlock>(const std::shared_ptr<CcuRepBlock> &refer)
      56              : {
      57            0 :     if (refer == nullptr) {
      58            0 :         HCCL_ERROR("input refer is nullptr");
      59            0 :         return false;
      60              :     }
      61            0 :     return refer->Type() == CcuRepType::LOOP_BLOCK ? true : false;
      62              : }
      63              : 
      64            5 : template <typename T1, typename T2> void CcuRepTranslator::BuildReference(const std::shared_ptr<CcuRepBase> &rep)
      65              : {
      66            5 :     auto caller = std::static_pointer_cast<T1>(rep);
      67            5 :     auto label  = caller->GetLabel();
      68              :     // 特例:针对函数地址调用,不需要依靠函数名索引
      69            5 :     if (label == "") {
      70            0 :         return;
      71              :     }
      72            5 :     auto refer = refManager->GetRefBlock(label);
      73            5 :     if (CheckType<T2>(refer)) {
      74            5 :         caller->Reference(std::static_pointer_cast<T2>(refer));
      75              :     } else {
      76            0 :         Hccl::THROW<Hccl::CcuApiException>("Invalid Reference: %s", label.c_str());
      77              :     }
      78            5 : }
      79              : 
      80          864 : CcuRepTranslator::CcuRepTranslator(int32_t deviceLogicId, uint8_t dieId,
      81              :                                    std::shared_ptr<CcuRepReferenceManager> refManager,
      82              :                                    std::array<uint16_t, CCU_MAX_IODIE_NUM>& reserverChannalId,
      83          864 :                                    std::pair<uint64_t, uint64_t>& ccuTokenInfo, uint64_t hbmTokenInfo)
      84         8640 :     : refManager(refManager)
      85              : {
      86          864 :     transDep.logicalId = deviceLogicId;
      87          864 :     transDep.dieId     = dieId;
      88          864 :     s32 result = memcpy_s(transDep.reserveChannalId, sizeof(transDep.reserveChannalId), reserverChannalId.data(), sizeof(reserverChannalId));
      89          864 :     if (result != 0) {
      90            0 :         Hccl::THROW<Hccl::InternalException>(Hccl::StringFormat("[NsRecovery] CcuRepTranslator::CcuRepTranslator: memcpy_s failed, ret = %d", result));
      91              :     }
      92              :     // 获取xn起始地址
      93          864 :     HcclResult ret = CcuDevMgrImp::GetXnBaseAddr(deviceLogicId, dieId, transDep.xnBaseAddr[dieId]);
      94          864 :     if (ret != HcclResult::HCCL_SUCCESS) {
      95            0 :         Hccl::THROW<Hccl::CcuApiException>("Failed to get xn base address. deviceLogicId = %d, dieId = %u, ret = %d",
      96              :                                deviceLogicId, dieId, ret);
      97              :     }
      98          864 :     transDep.ccuResSpaceTokenInfo = CcuRep::GetToken(ccuTokenInfo.first, ccuTokenInfo.second, 1);
      99              :     // 获取hbm token信息
     100          864 :     transDep.memTokenInfo = hbmTokenInfo;
     101              : 
     102          864 :     ret = CcuDevMgrImp::GetCcuVersion(transDep.logicalId, ccuVersion);
     103          864 :     if (ret != HcclResult::HCCL_SUCCESS || ccuVersion == CcuVersion::CCU_INVALID) {
     104            0 :         Hccl::THROW<Hccl::CcuApiException>("[CcuRepTranslator] Constructor: Invalid CCU Type!");
     105              :     }
     106              :     
     107              :     // 单Udie环境下暂不获取另一个die的信息
     108              :     #ifdef OPEN_GET_ANOTHER_DIE_XN_ADDR
     109              :     if (ccuVersion == CcuVersion::CCU_V2) {
     110              :         uint8_t anotherDieId = dieId == 0 ? 1 : 0;
     111              :         ret = CcuDevMgrImp::GetXnBaseAddr(deviceLogicId, anotherDieId, transDep.xnBaseAddr[anotherDieId]);
     112              :         if (ret != HcclResult::HCCL_SUCCESS) {
     113              :             Hccl::THROW<Hccl::CcuApiException>("Failed to get xn base address. deviceLogicId = %d, dieId = %u, "
     114              :                 "ret = %d", deviceLogicId, anotherDieId, ret);
     115              :         }
     116              :     }
     117              :     #endif
     118          864 : }
     119              : 
     120            4 : CcuRepTranslator::CcuRepTranslator(std::shared_ptr<CcuRepReferenceManager> refManager, const TransDep &transDep)
     121           40 :     : refManager(refManager), transDep(transDep)
     122              : {
     123            4 :     HcclResult ret = CcuDevMgrImp::GetCcuVersion(transDep.logicalId, ccuVersion);
     124            4 :     if (ret != HcclResult::HCCL_SUCCESS || ccuVersion == CcuVersion::CCU_INVALID) {
     125            0 :         Hccl::THROW<Hccl::CcuApiException>("[CcuRepTranslator] Constructor: Invalid CCU Type!");
     126              :     }
     127            4 : }
     128              : 
     129           38 : uint32_t CcuRepTranslator::GetInstrNum()
     130              : {
     131           38 :     return ccuVersion == CcuVersion::CCU_V1 ?
     132              :                4  // 4:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令)
     133              :                :
     134           38 :                13;  // 13:翻译器翻译过程中额外需要的指令空间大小(插入3条通用操作指令+1条终止指令+9条repJump)
     135              : }
     136              : 
     137          864 : CcuResReq CcuRepTranslator::GetResReq(uint8_t dieId)
     138              : {
     139              :     // xn 资源统一从 continuousXn 池子申请,离散 xn 帐户已废弃
     140              :     // 需要申请若干xn、gsa、cke设置为固定值用于通用操作
     141          864 :     CcuResReq resReq;
     142          864 :     int varNum = XN_NUM;
     143          864 :     int gsaNum = ccuVersion == CcuVersion::CCU_V1 ? GSA_NUM : 0;
     144          864 :     resReq.continuousXnReq[dieId] = varNum;
     145          864 :     resReq.gsaReq[dieId] = gsaNum;
     146          864 :     resReq.ckeReq[dieId] = CKE_NUM;
     147          864 :     return resReq;
     148              : }
     149              : 
     150          864 : void CcuRepTranslator::GetRes(CcuRepResource &res)
     151              : {
     152          864 :     int varNum = XN_NUM;
     153          864 :     int gsaNum = ccuVersion == CcuVersion::CCU_V1 ? GSA_NUM : 0;
     154         4320 :     for (int i = 0; i < varNum; i++) {
     155         3456 :         res.continuousVariable[transDep.dieId].push_back(var[i]);
     156              :     }
     157         3264 :     for (int i = 0; i < gsaNum; i++) {
     158         2400 :         res.address[transDep.dieId].push_back(addr[i]);
     159              :     }
     160         2592 :     for (int i = 0; i < CKE_NUM; i++) {
     161         1728 :         res.localNotify[transDep.dieId].push_back(signal[i]);
     162              :     }
     163          864 : }
     164              : 
     165          434 : void CcuRepTranslator::PreProcess(std::shared_ptr<CcuRepBase> rep)
     166              : {
     167          434 :     auto repType = rep->Type();
     168          434 :     if (repType == CcuRepType::FUNC_BLOCK) {
     169            4 :         auto funcBlock = std::static_pointer_cast<CcuRepFuncBlock>(rep);
     170            4 :         refManager->SetRefBlock(funcBlock->GetLabel(), funcBlock);
     171            4 :         funcBlock->SetFuncManager(refManager.get());
     172          434 :     } else if (repType == CcuRepType::LOOP_BLOCK) {
     173           24 :         auto loopBlock = std::static_pointer_cast<CcuRepLoopBlock>(rep);
     174           24 :         refManager->SetRefBlock(loopBlock->GetLabel(), loopBlock);
     175          430 :     } else if (repType == CcuRepType::FUNC_CALL) {
     176            5 :         BuildReference<CcuRepFuncCall, CcuRepFuncBlock>(rep);
     177            5 :         auto funcCall = std::static_pointer_cast<CcuRepFuncCall>(rep);
     178            5 :         funcCall->SetFuncManager(refManager.get());
     179          406 :     } else if (repType == CcuRepType::LOOP_CALL) {
     180            0 :         BuildReference<CcuRepLoopCall, CcuRepLoopBlock>(rep);
     181          401 :     } else if (repType == CcuRepType::LOOP) {
     182            0 :         BuildReference<CcuRepLoop, CcuRepLoopBlock>(rep);
     183              :     }
     184          434 : }
     185              : 
     186           80 : void CcuRepTranslator::Translate(CcuKernel* ccuKernel, const std::vector<std::shared_ptr<CcuRepBase>> &repVec, CcuInstr *&instr,
     187              :                                  uint16_t &instrId, std::function<bool(std::shared_ptr<CcuRepBase>)> filter)
     188              : {
     189           80 :     constexpr uint32_t maxTryCount = 10; // 最大尝试次数10
     190           80 :     uint32_t           tryCount    = 0;
     191           80 :     uint32_t           restCount   = 0;
     192              : 
     193           80 :     auto funcInVar = refManager.get()->GetFuncIn();
     194           80 :     int funcArgIndex = 0;
     195              : 
     196              :     do {
     197           86 :         restCount = 0;
     198         1625 :         for (uint32_t index = 0; index < repVec.size(); index++) {
     199         1539 :             if (!filter(repVec[index])) {
     200          790 :                 continue;
     201              :             }
     202              : 
     203          749 :             if (repVec[index]->Translated()) {
     204          315 :                 continue;
     205              :             }
     206              : 
     207          434 :             if (repVec[index]->Type() == CcuRepType::LOAD_ARG && transDep.isFuncBlock) {
     208            0 :                 transDep.loadXnId = funcInVar[funcArgIndex++].Id();
     209              :             }
     210              : 
     211          434 :             PreProcess(repVec[index]);
     212          434 :             bool flag = repVec[index]->Translate(ccuKernel, instr, instrId, transDep);
     213          434 :             if (!flag) {
     214           20 :                 restCount++;
     215              :             }
     216              :         }
     217           86 :         tryCount++;
     218           86 :         HCCL_INFO("tryCount = %u, remaining representation = %u", tryCount, restCount);
     219           86 :     } while (restCount > 0 && tryCount < maxTryCount);
     220              : 
     221           80 :     if (tryCount == maxTryCount && restCount > 0) {
     222            0 :         HCCL_ERROR("After translation, remaining representation: tryCount = %u, restCount = %u ", tryCount, restCount);
     223            0 :         for (uint32_t index = 0; index < repVec.size(); index++) {
     224            0 :             if (!repVec[index]->Translated()) {
     225            0 :                 HCCL_ERROR("index[%u], %s", index, repVec[index]->Describe().c_str());
     226              :             }
     227              :         }
     228            0 :         Hccl::THROW<Hccl::CcuApiException>("Translation Failed");
     229              :     }
     230           80 : }
     231              : 
     232           19 : CcuInstrInfo CcuRepTranslator::Translate(CcuKernel* ccuKernel, const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
     233              :     uint16_t startInstrId, bool isFuncBlock)
     234              : {
     235           19 :     constexpr uint32_t defaultInstrCapacity = 32 * 1024; // 默认最大容量32 * 1024条
     236           19 :     CcuInstrInfo       instrInfo;
     237           19 :     instrInfo.instrVec.resize(defaultInstrCapacity);
     238           19 :     CcuInstr *instr      = instrInfo.instrVec.data();
     239           19 :     uint16_t  curInstrId = startInstrId;
     240              : 
     241           19 :     BindResource(isFuncBlock);
     242              : 
     243              :     // 翻译LoopBlock
     244           19 :     Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     245          409 :         return rep->Type() == CcuRepType::LOOP_BLOCK;
     246              :     });
     247              : 
     248              :     // 翻译funcBlock
     249           19 :     Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool {
     250          409 :         return rep->Type() == CcuRepType::FUNC_BLOCK;
     251              :     });
     252              : 
     253           19 :     uint16_t missionStartInstrId = curInstrId;
     254              : 
     255              :     // 翻译Load:按全局 argId 升序排序后再翻译,确保 LoadSqeArgs 指令在 mission 切分时
     256              :     // 落入与其 slot id 匹配的 mission(避免用户乱序 LoadArg 导致取参错位)
     257           19 :     std::vector<std::shared_ptr<CcuRepBase>> sortedLoadArgReps;
     258           19 :     sortedLoadArgReps.reserve(repVec.size());
     259          428 :     for (const auto &rep : repVec) {
     260          409 :         if (rep->Type() == CcuRepType::LOAD_ARG) {
     261           32 :             sortedLoadArgReps.push_back(rep);
     262              :         }
     263              :     }
     264           19 :     std::stable_sort(sortedLoadArgReps.begin(), sortedLoadArgReps.end(),
     265           77 :         [](const std::shared_ptr<CcuRepBase> &a, const std::shared_ptr<CcuRepBase> &b) {
     266          154 :             return std::static_pointer_cast<CcuRepLoadArg>(a)->GetFullArgId()
     267           77 :                  < std::static_pointer_cast<CcuRepLoadArg>(b)->GetFullArgId();
     268              :         });
     269           19 :     Translate(ccuKernel, sortedLoadArgReps, instr, curInstrId,
     270           32 :         [](std::shared_ptr<CcuRepBase> rep) -> bool { return rep->Type() == CcuRepType::LOAD_ARG; });
     271              : 
     272              :     // 插入通用操作
     273           19 :     CommonProcess(ccuKernel, instr, curInstrId);
     274              : 
     275              :     // 翻译主体
     276          703 :     Translate(ccuKernel, repVec, instr, curInstrId, [](std::shared_ptr<CcuRepBase> rep) -> bool { return true; });
     277              : 
     278           19 :     FinishMainBlock(instr, curInstrId);
     279              : 
     280           19 :     instrInfo.startInstrId        = startInstrId;
     281           19 :     instrInfo.instrCount          = curInstrId - startInstrId;
     282           19 :     instrInfo.missionStartInstrId = missionStartInstrId;
     283           19 :     instrInfo.missionInstrCount   = curInstrId - missionStartInstrId;
     284           19 :     instrInfo.instrVec.resize(instrInfo.instrCount);
     285              : 
     286           19 :     DumpRep(repVec, instrInfo);
     287           19 :     DumpInstruction(instrInfo);
     288              : 
     289           19 :     return instrInfo;
     290           19 : }
     291              : 
     292           19 : void CcuRepTranslator::CommonProcess(CcuKernel* ccuKernel, CcuInstr *&instr, uint16_t &instrId)
     293              : {
     294           19 :     LoadImdToXnInstr(instr++, var[0].Id(), 0);
     295           19 :     LoadImdToGSAInstr(instr++, addr[0].Id(), 0);
     296           19 :     SetCKEInstr(instr++, signal[0].Id(), 0xffff, 0, 0, 1);
     297              : 
     298              :     // 遍历需要赋值的常量,A5场景下暂为空表
     299           19 :     std::unordered_map<uint64_t, CcuRep::Variable>& constValue2VarMap = ccuKernel->GetConstValue2VarMap();
     300           19 :     u32 constValueNum = constValue2VarMap.size();
     301           19 :     for (auto elem : constValue2VarMap) {
     302            0 :         uint64_t constValue = elem.first;
     303            0 :         CcuRep::Variable curVariable = elem.second;
     304            0 :         LoadImdToXnInstr(instr++, curVariable.Id(), constValue);
     305            0 :     }
     306              :  
     307           19 :     u32 instrNum = 3 + constValueNum;
     308           19 :     if (instrId > UINT16_MAX - instrNum) {
     309            0 :         Hccl::THROW<Hccl::InternalException>("integer overflow occurs");
     310              :     }
     311           19 :     instrId += instrNum;  // 插入3条指令
     312           19 : }
     313              : 
     314           19 : void CcuRepTranslator::FinishMainBlock(CcuInstr *&instr, uint16_t &instrId)
     315              : {
     316           19 :     if (transDep.isFuncBlock) {
     317            0 :         JumpInstr(instr++, refManager.get()->GetFuncRet(FUNC_NEST_MAX).Id(), transDep.reserveXnId, 1);
     318              :     } else {
     319           19 :         LoadImdToXnInstr(instr++, var[0].Id(), 0);
     320              :     }
     321           19 :     instrId++;
     322              : 
     323           19 :     if (instrId > UINT16_MAX - 1) {
     324            0 :         Hccl::THROW<Hccl::InternalException>("integer overflow occurs");
     325              :     }
     326           19 : }
     327              : 
     328           19 : void CcuRepTranslator::DumpInstruction(const CcuInstrInfo &instrInfo) const
     329              : {
     330           19 :     HCCL_INFO("CcuInstrInfo: startInstrId = %u, instrCount = %u, missionStartInstrId = %u, missionInstrCount = %u",
     331              :               instrInfo.startInstrId, instrInfo.instrCount, instrInfo.missionStartInstrId, instrInfo.missionInstrCount);
     332          814 :     for (uint16_t index = 0; index < instrInfo.instrVec.size(); index++) {
     333          795 :         HCCL_INFO("%d: %s", instrInfo.startInstrId + index, ParseInstr(instrInfo.instrVec.data() + index).c_str());
     334              :     }
     335           19 : }
     336              : 
     337           19 : void CcuRepTranslator::DumpRep(const std::vector<std::shared_ptr<CcuRepBase>> &repVec,
     338              :                                const CcuInstrInfo                             &instrInfo) const
     339              : {
     340           19 :     PLF_CONFIG_INFO(PLF_TASK, "Translated Ccu Rep:");
     341          428 :     for (uint32_t index = 0; index < repVec.size(); index++) {
     342          409 :         uint16_t startInstrId = repVec[index]->StartInstrId();
     343          409 :         uint32_t sum = static_cast<uint32_t>(startInstrId) + repVec[index]->InstrCount();
     344          409 :         if (sum > UINT16_MAX) {
     345            0 :             HCCL_ERROR("instrId overflow: startInstrId[%u] + InstrCount[%u] = %u exceeds UINT16_MAX",
     346              :                        startInstrId, repVec[index]->InstrCount(), sum);
     347            0 :             continue;
     348              :         }
     349          409 :         uint16_t endInstrId = static_cast<uint16_t>(sum);
     350          409 :         PLF_CONFIG_INFO(PLF_TASK, "rep[%u]: %s Instr[%u--%u]", index, repVec[index]->Describe().c_str(), startInstrId, endInstrId);
     351         1134 :         for (uint16_t instrId = startInstrId; instrId < endInstrId; instrId++) {
     352          725 :             if (instrId < instrInfo.startInstrId) {
     353            0 :                 HCCL_ERROR("instrId[%u] less than startInstrId[%u]", instrId, instrInfo.startInstrId);
     354            0 :                 continue;
     355              :             }
     356          725 :             PLF_CONFIG_INFO(PLF_TASK, "microcode[%u]: %s", instrId,
     357              :                 ParseInstr(instrInfo.instrVec.data() + (instrId - instrInfo.startInstrId)).c_str());
     358              :         }
     359              :     }
     360           19 : }
     361              : 
     362           19 : void CcuRepTranslator::BindResource(bool isFuncBlock)
     363              : {
     364           19 :     transDep.reserveXnId  = var[0].Id();
     365           19 :     transDep.reserveGsaId = addr[0].Id();
     366           19 :     transDep.reserveCkeId = signal[0].Id();
     367           76 :     for (int i = 0; i < XN_NUM - 1; i++) {
     368           57 :         transDep.commXn[i] = var[i + 1].Id();
     369              :     }
     370           57 :     for (int i = 0; i < GSA_NUM - 1; i++) {
     371           38 :         transDep.commGsa[i] = addr[i + 1].Id();
     372              :     }
     373           19 :     transDep.commSignal = signal[1].Id();
     374           19 :     transDep.isFuncBlock = isFuncBlock;
     375           19 :     HCCL_INFO("TransDep info: logicalId = %d, dieId = %u, reserveXnId = %u, reserveGsaId = %u, reserveCkeId = %u, "
     376              :               "innerDieChannelId = %u, interDieChannelId = %u",
     377              :               transDep.logicalId, transDep.dieId, transDep.reserveXnId, transDep.reserveGsaId, transDep.reserveCkeId,
     378              :               transDep.reserveChannalId[0], transDep.reserveChannalId[1]);
     379           19 : }
     380              : }; // namespace CcuRep
     381              : }; // namespace hcomm
        

Generated by: LCOV version 2.0-1