LCOV - code coverage report
Current view: top level - acl/utils - cann_info_utils.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 103 108 95.4 %
Date: 2026-08-27 13:24:42 Functions: 9 9 100.0 %

          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           8 :     aclError CannInfoUtils::GetAttribute(aclCannAttr cannAttr, int32_t *value)
      57             :     {
      58           8 :         const aclError ret = Initialize();
      59           8 :         if (ret != ACL_SUCCESS) {
      60           6 :             ACL_LOG_INNER_ERROR("initialize CannInfoUtils failed, ret = %d", static_cast<int32_t>(ret));
      61           6 :             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          11 :     aclError CannInfoUtils::Initialize()
      74             :     {
      75          22 :         std::lock_guard<std::mutex> lock(mutex_);
      76          11 :         if (initFlag_) {
      77           2 :             ACL_LOG_INFO("CannInfoUtils has already initialized.");
      78           2 :             return ACL_SUCCESS;
      79             :         }
      80           9 :         ACL_LOG_INFO("Start to initialize CannInfoUtils.");
      81             :         // init config path and CANN install path
      82           9 :         auto ret = GetConfigInstallPath();
      83           9 :         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           5 :         ret = JsonParser::GetAttrConfigFromFile(swConfigPath_.c_str(), attrToCannInfo_);
      90           5 :         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          10 :         const std::string runtimeVersionPath = defaultInstallPath_ + RUNTIME_VERSION_PATH;
      97           5 :         ret = ParseVersionInfo(runtimeVersionPath, &currentRuntimeVersion_);
      98           5 :         if (ret != ACL_SUCCESS) {
      99           4 :             ACL_LOG_WARN("cannot get runtime version in current environment!");
     100           4 :             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             :     }
     111             : 
     112           9 :     aclError CannInfoUtils::GetConfigInstallPath()
     113             :     {
     114          18 :         std::string path;
     115           9 :         const aclError ret = file_utils::GetSoRealPath(path);
     116           9 :         if (ret != ACL_SUCCESS) {
     117           4 :             ACL_LOG_WARN("failed to get libascendcl.so file path");
     118           4 :             return ret;
     119             :         }
     120           5 :         ACL_LOG_DEBUG("current path = %s", path.c_str());
     121           5 :         path = path.substr(0, path.rfind('/'));
     122           5 :         path = path.substr(0, path.rfind('/') + 1UL);
     123           5 :         swConfigPath_ = path + SW_CONFIG_FILE;
     124           5 :         ACL_LOG_DEBUG("swConfigPath = %s", swConfigPath_.c_str());
     125           5 :         path.pop_back();
     126           5 :         defaultInstallPath_ = path.substr(0, path.rfind('/') + 1UL);
     127           5 :         ACL_LOG_DEBUG("defaultInstallPath = %s", defaultInstallPath_.c_str());
     128           5 :         return ACL_SUCCESS;
     129             :     }
     130             : 
     131           5 :     aclError CannInfoUtils::ParseVersionInfo(const std::string &path, int32_t *version)
     132             :     {
     133          10 :         std::ifstream ifs(path, std::ifstream::in);
     134           5 :         if (!ifs.is_open()) {
     135           1 :             ACL_LOG_WARN("Open file [%s] failed.", path.c_str());
     136           1 :             return ACL_ERROR_INTERNAL_ERROR;
     137             :         }
     138           8 :         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             :     }
     154             : 
     155          16 :     aclError CannInfoUtils::ParseVersionValue(const std::string &str, int32_t *value)
     156             :     {
     157          16 :         const size_t pos = str.find('.');
     158             :         try {
     159          18 :             const int32_t major = std::stoi(str.substr(0, pos));
     160          14 :             const int32_t minor = std::stoi(str.substr(pos + 1UL));
     161          14 :             *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             :         }
     166          14 :         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 = 16UL;
     185           2 :         char_t value[kMaxValueLen] = {0};
     186           2 :         auto ret = rtGetSocSpec(configInfo.socSpecLabel.c_str(), configInfo.socSpecKey.c_str(), value, kMaxValueLen);
     187           2 :         if (ret != RT_ERROR_NONE) {
     188           0 :             ACL_LOG_WARN("Cannot get platform info, label = [%s], key = [%s]", configInfo.socSpecLabel.c_str(),
     189             :                          configInfo.socSpecKey.c_str());
     190           0 :             return false;
     191             :         }
     192             :         // value "0" 或空 或非法内容 都认为 false
     193           6 :         const std::string strVal(value);
     194           2 :         return strVal == "1";
     195             :     }
     196             : 
     197           1 :     void CannInfoUtils::CheckAndUpdateAttrAvailability()
     198             :     {
     199           4 :         for (auto &item : attrToCannInfo_) {
     200           3 :             auto &swConfigInfo = item.second;
     201           3 :             if (MatchVersionInfo(swConfigInfo) && CheckNPUFeatures(swConfigInfo)) {
     202           3 :                 ACL_LOG_INFO("support cann attribute [%s]", swConfigInfo.readableAttrName.c_str());
     203           3 :                 swConfigInfo.isAvailable = 1;
     204           3 :                 attrArray_[attrNum_] = item.first;
     205           3 :                 ++attrNum_;
     206             :             }
     207             :         }
     208           1 :     }
     209             : } // namespace acl

Generated by: LCOV version 1.14