LCOV - code coverage report
Current view: top level - acl/utils - cann_info_utils.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.6 % 113 108
Test Date: 2026-08-06 15:29:52 Functions: 100.0 % 9 9

            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 "utils/cann_info_utils.h"
      12              : 
      13              : #include <fstream>
      14              : #include "acl_rt_impl.h"
      15              : #include "utils/file_utils.h"
      16              : #include "common/json_parser.h"
      17              : 
      18              : namespace acl {
      19              :     namespace {
      20              : #if defined(ONLY_ENABLE_ACL_UT)
      21              :         constexpr const char_t *const SW_CONFIG_FILE = "tmp_run_data/ascendcl_config/swFeatureList.json";
      22              :         constexpr const char_t *const RUNTIME_VERSION_PATH = "tests/tmp_run_data/share/info/runtime/version.info";
      23              : #else
      24              :         constexpr const char_t *const SW_CONFIG_FILE = "data/ascendcl_config/swFeatureList.json";
      25              :         constexpr const char_t *const RUNTIME_VERSION_PATH = "share/info/runtime/version.info";
      26              : #endif
      27              :         constexpr const char_t *const VERSION_INFO_KEY = "Version=";
      28              :     } // namespace
      29              : 
      30              :     std::mutex CannInfoUtils::mutex_;
      31              :     bool CannInfoUtils::initFlag_ = false;
      32              :     int32_t CannInfoUtils::currentRuntimeVersion_ = UNKNOWN_VERSION;
      33              :     std::string CannInfoUtils::swConfigPath_;
      34              :     std::string CannInfoUtils::defaultInstallPath_;
      35              :     aclCannAttr CannInfoUtils::attrArray_[MAX_CANN_ATTR_SIZE];
      36              :     size_t CannInfoUtils::attrNum_ = 0;
      37              : 
      38              :     std::map<aclCannAttr, CannInfo> CannInfoUtils::attrToCannInfo_ = {
      39              :         {ACL_CANN_ATTR_INF_NAN, CannInfo("INF_NAN", "SoCInfo", "support_inf_nan")},
      40              :         {ACL_CANN_ATTR_BF16, CannInfo("BF16", "SoCInfo", "support_bf16")},
      41              :         {ACL_CANN_ATTR_JIT_COMPILE, CannInfo("JIT_COMPILE", "", "")},
      42              :     };
      43              : 
      44            3 :     aclError CannInfoUtils::GetAttributeList(const aclCannAttr **cannAttr, size_t *num)
      45              :     {
      46            3 :         const aclError ret = Initialize();
      47            3 :         if (ret != ACL_SUCCESS) {
      48            2 :             ACL_LOG_INNER_ERROR("initialize CannInfoUtils failed, ret = %d", static_cast<int32_t>(ret));
      49            2 :             return ret;
      50              :         }
      51            1 :         *cannAttr = attrArray_;
      52            1 :         *num = attrNum_;
      53            1 :         return ACL_SUCCESS;
      54              :     }
      55              : 
      56            9 :     aclError CannInfoUtils::GetAttribute(aclCannAttr cannAttr, int32_t *value)
      57              :     {
      58            9 :         const aclError ret = Initialize();
      59            9 :         if (ret != ACL_SUCCESS) {
      60            7 :             ACL_LOG_INNER_ERROR("initialize CannInfoUtils failed, ret = %d", static_cast<int32_t>(ret));
      61            7 :             return ret;
      62              :         }
      63              : 
      64            2 :         auto iter = attrToCannInfo_.find(cannAttr);
      65            2 :         if (iter == attrToCannInfo_.end()) {
      66            1 :             ACL_LOG_WARN("find cann attr failed, attr value = %d", static_cast<int32_t>(cannAttr));
      67            1 :             return ACL_ERROR_INVALID_PARAM;
      68              :         }
      69            1 :         *value = iter->second.isAvailable;
      70            1 :         return ACL_SUCCESS;
      71              :     }
      72              : 
      73           12 :     aclError CannInfoUtils::Initialize()
      74              :     {
      75           12 :         std::lock_guard<std::mutex> lock(mutex_);
      76           12 :         if (initFlag_) {
      77            2 :             ACL_LOG_INFO("CannInfoUtils has already initialized.");
      78            2 :             return ACL_SUCCESS;
      79              :         }
      80           10 :         ACL_LOG_INFO("Start to initialize CannInfoUtils.");
      81              :         // init config path and CANN install path
      82           10 :         auto ret = GetConfigInstallPath();
      83           10 :         if (ret != ACL_SUCCESS) {
      84            4 :             ACL_LOG_INNER_ERROR("Failed to get swFeatureList.json, please check ascendcl_config path.");
      85            4 :             return ret;
      86              :         }
      87              : 
      88              :         // parse requirments of each attributes
      89            6 :         ret = JsonParser::GetAttrConfigFromFile(swConfigPath_.c_str(), attrToCannInfo_);
      90            6 :         if (ret != ACL_SUCCESS) {
      91            0 :             ACL_LOG_INNER_ERROR("Failed to parse requirements of Cann attrs, ret = %d.", ret);
      92            0 :             return ret;
      93              :         }
      94              : 
      95              :         // parse current CannInfo
      96            6 :         const std::string runtimeVersionPath = defaultInstallPath_ + RUNTIME_VERSION_PATH;
      97            6 :         ret = ParseVersionInfo(runtimeVersionPath, &currentRuntimeVersion_);
      98            6 :         if (ret != ACL_SUCCESS) {
      99            5 :             ACL_LOG_WARN("cannot get runtime version in current environment!");
     100            5 :             return ACL_ERROR_INTERNAL_ERROR;
     101              :         }
     102              : 
     103              :         // check and update attr availability
     104            1 :         CheckAndUpdateAttrAvailability();
     105            1 :         initFlag_ = true;
     106            1 :         ACL_LOG_INFO("Successfully initialized CannInfoUtils: current CannInfo[runtime = %d, attrNum = %zu]",
     107              :                      currentRuntimeVersion_, attrNum_);
     108              : 
     109            1 :         return ACL_SUCCESS;
     110           12 :     }
     111              : 
     112           10 :     aclError CannInfoUtils::GetConfigInstallPath()
     113              :     {
     114           10 :         std::string path;
     115           10 :         const aclError ret = file_utils::GetSoRealPath(path);
     116           10 :         if (ret != ACL_SUCCESS) {
     117            4 :             ACL_LOG_WARN("Failed to get libascendcl.so file path.");
     118            4 :             return ret;
     119              :         }
     120            6 :         ACL_LOG_DEBUG("current path = %s", path.c_str());
     121            6 :         path = path.substr(0, path.rfind('/'));
     122            6 :         path = path.substr(0, path.rfind('/') + 1UL);
     123            6 :         swConfigPath_ = path + SW_CONFIG_FILE;
     124            6 :         ACL_LOG_DEBUG("swConfigPath = %s", swConfigPath_.c_str());
     125            6 :         path.pop_back();
     126            6 :         defaultInstallPath_ = path.substr(0, path.rfind('/') + 1UL);
     127            6 :         ACL_LOG_DEBUG("defaultInstallPath = %s", defaultInstallPath_.c_str());
     128            6 :         return ACL_SUCCESS;
     129           10 :     }
     130              : 
     131            6 :     aclError CannInfoUtils::ParseVersionInfo(const std::string &path, int32_t *version)
     132              :     {
     133            6 :         std::ifstream ifs(path, std::ifstream::in);
     134            6 :         if (!ifs.is_open()) {
     135            2 :             ACL_LOG_WARN("Open file [%s] failed.", path.c_str());
     136            2 :             return ACL_ERROR_INTERNAL_ERROR;
     137              :         }
     138            4 :         std::string line;
     139            5 :         while (std::getline(ifs, line)) {
     140            4 :             if (line.find(VERSION_INFO_KEY) != std::string::npos) {
     141            3 :                 ACL_LOG_DEBUG("Parse version success, content is [%s].", line.c_str());
     142            3 :                 ifs.close();
     143            3 :                 const size_t prefixLen = strlen(VERSION_INFO_KEY);
     144            3 :                 line = line.substr(prefixLen);
     145            3 :                 const size_t pos = line.find('.', line.find('.') + 1UL);
     146            3 :                 line = line.substr(0, pos);
     147            3 :                 return ParseVersionValue(line, version);
     148              :             }
     149              :         }
     150            1 :         ifs.close();
     151            1 :         ACL_LOG_WARN("cannot find valid Version info, please check path = %s", path.c_str());
     152            1 :         return ACL_ERROR_INTERNAL_ERROR;
     153            6 :     }
     154              : 
     155           17 :     aclError CannInfoUtils::ParseVersionValue(const std::string &str, int32_t *value)
     156              :     {
     157           17 :         const size_t pos = str.find('.');
     158              :         try {
     159           19 :             const int32_t major = std::stoi(str.substr(0, pos));
     160           15 :             const int32_t minor = std::stoi(str.substr(pos + 1UL));
     161           15 :             *value = 1000 * major + 10 * minor;
     162            2 :         } catch (...) {
     163            2 :             ACL_LOG_WARN("strVal[%s] can not be converted to version value", str.c_str());
     164            2 :             return ACL_ERROR_INTERNAL_ERROR;
     165            2 :         }
     166           15 :         return ACL_SUCCESS;
     167              :     }
     168              : 
     169            3 :     bool CannInfoUtils::MatchVersionInfo(const CannInfo &configCannInfo)
     170              :     {
     171              :         // if version is not set, skip matching and return true
     172            3 :         if (configCannInfo.minimumRuntimeVersion == UNKNOWN_VERSION) {
     173            0 :             return true;
     174              :         }
     175            3 :         return (currentRuntimeVersion_ >= configCannInfo.minimumRuntimeVersion);
     176              :     }
     177              : 
     178            3 :     bool CannInfoUtils::CheckNPUFeatures(const CannInfo &configInfo)
     179              :     {
     180            3 :         if (configInfo.socSpecLabel.empty() || configInfo.socSpecKey.empty()) {
     181              :             // label 或 key 为空说明特性与芯片无关, 无需查询
     182            1 :             return true;
     183              :         }
     184            2 :         constexpr uint32_t kMaxValueLen = 16U;
     185            2 :         char_t value[kMaxValueLen] = {0};
     186            2 :         const auto ret = rtGetSocSpec(configInfo.socSpecLabel.c_str(), configInfo.socSpecKey.c_str(), value,
     187              :             kMaxValueLen);
     188            2 :         if (ret != RT_ERROR_NONE) {
     189            0 :             ACL_LOG_WARN("Cannot get platform info, label = [%s], key = [%s]", configInfo.socSpecLabel.c_str(),
     190              :                          configInfo.socSpecKey.c_str());
     191            0 :             return false;
     192              :         }
     193              :         // value "0" 或空 或非法内容 都认为 false
     194            2 :         const std::string strVal(value);
     195            2 :         return strVal == "1";
     196            2 :     }
     197              : 
     198            1 :     void CannInfoUtils::CheckAndUpdateAttrAvailability()
     199              :     {
     200            4 :         for (auto &item : attrToCannInfo_) {
     201            3 :             auto &swConfigInfo = item.second;
     202            3 :             if (MatchVersionInfo(swConfigInfo) && CheckNPUFeatures(swConfigInfo)) {
     203            3 :                 ACL_LOG_INFO("support cann attribute [%s]", swConfigInfo.readableAttrName.c_str());
     204            3 :                 swConfigInfo.isAvailable = 1;
     205            3 :                 attrArray_[attrNum_] = item.first;
     206            3 :                 ++attrNum_;
     207              :             }
     208              :         }
     209            1 :     }
     210              : } // namespace acl
        

Generated by: LCOV version 2.0-1