Update Sysman frequency API as per latest spec

Change-Id: I5bfdb5e5681e9cfa054f48cf8cc4fd8e76740958
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2020-07-24 16:39:09 +05:30
committed by sys_ocldev
parent 887f52d9de
commit 70babc4b69
12 changed files with 553 additions and 32 deletions

View File

@@ -238,6 +238,14 @@ zetSysmanPowerSetEnergyThreshold(
return L0::Power::fromHandle(hPower)->powerSetEnergyThreshold(threshold);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesDeviceEnumFrequencyDomains(
zes_device_handle_t hDevice,
uint32_t *pCount,
zes_freq_handle_t *phFrequency) {
return L0::SysmanDevice::fromHandle(hDevice)->frequencyGet(pCount, phFrequency);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGet(
zet_sysman_handle_t hSysman,
@@ -246,6 +254,13 @@ zetSysmanFrequencyGet(
return L0::Sysman::fromHandle(hSysman)->frequencyGet(pCount, phFrequency);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencyGetProperties(
zes_freq_handle_t hFrequency,
zes_freq_properties_t *pProperties) {
return L0::Frequency::fromHandle(hFrequency)->frequencyGetProperties(pProperties);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGetProperties(
zet_sysman_freq_handle_t hFrequency,
@@ -253,6 +268,14 @@ zetSysmanFrequencyGetProperties(
return L0::Frequency::fromHandle(hFrequency)->frequencyGetProperties(pProperties);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencyGetAvailableClocks(
zes_freq_handle_t hFrequency,
uint32_t *pCount,
double *phFrequency) {
return L0::Frequency::fromHandle(hFrequency)->frequencyGetAvailableClocks(pCount, phFrequency);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGetAvailableClocks(
zet_sysman_freq_handle_t hFrequency,
@@ -261,6 +284,13 @@ zetSysmanFrequencyGetAvailableClocks(
return L0::Frequency::fromHandle(hFrequency)->frequencyGetAvailableClocks(pCount, phFrequency);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencyGetRange(
zes_freq_handle_t hFrequency,
zes_freq_range_t *pLimits) {
return L0::Frequency::fromHandle(hFrequency)->frequencyGetRange(pLimits);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGetRange(
zet_sysman_freq_handle_t hFrequency,
@@ -268,6 +298,13 @@ zetSysmanFrequencyGetRange(
return L0::Frequency::fromHandle(hFrequency)->frequencyGetRange(pLimits);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencySetRange(
zes_freq_handle_t hFrequency,
const zes_freq_range_t *pLimits) {
return L0::Frequency::fromHandle(hFrequency)->frequencySetRange(pLimits);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencySetRange(
zet_sysman_freq_handle_t hFrequency,
@@ -275,6 +312,13 @@ zetSysmanFrequencySetRange(
return L0::Frequency::fromHandle(hFrequency)->frequencySetRange(pLimits);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencyGetState(
zes_freq_handle_t hFrequency,
zes_freq_state_t *pState) {
return L0::Frequency::fromHandle(hFrequency)->frequencyGetState(pState);
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGetState(
zet_sysman_freq_handle_t hFrequency,
@@ -282,6 +326,13 @@ zetSysmanFrequencyGetState(
return L0::Frequency::fromHandle(hFrequency)->frequencyGetState(pState);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zesFrequencyGetThrottleTime(
zes_freq_handle_t hFrequency,
zes_freq_throttle_time_t *pThrottleTime) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
__zedllexport ze_result_t __zecall
zetSysmanFrequencyGetThrottleTime(
zet_sysman_freq_handle_t hFrequency,

View File

@@ -38,4 +38,19 @@ ze_result_t FrequencyHandleContext::frequencyGet(uint32_t *pCount, zet_sysman_fr
return ZE_RESULT_SUCCESS;
}
ze_result_t FrequencyHandleContext::frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) {
if (nullptr == phFrequency) {
*pCount = static_cast<uint32_t>(handle_list.size());
return ZE_RESULT_SUCCESS;
}
uint32_t i = 0;
for (Frequency *freq : handle_list) {
if (i >= *pCount)
break;
phFrequency[i++] = freq->toZesFreqHandle();
}
*pCount = i;
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@@ -8,15 +8,23 @@
#pragma once
#include <level_zero/zet_api.h>
#include "third_party/level_zero/zes_api_ext.h"
#include <vector>
struct _zet_sysman_freq_handle_t {};
struct _zet_sysman_freq_handle_t {
virtual ~_zet_sysman_freq_handle_t() = default;
};
struct _zes_freq_handle_t {
virtual ~_zes_freq_handle_t() = default;
};
namespace L0 {
struct OsSysman;
class Frequency : _zet_sysman_freq_handle_t {
class Frequency : _zet_sysman_freq_handle_t, _zes_freq_handle_t {
public:
virtual ~Frequency() {}
virtual ze_result_t frequencyGetProperties(zet_freq_properties_t *pProperties) = 0;
@@ -25,10 +33,20 @@ class Frequency : _zet_sysman_freq_handle_t {
virtual ze_result_t frequencySetRange(const zet_freq_range_t *pLimits) = 0;
virtual ze_result_t frequencyGetState(zet_freq_state_t *pState) = 0;
virtual ze_result_t frequencyGetProperties(zes_freq_properties_t *pProperties) = 0;
virtual ze_result_t frequencyGetRange(zes_freq_range_t *pLimits) = 0;
virtual ze_result_t frequencySetRange(const zes_freq_range_t *pLimits) = 0;
virtual ze_result_t frequencyGetState(zes_freq_state_t *pState) = 0;
virtual ze_result_t frequencyGetThrottleTime(zes_freq_throttle_time_t *pThrottleTime) = 0;
static Frequency *fromHandle(zet_sysman_freq_handle_t handle) {
return static_cast<Frequency *>(handle);
}
static Frequency *fromHandle(zes_freq_handle_t handle) {
return static_cast<Frequency *>(handle);
}
inline zet_sysman_freq_handle_t toHandle() { return this; }
inline zes_freq_handle_t toZesFreqHandle() { return this; }
};
struct FrequencyHandleContext {
@@ -38,6 +56,7 @@ struct FrequencyHandleContext {
ze_result_t init();
ze_result_t frequencyGet(uint32_t *pCount, zet_sysman_freq_handle_t *phFrequency);
ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency);
OsSysman *pOsSysman;
std::vector<Frequency *> handle_list = {};

View File

@@ -16,6 +16,88 @@ namespace L0 {
const double FrequencyImp::step = 50.0 / 3; // Step of 16.6666667 Mhz (GEN9 Hardcode)
const bool FrequencyImp::canControl = true; // canControl is true on i915 (GEN9 Hardcode)
ze_result_t FrequencyImp::frequencyGetProperties(zes_freq_properties_t *pProperties) {
*pProperties = zesFrequencyProperties;
return ZE_RESULT_SUCCESS;
}
ze_result_t FrequencyImp::frequencyGetRange(zes_freq_range_t *pLimits) {
ze_result_t result = pOsFrequency->getMax(pLimits->max);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
return pOsFrequency->getMin(pLimits->min);
}
ze_result_t FrequencyImp::frequencySetRange(const zes_freq_range_t *pLimits) {
double newMin = round(pLimits->min);
double newMax = round(pLimits->max);
bool newMinValid = false, newMaxValid = false;
for (unsigned int i = 0; i < numClocks; i++) {
if (newMin == pClocks[i]) {
newMinValid = true;
}
if (newMax == pClocks[i]) {
newMaxValid = true;
}
}
if (newMin > newMax || !newMinValid || !newMaxValid) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
double currentMax;
pOsFrequency->getMax(currentMax);
if (newMin > currentMax) {
// set the max first
ze_result_t result = pOsFrequency->setMax(newMax);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
return pOsFrequency->setMin(newMin);
}
// set the min first
ze_result_t result = pOsFrequency->setMin(newMin);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
return pOsFrequency->setMax(newMax);
}
ze_result_t FrequencyImp::frequencyGetState(zes_freq_state_t *pState) {
ze_result_t result;
result = pOsFrequency->getRequest(pState->request);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
result = pOsFrequency->getTdp(pState->tdp);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
result = pOsFrequency->getEfficient(pState->efficient);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
result = pOsFrequency->getActual(pState->actual);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
pState->stype = ZES_STRUCTURE_TYPE_FREQ_STATE;
pState->pNext = nullptr;
pState->currentVoltage = -1.0;
pState->throttleReasons = 0u;
return result;
}
ze_result_t FrequencyImp::frequencyGetThrottleTime(zes_freq_throttle_time_t *pThrottleTime) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t FrequencyImp::frequencyGetProperties(zet_freq_properties_t *pProperties) {
*pProperties = frequencyProperties;
return ZE_RESULT_SUCCESS;
@@ -133,6 +215,22 @@ void FrequencyImp::init() {
pClocks[i] = round(frequencyProperties.min + (frequencyProperties.step * i));
}
frequencyProperties.isThrottleEventSupported = false;
zesFrequencyProperties.stype = ZES_STRUCTURE_TYPE_FREQ_PROPERTIES;
zesFrequencyProperties.pNext = nullptr;
zesFrequencyProperties.type = ZES_FREQ_DOMAIN_GPU;
zesFrequencyProperties.onSubdevice = false;
zesFrequencyProperties.subdeviceId = 0;
zesFrequencyProperties.canControl = canControl;
ze_result_t result3 = pOsFrequency->getMinVal(zesFrequencyProperties.min);
ze_result_t result4 = pOsFrequency->getMaxVal(zesFrequencyProperties.max);
// If can't figure out the valid range, then can't control it.
if (ZE_RESULT_SUCCESS != result3 || ZE_RESULT_SUCCESS != result4) {
zesFrequencyProperties.canControl = false;
zesFrequencyProperties.min = 0.0;
zesFrequencyProperties.max = 0.0;
}
zesFrequencyProperties.isThrottleEventSupported = false;
}
FrequencyImp::FrequencyImp(OsSysman *pOsSysman) {

View File

@@ -23,6 +23,12 @@ class FrequencyImp : public Frequency, NEO::NonCopyableOrMovableClass {
ze_result_t frequencySetRange(const zet_freq_range_t *pLimits) override;
ze_result_t frequencyGetState(zet_freq_state_t *pState) override;
ze_result_t frequencyGetProperties(zes_freq_properties_t *pProperties) override;
ze_result_t frequencyGetRange(zes_freq_range_t *pLimits) override;
ze_result_t frequencySetRange(const zes_freq_range_t *pLimits) override;
ze_result_t frequencyGetState(zes_freq_state_t *pState) override;
ze_result_t frequencyGetThrottleTime(zes_freq_throttle_time_t *pThrottleTime) override;
FrequencyImp() = default;
FrequencyImp(OsSysman *pOsSysman);
~FrequencyImp() override;
@@ -34,6 +40,7 @@ class FrequencyImp : public Frequency, NEO::NonCopyableOrMovableClass {
static const bool canControl;
zet_freq_properties_t frequencyProperties = {};
zes_freq_properties_t zesFrequencyProperties = {};
double *pClocks = nullptr;
uint32_t numClocks = 0;
};

View File

@@ -7,6 +7,8 @@
#include "level_zero/tools/source/sysman/frequency/linux/os_frequency_imp.h"
#include "sysman/linux/os_sysman_imp.h"
namespace L0 {
const std::string LinuxFrequencyImp::minFreqFile("gt_min_freq_mhz");

View File

@@ -11,7 +11,6 @@
#include "sysman/frequency/frequency_imp.h"
#include "sysman/frequency/os_frequency.h"
#include "sysman/linux/fs_access.h"
#include "sysman/linux/os_sysman_imp.h"
namespace L0 {

View File

@@ -82,6 +82,7 @@ struct SysmanDevice : _ze_device_handle_t {
static SysmanDevice *fromHandle(zes_device_handle_t handle) { return Device::fromHandle(handle)->getSysmanHandle(); }
virtual ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) = 0;
virtual ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) = 0;
virtual ~SysmanDevice() = default;
};

View File

@@ -23,11 +23,13 @@ SysmanDeviceImp::SysmanDeviceImp(ze_device_handle_t hDevice) {
pOsSysman = OsSysman::create(this);
UNRECOVERABLE_IF(nullptr == pOsSysman);
pPowerHandleContext = new PowerHandleContext(pOsSysman);
pFrequencyHandleContext = new FrequencyHandleContext(pOsSysman);
}
SysmanDeviceImp::~SysmanDeviceImp() {
freeResource(pOsSysman);
freeResource(pPowerHandleContext);
freeResource(pFrequencyHandleContext);
}
void SysmanDeviceImp::init() {
@@ -35,6 +37,9 @@ void SysmanDeviceImp::init() {
if (pPowerHandleContext) {
pPowerHandleContext->init();
}
if (pFrequencyHandleContext) {
pFrequencyHandleContext->init();
}
}
SysmanImp::SysmanImp(ze_device_handle_t hDevice) {
@@ -199,6 +204,10 @@ ze_result_t SysmanImp::frequencyGet(uint32_t *pCount, zet_sysman_freq_handle_t *
return pFrequencyHandleContext->frequencyGet(pCount, phFrequency);
}
ze_result_t SysmanDeviceImp::frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) {
return pFrequencyHandleContext->frequencyGet(pCount, phFrequency);
}
ze_result_t SysmanImp::engineGet(uint32_t *pCount, zet_sysman_engine_handle_t *phEngine) {
return pEngineHandleContext->engineGet(pCount, phEngine);
}

View File

@@ -93,8 +93,10 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass {
OsSysman *pOsSysman = nullptr;
PowerHandleContext *pPowerHandleContext = nullptr;
FrequencyHandleContext *pFrequencyHandleContext = nullptr;
ze_result_t powerGet(uint32_t *pCount, zes_pwr_handle_t *phPower) override;
ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) override;
private:
template <typename T>

View File

@@ -6,20 +6,8 @@
*/
#pragma once
#include "level_zero/core/test/unit_tests/mock.h"
#include "level_zero/tools/source/sysman/frequency/linux/os_frequency_imp.h"
#include "sysman/frequency/frequency_imp.h"
#include "sysman/frequency/os_frequency.h"
#include "sysman/linux/fs_access.h"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
#endif
using ::testing::_;
namespace L0 {
namespace ult {
@@ -45,8 +33,40 @@ struct Mock<FrequencySysfsAccess> : public FrequencySysfsAccess {
double mockMaxVal = 0;
double mockMinVal = 0;
MOCK_METHOD2(read, ze_result_t(const std::string file, double &val));
MOCK_METHOD2(write, ze_result_t(const std::string file, const double val));
MOCK_METHOD(ze_result_t, read, (const std::string file, double &val), (override));
MOCK_METHOD(ze_result_t, write, (const std::string file, const double val), (override));
ze_result_t getValReturnError(const std::string file, double &val) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
ze_result_t getValActualReturnError(const std::string file, double &val) {
if (file.compare(actualFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getValEfficientReturnError(const std::string file, double &val) {
if (file.compare(efficientFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getValTdpReturnError(const std::string file, double &val) {
if (file.compare(tdpFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getValRequestReturnError(const std::string file, double &val) {
if (file.compare(requestFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getVal(const std::string file, double &val) {
if (file.compare(minFreqFile) == 0) {
@@ -75,6 +95,21 @@ struct Mock<FrequencySysfsAccess> : public FrequencySysfsAccess {
}
return ZE_RESULT_SUCCESS;
}
ze_result_t setValMinReturnError(const std::string file, const double val) {
if (file.compare(minFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t setValMaxReturnError(const std::string file, const double val) {
if (file.compare(maxFreqFile) == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t setVal(const std::string file, const double val) {
if (file.compare(minFreqFile) == 0) {
mockMin = val;
@@ -113,8 +148,4 @@ class PublicLinuxFrequencyImp : public L0::LinuxFrequencyImp {
};
} // namespace ult
} // namespace L0
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace L0

View File

@@ -5,9 +5,7 @@
*
*/
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/tools/source/sysman/frequency/linux/os_frequency_imp.h"
#include "level_zero/tools/source/sysman/sysman_imp.h"
#include "level_zero/tools/test/unit_tests/sources/sysman/mock_sysman_fixture.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -15,13 +13,7 @@
#include <cmath>
using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Matcher;
using ::testing::NiceMock;
using ::testing::Return;
namespace L0 {
namespace ult {
@@ -36,6 +28,301 @@ constexpr double efficient = 300.0;
constexpr double maxVal = 1100.0;
constexpr double minVal = 300.0;
constexpr uint32_t numClocks = static_cast<uint32_t>((maxFreq - minFreq) / step) + 1;
constexpr uint32_t handleComponentCount = 1u;
class SysmanDeviceFrequencyFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<FrequencySysfsAccess>> pSysfsAccess;
SysfsAccess *pSysfsAccessOld = nullptr;
void SetUp() override {
SysmanDeviceFixture::SetUp();
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pSysfsAccess = std::make_unique<NiceMock<Mock<FrequencySysfsAccess>>>();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pSysfsAccess->setVal(minFreqFile, minFreq);
pSysfsAccess->setVal(maxFreqFile, maxFreq);
pSysfsAccess->setVal(requestFreqFile, request);
pSysfsAccess->setVal(tdpFreqFile, tdp);
pSysfsAccess->setVal(actualFreqFile, actual);
pSysfsAccess->setVal(efficientFreqFile, efficient);
pSysfsAccess->setVal(maxValFreqFile, maxVal);
pSysfsAccess->setVal(minValFreqFile, minVal);
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getVal));
ON_CALL(*pSysfsAccess.get(), write(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::setVal));
// delete handles created in initial SysmanDeviceHandleContext::init() call
for (auto handle : pSysmanDeviceImp->pFrequencyHandleContext->handle_list) {
delete handle;
}
pSysmanDeviceImp->pFrequencyHandleContext->handle_list.clear();
pSysmanDeviceImp->pFrequencyHandleContext->init();
}
void TearDown() override {
SysmanDeviceFixture::TearDown();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
}
double clockValue(const double calculatedClock) {
// i915 specific. frequency step is a fraction
// However, the i915 represents all clock
// rates as integer values. So clocks are
// rounded to the nearest integer.
uint32_t actualClock = static_cast<uint32_t>(calculatedClock + 0.5);
return static_cast<double>(actualClock);
}
std::vector<zes_freq_handle_t> get_freq_handles(uint32_t count) {
std::vector<zes_freq_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumFrequencyDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
return handles;
}
};
TEST_F(SysmanDeviceFrequencyFixture, GivenComponentCountZeroWhenEnumeratingFrequencyHandlesThenNonZeroCountIsReturnedAndCallSucceds) {
uint32_t count;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumFrequencyDomains(device->toHandle(), &count, nullptr));
EXPECT_EQ(count, handleComponentCount);
uint32_t testCount = count + 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumFrequencyDomains(device->toHandle(), &testCount, nullptr));
EXPECT_EQ(count, testCount);
auto handles = get_freq_handles(count);
for (auto handle : handles) {
EXPECT_NE(handle, nullptr);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenActualComponentCountTwoWhenTryingToGetOneComponentOnlyThenOneComponentIsReturnedAndCountUpdated) {
auto pFrequencyHandleContextTest = std::make_unique<FrequencyHandleContext>(pOsSysman);
pFrequencyHandleContextTest->handle_list.push_back(new FrequencyImp(pOsSysman));
pFrequencyHandleContextTest->handle_list.push_back(new FrequencyImp(pOsSysman));
uint32_t count = 1;
std::vector<zes_freq_handle_t> phFrequency(count, nullptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, pFrequencyHandleContextTest->frequencyGet(&count, phFrequency.data()));
EXPECT_EQ(count, 1u);
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFrequencyGetPropertiesThenSuccessIsReturned) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
EXPECT_NE(handle, nullptr);
zes_freq_properties_t properties;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetProperties(handle, &properties));
EXPECT_EQ(ZES_STRUCTURE_TYPE_FREQ_PROPERTIES, properties.stype);
EXPECT_EQ(nullptr, properties.pNext);
EXPECT_EQ(ZES_FREQ_DOMAIN_GPU, properties.type);
EXPECT_FALSE(properties.onSubdevice);
EXPECT_DOUBLE_EQ(maxFreq, properties.max);
EXPECT_DOUBLE_EQ(minFreq, properties.min);
EXPECT_TRUE(properties.canControl);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleAndZeroCountWhenCallingzesFrequencyGetAvailableClocksThenCallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
EXPECT_NE(handle, nullptr);
uint32_t count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetAvailableClocks(handle, &count, nullptr));
EXPECT_EQ(numClocks, count);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleAndCorrectCountWhenCallingzesFrequencyGetAvailableClocksThenCallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
uint32_t count = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetAvailableClocks(handle, &count, nullptr));
EXPECT_EQ(numClocks, count);
double *clocks = new double[count];
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetAvailableClocks(handle, &count, clocks));
EXPECT_EQ(numClocks, count);
for (uint32_t i = 0; i < count; i++) {
EXPECT_DOUBLE_EQ(clockValue(minFreq + (step * i)), clocks[i]);
}
delete[] clocks;
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidateFrequencyGetRangeWhengetMaxFailsThenFrequencyGetRangeCallShouldFail) {
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getValReturnError));
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limit = {};
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencyGetRange(&limit));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFrequencyGetRangeThenVerifyzesFrequencyGetRangeTestCallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
zes_freq_range_t limits;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetRange(handle, &limits));
EXPECT_DOUBLE_EQ(minFreq, limits.min);
EXPECT_DOUBLE_EQ(maxFreq, limits.max);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyLimitsWhenCallingFrequencySetRangeForFailures1ThenAPIExitsGracefully) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits = {};
// Verify that Max must be within range.
limits.min = minFreq;
limits.max = 600.0;
ON_CALL(*pSysfsAccess.get(), write(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::setValMinReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyLimitsWhenCallingFrequencySetRangeForFailures2ThenAPIExitsGracefully) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits = {};
// Verify that Max must be within range.
limits.min = 900.0;
limits.max = maxFreq;
ON_CALL(*pSysfsAccess.get(), write(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::setValMaxReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFrequencySetRangeThenVerifyzesFrequencySetRangeTest1CallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
const double startingMin = 900.0;
const double newMax = 600.0;
zes_freq_range_t limits;
pSysfsAccess->setVal(minFreqFile, startingMin);
// If the new Max value is less than the old Min
// value, the new Min must be set before the new Max
limits.min = minFreq;
limits.max = newMax;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencySetRange(handle, &limits));
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetRange(handle, &limits));
EXPECT_DOUBLE_EQ(minFreq, limits.min);
EXPECT_DOUBLE_EQ(newMax, limits.max);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFrequencySetRangeThenVerifyzesFrequencySetRangeTest2CallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
const double startingMax = 600.0;
const double newMin = 900.0;
zes_freq_range_t limits;
pSysfsAccess->setVal(maxFreqFile, startingMax);
// If the new Min value is greater than the old Max
// value, the new Max must be set before the new Min
limits.min = newMin;
limits.max = maxFreq;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencySetRange(handle, &limits));
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetRange(handle, &limits));
EXPECT_DOUBLE_EQ(newMin, limits.min);
EXPECT_DOUBLE_EQ(maxFreq, limits.max);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenInvalidFrequencyLimitsWhenCallingFrequencySetRangeThenVerifyFrequencySetRangeTest1ReturnsError) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits;
// Verify that Max must be within range.
limits.min = minFreq;
limits.max = clockValue(maxFreq + step);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenInvalidFrequencyLimitsWhenCallingFrequencySetRangeThenVerifyFrequencySetRangeTest2ReturnsError) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits;
// Verify that Min must be within range.
limits.min = clockValue(minFreq - step);
limits.max = maxFreq;
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenInvalidFrequencyLimitsWhenCallingFrequencySetRangeThenVerifyFrequencySetRangeTest3ReturnsError) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits;
// Verify that values must be multiples of step.
limits.min = clockValue(minFreq + (step * 0.5));
limits.max = maxFreq;
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenInvalidFrequencyLimitsWhenCallingFrequencySetRangeThenVerifyFrequencySetRangeTest4ReturnsError) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_range_t limits;
// Verify that Max must be greater than min range.
limits.min = clockValue(maxFreq + step);
limits.max = minFreq;
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, pFrequencyImp->frequencySetRange(&limits));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFrequencyGetStateThenVerifyzesFrequencyGetStateTestCallSucceeds) {
auto handles = get_freq_handles(handleComponentCount);
for (auto handle : handles) {
const double testRequestValue = 450.0;
const double testTdpValue = 1200.0;
const double testEfficientValue = 400.0;
const double testActualValue = 550.0;
zes_freq_state_t state;
pSysfsAccess->setVal(requestFreqFile, testRequestValue);
pSysfsAccess->setVal(tdpFreqFile, testTdpValue);
pSysfsAccess->setVal(actualFreqFile, testActualValue);
pSysfsAccess->setVal(efficientFreqFile, testEfficientValue);
EXPECT_EQ(ZE_RESULT_SUCCESS, zesFrequencyGetState(handle, &state));
EXPECT_DOUBLE_EQ(testRequestValue, state.request);
EXPECT_DOUBLE_EQ(testTdpValue, state.tdp);
EXPECT_DOUBLE_EQ(testEfficientValue, state.efficient);
EXPECT_DOUBLE_EQ(testActualValue, state.actual);
EXPECT_EQ(0u, state.throttleReasons);
EXPECT_EQ(nullptr, state.pNext);
EXPECT_EQ(ZES_STRUCTURE_TYPE_FREQ_STATE, state.stype);
EXPECT_LE(state.currentVoltage, 0);
}
}
TEST_F(SysmanDeviceFrequencyFixture, GivenValidStatePointerWhenValidatingfrequencyGetStateForFailuresThenAPIExitsGracefully) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_state_t state = {};
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getValRequestReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencyGetState(&state));
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getValTdpReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencyGetState(&state));
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getValEfficientReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencyGetState(&state));
ON_CALL(*pSysfsAccess.get(), read(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<FrequencySysfsAccess>::getValActualReturnError));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pFrequencyImp->frequencyGetState(&state));
}
TEST_F(SysmanDeviceFrequencyFixture, GivenThrottleTimeStructPointerWhenCallingfrequencyGetThrottleTimeThenUnsupportedIsReturned) {
auto pFrequencyImp = std::make_unique<FrequencyImp>(pOsSysman);
zes_freq_throttle_time_t throttleTime = {};
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pFrequencyImp->frequencyGetThrottleTime(&throttleTime));
}
class SysmanFrequencyFixture : public DeviceFixture, public ::testing::Test {
@@ -273,4 +560,4 @@ TEST_F(SysmanFrequencyFixture, GivenValidFrequencyHandleWhenCallingzetSysmanFreq
}
} // namespace ult
} // namespace L0
} // namespace L0