LCOV - code coverage report
Current view: top level - adump/operator/operator_preliminary - operator_preliminary.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 96.2 % 156 150
Test Date: 2026-07-28 10:54:24 Functions: 100.0 % 11 11

            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              : #include "operator_preliminary.h"
      11              : 
      12              : #include <cinttypes>
      13              : #include <fstream>
      14              : #include <algorithm>
      15              : #include "lib_path.h"
      16              : #include "file_utils.h"
      17              : #include "log/adx_log.h"
      18              : #include "adump_platform_api.h"
      19              : #include "adump_platform_manager.h"
      20              : #include "runtime/kernel.h"
      21              : #include "runtime/mem.h"
      22              : #include "runtime/dev.h"
      23              : 
      24              : namespace Adx {
      25              : constexpr uint32_t SINGLE_STATS_BYTE = 8;   // 单个统计项的占用大小
      26              : constexpr uint32_t BLOCK_MIN_SIZE = 32;     // 最小搬运单元
      27              : constexpr uint32_t DCCI_SYNC_SIZE = 64;     // DCCI强制同步数据64B
      28              : constexpr uint32_t MAX_STATS_NUM = 64;      // 最大统计项个数
      29              : constexpr uint32_t INTEGER_KILOBYTE = 1024; // 表示1KB
      30              : 
      31              : constexpr const char *const KFC_OPERATOR_STUB_NAME = "kfc_dump_stat_stub";
      32              : constexpr const char *const KFC_OPERATOR_NAME = "kfc_dump_stat";
      33              : 
      34              : static const std::vector<PlatformType> AICORE_RELATED = {PlatformType::CHIP_DC_TYPE};
      35              : 
      36           21 : OperatorPreliminary::OperatorPreliminary(const DumpSetting &setting, const uint32_t deviceId)
      37           21 :     : deviceId_(deviceId), setting_(setting), opData_({})
      38              : {
      39           21 : }
      40              : 
      41           21 : OperatorPreliminary::~OperatorPreliminary()
      42              : {
      43           21 : }
      44              : 
      45            3 : uint64_t OperatorPreliminary::CalcWorkspaceSize(uint64_t statsCnt)
      46              : {
      47            3 :     PlatformType platform = setting_.GetPlatformType();
      48            3 :     uint32_t coreSize = opData_.vectCoreCnt;
      49            3 :     auto coreIter = std::find(AICORE_RELATED.begin(), AICORE_RELATED.end(), platform);
      50            3 :     if (coreIter != AICORE_RELATED.cend()) {
      51            0 :         return DCCI_SYNC_SIZE * opData_.aiCoreCnt * statsCnt;
      52              :     }
      53            3 :     return BLOCK_MIN_SIZE * (coreSize + 1) * statsCnt; // + 1 用于当做同步空间
      54              : }
      55              : 
      56            3 : std::string OperatorPreliminary::GetBinName() const
      57              : {
      58            3 :     auto plat = PlatformReflection<DataDumpInterface>::CreatePlatform(setting_.GetPlatformType());
      59            3 :     if (plat == nullptr) {
      60            0 :         return "UNKNOW_FILENAME";
      61              :     }
      62            3 :     std::string name = plat->GetKfcBinName();
      63            3 :     return name.empty() ? "UNKNOW_FILENAME" : name;
      64            3 : }
      65              : 
      66            6 : int32_t OperatorPreliminary::GetStreamInfo()
      67              : {
      68            6 :     IDE_LOGI("Start GetStreamInfo on device %u.", deviceId_);
      69            6 :     rtError_t ret = rtSetDevice(deviceId_);
      70            6 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
      71              :         "Execute rtSetDevice on device %u failed with result %d", deviceId_, ret);
      72            6 :     opData_.setDevice = true;
      73              : 
      74            6 :     ret = rtStreamCreateWithFlags(&opData_.deviceStm, 0, RT_STREAM_CP_PROCESS_USE);
      75            6 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
      76              :         "Execute rtStreamCreateWithFlags on device %u failed with result %d", deviceId_, ret);
      77              : 
      78            6 :     ret = rtGetStreamId(opData_.deviceStm, &opData_.streamId);
      79            6 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
      80              :         "Execute rtGetStreamId on device %u failed with result %d", deviceId_, ret);
      81              : 
      82            6 :     ret = rtStreamGetSqid(opData_.deviceStm, &opData_.sqId);
      83            6 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
      84              :         "Execute rtStreamGetSqid on device %u failed with result %d", deviceId_, ret);
      85              : 
      86            6 :     ret = rtStreamGetCqid(opData_.deviceStm, &opData_.cqIds, &opData_.logicCqIds);
      87            6 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
      88              :         "Execute rtStreamGetCqid on device %u failed with result %d", deviceId_, ret);
      89              : 
      90            6 :     IDE_LOGI("Success to get stream id=%d, sqId=%u, cqId=%u, logic cqId=%u on device %u.", opData_.streamId,
      91              :         opData_.sqId, opData_.cqIds, opData_.logicCqIds, deviceId_);
      92            6 :     return ADUMP_SUCCESS;
      93              : }
      94              : 
      95            6 : int32_t OperatorPreliminary::GetUBSizeAndCoreNum()
      96              : {
      97            6 :     char version[SOC_VERSION_LEN] = {};
      98            6 :     IDE_CTRL_VALUE_FAILED(rtGetSocVersion(version, SOC_VERSION_LEN) == RT_ERROR_NONE, return ADUMP_FAILED,
      99              :         "Failed to get soc version");
     100            6 :     const std::string socVersion(version);
     101              : 
     102              :     PlatformData platformData;
     103            6 :     IDE_CTRL_VALUE_FAILED(AdumpPlatformApi::GetUBSizeAndCoreNum(socVersion, setting_.GetPlatformType(), platformData),
     104              :         return ADUMP_FAILED, "Failed to read platform info from fe api.");
     105              : 
     106            3 :     opData_.ubSize = platformData.ubSize;
     107            3 :     opData_.aiCoreCnt = platformData.aiCoreCnt;
     108            3 :     opData_.vectCoreCnt = platformData.vectCoreCnt;
     109            3 :     IDE_LOGI("Get ub size:%" PRIu64 ", ai core count:%" PRIu64 ", vector core count:%" PRIu64 " on device %u.",
     110              :         opData_.ubSize, opData_.aiCoreCnt, opData_.vectCoreCnt, deviceId_);
     111            3 :     return ADUMP_SUCCESS;
     112            6 : }
     113              : 
     114            3 : std::unique_ptr<char[]> OperatorPreliminary::LoadBinFile(const std::string &filename, size_t &fileSize) const
     115              : {
     116            3 :     std::string realPath;
     117            3 :     IDE_CTRL_VALUE_FAILED(FileUtils::FileNameIsReal(filename, realPath) == IDE_DAEMON_OK, return nullptr,
     118              :         "LoadBinFile failed. The real path is %s.", filename.c_str());
     119              : 
     120            3 :     std::ifstream iFile(realPath, std::ios::binary | std::ios::ate);
     121            3 :     IDE_CTRL_VALUE_FAILED(iFile.is_open(), return nullptr, "Failed to open file: %s", realPath.c_str());
     122              : 
     123            3 :     auto pos = iFile.tellg();
     124            3 :     if (pos <= 0) {
     125            0 :         IDE_LOGE("Failed to get file size. file: %s, size: %ld", realPath.c_str(), pos);
     126            0 :         return nullptr;
     127              :     }
     128            3 :     fileSize = static_cast<size_t>(pos);
     129            3 :     iFile.seekg(0, std::ios::beg);
     130            3 :     char* buffer = new(std::nothrow) char[fileSize];
     131            3 :     IDE_CTRL_VALUE_FAILED(buffer != nullptr, return nullptr, "Failed to new file buffer");
     132            3 :     IDE_CTRL_VALUE_FAILED(iFile.read(buffer, fileSize), {delete[] buffer; return nullptr;},
     133              :         "Failed to read file data. file: %s, size: %ld", filename.c_str(), fileSize);
     134            3 :     return std::unique_ptr<char []>(buffer);
     135            3 : }
     136              : 
     137            3 : int32_t OperatorPreliminary::GetOperatorPCAddr()
     138              : {
     139            3 :     static std::unique_ptr<char[]> binData = nullptr;
     140            3 :     rtError_t ret = RT_ERROR_NONE;
     141              : 
     142            3 :     if (binData == nullptr) {
     143            3 :         std::string opName = GetBinName();
     144            3 :         IDE_CTRL_VALUE_FAILED(!opName.empty(), return ADUMP_FAILED, "Failed to find kfc operator file.");
     145              : 
     146            3 :         const std::string opPath = LibPath::Instance().GetTargetPath(opName);
     147            3 :         IDE_CTRL_VALUE_FAILED(!opPath.empty(), return ADUMP_FAILED, "Received an empty path for file %s.", opName.c_str());
     148            3 :         IDE_CTRL_VALUE_FAILED(FileUtils::IsFileExist(opPath), return ADUMP_FAILED,
     149              :             "Failed to binary file from %s.", opPath.c_str());
     150              : 
     151            3 :         size_t fileSize = 0;
     152            3 :         binData = LoadBinFile(opPath, fileSize);
     153            3 :         IDE_CTRL_VALUE_FAILED(binData != nullptr, return ADUMP_FAILED, "Get binary handle failed");
     154              : 
     155            3 :         rtDevBinary_t bin{.magic = RT_DEV_BINARY_MAGIC_ELF_AIVEC, .version = 0,
     156            3 :             .data = static_cast<void*>(binData.get()), .length = fileSize};
     157              : 
     158            3 :         ret = rtDevBinaryRegister(&bin, &opData_.binHandle);
     159            3 :         IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     160              :             "Failed to parse bin data into handle, ret is %d", ret);
     161              : 
     162            3 :         ret = rtFunctionRegister(opData_.binHandle, KFC_OPERATOR_STUB_NAME, KFC_OPERATOR_NAME, KFC_OPERATOR_NAME, 0U);
     163            3 :         IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     164              :             "Failed to register handle into stub kernel name %s, ret is %d", KFC_OPERATOR_STUB_NAME, ret);
     165            3 :     }
     166              : 
     167            3 :     ret = rtGetAddrByFun(KFC_OPERATOR_STUB_NAME, &opData_.pcAddr);
     168            3 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     169              :         "Failed to get pc addr from stub kernel name %s, ret is %d", KFC_OPERATOR_STUB_NAME, ret);
     170              : 
     171            3 :     IDE_LOGI("Success to get pc address %p on device %u.", opData_.pcAddr, deviceId_);
     172            3 :     return ADUMP_SUCCESS;
     173              : }
     174              : 
     175            3 : int32_t OperatorPreliminary::CreateMemory()
     176              : {
     177            3 :     opData_.msgQSize = INTEGER_KILOBYTE * INTEGER_KILOBYTE; // 1M 消息轮询、参数保存、多核同步空间
     178            3 :     opData_.outputSize = MAX_STATS_NUM * SINGLE_STATS_BYTE;
     179            3 :     uint64_t statsCnt = 0;
     180          195 :     for (uint64_t idx = 0; idx < MAX_STATS_NUM; idx++) {
     181          192 :         if ((setting_.GetDumpStatsItem() & (1LLU << idx)) != 0) {
     182           18 :             statsCnt++; // 统计项个数
     183              :         }
     184              :     }
     185            3 :     opData_.workspaceSize = CalcWorkspaceSize(statsCnt);
     186            3 :     opData_.stackBaseSize = CalcStackSize();
     187              : 
     188            3 :     IDE_CTRL_VALUE_FAILED(opData_.workspaceSize != 0 && opData_.stackBaseSize != 0, return ADUMP_FAILED,
     189              :         "The size of the workspaceSize is 0");
     190            3 :     IDE_LOGI("Calculate MsgQ Size:%" PRIu64 "Byte, output size:%" PRIu64 "Byte, workspace size:%" PRIu64 "Byte,"
     191              :         "stack base size:%" PRIu64 "Byte on device %u.", opData_.msgQSize, opData_.outputSize,
     192              :         opData_.workspaceSize, opData_.stackBaseSize, deviceId_);
     193              : 
     194            6 :     rtError_t ret = rtMalloc(&opData_.memoryAddr, opData_.msgQSize + opData_.outputSize +
     195            3 :         opData_.workspaceSize + opData_.stackBaseSize, RT_MEMORY_DEFAULT, AICPU);
     196            3 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     197              :         "Execute rtMalloc failed with result %d", ret);
     198            3 :     IDE_LOGI("Rt malloc success on device %u.", deviceId_);
     199            3 :     return ADUMP_SUCCESS;
     200              : }
     201              : 
     202            3 : int32_t OperatorPreliminary::KFCKernelLaunch()
     203              : {
     204            3 :     IDE_LOGD("Start to init kfc kernel information for device %u.", deviceId_);
     205            3 :     KfcDumpOpInitParam kfcParam;
     206            3 :     kfcParam.kfcWorkSpace.msgQ = reinterpret_cast<uint64_t>(opData_.memoryAddr);
     207            3 :     kfcParam.kfcWorkSpace.msgQSize = opData_.msgQSize;
     208            3 :     kfcParam.kfcWorkSpace.output = kfcParam.kfcWorkSpace.msgQ  + opData_.msgQSize;
     209            3 :     kfcParam.kfcWorkSpace.outputSize = opData_.outputSize;
     210            3 :     kfcParam.kfcWorkSpace.workspace = kfcParam.kfcWorkSpace.output + opData_.outputSize;
     211            3 :     kfcParam.kfcWorkSpace.workspaceSize = opData_.workspaceSize;
     212            3 :     kfcParam.kfcWorkSpace.stackBase = kfcParam.kfcWorkSpace.workspace + opData_.workspaceSize;
     213            3 :     kfcParam.kfcWorkSpace.stackBaseSize = opData_.stackBaseSize;
     214              : 
     215            3 :     kfcParam.config.aiCoreNum = opData_.aiCoreCnt;
     216            3 :     kfcParam.config.vectorCoreNum = opData_.vectCoreCnt;
     217            3 :     kfcParam.config.ubSize = opData_.ubSize;
     218            3 :     kfcParam.config.dumpStatPcAddr = reinterpret_cast<uint64_t>(opData_.pcAddr);
     219            3 :     kfcParam.config.statsType = setting_.GetDumpStatsItem();
     220            3 :     kfcParam.config.chipType = static_cast<uint64_t>(setting_.GetPlatformType());
     221              : 
     222            3 :     kfcParam.streamInfo.streamId = opData_.streamId;
     223            3 :     kfcParam.streamInfo.sqIds = opData_.sqId;
     224            3 :     kfcParam.streamInfo.cqIds = opData_.cqIds;
     225            3 :     kfcParam.streamInfo.logicCqIds = opData_.logicCqIds;
     226            3 :     kfcParam.streamInfo.deviceId = deviceId_;
     227              : 
     228              :     rtAicpuArgsEx_t argsInfo;
     229            3 :     argsInfo.args = static_cast<void*>(&kfcParam);
     230            3 :     argsInfo.argsSize = sizeof(kfcParam);
     231            3 :     argsInfo.soNameAddrOffset = static_cast<uint16_t>(offsetof(KfcDumpOpInitParam, soName));
     232            3 :     argsInfo.kernelNameAddrOffset = static_cast<uint16_t>(offsetof(KfcDumpOpInitParam, kernelName));
     233            3 :     argsInfo.hostInputInfoPtr = nullptr;
     234            3 :     argsInfo.kernelOffsetInfoPtr = nullptr;
     235            3 :     argsInfo.hostInputInfoNum = 0;
     236            3 :     argsInfo.kernelOffsetInfoNum = 0;
     237            3 :     argsInfo.isNoNeedH2DCopy = false;
     238              : 
     239            3 :     rtError_t ret = rtAicpuKernelLaunchExWithArgs(KERNEL_TYPE_AICPU_KFC, "VectorStats", 1, &argsInfo, nullptr,
     240              :         nullptr, 0);
     241            3 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     242              :         "Failed to launch kernel for KFC, ret is %d", ret);
     243              : 
     244            3 :     ret = rtStreamSynchronize(nullptr); // Use the default flow to ensure successful execution.
     245            3 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED,
     246              :         "Execute rtStreamSynchronize for kernel launch failed with result %d", ret);
     247              : 
     248            3 :     IDE_LOGI("Success to init kfc kernel information on device %u.", deviceId_);
     249            3 :     return ADUMP_SUCCESS;
     250              : }
     251              : 
     252            6 : int32_t OperatorPreliminary::OperatorInit()
     253              : {
     254            6 :     int32_t version = AdumpDsmi::DrvGetAPIVersion();
     255            6 :     if (version != 0 && version < SUPPORTED_DRV_VERSION) {
     256            0 :         IDE_LOGW("Current driver version %d does not support this feature.", version);
     257            0 :         return ADUMP_SUCCESS;
     258              :     }
     259              :     // If version is 0, it indicates that the interface is obsolete and the current operator continues to execute.
     260              : 
     261            6 :     IDE_LOGI("Prepare to initialize the resources of kfc kernel on device %u.", deviceId_);
     262              :     do {
     263            6 :         int32_t ret = GetStreamInfo();
     264            6 :         IDE_CTRL_VALUE_FAILED_NODO(ret == ADUMP_SUCCESS, break, "OperatorInit fails at GetStreamInfo when executed.");
     265              : 
     266            6 :         ret = GetUBSizeAndCoreNum();
     267            6 :         IDE_CTRL_VALUE_FAILED_NODO(ret == ADUMP_SUCCESS, break,
     268              :             "OperatorInit fails at GetUBSizeAndCoreNum when executed.");
     269              : 
     270            3 :         ret = GetOperatorPCAddr();
     271            3 :         IDE_CTRL_VALUE_FAILED_NODO(ret == ADUMP_SUCCESS, break,
     272              :             "OperatorInit fails at GetOperatorPCAddr when executed.");
     273              : 
     274            3 :         ret = CreateMemory();
     275            3 :         IDE_CTRL_VALUE_FAILED_NODO(ret == ADUMP_SUCCESS, break, "OperatorInit fails at CreateMemory when executed.");
     276              : 
     277            3 :         ret = KFCKernelLaunch();
     278            3 :         IDE_CTRL_VALUE_FAILED_NODO(ret == ADUMP_SUCCESS, break, "OperatorInit fails at kernel launch when executed.");
     279            3 :         return ADUMP_SUCCESS;
     280              :     } while (0);
     281            3 :     IDE_LOGW("Start to destroy rt api resources on device %u.", deviceId_);
     282            3 :     return ADUMP_FAILED;
     283              : }
     284              : 
     285              : } // namespace Adx
        

Generated by: LCOV version 2.0-1