LCOV - code coverage report
Current view: top level - adump/operator/operator_preliminary - operator_preliminary.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.8 % 192 180
Test Date: 2026-08-31 10:09:28 Functions: 100.0 % 13 13

            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 "securec.h"
      16              : #include "lib_path.h"
      17              : #include "file_utils.h"
      18              : #include "log/adx_log.h"
      19              : #include "adump_platform_api.h"
      20              : #include "adump_platform_manager.h"
      21              : #include "runtime/kernel.h"
      22              : #include "runtime/mem.h"
      23              : #include "runtime/dev.h"
      24              : 
      25              : namespace Adx {
      26              : constexpr uint32_t SINGLE_STATS_BYTE = 8;   // 单个统计项的占用大小
      27              : constexpr uint32_t BLOCK_MIN_SIZE = 32;     // 最小搬运单元
      28              : constexpr uint32_t DCCI_SYNC_SIZE = 64;     // DCCI强制同步数据64B
      29              : constexpr uint32_t MAX_STATS_NUM = 64;      // 最大统计项个数
      30              : constexpr uint32_t INTEGER_KILOBYTE = 1024; // 表示1KB
      31              : 
      32              : constexpr const char* const KFC_OPERATOR_STUB_NAME = "kfc_dump_stat_stub";
      33              : constexpr const char* const KFC_OPERATOR_NAME = "kfc_dump_stat";
      34              : 
      35              : static const std::vector<PlatformType> AICORE_RELATED = {PlatformType::CHIP_DC_TYPE};
      36              : 
      37           42 : OperatorPreliminary::OperatorPreliminary(const DumpSetting& setting, const uint32_t deviceId)
      38           42 :     : deviceId_(deviceId), setting_(setting), opData_({})
      39           42 : {}
      40              : 
      41           42 : OperatorPreliminary::~OperatorPreliminary() {}
      42              : 
      43           15 : uint64_t OperatorPreliminary::CalcWorkspaceSize(uint64_t statsCnt)
      44              : {
      45           15 :     PlatformType platform = setting_.GetPlatformType();
      46           15 :     uint32_t coreSize = opData_.vectCoreCnt;
      47           15 :     auto coreIter = std::find(AICORE_RELATED.begin(), AICORE_RELATED.end(), platform);
      48           30 :     if (coreIter != AICORE_RELATED.cend()) {
      49            0 :         return DCCI_SYNC_SIZE * opData_.aiCoreCnt * statsCnt;
      50              :     }
      51           15 :     return BLOCK_MIN_SIZE * (coreSize + 1) * statsCnt; // + 1 用于当做同步空间
      52              : }
      53              : 
      54            3 : std::vector<std::string> OperatorPreliminary::GetBinNames() const
      55              : {
      56            3 :     auto plat = PlatformReflection<DataDumpInterface>::CreatePlatform(setting_.GetPlatformType());
      57            3 :     if (plat == nullptr) {
      58            0 :         return {};
      59              :     }
      60            3 :     return plat->GetKfcBinNames();
      61            3 : }
      62              : 
      63           18 : int32_t OperatorPreliminary::GetStreamInfo()
      64              : {
      65           18 :     IDE_LOGI("Start GetStreamInfo on device %u.", deviceId_);
      66           18 :     rtError_t ret = rtSetDevice(deviceId_);
      67           18 :     IDE_CTRL_VALUE_FAILED(
      68              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtSetDevice on device %u failed with result %d", deviceId_,
      69              :         ret);
      70           18 :     opData_.setDevice = true;
      71              : 
      72           18 :     ret = rtStreamCreateWithFlags(&opData_.deviceStm, 0, RT_STREAM_CP_PROCESS_USE);
      73           18 :     IDE_CTRL_VALUE_FAILED(
      74              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtStreamCreateWithFlags on device %u failed with result %d",
      75              :         deviceId_, ret);
      76              : 
      77           18 :     ret = rtGetStreamId(opData_.deviceStm, &opData_.streamId);
      78           18 :     IDE_CTRL_VALUE_FAILED(
      79              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtGetStreamId on device %u failed with result %d",
      80              :         deviceId_, ret);
      81              : 
      82           18 :     ret = rtStreamGetSqid(opData_.deviceStm, &opData_.sqId);
      83           18 :     IDE_CTRL_VALUE_FAILED(
      84              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtStreamGetSqid on device %u failed with result %d",
      85              :         deviceId_, ret);
      86              : 
      87           18 :     ret = rtStreamGetCqid(opData_.deviceStm, &opData_.cqIds, &opData_.logicCqIds);
      88           18 :     IDE_CTRL_VALUE_FAILED(
      89              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtStreamGetCqid on device %u failed with result %d",
      90              :         deviceId_, ret);
      91              : 
      92           18 :     IDE_LOGI(
      93              :         "Success to get stream id=%d, sqId=%u, cqId=%u, logic cqId=%u on device %u.", opData_.streamId, opData_.sqId,
      94              :         opData_.cqIds, opData_.logicCqIds, deviceId_);
      95           18 :     return ADUMP_SUCCESS;
      96              : }
      97              : 
      98           18 : int32_t OperatorPreliminary::GetUBSizeAndCoreNum()
      99              : {
     100           18 :     char version[SOC_VERSION_LEN] = {};
     101           18 :     IDE_CTRL_VALUE_FAILED(
     102              :         rtGetSocVersion(version, SOC_VERSION_LEN) == RT_ERROR_NONE, return ADUMP_FAILED, "Failed to get soc version");
     103           18 :     const std::string socVersion(version);
     104              : 
     105              :     PlatformData platformData;
     106           18 :     IDE_CTRL_VALUE_FAILED(
     107              :         AdumpPlatformApi::GetUBSizeAndCoreNum(socVersion, setting_.GetPlatformType(), platformData),
     108              :         return ADUMP_FAILED, "Failed to read platform information from fe api.");
     109              : 
     110           15 :     opData_.ubSize = platformData.ubSize;
     111           15 :     opData_.aiCoreCnt = platformData.aiCoreCnt;
     112           15 :     opData_.vectCoreCnt = platformData.vectCoreCnt;
     113           15 :     IDE_LOGI(
     114              :         "Get ub size:%" PRIu64 ", ai core count:%" PRIu64 ", vector core count:%" PRIu64 " on device %u.",
     115              :         opData_.ubSize, opData_.aiCoreCnt, opData_.vectCoreCnt, deviceId_);
     116           15 :     return ADUMP_SUCCESS;
     117           18 : }
     118              : 
     119            3 : std::unique_ptr<char[]> OperatorPreliminary::LoadBinFile(const std::string& filename, size_t& fileSize) const
     120              : {
     121            3 :     std::string realPath;
     122            3 :     IDE_CTRL_VALUE_FAILED(
     123              :         FileUtils::FileNameIsReal(filename, realPath) == IDE_DAEMON_OK, return nullptr,
     124              :         "LoadBinFile failed. The real path is %s.", filename.c_str());
     125              : 
     126            3 :     std::ifstream iFile(realPath, std::ios::binary | std::ios::ate);
     127            3 :     IDE_CTRL_VALUE_FAILED(iFile.is_open(), return nullptr, "Failed to open file: %s", realPath.c_str());
     128              : 
     129            3 :     auto pos = iFile.tellg();
     130            3 :     if (pos <= 0) {
     131            0 :         IDE_LOGE("Failed to get file size. file: %s, size: %ld", realPath.c_str(), pos);
     132            0 :         return nullptr;
     133              :     }
     134            3 :     fileSize = static_cast<size_t>(pos);
     135            3 :     iFile.seekg(0, std::ios::beg);
     136            3 :     char* buffer = new (std::nothrow) char[fileSize];
     137            3 :     IDE_CTRL_VALUE_FAILED(buffer != nullptr, return nullptr, "Failed to new file buffer");
     138            3 :     IDE_CTRL_VALUE_FAILED(
     139              :         iFile.read(buffer, fileSize),
     140              :         {
     141              :             delete[] buffer;
     142              :             return nullptr;
     143              :         },
     144              :         "Failed to read file data. file: %s, size: %ld", filename.c_str(), fileSize);
     145            3 :     return std::unique_ptr<char[]>(buffer);
     146            3 : }
     147              : 
     148           15 : int32_t OperatorPreliminary::GetOperatorPCAddr()
     149              : {
     150           15 :     static std::unique_ptr<char[]> binData = nullptr;
     151           15 :     rtError_t ret = RT_ERROR_NONE;
     152              : 
     153           15 :     if (binData == nullptr) {
     154            3 :         const std::vector<std::string> opNames = GetBinNames();
     155            3 :         std::string hitPath;
     156            6 :         for (const auto& opName : opNames) {
     157            3 :             const std::string opPath = LibPath::Instance().GetTargetPath(opName);
     158            3 :             IDE_CTRL_VALUE_FAILED(
     159              :                 !opPath.empty(), continue, "Failed to get the path of the kfc operator. opName=%s", opName.c_str());
     160            3 :             if (FileUtils::IsFileExist(opPath)) {
     161            3 :                 hitPath = opPath;
     162            3 :                 break;
     163              :             }
     164            3 :         }
     165            3 :         IDE_CTRL_VALUE_FAILED(
     166              :             !hitPath.empty(), return ADUMP_FAILED, "Failed to find an existing kfc operator file. candidates=%zu",
     167              :             opNames.size());
     168              : 
     169            3 :         size_t fileSize = 0;
     170            3 :         binData = LoadBinFile(hitPath, fileSize);
     171            3 :         IDE_CTRL_VALUE_FAILED(
     172              :             binData != nullptr, return ADUMP_FAILED, "Failed to load the kfc operator data. opPath=%s",
     173              :             hitPath.c_str());
     174            3 :         IDE_LOGI("Success to load the kfc operator data. opPath=%s, fileSize=%zu", hitPath.c_str(), fileSize);
     175              : 
     176            3 :         rtDevBinary_t bin{
     177              :             .magic = RT_DEV_BINARY_MAGIC_ELF_AIVEC,
     178              :             .version = 0,
     179            3 :             .data = static_cast<void*>(binData.get()),
     180            3 :             .length = fileSize};
     181              : 
     182            3 :         ret = rtDevBinaryRegister(&bin, &opData_.binHandle);
     183            3 :         IDE_CTRL_VALUE_FAILED(
     184              :             ret == RT_ERROR_NONE, return ADUMP_FAILED, "Failed to register the kfc operator binary. ret=%d", ret);
     185              : 
     186            3 :         ret = rtFunctionRegister(opData_.binHandle, KFC_OPERATOR_STUB_NAME, KFC_OPERATOR_NAME, KFC_OPERATOR_NAME, 0U);
     187            3 :         IDE_CTRL_VALUE_FAILED(
     188              :             ret == RT_ERROR_NONE, return ADUMP_FAILED,
     189              :             "Failed to register the kfc operator function. stubFunc=%s, stubName=%s, ret=%d", KFC_OPERATOR_STUB_NAME,
     190              :             KFC_OPERATOR_NAME, ret);
     191            3 :     }
     192              : 
     193           15 :     ret = rtGetAddrByFun(KFC_OPERATOR_STUB_NAME, &opData_.pcAddr);
     194           15 :     IDE_CTRL_VALUE_FAILED(
     195              :         ret == RT_ERROR_NONE, return ADUMP_FAILED,
     196              :         "Failed to get the kfc pc address with stubFunc. stubFunc=%s, ret=%d", KFC_OPERATOR_STUB_NAME, ret);
     197              : 
     198           15 :     IDE_LOGI("Success to get the kfc pc address on device %u. pcAddr=%p", deviceId_, opData_.pcAddr);
     199           15 :     return ADUMP_SUCCESS;
     200              : }
     201              : 
     202           15 : int32_t OperatorPreliminary::CreateMemory()
     203              : {
     204           15 :     opData_.msgQSize = INTEGER_KILOBYTE * INTEGER_KILOBYTE; // 1M 消息轮询、参数保存、多核同步空间
     205           15 :     opData_.outputSize = MAX_STATS_NUM * SINGLE_STATS_BYTE;
     206           15 :     uint64_t statsCnt = 0;
     207          975 :     for (uint64_t idx = 0; idx < MAX_STATS_NUM; idx++) {
     208          960 :         if ((setting_.GetDumpStatsItem() & (1LLU << idx)) != 0) {
     209           90 :             statsCnt++; // 统计项个数
     210              :         }
     211              :     }
     212           15 :     opData_.workspaceSize = CalcWorkspaceSize(statsCnt);
     213           15 :     opData_.stackBaseSize = CalcStackSize();
     214              : 
     215           15 :     IDE_CTRL_VALUE_FAILED(
     216              :         opData_.workspaceSize != 0 && opData_.stackBaseSize != 0, return ADUMP_FAILED,
     217              :         "The workspaceSize is 0 or the stackBaseSize is 0");
     218           15 :     IDE_LOGI(
     219              :         "Calculate MsgQ Size:%" PRIu64 "Byte, output size:%" PRIu64 "Byte, workspace size:%" PRIu64 "Byte,"
     220              :         "stack base size:%" PRIu64 "Byte on device %u.",
     221              :         opData_.msgQSize, opData_.outputSize, opData_.workspaceSize, opData_.stackBaseSize, deviceId_);
     222              : 
     223           15 :     uint64_t memSize = opData_.msgQSize + opData_.outputSize + opData_.workspaceSize + opData_.stackBaseSize;
     224           15 :     rtError_t ret = rtMalloc(&opData_.memoryAddr, memSize, RT_MEMORY_DEFAULT, AICPU);
     225           15 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED, "rtMalloc failed. ret=%d", ret);
     226           15 :     IDE_LOGI("rtMalloc success for the kfc operator. memAddr=%p, memSize=%llu", opData_.memoryAddr, memSize);
     227           15 :     return ADUMP_SUCCESS;
     228              : }
     229              : 
     230           15 : int32_t OperatorPreliminary::KFCKernelLaunch()
     231              : {
     232           15 :     IDE_LOGD("Start to initialize the kfc kernel information on device %u.", deviceId_);
     233           15 :     KfcDumpOpInitParam kfcParam;
     234           15 :     kfcParam.kfcWorkSpace.msgQ = reinterpret_cast<uint64_t>(opData_.memoryAddr);
     235           15 :     kfcParam.kfcWorkSpace.msgQSize = opData_.msgQSize;
     236           15 :     kfcParam.kfcWorkSpace.output = kfcParam.kfcWorkSpace.msgQ + opData_.msgQSize;
     237           15 :     kfcParam.kfcWorkSpace.outputSize = opData_.outputSize;
     238           15 :     kfcParam.kfcWorkSpace.workspace = kfcParam.kfcWorkSpace.output + opData_.outputSize;
     239           15 :     kfcParam.kfcWorkSpace.workspaceSize = opData_.workspaceSize;
     240           15 :     kfcParam.kfcWorkSpace.stackBase = kfcParam.kfcWorkSpace.workspace + opData_.workspaceSize;
     241           15 :     kfcParam.kfcWorkSpace.stackBaseSize = opData_.stackBaseSize;
     242              : 
     243           15 :     kfcParam.config.aiCoreNum = opData_.aiCoreCnt;
     244           15 :     kfcParam.config.vectorCoreNum = opData_.vectCoreCnt;
     245           15 :     kfcParam.config.ubSize = opData_.ubSize;
     246           15 :     kfcParam.config.dumpStatPcAddr = reinterpret_cast<uint64_t>(opData_.pcAddr);
     247           15 :     kfcParam.config.statsType = setting_.GetDumpStatsItem();
     248           15 :     kfcParam.config.chipType = static_cast<uint64_t>(setting_.GetPlatformType());
     249              : 
     250           15 :     kfcParam.streamInfo.streamId = opData_.streamId;
     251           15 :     kfcParam.streamInfo.sqIds = opData_.sqId;
     252           15 :     kfcParam.streamInfo.cqIds = opData_.cqIds;
     253           15 :     kfcParam.streamInfo.logicCqIds = opData_.logicCqIds;
     254           15 :     kfcParam.streamInfo.deviceId = deviceId_;
     255              : 
     256           15 :     if (UpdateKFCLaunchInfo(kfcParam) != ADUMP_SUCCESS) {
     257            0 :         return ADUMP_FAILED;
     258              :     }
     259              : 
     260              :     rtAicpuArgsEx_t argsInfo;
     261           15 :     argsInfo.args = static_cast<void*>(&kfcParam);
     262           15 :     argsInfo.argsSize = sizeof(kfcParam);
     263           15 :     argsInfo.soNameAddrOffset = static_cast<uint16_t>(offsetof(KfcDumpOpInitParam, soName));
     264           15 :     argsInfo.kernelNameAddrOffset = static_cast<uint16_t>(offsetof(KfcDumpOpInitParam, kernelName));
     265           15 :     argsInfo.hostInputInfoPtr = nullptr;
     266           15 :     argsInfo.kernelOffsetInfoPtr = nullptr;
     267           15 :     argsInfo.hostInputInfoNum = 0;
     268           15 :     argsInfo.kernelOffsetInfoNum = 0;
     269           15 :     argsInfo.isNoNeedH2DCopy = false;
     270              : 
     271              :     rtError_t ret =
     272           15 :         rtAicpuKernelLaunchExWithArgs(KERNEL_TYPE_AICPU_KFC, "VectorStats", 1, &argsInfo, nullptr, nullptr, 0);
     273           15 :     IDE_CTRL_VALUE_FAILED(ret == RT_ERROR_NONE, return ADUMP_FAILED, "Failed to launch kfc kernel, ret=%d", ret);
     274              : 
     275           15 :     ret = rtStreamSynchronize(nullptr); // Use the default flow to ensure successful execution.
     276           15 :     IDE_CTRL_VALUE_FAILED(
     277              :         ret == RT_ERROR_NONE, return ADUMP_FAILED, "Execute rtStreamSynchronize failed for kfc kernel. ret=%d", ret);
     278              : 
     279           15 :     IDE_LOGI("Success to initialize the kfc kernel information on device %u.", deviceId_);
     280           15 :     return ADUMP_SUCCESS;
     281              : }
     282              : 
     283           27 : KfcLaunchMode OperatorPreliminary::DecideKFCLaunchMode(int32_t driverApiVersion)
     284              : {
     285              :     // 低于LAUNCH_MODE_AICPU,驱动版本过低(含:0(无驱动接口符号)和-1(获取驱动失败))),统一不支持KFC算子。
     286           27 :     if (driverApiVersion < KFC_AICPU_DRV_VERSION) {
     287            9 :         return KfcLaunchMode::UNSUPPORTED;
     288              :     }
     289           18 :     if (driverApiVersion < KFC_ADUMP_DRV_VERSION) {
     290           12 :         return KfcLaunchMode::LAUNCH_MODE_AICPU;
     291              :     }
     292            6 :     return KfcLaunchMode::LAUNCH_MODE_ADUMP;
     293              : }
     294              : 
     295           15 : int32_t OperatorPreliminary::UpdateKFCLaunchInfo(KfcDumpOpInitParam& kfcParam) const
     296              : {
     297           15 :     KfcLaunchInfo launchInfo = {};
     298           15 :     switch (kfcLaunchMode_) {
     299            9 :         case KfcLaunchMode::LAUNCH_MODE_AICPU:
     300            9 :             launchInfo = AICPU_LAUNCH_INFO;
     301            9 :             break;
     302            6 :         case KfcLaunchMode::LAUNCH_MODE_ADUMP:
     303            6 :             launchInfo = ADUMP_LAUNCH_INFO;
     304            6 :             break;
     305            0 :         default:
     306            0 :             IDE_LOGE("Kfc launch mode is unsupported");
     307            0 :             return ADUMP_FAILED;
     308              :     }
     309              : 
     310           15 :     errno_t ret = strcpy_s(kfcParam.soName, FILE_NAME_MAX, launchInfo.soName);
     311           15 :     if (ret != EOK) {
     312            0 :         IDE_LOGE("Failed to set kfc soName, ret=%d", ret);
     313            0 :         return ADUMP_FAILED;
     314              :     }
     315           15 :     ret = strcpy_s(kfcParam.kernelName, FILE_NAME_MAX, launchInfo.kernelName);
     316           15 :     if (ret != EOK) {
     317            0 :         IDE_LOGE("Failed to set kfc kernelName, ret=%d", ret);
     318            0 :         return ADUMP_FAILED;
     319              :     }
     320              : 
     321           15 :     IDE_LOGI("Kfc operator uses soName[%s], kernelName[%s]", launchInfo.soName, launchInfo.kernelName);
     322           15 :     return ADUMP_SUCCESS;
     323              : }
     324              : 
     325           27 : int32_t OperatorPreliminary::OperatorInit()
     326              : {
     327           27 :     int32_t version = AdumpDsmi::DrvGetAPIVersion();
     328           27 :     kfcLaunchMode_ = DecideKFCLaunchMode(version);
     329           27 :     if (kfcLaunchMode_ == KfcLaunchMode::UNSUPPORTED) {
     330            9 :         IDE_LOGW("Current driver version %d does not support kfc feature for dump statistics.", version);
     331            9 :         return ADUMP_SUCCESS;
     332              :     }
     333              : 
     334           18 :     IDE_LOGI("Prepare to initialize the resources of kfc operator on device %u.", deviceId_);
     335              :     do {
     336           18 :         int32_t ret = GetStreamInfo();
     337           18 :         IDE_CTRL_VALUE_FAILED_NODO(
     338              :             ret == ADUMP_SUCCESS, break, "OperatorInit is failed at GetStreamInfo when executed.");
     339              : 
     340           18 :         ret = GetUBSizeAndCoreNum();
     341           18 :         IDE_CTRL_VALUE_FAILED_NODO(
     342              :             ret == ADUMP_SUCCESS, break, "OperatorInit is failed at GetUBSizeAndCoreNum when executed.");
     343              : 
     344           15 :         ret = GetOperatorPCAddr();
     345           15 :         IDE_CTRL_VALUE_FAILED_NODO(
     346              :             ret == ADUMP_SUCCESS, break, "OperatorInit is failed at GetOperatorPCAddr when executed.");
     347              : 
     348           15 :         ret = CreateMemory();
     349           15 :         IDE_CTRL_VALUE_FAILED_NODO(
     350              :             ret == ADUMP_SUCCESS, break, "OperatorInit is failed at CreateMemory when executed.");
     351              : 
     352           15 :         ret = KFCKernelLaunch();
     353           15 :         IDE_CTRL_VALUE_FAILED_NODO(
     354              :             ret == ADUMP_SUCCESS, break, "OperatorInit is failed at kernel launch when executed.");
     355           15 :         return ADUMP_SUCCESS;
     356              :     } while (0);
     357            3 :     IDE_LOGW("Start to destroy rt api resources on device %u.", deviceId_);
     358            3 :     return ADUMP_FAILED;
     359              : }
     360              : 
     361              : } // namespace Adx
        

Generated by: LCOV version 2.0-1