mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-09 06:23:01 +08:00
feature(sysman): Add support of zesPowerGetEnergyCounter() API for BMG
Related-To: NEO-11296 Signed-off-by: Anvesh Bakwad <anvesh.bakwad@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
f3ad230c45
commit
615a41b9f5
@@ -80,18 +80,17 @@ ze_result_t LinuxPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy)
|
||||
ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
|
||||
if (isTelemetrySupportAvailable) {
|
||||
result = pSysmanProductHelper->getPowerEnergyCounter(pEnergy, pLinuxSysmanImp, powerDomain, subdeviceId);
|
||||
}
|
||||
|
||||
if (result != ZE_RESULT_SUCCESS) {
|
||||
if ((result = pSysfsAccess->read(energyCounterNodeFile, pEnergy->energy)) != ZE_RESULT_SUCCESS) {
|
||||
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s/%s and returning error:0x%x \n", __FUNCTION__, intelGraphicsHwmonDir.c_str(), energyCounterNodeFile.c_str(), getErrorCode(result));
|
||||
if ((result = pSysmanProductHelper->getPowerEnergyCounter(pEnergy, pLinuxSysmanImp, powerDomain, subdeviceId)) == ZE_RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
pEnergy->timestamp = SysmanDevice::getSysmanTimestamp();
|
||||
if ((result = pSysfsAccess->read(energyCounterNodeFile, pEnergy->energy)) != ZE_RESULT_SUCCESS) {
|
||||
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s/%s and returning error:0x%x \n", __FUNCTION__, intelGraphicsHwmonDir.c_str(), energyCounterNodeFile.c_str(), getErrorCode(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
pEnergy->timestamp = SysmanDevice::getSysmanTimestamp();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ enum class SysfsName {
|
||||
sysfsNamePackageEnergyCounterNode,
|
||||
sysfsNamePackageDefaultPowerLimit,
|
||||
sysfsNamePackageCriticalPowerLimit,
|
||||
sysfsNameCardEnergyCounterNode,
|
||||
sysfsNameStandbyModeControl,
|
||||
sysfsNameMemoryAddressRange,
|
||||
sysfsNameMaxMemoryFrequency,
|
||||
@@ -331,7 +332,7 @@ class SysmanKmdInterfaceXe : public SysmanKmdInterface {
|
||||
bool isBoostFrequencyAvailable() const override { return false; }
|
||||
bool isTdpFrequencyAvailable() const override { return false; }
|
||||
bool isPhysicalMemorySizeSupported() const override { return true; }
|
||||
std::vector<zes_power_domain_t> getPowerDomains() const override { return {ZES_POWER_DOMAIN_PACKAGE}; }
|
||||
std::vector<zes_power_domain_t> getPowerDomains() const override;
|
||||
|
||||
// Wedged state is not supported in XE.
|
||||
void getWedgedStatus(LinuxSysmanImp *pLinuxSysmanImp, zes_device_state_t *pState) override{};
|
||||
|
||||
@@ -50,9 +50,10 @@ void SysmanKmdInterfaceXe::initSysfsNameToFileMap(SysmanProductHelper *pSysmanPr
|
||||
sysfsNameToFileMap[SysfsName::sysfsNameThrottleReasonThermal] = std::make_pair("freq0/throttle/reason_thermal", "");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageSustainedPowerLimit] = std::make_pair("", "power1_max");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageSustainedPowerLimitInterval] = std::make_pair("", "power1_max_interval");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageEnergyCounterNode] = std::make_pair("", "energy1_input");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageEnergyCounterNode] = std::make_pair("", "energy2_input");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageDefaultPowerLimit] = std::make_pair("", "power1_rated_max");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNamePackageCriticalPowerLimit] = std::make_pair("", pSysmanProductHelper->getPackageCriticalPowerLimitFile());
|
||||
sysfsNameToFileMap[SysfsName::sysfsNameCardEnergyCounterNode] = std::make_pair("", "energy1_input");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNameMemoryAddressRange] = std::make_pair("physical_vram_size_bytes", "");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNameMaxMemoryFrequency] = std::make_pair("freq_vram_rp0", "");
|
||||
sysfsNameToFileMap[SysfsName::sysfsNameMinMemoryFrequency] = std::make_pair("freq_vram_rpn", "");
|
||||
@@ -97,6 +98,8 @@ std::string SysmanKmdInterfaceXe::getEnergyCounterNodeFile(zes_power_domain_t po
|
||||
std::string filePath = {};
|
||||
if (powerDomain == ZES_POWER_DOMAIN_PACKAGE) {
|
||||
filePath = sysfsNameToFileMap[SysfsName::sysfsNamePackageEnergyCounterNode].second;
|
||||
} else if (powerDomain == ZES_POWER_DOMAIN_CARD) {
|
||||
filePath = sysfsNameToFileMap[SysfsName::sysfsNameCardEnergyCounterNode].second;
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
@@ -171,6 +174,10 @@ std::string SysmanKmdInterfaceXe::getHwmonName(uint32_t subDeviceId, bool isSubd
|
||||
return "xe";
|
||||
}
|
||||
|
||||
std::vector<zes_power_domain_t> SysmanKmdInterfaceXe::getPowerDomains() const {
|
||||
return {ZES_POWER_DOMAIN_CARD, ZES_POWER_DOMAIN_PACKAGE, ZES_POWER_DOMAIN_MEMORY, ZES_POWER_DOMAIN_GPU};
|
||||
}
|
||||
|
||||
std::optional<std::string> SysmanKmdInterfaceXe::getEngineClassString(uint16_t engineClass) {
|
||||
auto sysfEngineString = xeEngineClassToSysfsEngineMap.find(engineClass);
|
||||
if (sysfEngineString == xeEngineClassToSysfsEngineMap.end()) {
|
||||
|
||||
@@ -17,11 +17,29 @@ constexpr static auto gfxProduct = IGFX_BMG;
|
||||
|
||||
#include "level_zero/sysman/source/shared/linux/product_helper/sysman_product_helper_xe_hp_and_later.inl"
|
||||
|
||||
// XTAL clock frequency is denoted as an integer between [0-3] with a predefined value for each number.
|
||||
// This vector defines the predefined value for each integer represented by the index of the vector.
|
||||
static const std::vector<double> indexToXtalClockFrequecyMap = {24, 19.2, 38.4, 25};
|
||||
|
||||
static std::map<std::string, std::map<std::string, uint64_t>> guidToKeyOffsetMap = {
|
||||
{"0x1e2f8200", // BMG PUNIT rev 1
|
||||
{{"VRAM_BANDWIDTH", 56}}},
|
||||
{{"XTAL_CLK_FREQUENCY", 4},
|
||||
{"VRAM_BANDWIDTH", 56},
|
||||
{"XTAL_COUNT", 1024},
|
||||
{"VCCGT_ENERGY_ACCUMULATOR", 1628},
|
||||
{"VCCDDR_ENERGY_ACCUMULATOR", 1640}}},
|
||||
{"0x1e2f8201", // BMG PUNIT rev 2
|
||||
{{"XTAL_CLK_FREQUENCY", 4},
|
||||
{"ACCUM_PACKAGE_ENERGY", 48},
|
||||
{"ACCUM_PSYS_ENERGY", 52},
|
||||
{"VRAM_BANDWIDTH", 56},
|
||||
{"XTAL_COUNT", 1024},
|
||||
{"VCCGT_ENERGY_ACCUMULATOR", 1628},
|
||||
{"VCCDDR_ENERGY_ACCUMULATOR", 1640}}},
|
||||
{"0x5e2f8210", // BMG OOBMSM Rev 15
|
||||
{{"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 164},
|
||||
{{"PACKAGE_ENERGY_STATUS_SKU_0_0_0_PCU", 136},
|
||||
{"PLATFORM_ENERGY_STATUS", 140},
|
||||
{"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 164},
|
||||
{"VRAM_TEMPERATURE_0_2_0_GTTMMADR", 168},
|
||||
{"reg_PCIESS_rx_bytecount_lsb", 280},
|
||||
{"reg_PCIESS_rx_bytecount_msb", 276},
|
||||
@@ -275,7 +293,9 @@ static std::map<std::string, std::map<std::string, uint64_t>> guidToKeyOffsetMap
|
||||
{"GDDR5_CH1_GT_64B_WR_REQ_UPPER", 1280},
|
||||
{"GDDR5_CH1_GT_64B_WR_REQ_LOWER", 1284}}},
|
||||
{"0x5e2f8211", // BMG OOBMSM Rev 16
|
||||
{{"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 164},
|
||||
{{"PACKAGE_ENERGY_STATUS_SKU_0_0_0_PCU", 136},
|
||||
{"PLATFORM_ENERGY_STATUS", 140},
|
||||
{"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 164},
|
||||
{"VRAM_TEMPERATURE_0_2_0_GTTMMADR", 168},
|
||||
{"reg_PCIESS_rx_bytecount_lsb", 280},
|
||||
{"reg_PCIESS_rx_bytecount_msb", 284},
|
||||
@@ -966,6 +986,95 @@ ze_result_t SysmanProductHelperHw<gfxProduct>::getGroupEngineBusynessFromSingleE
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
template <>
|
||||
ze_result_t SysmanProductHelperHw<gfxProduct>::getPowerEnergyCounter(zes_power_energy_counter_t *pEnergy, LinuxSysmanImp *pLinuxSysmanImp, zes_power_domain_t powerDomain, uint32_t subdeviceId) {
|
||||
|
||||
const std::unordered_map<zes_power_domain_t, std::vector<std::string>> powerDomainToKeyMap = {
|
||||
{ZES_POWER_DOMAIN_PACKAGE, {"ACCUM_PACKAGE_ENERGY", "PACKAGE_ENERGY_STATUS_SKU_0_0_0_PCU"}},
|
||||
{ZES_POWER_DOMAIN_CARD, {"ACCUM_PSYS_ENERGY", "PLATFORM_ENERGY_STATUS"}},
|
||||
{ZES_POWER_DOMAIN_MEMORY, {"VCCDDR_ENERGY_ACCUMULATOR"}},
|
||||
{ZES_POWER_DOMAIN_GPU, {"VCCGT_ENERGY_ACCUMULATOR"}}};
|
||||
|
||||
auto powerDomainToKeyMapIter = powerDomainToKeyMap.find(powerDomain);
|
||||
if (powerDomainToKeyMapIter == powerDomainToKeyMap.end()) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
std::string &rootPath = pLinuxSysmanImp->getPciRootPath();
|
||||
std::map<uint32_t, std::string> telemNodes = {};
|
||||
NEO::PmtUtil::getTelemNodesInPciPath(std::string_view(rootPath), telemNodes);
|
||||
if (telemNodes.empty()) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
std::map<std::string, uint64_t> keyOffsetMap = {};
|
||||
std::unordered_map<std::string, std::string> keyTelemInfoMap = {};
|
||||
|
||||
// Iterate through all the TelemNodes to find both OOBMSM and PUNIT guids along with their keyOffsetMap
|
||||
for (const auto &telemNode : telemNodes) {
|
||||
std::string telemNodeDir = telemNode.second;
|
||||
|
||||
std::array<char, NEO::PmtUtil::guidStringSize> guidString = {};
|
||||
if (!NEO::PmtUtil::readGuid(telemNodeDir, guidString)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto keyOffsetMapIterator = guidToKeyOffsetMap.find(guidString.data());
|
||||
if (keyOffsetMapIterator == guidToKeyOffsetMap.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &tempKeyOffsetMap = keyOffsetMapIterator->second;
|
||||
for (auto it = tempKeyOffsetMap.begin(); it != tempKeyOffsetMap.end(); it++) {
|
||||
keyOffsetMap[it->first] = it->second;
|
||||
keyTelemInfoMap[it->first] = telemNodeDir;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyOffsetMap.empty()) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
// Energy Counter calculation
|
||||
uint32_t energyCounter = 0;
|
||||
bool isReadValueSuccess = false;
|
||||
for (const auto &key : powerDomainToKeyMapIter->second) {
|
||||
if (PlatformMonitoringTech::readValue(keyOffsetMap, keyTelemInfoMap[key], key, 0, energyCounter)) {
|
||||
isReadValueSuccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReadValueSuccess) {
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// Energy counter is in U(18.14) format. Need to convert it into uint64_t and then in MicroJoule
|
||||
const uint32_t energyIntegerPart = static_cast<uint32_t>(energyCounter >> 14);
|
||||
const uint32_t energyDecimalBits = static_cast<uint32_t>((energyCounter & 0x3FFF));
|
||||
const double energyDecimalPart = static_cast<double>(energyDecimalBits) / (1 << 14);
|
||||
const double energyInJoules = static_cast<double>(energyIntegerPart + energyDecimalPart);
|
||||
pEnergy->energy = static_cast<uint64_t>((energyInJoules * convertJouleToMicroJoule));
|
||||
|
||||
// Timestamp calcuation
|
||||
uint64_t timestamp64 = 0;
|
||||
std::string key = "XTAL_COUNT";
|
||||
if (!PlatformMonitoringTech::readValue(keyOffsetMap, keyTelemInfoMap[key], key, 0, timestamp64)) {
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
uint32_t frequency = 0;
|
||||
key = "XTAL_CLK_FREQUENCY";
|
||||
if (!PlatformMonitoringTech::readValue(keyOffsetMap, keyTelemInfoMap[key], key, 0, frequency)) {
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
double timestamp = timestamp64 / indexToXtalClockFrequecyMap[frequency & 0x2];
|
||||
pEnergy->timestamp = static_cast<uint64_t>(timestamp);
|
||||
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
template class SysmanProductHelperHw<gfxProduct>;
|
||||
|
||||
} // namespace Sysman
|
||||
|
||||
@@ -228,6 +228,7 @@ ze_result_t SysmanProductHelperHw<gfxProduct>::getPowerEnergyCounter(zes_power_e
|
||||
// PMT will return energy counter in Q20 format(fixed point representation) where first 20 bits(from LSB) represent decimal part
|
||||
// and remaining integral part which is converted into joule by division with 1048576(2^20) and then converted into microjoules
|
||||
pEnergy->energy = (energyCounter / fixedPointToJoule) * convertJouleToMicroJoule;
|
||||
pEnergy->timestamp = SysmanDevice::getSysmanTimestamp();
|
||||
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
set(L0_TESTS_SYSMAN_POWER_LINUX
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_power.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_power_xe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_power_helper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_power.h
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ const std::string sustainedPowerLimit("power1_max");
|
||||
const std::string sustainedPowerLimitInterval("power1_max_interval");
|
||||
const std::string criticalPowerLimit1("curr1_crit");
|
||||
const std::string criticalPowerLimit2("power1_crit");
|
||||
const std::string energyCounterNode("energy1_input");
|
||||
const std::string packageEnergyCounterNode("energy1_input");
|
||||
const std::string defaultPowerLimit("power1_rated_max");
|
||||
constexpr uint64_t expectedEnergyCounter = 123456785u;
|
||||
constexpr uint64_t expectedEnergyCounterTile0 = 123456785u;
|
||||
@@ -106,11 +106,11 @@ struct MockPowerSysfsAccessInterface : public L0::Sysman::SysFsAccessInterface {
|
||||
return mockReadPeakResult;
|
||||
}
|
||||
val = criticalPowerLimitVal;
|
||||
} else if (file.compare(i915HwmonDirTile0 + "/" + energyCounterNode) == 0) {
|
||||
} else if (file.compare(i915HwmonDirTile0 + "/" + packageEnergyCounterNode) == 0) {
|
||||
val = expectedEnergyCounterTile0;
|
||||
} else if (file.compare(i915HwmonDirTile1 + "/" + energyCounterNode) == 0) {
|
||||
} else if (file.compare(i915HwmonDirTile1 + "/" + packageEnergyCounterNode) == 0) {
|
||||
val = expectedEnergyCounterTile1;
|
||||
} else if (file.compare(i915HwmonDir + "/" + energyCounterNode) == 0) {
|
||||
} else if (file.compare(i915HwmonDir + "/" + packageEnergyCounterNode) == 0) {
|
||||
val = expectedEnergyCounter;
|
||||
} else if (file.compare(i915HwmonDir + "/" + defaultPowerLimit) == 0) {
|
||||
val = mockDefaultPowerLimitVal;
|
||||
@@ -248,7 +248,7 @@ struct MockPowerSysfsAccessInterface : public L0::Sysman::SysFsAccessInterface {
|
||||
}
|
||||
|
||||
bool fileExists(const std::string file) override {
|
||||
if (file.find(energyCounterNode) != std::string::npos) {
|
||||
if (file.find(packageEnergyCounterNode) != std::string::npos) {
|
||||
return isEnergyCounterFilePresent;
|
||||
} else if (file.find(sustainedPowerLimit) != std::string::npos) {
|
||||
return isSustainedPowerLimitFilePresent;
|
||||
@@ -304,19 +304,6 @@ class SysmanDevicePowerFixtureI915 : public SysmanDeviceFixture {
|
||||
}
|
||||
};
|
||||
|
||||
class SysmanDevicePowerFixtureXe : public SysmanDeviceFixture {
|
||||
protected:
|
||||
L0::Sysman::SysmanDevice *device = nullptr;
|
||||
void SetUp() override {
|
||||
SysmanDeviceFixture::SetUp();
|
||||
device = pSysmanDevice;
|
||||
pSysmanDeviceImp->pPowerHandleContext->handleList.clear();
|
||||
}
|
||||
void TearDown() override {
|
||||
SysmanDeviceFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
class SysmanDevicePowerMultiDeviceFixture : public SysmanMultiDeviceFixture {
|
||||
protected:
|
||||
L0::Sysman::SysmanDevice *device = nullptr;
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/helpers/string.h"
|
||||
|
||||
#include "level_zero/sysman/source/api/power/linux/sysman_os_power_imp.h"
|
||||
#include "level_zero/sysman/source/device/sysman_device_imp.h"
|
||||
#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h"
|
||||
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h"
|
||||
#include "level_zero/sysman/test/unit_tests/sources/shared/linux/kmd_interface/mock_sysman_kmd_interface_xe.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
namespace ult {
|
||||
|
||||
constexpr uint64_t expectedEnergyCounter = 123456785u;
|
||||
const std::string xeHwmonDir("device/hwmon/hwmon1");
|
||||
const std::string cardEnergyCounterNode("energy1_input");
|
||||
const std::string packageEnergyCounterNode("energy2_input");
|
||||
|
||||
class MockXePowerSysfsAccess : public L0::Sysman::SysFsAccessInterface {
|
||||
|
||||
public:
|
||||
ze_result_t mockScanDirEntriesResult = ZE_RESULT_SUCCESS;
|
||||
ze_result_t mockReadResult = ZE_RESULT_SUCCESS;
|
||||
std::vector<ze_result_t> mockReadValUnsignedLongResult{};
|
||||
|
||||
bool isCardEnergyCounterFilePresent = true;
|
||||
bool isPackageEnergyCounterFilePresent = true;
|
||||
|
||||
ze_result_t read(const std::string file, std::string &val) override {
|
||||
if (mockReadResult != ZE_RESULT_SUCCESS) {
|
||||
return mockReadResult;
|
||||
}
|
||||
ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
|
||||
if (file.compare(xeHwmonDir + "/" + "name") == 0) {
|
||||
val = "xe";
|
||||
result = ZE_RESULT_SUCCESS;
|
||||
} else {
|
||||
val = "";
|
||||
result = ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ze_result_t read(const std::string file, uint64_t &val) override {
|
||||
ze_result_t result = ZE_RESULT_SUCCESS;
|
||||
|
||||
if (!mockReadValUnsignedLongResult.empty()) {
|
||||
result = mockReadValUnsignedLongResult.front();
|
||||
mockReadValUnsignedLongResult.erase(mockReadValUnsignedLongResult.begin());
|
||||
if (result != ZE_RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if ((file.compare(xeHwmonDir + "/" + cardEnergyCounterNode) == 0) || (file.compare(xeHwmonDir + "/" + packageEnergyCounterNode) == 0)) {
|
||||
val = expectedEnergyCounter;
|
||||
} else {
|
||||
result = ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ze_result_t scanDirEntries(const std::string path, std::vector<std::string> &listOfEntries) override {
|
||||
const std::string hwmonDir("device/hwmon");
|
||||
if (mockScanDirEntriesResult != ZE_RESULT_SUCCESS) {
|
||||
return mockScanDirEntriesResult;
|
||||
}
|
||||
if (path.compare(hwmonDir) == 0) {
|
||||
listOfEntries.push_back("hwmon1");
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool fileExists(const std::string file) override {
|
||||
if (file.find(cardEnergyCounterNode) != std::string::npos) {
|
||||
return isCardEnergyCounterFilePresent;
|
||||
} else if (file.find(packageEnergyCounterNode) != std::string::npos) {
|
||||
return isPackageEnergyCounterFilePresent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
MockXePowerSysfsAccess() = default;
|
||||
};
|
||||
|
||||
struct MockXePowerFsAccess : public L0::Sysman::FsAccessInterface {
|
||||
MockXePowerFsAccess() = default;
|
||||
};
|
||||
|
||||
class PublicLinuxPowerImp : public L0::Sysman::LinuxPowerImp {
|
||||
public:
|
||||
PublicLinuxPowerImp(L0::Sysman::OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) : L0::Sysman::LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId, powerDomain) {}
|
||||
using L0::Sysman::LinuxPowerImp::isTelemetrySupportAvailable;
|
||||
using L0::Sysman::LinuxPowerImp::pSysfsAccess;
|
||||
};
|
||||
|
||||
class SysmanDevicePowerFixtureXe : public SysmanDeviceFixture {
|
||||
protected:
|
||||
L0::Sysman::SysmanDevice *device = nullptr;
|
||||
MockXePowerFsAccess *pFsAccess = nullptr;
|
||||
MockXePowerSysfsAccess *pSysfsAccess = nullptr;
|
||||
MockSysmanKmdInterfaceXe *pSysmanKmdInterface = nullptr;
|
||||
|
||||
void SetUp() override {
|
||||
SysmanDeviceFixture::SetUp();
|
||||
device = pSysmanDevice;
|
||||
pFsAccess = new MockXePowerFsAccess();
|
||||
pSysfsAccess = new MockXePowerSysfsAccess();
|
||||
pSysmanKmdInterface = new MockSysmanKmdInterfaceXe(pLinuxSysmanImp->getSysmanProductHelper());
|
||||
pSysmanKmdInterface->pFsAccess.reset(pFsAccess);
|
||||
pSysmanKmdInterface->pSysfsAccess.reset(pSysfsAccess);
|
||||
pLinuxSysmanImp->pSysmanKmdInterface.reset(pSysmanKmdInterface);
|
||||
pLinuxSysmanImp->pFsAccess = pFsAccess;
|
||||
pSysfsAccess->mockScanDirEntriesResult = ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
SysmanDeviceFixture::TearDown();
|
||||
}
|
||||
|
||||
std::vector<zes_pwr_handle_t> getPowerHandles(uint32_t count) {
|
||||
std::vector<zes_pwr_handle_t> handles(count, nullptr);
|
||||
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
|
||||
return handles;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ult
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
@@ -564,7 +564,7 @@ TEST_F(SysmanDevicePowerFixtureI915, GivenHwMonDoesNotExistAndTelemDataNotAvaila
|
||||
TEST_F(SysmanDevicePowerFixtureI915, GivenValidPowerHandlesWithTelemetrySupportNotAvailableButSysfsReadSucceedsWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrievedFromSysfsNode) {
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
std::unique_ptr<PublicLinuxPowerImp> pLinuxPowerImp(new PublicLinuxPowerImp(pOsSysman, false, 0, ZES_POWER_DOMAIN_PACKAGE));
|
||||
pLinuxPowerImp->isTelemetrySupportAvailable = true;
|
||||
pLinuxPowerImp->isTelemetrySupportAvailable = false;
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, pLinuxPowerImp->getEnergyCounter(&energyCounter));
|
||||
EXPECT_EQ(energyCounter.energy, expectedEnergyCounter);
|
||||
}
|
||||
@@ -588,14 +588,6 @@ TEST_F(SysmanDevicePowerFixtureI915, GivenValidPowerHandleWhenSettingPowerEnergy
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SysmanDevicePowerFixtureXe, GivenKmdInterfaceWhenGettingSysFsFilenamesForPowerForXeVersionThenProperPathsAreReturned) {
|
||||
auto pSysmanKmdInterface = std::make_unique<SysmanKmdInterfaceXe>(pLinuxSysmanImp->getSysmanProductHelper());
|
||||
EXPECT_STREQ("energy1_input", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageEnergyCounterNode, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_rated_max", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageDefaultPowerLimit, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_max", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageSustainedPowerLimit, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_max_interval", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageSustainedPowerLimitInterval, 0, false).c_str());
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power_xe.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
namespace ult {
|
||||
|
||||
TEST_F(SysmanDevicePowerFixtureXe, GivenKmdInterfaceWhenGettingSysFsFilenamesForPowerForXeVersionThenProperPathsAreReturned) {
|
||||
auto pSysmanKmdInterface = std::make_unique<SysmanKmdInterfaceXe>(pLinuxSysmanImp->getSysmanProductHelper());
|
||||
EXPECT_STREQ("energy1_input", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameCardEnergyCounterNode, 0, false).c_str());
|
||||
EXPECT_STREQ("energy2_input", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageEnergyCounterNode, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_rated_max", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageDefaultPowerLimit, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_max", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageSustainedPowerLimit, 0, false).c_str());
|
||||
EXPECT_STREQ("power1_max_interval", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePackageSustainedPowerLimitInterval, 0, false).c_str());
|
||||
}
|
||||
|
||||
TEST_F(SysmanDevicePowerFixtureXe, GivenComponentCountZeroWhenEnumeratingPowerDomainsWhenOnlySysfsNodesExistThenValidCountIsReturned) {
|
||||
uint32_t count = 0;
|
||||
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
|
||||
EXPECT_EQ(count, 2u);
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
@@ -143,7 +143,7 @@ TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenCallingGetNativ
|
||||
TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenCallingGetPowerDomainsThenValidPowerDomainsAreReturned) {
|
||||
auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface();
|
||||
|
||||
std::vector<zes_power_domain_t> validPowerDomains = {ZES_POWER_DOMAIN_PACKAGE};
|
||||
std::vector<zes_power_domain_t> validPowerDomains = {ZES_POWER_DOMAIN_PACKAGE, ZES_POWER_DOMAIN_CARD, ZES_POWER_DOMAIN_MEMORY, ZES_POWER_DOMAIN_GPU};
|
||||
auto powerDomains = pSysmanKmdInterface->getPowerDomains();
|
||||
|
||||
std::unordered_set<zes_power_domain_t> outputPowerDomainList(powerDomains.begin(), powerDomains.end());
|
||||
@@ -188,12 +188,13 @@ TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenCallingGpuBindA
|
||||
EXPECT_STREQ("/sys/bus/pci/drivers/xe/unbind", pSysmanKmdInterface->getGpuUnBindEntry().c_str());
|
||||
}
|
||||
|
||||
TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceWhenGetEnergyCounterNodeFilePathIsCalledForDifferentPowerDomainsThenProperPathIsReturned) {
|
||||
TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceWhenGetEnergyCounterNodeFileIsCalledForDifferentPowerDomainsThenProperFileNameIsReturned) {
|
||||
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
|
||||
std::string expectedFilePath = "energy1_input";
|
||||
EXPECT_EQ(expectedFilePath, pSysmanKmdInterface->getEnergyCounterNodeFile(ZES_POWER_DOMAIN_CARD));
|
||||
expectedFilePath = "energy2_input";
|
||||
EXPECT_EQ(expectedFilePath, pSysmanKmdInterface->getEnergyCounterNodeFile(ZES_POWER_DOMAIN_PACKAGE));
|
||||
expectedFilePath = "";
|
||||
EXPECT_EQ(expectedFilePath, pSysmanKmdInterface->getEnergyCounterNodeFile(ZES_POWER_DOMAIN_CARD));
|
||||
EXPECT_EQ(expectedFilePath, pSysmanKmdInterface->getEnergyCounterNodeFile(ZES_POWER_DOMAIN_UNKNOWN));
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ if(UNIX)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_frequency_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_ras_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_power_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_power_tests_xe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_pmt_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_device_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_pci_tests.cpp
|
||||
|
||||
@@ -19,8 +19,7 @@ constexpr uint32_t powerHandleComponentCount = 1u;
|
||||
|
||||
static int mockReadLinkSuccess(const char *path, char *buf, size_t bufsize) {
|
||||
std::map<std::string, std::string> fileNameLinkMap = {
|
||||
{sysfsPathTelem1, realPathTelem1},
|
||||
};
|
||||
{sysfsPathTelem1, realPathTelem1}};
|
||||
auto it = fileNameLinkMap.find(std::string(path));
|
||||
if (it != fileNameLinkMap.end()) {
|
||||
std::memcpy(buf, it->second.c_str(), it->second.size());
|
||||
@@ -43,7 +42,7 @@ static int mockOpenSuccess(const char *pathname, int flags) {
|
||||
returnValue = 5;
|
||||
} else if ((strPathName == telem1TelemFileName) || (strPathName == telem2TelemFileName) || (strPathName == telem3TelemFileName)) {
|
||||
returnValue = 6;
|
||||
} else if (strPathName.find(energyCounterNode) != std::string::npos) {
|
||||
} else if (strPathName.find(packageEnergyCounterNode) != std::string::npos) {
|
||||
returnValue = 7;
|
||||
}
|
||||
return returnValue;
|
||||
@@ -160,8 +159,8 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleForPackageDomainWit
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
uint64_t telem1Offset = 0;
|
||||
std::string validGuid = "0x4f9302";
|
||||
constexpr uint64_t telem1Offset = 0;
|
||||
constexpr std::string_view validGuid = "0x4f9302";
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telem1Offset, count);
|
||||
} else if (fd == 5) {
|
||||
@@ -178,13 +177,12 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleForPackageDomainWit
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pLinuxPowerImp->getEnergyCounter(&energyCounter));
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleForPackageDomainWithTelemetryOffsetReadFailsAndSysfsNodeReadAlsoFailsWhenGettingPowerEnergyCounterThenFailureIsReturned, IsDG2) {
|
||||
HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleForPackageDomainWithTelemetrySupportAvailableAndTelemetryOffsetReadFailsWhenGettingPowerEnergyCounterThenFailureIsReturned, IsDG2) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
std::string invalidGuid = "0x4f9302";
|
||||
if (fd == 4) {
|
||||
count = -1;
|
||||
}
|
||||
@@ -204,8 +202,8 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleForPackageDomainWit
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
uint64_t telem1Offset = 0;
|
||||
std::string invalidGuid = "0xABCDEFG";
|
||||
constexpr uint64_t telem1Offset = 0;
|
||||
constexpr std::string_view invalidGuid = "0xABCDEFG";
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telem1Offset, count);
|
||||
} else if (fd == 5) {
|
||||
@@ -228,8 +226,8 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandlesWithTelemetrySuppo
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
uint64_t telem1Offset = 0;
|
||||
std::string validGuid = "0x4f9302";
|
||||
constexpr uint64_t telem1Offset = 0;
|
||||
constexpr std::string_view validGuid = "0x4f9302";
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telem1Offset, count);
|
||||
@@ -256,6 +254,7 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandlesWithTelemetrySuppo
|
||||
EXPECT_EQ(ZES_POWER_DOMAIN_PACKAGE, extProperties.domain);
|
||||
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
uint64_t timeStampInitial = SysmanDevice::getSysmanTimestamp();
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetEnergyCounter(handle, &energyCounter));
|
||||
|
||||
// Calculate output energyCounter value
|
||||
@@ -263,10 +262,11 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandlesWithTelemetrySuppo
|
||||
uint64_t outputEnergyCounter = static_cast<uint64_t>((setEnergyCounter / fixedPointToJoule) * convertJouleToMicroJoule);
|
||||
|
||||
EXPECT_EQ(energyCounter.energy, outputEnergyCounter);
|
||||
EXPECT_GE(energyCounter.timestamp, timeStampInitial);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanProductHelperPowerTest, GivenValidSubdevicePowerHandleForPackagePackageDomainWithTelemetrySupportNotAvailableAndSysfsNodeReadFailsWhenGettingPowerEnergyCounterThenFailureIsReturned, IsPVC) {
|
||||
HWTEST2_F(SysmanProductHelperPowerTest, GivenValidSubdevicePowerHandleForPackageDomainWithTelemetrySupportNotAvailableAndSysfsNodeReadFailsWhenGettingPowerEnergyCounterThenFailureIsReturned, IsPVC) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkFailure);
|
||||
pSysfsAccess->mockReadValUnsignedLongResult.push_back(ZE_RESULT_ERROR_NOT_AVAILABLE);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
@@ -496,6 +496,50 @@ HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleWhenWritingToSustai
|
||||
using SysmanProductHelperPowerMultiDeviceTest = SysmanDevicePowerMultiDeviceFixture;
|
||||
constexpr uint32_t powerHandleComponentCountMultiDevice = 3u;
|
||||
|
||||
HWTEST2_F(SysmanProductHelperPowerMultiDeviceTest, GivenValidPowerHandlesWithTelemetrySupportAvailableButNoTelemDataWhenGettingPowerEnergyCounterThenEnergyCounterIsRetrievedThroughSysfsNode, IsPVC) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
constexpr uint64_t telem1Offset = 0;
|
||||
constexpr std::string_view validGuid = "0xb15a0edd";
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telem1Offset, count);
|
||||
} else if (fd == 5) {
|
||||
memcpy(buf, validGuid.data(), count);
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
auto handles = getPowerHandles(powerHandleComponentCountMultiDevice);
|
||||
for (auto handle : handles) {
|
||||
ASSERT_NE(nullptr, handle);
|
||||
|
||||
zes_power_properties_t properties = {};
|
||||
zes_power_ext_properties_t extProperties = {};
|
||||
|
||||
properties.pNext = &extProperties;
|
||||
extProperties.stype = ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES;
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetProperties(handle, &properties));
|
||||
EXPECT_EQ(ZES_POWER_DOMAIN_PACKAGE, extProperties.domain);
|
||||
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
const uint64_t timeStampInitial = SysmanDevice::getSysmanTimestamp();
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetEnergyCounter(handle, &energyCounter));
|
||||
|
||||
if (!properties.onSubdevice) {
|
||||
EXPECT_EQ(energyCounter.energy, expectedEnergyCounter);
|
||||
} else if (properties.subdeviceId == 0u) {
|
||||
EXPECT_EQ(energyCounter.energy, expectedEnergyCounterTile0);
|
||||
} else if (properties.subdeviceId == 1u) {
|
||||
EXPECT_EQ(energyCounter.energy, expectedEnergyCounterTile1);
|
||||
}
|
||||
|
||||
EXPECT_GE(energyCounter.timestamp, timeStampInitial);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanProductHelperPowerMultiDeviceTest, GivenSetPowerLimitsWhenGettingPowerLimitsThenLimitsSetEarlierAreRetrieved, IsXeHpOrXeHpcOrXeHpgCore) {
|
||||
auto handles = getPowerHandles(powerHandleComponentCountMultiDevice);
|
||||
for (auto handle : handles) {
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "level_zero/sysman/source/shared/linux/product_helper/sysman_product_helper.h"
|
||||
#include "level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power_xe.h"
|
||||
|
||||
namespace L0 {
|
||||
namespace Sysman {
|
||||
namespace ult {
|
||||
|
||||
const std::string_view telem2OffsetFileName("/sys/class/intel_pmt/telem2/offset");
|
||||
const std::string_view telem2GuidFileName("/sys/class/intel_pmt/telem2/guid");
|
||||
const std::string_view telem2TelemFileName("/sys/class/intel_pmt/telem2/telem");
|
||||
const std::string_view telem3OffsetFileName("/sys/class/intel_pmt/telem3/offset");
|
||||
const std::string_view telem3GuidFileName("/sys/class/intel_pmt/telem3/guid");
|
||||
const std::string_view telem3TelemFileName("/sys/class/intel_pmt/telem3/telem");
|
||||
|
||||
using SysmanXeProductHelperPowerTest = SysmanDevicePowerFixtureXe;
|
||||
constexpr uint32_t bmgPowerHandleComponentCount = 4u;
|
||||
|
||||
static int mockReadLinkSuccess(const char *path, char *buf, size_t bufsize) {
|
||||
|
||||
const std::string sysfsPathTelem1 = "/sys/class/intel_pmt/telem1";
|
||||
const std::string sysfsPathTelem2 = "/sys/class/intel_pmt/telem2";
|
||||
const std::string sysfsPathTelem3 = "/sys/class/intel_pmt/telem3";
|
||||
const std::string realPathTelem1 = "/sys/devices/pci0000:00/0000:00:0a.0/intel_vsec.telemetry.0/intel_pmt/telem1";
|
||||
const std::string realPathTelem2 = "/sys/devices/pci0000:00/0000:00:1c.4/0000:06:00.0/0000:07:01.0/0000:08:00.0/intel_vsec.telemetry.1/intel_pmt/telem2";
|
||||
const std::string realPathTelem3 = "/sys/devices/pci0000:00/0000:00:1c.4/0000:06:00.0/0000:07:01.0/0000:08:00.0/intel_vsec.telemetry.1/intel_pmt/telem3";
|
||||
|
||||
std::map<std::string, std::string> fileNameLinkMap = {
|
||||
{sysfsPathTelem1, realPathTelem1},
|
||||
{sysfsPathTelem2, realPathTelem2},
|
||||
{sysfsPathTelem3, realPathTelem3}};
|
||||
auto it = fileNameLinkMap.find(std::string(path));
|
||||
if (it != fileNameLinkMap.end()) {
|
||||
std::memcpy(buf, it->second.c_str(), it->second.size());
|
||||
return static_cast<int>(it->second.size());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mockOpenSuccess(const char *pathname, int flags) {
|
||||
int returnValue = -1;
|
||||
std::string strPathName(pathname);
|
||||
if ((strPathName == telem2OffsetFileName) || (strPathName == telem3OffsetFileName)) {
|
||||
returnValue = 4;
|
||||
} else if (strPathName == telem2GuidFileName) {
|
||||
returnValue = 5;
|
||||
} else if (strPathName == telem3GuidFileName) {
|
||||
returnValue = 6;
|
||||
} else if (strPathName == telem2TelemFileName) {
|
||||
returnValue = 7;
|
||||
} else if (strPathName == telem3TelemFileName) {
|
||||
returnValue = 8;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
inline static int mockStatSuccess(const std::string &filePath, struct stat *statbuf) noexcept {
|
||||
statbuf->st_mode = S_IWUSR | S_IRUSR | S_IFREG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenComponentCountZeroWhenEnumeratingPowerDomainsWhenPmtSupportIsAvailableThenValidCountIsReturned, IsBMG) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
constexpr uint64_t telemOffset = 0;
|
||||
constexpr std::string_view validOobmsmGuid = "0x5e2f8211";
|
||||
constexpr std::string_view validPunitGuid = "0x1e2f8200";
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telemOffset, count);
|
||||
} else if (fd == 5) {
|
||||
memcpy(buf, validOobmsmGuid.data(), count);
|
||||
} else if (fd == 6) {
|
||||
memcpy(buf, validPunitGuid.data(), count);
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
uint32_t count = 0;
|
||||
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
|
||||
EXPECT_EQ(count, bmgPowerHandleComponentCount);
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenSysmanProductHelperInstanceWhenGettingPowerEnergyCounterForUnknownPowerDomainThenFailureIsReturned, IsBMG) {
|
||||
auto pSysmanProductHelper = L0::Sysman::SysmanProductHelper::create(defaultHwInfo->platform.eProductFamily);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = pSysmanProductHelper->getPowerEnergyCounter(&energyCounter, pLinuxSysmanImp, ZES_POWER_DOMAIN_UNKNOWN, 0u);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenSysmanProductHelperInstanceWhenGettingPowerEnergyCounterAndNoTelemNodesAreAvailableThenFailureIsReturned, IsBMG) {
|
||||
auto pSysmanProductHelper = L0::Sysman::SysmanProductHelper::create(defaultHwInfo->platform.eProductFamily);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = pSysmanProductHelper->getPowerEnergyCounter(&energyCounter, pLinuxSysmanImp, ZES_POWER_DOMAIN_CARD, 0u);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenSysmanProductHelperInstanceWhenGettingPowerEnergyCounterAndReadGuidFailsFromPmtUtilThenFailureIsReturned, IsBMG) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
if (fd == 5 || fd == 6) {
|
||||
count = -1;
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
auto pSysmanProductHelper = L0::Sysman::SysmanProductHelper::create(defaultHwInfo->platform.eProductFamily);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = pSysmanProductHelper->getPowerEnergyCounter(&energyCounter, pLinuxSysmanImp, ZES_POWER_DOMAIN_CARD, 0u);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenSysmanProductHelperInstanceWhenGettingPowerEnergyCounterAndKeyOffsetMapIsNotAvailableThenFailureIsReturned, IsBMG) {
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
constexpr uint64_t telemOffset = 0;
|
||||
constexpr std::string_view dummyGuid = "0xABCDEF";
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telemOffset, count);
|
||||
} else if (fd == 5 || fd == 6) {
|
||||
memcpy(buf, dummyGuid.data(), count);
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
auto pSysmanProductHelper = L0::Sysman::SysmanProductHelper::create(defaultHwInfo->platform.eProductFamily);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = pSysmanProductHelper->getPowerEnergyCounter(&energyCounter, pLinuxSysmanImp, ZES_POWER_DOMAIN_CARD, 0u);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenSysmanProductHelperInstanceWhenGettingPowerEnergyCounterAndReadValueFailsForDifferentKeysThenFailureIsReturned, IsBMG) {
|
||||
static int readFailCount = 1;
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
constexpr uint64_t telemOffset = 0;
|
||||
constexpr std::string_view validOobmsmGuid = "0x5e2f8211";
|
||||
constexpr std::string_view validPunitGuid = "0x1e2f8200";
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telemOffset, count);
|
||||
} else if (fd == 5) {
|
||||
memcpy(buf, validOobmsmGuid.data(), count);
|
||||
} else if (fd == 6) {
|
||||
memcpy(buf, validPunitGuid.data(), count);
|
||||
} else if (fd == 7) {
|
||||
switch (offset) {
|
||||
case 140:
|
||||
count = (readFailCount == 1) ? -1 : sizeof(uint32_t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (fd == 8) {
|
||||
switch (offset) {
|
||||
case 4:
|
||||
count = (readFailCount == 2) ? -1 : sizeof(uint32_t);
|
||||
break;
|
||||
case 1024:
|
||||
count = (readFailCount == 3) ? -1 : sizeof(uint64_t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
auto pSysmanProductHelper = L0::Sysman::SysmanProductHelper::create(defaultHwInfo->platform.eProductFamily);
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
while (readFailCount <= 3) {
|
||||
auto result = pSysmanProductHelper->getPowerEnergyCounter(&energyCounter, pLinuxSysmanImp, ZES_POWER_DOMAIN_CARD, 0u);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
|
||||
readFailCount++;
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenValidPowerHandlesWhenGettingPowerEnergyCounterThenValidValuesAreReturnedFromBothOobmsmAndPunitPath, IsBMG) {
|
||||
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
uint64_t telemOffset = 0;
|
||||
constexpr std::string_view validOobmsmGuid = "0x5e2f8211";
|
||||
constexpr std::string_view validPunitGuid = "0x1e2f8200";
|
||||
constexpr uint32_t mockEnergyCounter = 0xabcd;
|
||||
constexpr uint32_t mockXtalFrequency = 0xef;
|
||||
constexpr uint64_t mockTimestamp = 0xabef;
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telemOffset, count);
|
||||
} else if (fd == 5) {
|
||||
memcpy(buf, validOobmsmGuid.data(), count);
|
||||
} else if (fd == 6) {
|
||||
memcpy(buf, validPunitGuid.data(), count);
|
||||
} else if (fd == 7) {
|
||||
switch (offset) {
|
||||
case 136:
|
||||
case 140:
|
||||
memcpy(buf, &mockEnergyCounter, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (fd == 8) {
|
||||
switch (offset) {
|
||||
case 4:
|
||||
memcpy(buf, &mockXtalFrequency, count);
|
||||
break;
|
||||
case 1024:
|
||||
memcpy(buf, &mockTimestamp, count);
|
||||
break;
|
||||
case 1628:
|
||||
case 1640:
|
||||
memcpy(buf, &mockEnergyCounter, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
constexpr uint32_t mockEnergyCounter = 0xabcd;
|
||||
constexpr uint32_t mockXtalFrequency = 0xef;
|
||||
constexpr uint64_t mockTimestamp = 0xabef;
|
||||
constexpr double indexToXtalClockFrequecyMap[4] = {24, 19.2, 38.4, 25};
|
||||
|
||||
auto handles = getPowerHandles(bmgPowerHandleComponentCount);
|
||||
|
||||
for (auto handle : handles) {
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = zesPowerGetEnergyCounter(handle, &energyCounter);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
const uint32_t integerPart = static_cast<uint32_t>(mockEnergyCounter >> 14);
|
||||
const uint32_t decimalBits = static_cast<uint32_t>(mockEnergyCounter & 0x3FFF);
|
||||
const double decimalPart = static_cast<double>(decimalBits) / (1 << 14);
|
||||
const double finalValue = static_cast<double>(integerPart + decimalPart);
|
||||
const uint64_t expectedEnergyCounter = static_cast<uint64_t>((finalValue * convertJouleToMicroJoule));
|
||||
EXPECT_EQ(expectedEnergyCounter, energyCounter.energy);
|
||||
|
||||
const double timestamp = mockTimestamp / indexToXtalClockFrequecyMap[mockXtalFrequency & 0x2];
|
||||
const uint64_t expectedTimestamp = static_cast<uint64_t>(timestamp);
|
||||
EXPECT_EQ(expectedTimestamp, energyCounter.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenValidPowerHandlesWhenGettingPowerEnergyCounterThenAllValidValuesAreReturnedFromPunitPath, IsBMG) {
|
||||
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, &mockReadLinkSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsStat)> mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess);
|
||||
VariableBackup<bool> allowFakeDevicePathBackup(&NEO::SysCalls::allowFakeDevicePath, true);
|
||||
VariableBackup<decltype(NEO::SysCalls::sysCallsPread)> mockPread(&NEO::SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
|
||||
uint64_t telemOffset = 0;
|
||||
constexpr std::string_view validOobmsmGuid = "0x5e2f8211";
|
||||
constexpr std::string_view validPunitGuid = "0x1e2f8201";
|
||||
constexpr uint32_t mockEnergyCounter = 0xabcd;
|
||||
constexpr uint32_t mockXtalFrequency = 0xef;
|
||||
constexpr uint64_t mockTimestamp = 0xabef;
|
||||
|
||||
if (fd == 4) {
|
||||
memcpy(buf, &telemOffset, count);
|
||||
} else if (fd == 5) {
|
||||
memcpy(buf, validOobmsmGuid.data(), count);
|
||||
} else if (fd == 6) {
|
||||
memcpy(buf, validPunitGuid.data(), count);
|
||||
} else if (fd == 7) {
|
||||
switch (offset) {
|
||||
case 136:
|
||||
case 140:
|
||||
memcpy(buf, &mockEnergyCounter, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (fd == 8) {
|
||||
switch (offset) {
|
||||
case 4:
|
||||
memcpy(buf, &mockXtalFrequency, count);
|
||||
break;
|
||||
case 1024:
|
||||
memcpy(buf, &mockTimestamp, count);
|
||||
break;
|
||||
case 48:
|
||||
case 52:
|
||||
case 1628:
|
||||
case 1640:
|
||||
memcpy(buf, &mockEnergyCounter, count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
});
|
||||
|
||||
constexpr uint32_t mockEnergyCounter = 0xabcd;
|
||||
constexpr uint32_t mockXtalFrequency = 0xef;
|
||||
constexpr uint64_t mockTimestamp = 0xabef;
|
||||
constexpr double indexToXtalClockFrequecyMap[4] = {24, 19.2, 38.4, 25};
|
||||
|
||||
auto handles = getPowerHandles(bmgPowerHandleComponentCount);
|
||||
|
||||
for (auto handle : handles) {
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
auto result = zesPowerGetEnergyCounter(handle, &energyCounter);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
|
||||
const uint32_t integerPart = static_cast<uint32_t>(mockEnergyCounter >> 14);
|
||||
const uint32_t decimalBits = static_cast<uint32_t>(mockEnergyCounter & 0x3FFF);
|
||||
const double decimalPart = static_cast<double>(decimalBits) / (1 << 14);
|
||||
const double finalValue = static_cast<double>(integerPart + decimalPart);
|
||||
const uint64_t expectedEnergyCounter = static_cast<uint64_t>((finalValue * convertJouleToMicroJoule));
|
||||
EXPECT_EQ(expectedEnergyCounter, energyCounter.energy);
|
||||
|
||||
const double timestamp = mockTimestamp / indexToXtalClockFrequecyMap[mockXtalFrequency & 0x2];
|
||||
const uint64_t expectedTimestamp = static_cast<uint64_t>(timestamp);
|
||||
EXPECT_EQ(expectedTimestamp, energyCounter.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST2_F(SysmanXeProductHelperPowerTest, GivenValidPowerHandlesWithTelemetrySupportNotAvailableButSysfsReadSucceedsWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrievedFromSysfsNode, IsBMG) {
|
||||
std::vector<zes_power_domain_t> powerDomains = {ZES_POWER_DOMAIN_PACKAGE, ZES_POWER_DOMAIN_CARD};
|
||||
for (const auto &powerDomain : powerDomains) {
|
||||
zes_power_energy_counter_t energyCounter = {};
|
||||
std::unique_ptr<PublicLinuxPowerImp> pLinuxPowerImp(new PublicLinuxPowerImp(pOsSysman, false, 0, powerDomain));
|
||||
pLinuxPowerImp->isTelemetrySupportAvailable = false;
|
||||
const uint64_t timeStampInitial = SysmanDevice::getSysmanTimestamp();
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, pLinuxPowerImp->getEnergyCounter(&energyCounter));
|
||||
EXPECT_EQ(energyCounter.energy, expectedEnergyCounter);
|
||||
EXPECT_GE(energyCounter.timestamp, timeStampInitial);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace Sysman
|
||||
} // namespace L0
|
||||
Reference in New Issue
Block a user