Enabling Power Component for Windows.

Change-Id: I67a170279994e5637e353c9eca9fff04fb02d87e
This commit is contained in:
Daniel Enriquez 2020-08-12 19:46:01 -07:00 committed by sys_ocldev
parent fe163311b1
commit d36c013acf
15 changed files with 904 additions and 59 deletions

View File

@ -12,31 +12,51 @@
#include "sysman/linux/os_sysman_imp.h"
namespace L0 {
constexpr uint64_t convertJouleToMicroJoule = 1000000u;
void powerGetTimestamp(uint64_t &timestamp) {
std::chrono::time_point<std::chrono::steady_clock> ts = std::chrono::steady_clock::now();
timestamp = std::chrono::duration_cast<std::chrono::microseconds>(ts.time_since_epoch()).count();
}
ze_result_t LinuxPowerImp::getProperties(zes_power_properties_t *pProperties) {
pProperties->onSubdevice = false;
pProperties->subdeviceId = 0;
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) {
const std::string key("PACKAGE_ENERGY");
uint64_t energy = 0;
ze_result_t result = pPmt->readValue(key, energy);
// PMT will return in joules and need to convert into microjoules
pEnergy->energy = energy * convertJouleToMicroJoule;
powerGetTimestamp(pEnergy->timestamp);
return result;
}
ze_result_t LinuxPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t LinuxPowerImp::setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t LinuxPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t LinuxPowerImp::setEnergyThreshold(double threshold) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t LinuxPowerImp::getEnergyCounter(uint64_t &energy) {
const std::string key("PACKAGE_ENERGY");
ze_result_t result = pPmt->readValue(key, energy);
// PMT will return in joules and need to convert into microjoules
energy = energy * convertJouleToMicroJoule;
return result;
}
bool LinuxPowerImp::isPowerModuleSupported() {
return pPmt->isPmtSupported();
}
LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
pPmt = &pLinuxSysmanImp->getPlatformMonitoringTechAccess();
}

View File

@ -16,16 +16,19 @@ class SysfsAccess;
class PlatformMonitoringTech;
class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass {
public:
ze_result_t getEnergyCounter(uint64_t &energy) override;
ze_result_t getProperties(zes_power_properties_t *pProperties) override;
ze_result_t getEnergyCounter(zes_power_energy_counter_t *pEnergy) override;
ze_result_t getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) override;
ze_result_t setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) override;
ze_result_t getEnergyThreshold(zes_energy_threshold_t *pThreshold) override;
ze_result_t setEnergyThreshold(double threshold) override;
bool isPowerModuleSupported() override;
LinuxPowerImp(OsSysman *pOsSysman);
LinuxPowerImp() = default;
~LinuxPowerImp() override = default;
protected:
SysfsAccess *pSysfsAccess = nullptr;
PlatformMonitoringTech *pPmt = nullptr;
};
} // namespace L0

View File

@ -14,12 +14,18 @@ namespace L0 {
struct OsSysman;
class OsPower {
public:
virtual ze_result_t getEnergyCounter(uint64_t &energy) = 0;
virtual ze_result_t getProperties(zes_power_properties_t *pProperties) = 0;
virtual ze_result_t getEnergyCounter(zes_power_energy_counter_t *pEnergy) = 0;
virtual ze_result_t getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) = 0;
virtual ze_result_t setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) = 0;
virtual ze_result_t getEnergyThreshold(zes_energy_threshold_t *pThreshold) = 0;
virtual ze_result_t setEnergyThreshold(double threshold) = 0;
virtual bool isPowerModuleSupported() = 0;
static OsPower *create(OsSysman *pOsSysman);
virtual ~OsPower() = default;
};
constexpr uint64_t convertJouleToMicroJoule = 1000000u;
} // namespace L0

View File

@ -35,6 +35,7 @@ class Power : _zet_sysman_pwr_handle_t, _zes_pwr_handle_t {
}
inline zes_pwr_handle_t toHandle() { return this; }
bool initSuccess = false;
zes_power_properties_t powerProperties = {};
};
struct PowerHandleContext {
PowerHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};

View File

@ -9,47 +9,30 @@
#include "shared/source/helpers/debug_helpers.h"
#include "level_zero/core/source/device/device.h"
#include <chrono>
namespace L0 {
void powerGetTimestamp(uint64_t &timestamp) {
std::chrono::time_point<std::chrono::steady_clock> ts = std::chrono::steady_clock::now();
timestamp = std::chrono::duration_cast<std::chrono::microseconds>(ts.time_since_epoch()).count();
}
ze_result_t PowerImp::powerSetEnergyThreshold(double threshold) {
return (pOsPower->setEnergyThreshold(threshold));
}
ze_result_t PowerImp::powerGetProperties(zes_power_properties_t *pProperties) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
*pProperties = powerProperties;
return ZE_RESULT_SUCCESS;
}
ze_result_t PowerImp::powerGetEnergyCounter(zes_power_energy_counter_t *pEnergy) {
ze_result_t result = pOsPower->getEnergyCounter(pEnergy->energy);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
powerGetTimestamp(pEnergy->timestamp);
return result;
return pOsPower->getEnergyCounter(pEnergy);
}
ze_result_t PowerImp::powerGetLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
return pOsPower->getLimits(pSustained, pBurst, pPeak);
}
ze_result_t PowerImp::powerSetLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
return pOsPower->setLimits(pSustained, pBurst, pPeak);
}
ze_result_t PowerImp::powerGetEnergyThreshold(zes_energy_threshold_t *pThreshold) {
return (pOsPower->getEnergyThreshold(pThreshold));
return pOsPower->getEnergyThreshold(pThreshold);
}
ze_result_t PowerImp::powerSetEnergyThreshold(double threshold) {
return pOsPower->setEnergyThreshold(threshold);
}
PowerImp::PowerImp(OsSysman *pOsSysman) {
@ -60,7 +43,10 @@ PowerImp::PowerImp(OsSysman *pOsSysman) {
}
void PowerImp::init() {
this->initSuccess = pOsPower->isPowerModuleSupported();
if (pOsPower->isPowerModuleSupported()) {
pOsPower->getProperties(&powerProperties);
this->initSuccess = true;
}
}
PowerImp::~PowerImp() {

View File

@ -15,13 +15,12 @@
namespace L0 {
class PowerImp : public Power, NEO::NonCopyableOrMovableClass {
public:
ze_result_t powerSetEnergyThreshold(double threshold) override;
ze_result_t powerGetProperties(zes_power_properties_t *pProperties) override;
ze_result_t powerGetEnergyCounter(zes_power_energy_counter_t *pEnergy) override;
ze_result_t powerGetLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) override;
ze_result_t powerSetLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) override;
ze_result_t powerGetEnergyThreshold(zes_energy_threshold_t *pThreshold) override;
ze_result_t powerSetEnergyThreshold(double threshold) override;
PowerImp() = default;
PowerImp(OsSysman *pOsSysman);

View File

@ -5,6 +5,8 @@
#
set(L0_SRCS_TOOLS_SYSMAN_POWER_WINDOWS
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.cpp
)

View File

@ -5,39 +5,320 @@
*
*/
#include "sysman/power/os_power.h"
#include "sysman/power/windows/os_power_imp.h"
namespace L0 {
class WddmPowerImp : public OsPower {
public:
ze_result_t getEnergyCounter(uint64_t &energy) override;
ze_result_t getEnergyThreshold(zes_energy_threshold_t *pThreshold) override;
ze_result_t setEnergyThreshold(double threshold) override;
bool isPowerModuleSupported() override;
};
ze_result_t WddmPowerImp::getProperties(zes_power_properties_t *pProperties) {
pProperties->onSubdevice = false;
pProperties->subdeviceId = 0;
ze_result_t WddmPowerImp::getEnergyCounter(uint64_t &energy) {
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
request.commandId = KmdSysman::Command::Get;
request.componentId = KmdSysman::Component::PowerComponent;
request.requestId = KmdSysman::Requests::Power::EnergyThresholdSupported;
ze_result_t status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pProperties->canControl, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t));
memcpy_s(&pProperties->isEnergyThresholdSupported, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t));
request.requestId = KmdSysman::Requests::Power::TdpDefault;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pProperties->defaultLimit, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
request.requestId = KmdSysman::Requests::Power::MinPowerLimitDefault;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pProperties->minLimit, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
request.requestId = KmdSysman::Requests::Power::MaxPowerLimitDefault;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pProperties->maxLimit, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
return status;
}
ze_result_t WddmPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) {
uint32_t energyUnits = 0;
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
request.commandId = KmdSysman::Command::Get;
request.componentId = KmdSysman::Component::PowerComponent;
request.requestId = KmdSysman::Requests::Power::EnergyCounterUnits;
ze_result_t status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&energyUnits, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
request.requestId = KmdSysman::Requests::Power::CurrentEnergyCounter;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
uint32_t valueCounter = 0;
uint64_t valueTimeStamp = 0;
memcpy_s(&valueCounter, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
valueCounter = (valueCounter >> energyUnits);
pEnergy->energy = static_cast<uint64_t>(valueCounter) * convertJouleToMicroJoule;
memcpy_s(&valueTimeStamp, sizeof(uint64_t), (response.dataBuffer + sizeof(uint32_t)), sizeof(uint64_t));
pEnergy->timestamp = valueTimeStamp;
return status;
}
ze_result_t WddmPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) {
ze_result_t status = ZE_RESULT_SUCCESS;
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
request.commandId = KmdSysman::Command::Get;
request.componentId = KmdSysman::Component::PowerComponent;
if (pSustained) {
memset(pSustained, 0, sizeof(zes_power_sustained_limit_t));
request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pSustained->enabled, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t));
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pSustained->power, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1Tau;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pSustained->interval, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
}
if (pBurst) {
memset(pBurst, 0, sizeof(zes_power_burst_limit_t));
request.requestId = KmdSysman::Requests::Power::PowerLimit2Enabled;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pBurst->enabled, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t));
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit2;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pBurst->power, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
}
if (pPeak) {
memset(pPeak, 0, sizeof(zes_power_peak_limit_t));
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Ac;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pPeak->powerAC, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Dc;
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memcpy_s(&pPeak->powerDC, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
}
return status;
}
ze_result_t WddmPowerImp::setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) {
ze_result_t status = ZE_RESULT_SUCCESS;
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
request.commandId = KmdSysman::Command::Set;
request.componentId = KmdSysman::Component::PowerComponent;
request.dataSize = sizeof(uint32_t);
if (pSustained) {
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1;
memcpy_s(request.dataBuffer, sizeof(uint32_t), &pSustained->power, sizeof(uint32_t));
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1Tau;
memcpy_s(request.dataBuffer, sizeof(uint32_t), &pSustained->interval, sizeof(uint32_t));
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
}
if (pBurst) {
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit2;
memcpy_s(request.dataBuffer, sizeof(uint32_t), &pBurst->power, sizeof(uint32_t));
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
}
if (pPeak) {
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Ac;
memcpy_s(request.dataBuffer, sizeof(uint32_t), &pPeak->powerAC, sizeof(uint32_t));
status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Dc;
memcpy_s(request.dataBuffer, sizeof(uint32_t), &pPeak->powerDC, sizeof(uint32_t));
status = pKmdSysManager->requestSingle(request, response);
}
return status;
}
ze_result_t WddmPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) {
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
pThreshold->processId = 0;
request.commandId = KmdSysman::Command::Get;
request.componentId = KmdSysman::Component::PowerComponent;
request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold;
ze_result_t status = pKmdSysManager->requestSingle(request, response);
if (status != ZE_RESULT_SUCCESS) {
return status;
}
memset(pThreshold, 0, sizeof(zes_energy_threshold_t));
uint32_t value = 0;
memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
pThreshold->threshold = static_cast<double>(value);
pThreshold->enable = true;
return status;
}
ze_result_t WddmPowerImp::setEnergyThreshold(double threshold) {
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
request.commandId = KmdSysman::Command::Set;
request.componentId = KmdSysman::Component::PowerComponent;
request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold;
request.dataSize = sizeof(uint32_t);
uint32_t value = static_cast<uint32_t>(threshold);
memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t));
return pKmdSysManager->requestSingle(request, response);
}
bool WddmPowerImp::isPowerModuleSupported() {
return false;
KmdSysman::RequestProperty request;
KmdSysman::ResponseProperty response;
request.commandId = KmdSysman::Command::Get;
request.componentId = KmdSysman::Component::PowerComponent;
request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled;
ze_result_t status = pKmdSysManager->requestSingle(request, response);
uint32_t enabled = 0;
memcpy_s(&enabled, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t));
return ((status == ZE_RESULT_SUCCESS) && (enabled));
}
WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman) {
WddmSysmanImp *pWddmSysmanImp = static_cast<WddmSysmanImp *>(pOsSysman);
pKmdSysManager = &pWddmSysmanImp->getKmdSysManager();
}
OsPower *OsPower::create(OsSysman *pOsSysman) {
WddmPowerImp *pWddmPowerImp = new WddmPowerImp();
WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman);
return static_cast<OsPower *>(pWddmPowerImp);
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "sysman/power/os_power.h"
#include "sysman/windows/os_sysman_imp.h"
namespace L0 {
class KmdSysManager;
class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass {
public:
ze_result_t getProperties(zes_power_properties_t *pProperties) override;
ze_result_t getEnergyCounter(zes_power_energy_counter_t *pEnergy) override;
ze_result_t getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) override;
ze_result_t setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) override;
ze_result_t getEnergyThreshold(zes_energy_threshold_t *pThreshold) override;
ze_result_t setEnergyThreshold(double threshold) override;
bool isPowerModuleSupported() override;
WddmPowerImp(OsSysman *pOsSysman);
WddmPowerImp() = default;
~WddmPowerImp() override = default;
protected:
KmdSysManager *pKmdSysManager = nullptr;
};
} // namespace L0

View File

@ -45,7 +45,6 @@ struct Mock<PowerPmt> : public PlatformMonitoringTech {
class PublicLinuxPowerImp : public L0::LinuxPowerImp {
public:
using LinuxPowerImp::pPmt;
using LinuxPowerImp::pSysfsAccess;
};
} // namespace ult
} // namespace L0

View File

@ -70,6 +70,17 @@ TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDoma
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesThenCallSucceeds) {
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_properties_t properties;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetProperties(handle, &properties));
EXPECT_FALSE(properties.onSubdevice);
EXPECT_EQ(properties.subdeviceId, 0u);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) {
auto handles = get_power_handles(powerHandleComponentCount);
@ -97,5 +108,25 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerEnergyThre
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsThenUnsupportedFeatureErrorIsReturned) {
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_sustained_limit_t sustained;
zes_power_burst_limit_t burst;
zes_power_peak_limit_t peak;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerGetLimits(handle, &sustained, &burst, &peak));
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsThenUnsupportedFeatureErrorIsReturned) {
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_sustained_limit_t sustained;
zes_power_burst_limit_t burst;
zes_power_peak_limit_t peak;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerSetLimits(handle, &sustained, &burst, &peak));
}
}
} // namespace ult
} // namespace L0

View File

@ -0,0 +1,14 @@
#
# Copyright (C) 2020 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(WIN32)
target_sources(${TARGET_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_sysman_power.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_power.h
)
endif()

View File

@ -0,0 +1,188 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/core/test/unit_tests/mock.h"
#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h"
#include "sysman/power/power_imp.h"
namespace L0 {
namespace ult {
class PowerKmdSysManager : public Mock<MockKmdSysManager> {};
template <>
struct Mock<PowerKmdSysManager> : public PowerKmdSysManager {
uint32_t mockPowerLimit1Enabled = 1;
uint32_t mockPowerLimit2Enabled = 1;
int32_t mockPowerLimit1 = 25000;
int32_t mockPowerLimit2 = 41000;
int32_t mockTauPowerLimit1 = 20800;
uint32_t mockTpdDefault = 34000;
uint32_t mockMinPowerLimit = 1000;
uint32_t mockMaxPowerLimit = 80000;
int32_t mockAcPowerPeak = 0;
int32_t mockDcPowerPeak = 0;
uint32_t mockEnergyThreshold = 0;
uint32_t mockEnergyCounter = 3231121;
uint32_t mockTimeStamp = 1123412412;
uint32_t mockEnergyUnit = 14;
void getPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override {
uint8_t *pBuffer = reinterpret_cast<uint8_t *>(pResponse);
pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut);
switch (pRequest->inRequestId) {
case KmdSysman::Requests::Power::EnergyThresholdSupported: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = static_cast<uint32_t>(this->allowSetCalls);
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::TdpDefault: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockTpdDefault;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::MinPowerLimitDefault: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockMinPowerLimit;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::MaxPowerLimitDefault: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockMaxPowerLimit;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::PowerLimit1Enabled: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockPowerLimit1Enabled;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::PowerLimit2Enabled: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockPowerLimit2Enabled;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit1: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
*pValue = mockPowerLimit1;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(int32_t);
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit1Tau: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
*pValue = mockTauPowerLimit1;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(int32_t);
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit2: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
*pValue = mockPowerLimit2;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(int32_t);
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit4Ac: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
*pValue = mockAcPowerPeak;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(int32_t);
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit4Dc: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
*pValue = mockDcPowerPeak;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::CurrentEnergyThreshold: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockEnergyThreshold;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
case KmdSysman::Requests::Power::CurrentEnergyCounter: {
uint32_t *pValueCounter = reinterpret_cast<uint32_t *>(pBuffer);
uint64_t *pValueTS = reinterpret_cast<uint64_t *>(pBuffer + sizeof(uint32_t));
*pValueCounter = mockEnergyCounter;
*pValueTS = mockTimeStamp;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t) + sizeof(uint64_t);
} break;
case KmdSysman::Requests::Power::EnergyCounterUnits: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
*pValue = mockEnergyUnit;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
pResponse->outDataSize = sizeof(uint32_t);
} break;
default: {
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanFail;
} break;
}
}
void setPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override {
uint8_t *pBuffer = reinterpret_cast<uint8_t *>(pRequest);
pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn);
switch (pRequest->inRequestId) {
case KmdSysman::Requests::Power::CurrentPowerLimit1: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
mockPowerLimit1 = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit1Tau: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
mockTauPowerLimit1 = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit2: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
mockPowerLimit2 = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit4Ac: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
mockAcPowerPeak = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
case KmdSysman::Requests::Power::CurrentPowerLimit4Dc: {
int32_t *pValue = reinterpret_cast<int32_t *>(pBuffer);
mockDcPowerPeak = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
case KmdSysman::Requests::Power::CurrentEnergyThreshold: {
uint32_t *pValue = reinterpret_cast<uint32_t *>(pBuffer);
mockEnergyThreshold = *pValue;
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess;
} break;
default: {
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanFail;
} break;
}
}
Mock() = default;
~Mock() = default;
};
} // namespace ult
} // namespace L0

View File

@ -0,0 +1,279 @@
/*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/tools/source/sysman/power/windows/os_power_imp.h"
#include "level_zero/tools/test/unit_tests/sources/sysman/power/windows/mock_power.h"
#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_sysman_fixture.h"
namespace L0 {
namespace ult {
constexpr uint32_t powerHandleComponentCount = 1u;
class SysmanDevicePowerFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<PowerKmdSysManager>> pKmdSysManager;
KmdSysManager *pOriginalKmdSysManager = nullptr;
void SetUp(bool allowSetCalls) { // NOLINT(readability-identifier-naming)
SysmanDeviceFixture::SetUp();
pKmdSysManager.reset(new Mock<PowerKmdSysManager>);
pKmdSysManager->allowSetCalls = allowSetCalls;
EXPECT_CALL(*pKmdSysManager, escape(_, _, _, _, _))
.WillRepeatedly(::testing::Invoke(pKmdSysManager.get(), &Mock<PowerKmdSysManager>::mock_escape));
pOriginalKmdSysManager = pWddmSysmanImp->pKmdSysManager;
pWddmSysmanImp->pKmdSysManager = pKmdSysManager.get();
for (auto handle : pSysmanDeviceImp->pPowerHandleContext->handleList) {
delete handle;
}
pSysmanDeviceImp->pPowerHandleContext->handleList.clear();
pSysmanDeviceImp->pPowerHandleContext->init();
}
void TearDown() override {
SysmanDeviceFixture::TearDown();
pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager;
}
std::vector<zes_pwr_handle_t> get_power_handles(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;
}
};
TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) {
SetUp(true);
uint32_t count = 0;
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, powerHandleComponentCount);
}
TEST_F(SysmanDevicePowerFixture, GivenInvalidComponentCountWhenEnumeratingPowerDomainThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) {
SetUp(true);
uint32_t count = 0;
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, powerHandleComponentCount);
count = count + 1;
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, powerHandleComponentCount);
}
TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainThenValidPowerHandlesIsReturned) {
SetUp(true);
uint32_t count = 0;
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS);
EXPECT_EQ(count, powerHandleComponentCount);
std::vector<zes_pwr_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
for (auto handle : handles) {
EXPECT_NE(handle, nullptr);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAllowSetToTrueThenCallSucceeds) {
// Setting allow set calls or not
SetUp(true);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_properties_t properties;
ze_result_t result = zesPowerGetProperties(handle, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(properties.onSubdevice);
EXPECT_EQ(properties.subdeviceId, 0);
EXPECT_TRUE(properties.canControl);
EXPECT_TRUE(properties.isEnergyThresholdSupported);
EXPECT_EQ(properties.maxLimit, pKmdSysManager->mockMaxPowerLimit);
EXPECT_EQ(properties.minLimit, pKmdSysManager->mockMinPowerLimit);
EXPECT_EQ(properties.defaultLimit, pKmdSysManager->mockTpdDefault);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAllowSetToFalseThenCallSucceeds) {
// Setting allow set calls or not
SetUp(false);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_properties_t properties;
ze_result_t result = zesPowerGetProperties(handle, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_FALSE(properties.onSubdevice);
EXPECT_EQ(properties.subdeviceId, 0);
EXPECT_FALSE(properties.canControl);
EXPECT_FALSE(properties.isEnergyThresholdSupported);
EXPECT_EQ(properties.maxLimit, pKmdSysManager->mockMaxPowerLimit);
EXPECT_EQ(properties.minLimit, pKmdSysManager->mockMinPowerLimit);
EXPECT_EQ(properties.defaultLimit, pKmdSysManager->mockTpdDefault);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) {
// Setting allow set calls or not
SetUp(true);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_energy_counter_t energyCounter;
ze_result_t result = zesPowerGetEnergyCounter(handle, &energyCounter);
uint32_t mockEnergytoMicroJoules = (pKmdSysManager->mockEnergyCounter >> pKmdSysManager->mockEnergyUnit) * convertJouleToMicroJoule;
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(energyCounter.energy, mockEnergytoMicroJoules);
EXPECT_EQ(energyCounter.timestamp, pKmdSysManager->mockTimeStamp);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsAllowSetToFalseThenCallSucceedsWithValidPowerReadingsRetrieved) {
// Setting allow set calls or not
SetUp(false);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_sustained_limit_t sustained;
zes_power_burst_limit_t burst;
zes_power_peak_limit_t peak;
ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(sustained.enabled);
EXPECT_EQ(sustained.power, pKmdSysManager->mockPowerLimit1);
EXPECT_EQ(sustained.interval, pKmdSysManager->mockTauPowerLimit1);
EXPECT_TRUE(burst.enabled);
EXPECT_EQ(burst.power, pKmdSysManager->mockPowerLimit2);
EXPECT_EQ(peak.powerAC, pKmdSysManager->mockAcPowerPeak);
EXPECT_EQ(peak.powerDC, pKmdSysManager->mockDcPowerPeak);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsAllowSetToFalseThenCallFails) {
// Setting allow set calls or not
SetUp(false);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_sustained_limit_t sustained;
zes_power_burst_limit_t burst;
zes_power_peak_limit_t peak;
ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
sustained.power += 1000;
result = zesPowerSetLimits(handle, &sustained, &burst, &peak);
EXPECT_NE(ZE_RESULT_SUCCESS, result);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingEnergyThresholdAllowSetToFalseThenCallFails) {
// Setting allow set calls or not
SetUp(false);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
double energyThreshold = 2000;
ze_result_t result = zesPowerSetEnergyThreshold(handle, energyThreshold);
EXPECT_NE(ZE_RESULT_SUCCESS, result);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingEnergyThresholdAllowSetToTrueThenCallSucceeds) {
// Setting allow set calls or not
SetUp(true);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
double energyThreshold = 2000;
ze_result_t result = zesPowerSetEnergyThreshold(handle, energyThreshold);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
zes_energy_threshold_t newEnergyThreshold;
result = zesPowerGetEnergyThreshold(handle, &newEnergyThreshold);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(newEnergyThreshold.threshold, energyThreshold);
}
}
TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsAllowSetToTrueThenCallSucceeds) {
// Setting allow set calls or not
SetUp(true);
auto handles = get_power_handles(powerHandleComponentCount);
for (auto handle : handles) {
zes_power_sustained_limit_t sustained;
zes_power_burst_limit_t burst;
zes_power_peak_limit_t peak;
uint32_t powerIncrement = 1500;
uint32_t timeIncrement = 12000;
uint32_t AcPeakPower = 56000;
uint32_t DcPeakPower = 44100;
ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
sustained.power += powerIncrement;
sustained.interval += timeIncrement;
burst.power += powerIncrement;
peak.powerAC = AcPeakPower;
peak.powerDC = DcPeakPower;
result = zesPowerSetLimits(handle, &sustained, &burst, &peak);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
zes_power_sustained_limit_t newSustained;
zes_power_burst_limit_t newBurst;
zes_power_peak_limit_t newPeak;
result = zesPowerGetLimits(handle, &newSustained, &newBurst, &newPeak);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(newSustained.power, sustained.power);
EXPECT_EQ(newSustained.interval, sustained.interval);
EXPECT_EQ(newBurst.power, burst.power);
EXPECT_EQ(newPeak.powerAC, peak.powerAC);
EXPECT_EQ(newPeak.powerDC, peak.powerDC);
}
}
} // namespace ult
} // namespace L0

View File

@ -204,6 +204,8 @@ struct Mock<MockKmdSysManager> : public MockKmdSysManager {
void setProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) {
if (!allowSetCalls) {
pResponse->outDataSize = 0;
pResponse->outReturnCode = KmdSysman::KmdSysmanFail;
return;
}