Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion bindings/sysman/python/source/examples/pyzes_black_box_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,19 @@ def get_frequency_domain_string(freq_domain):
return domain_map.get(freq_domain, f"UNKNOWN_FREQ_DOMAIN_{freq_domain}")


def get_power_domain_string(power_domain):
"""Convert power domain enum to string"""
domain_map = {
pz.ZES_POWER_DOMAIN_UNKNOWN: "ZES_POWER_DOMAIN_UNKNOWN",
pz.ZES_POWER_DOMAIN_CARD: "ZES_POWER_DOMAIN_CARD",
pz.ZES_POWER_DOMAIN_PACKAGE: "ZES_POWER_DOMAIN_PACKAGE",
pz.ZES_POWER_DOMAIN_STACK: "ZES_POWER_DOMAIN_STACK",
pz.ZES_POWER_DOMAIN_MEMORY: "ZES_POWER_DOMAIN_MEMORY",
pz.ZES_POWER_DOMAIN_GPU: "ZES_POWER_DOMAIN_GPU",
}
return domain_map.get(power_domain, f"UNKNOWN_POWER_DOMAIN_{power_domain}")


def get_throttle_reasons_string(throttle_reasons):
"""Convert throttle reason flags to human-readable string"""
if throttle_reasons == 0:
Expand Down Expand Up @@ -638,7 +651,7 @@ def test_memory_modules(device_handle, device_index):


def test_power_module(device_handle, device_index):
"""Test power domain enumeration and energy counter operations"""
"""Test power domain enumeration, usage, and energy counter operations"""
print(f"\n---- Device {device_index} Power Domains Test ----")

# Get power domain count
Expand All @@ -665,6 +678,46 @@ def test_power_module(device_handle, device_index):
for i in range(power_count.value):
print_verbose(f"\n Power Domain {i}:")

power_props = pz.zes_power_properties_t()
power_ext_props = pz.zes_power_ext_properties_t()
default_limit = pz.zes_power_limit_ext_desc_t()
power_props.stype = pz.ZES_STRUCTURE_TYPE_POWER_PROPERTIES
power_props.pNext = cast(byref(power_ext_props), c_void_p)
power_ext_props.stype = pz.ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES
power_ext_props.pNext = None
power_ext_props.defaultLimit = pointer(default_limit)

rc = pz.zesPowerGetProperties(power_handles[i], byref(power_props))
if check_rc(f"zesPowerGetProperties(power {i})", rc):
print_verbose(" Properties:")
print_verbose(f" On Subdevice: {bool(power_props.onSubdevice)}")
print_verbose(f" Subdevice ID: {power_props.subdeviceId}")
print_verbose(f" Can Control: {bool(power_props.canControl)}")
print_verbose(
" Energy Threshold Supported: "
f"{bool(power_props.isEnergyThresholdSupported)}"
)
print_verbose(f" Default Limit: {power_props.defaultLimit}")
print_verbose(f" Min Limit: {power_props.minLimit}")
print_verbose(f" Max Limit: {power_props.maxLimit}")
print_verbose(
" Extended Domain: "
f"{get_power_domain_string(power_ext_props.domain)}"
)
print_verbose(f" Extended Default Limit: {default_limit.limit}")

# Test power usage
instant_power = c_uint32(0)
average_power = c_uint32(0)

rc = pz.zesPowerGetUsage(
power_handles[i], byref(instant_power), byref(average_power)
)
if check_rc(f"zesPowerGetUsage(power {i})", rc):
print_verbose(" Usage:")
print_verbose(f" Instant Power: {instant_power.value}")
print_verbose(f" Average Power: {average_power.value}")

# Test power energy counter
energy_counter = pz.zes_power_energy_counter_t()

Expand Down Expand Up @@ -726,6 +779,37 @@ def test_frequency_domains(device_handle, device_index):
for i in range(freq_count.value):
print_verbose(f"\n Frequency Domain {i}:")

# Test frequency properties
freq_props = pz.zes_freq_properties_t()
freq_props.stype = pz.ZES_STRUCTURE_TYPE_FREQ_PROPERTIES
freq_props.pNext = None

rc = pz.zesFrequencyGetProperties(freq_handles[i], byref(freq_props))
if not check_rc(f"zesFrequencyGetProperties(frequency {i})", rc):
continue

print_verbose(" Frequency Properties:")
print_verbose(
f" Domain Type: {get_frequency_domain_string(freq_props.type)}"
)
print_verbose(f" On Subdevice: {bool(freq_props.onSubdevice)}")
print_verbose(f" Subdevice ID: {freq_props.subdeviceId}")
print_verbose(f" Can Control: {bool(freq_props.canControl)}")
print_verbose(
" Throttle Event Supported: "
f"{bool(freq_props.isThrottleEventSupported)}"
)
print_verbose(
f" Min Frequency: {freq_props.min:.1f}"
if freq_props.min >= 0
else " Min Frequency: Unknown"
)
print_verbose(
f" Max Frequency: {freq_props.max:.1f}"
if freq_props.max >= 0
else " Max Frequency: Unknown"
)

# Test frequency state
freq_state = pz.zes_freq_state_t()
freq_state.stype = pz.ZES_STRUCTURE_TYPE_FREQ_STATE
Expand Down
152 changes: 151 additions & 1 deletion bindings/sysman/python/source/pyzes.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class zes_engine_handle_t(c_void_p):

##

ze_bool_t = c_uint32
ze_bool_t = c_uint8
ze_device_property_flags_t = c_uint32
zes_engine_type_flags_t = c_uint32
zes_device_property_flags_t = c_uint32
Expand Down Expand Up @@ -224,6 +224,29 @@ class zes_engine_handle_t(c_void_p):
ZES_POWER_DOMAIN_GPU = 5
ZES_POWER_DOMAIN_FORCE_UINT32 = 0x7FFFFFFF

# Power limit level enumeration
zes_power_level_t = c_int32
ZES_POWER_LEVEL_UNKNOWN = 0
ZES_POWER_LEVEL_SUSTAINED = 1
ZES_POWER_LEVEL_BURST = 2
ZES_POWER_LEVEL_PEAK = 3
ZES_POWER_LEVEL_INSTANTANEOUS = 4
ZES_POWER_LEVEL_FORCE_UINT32 = 0x7FFFFFFF

# Power source enumeration
zes_power_source_t = c_int32
ZES_POWER_SOURCE_ANY = 0
ZES_POWER_SOURCE_MAINS = 1
ZES_POWER_SOURCE_BATTERY = 2
ZES_POWER_SOURCE_FORCE_UINT32 = 0x7FFFFFFF

# Power limit unit enumeration
zes_limit_unit_t = c_int32
ZES_LIMIT_UNIT_UNKNOWN = 0
ZES_LIMIT_UNIT_CURRENT = 1
ZES_LIMIT_UNIT_POWER = 2
ZES_LIMIT_UNIT_FORCE_UINT32 = 0x7FFFFFFF

## Frequency domain enums ##
zes_freq_domain_t = c_int32
ZES_FREQ_DOMAIN_GPU = 0
Expand Down Expand Up @@ -340,6 +363,9 @@ class zes_engine_handle_t(c_void_p):
ZES_STRUCTURE_TYPE_MEM_STATE = 0x1E
ZES_STRUCTURE_TYPE_FREQ_PROPERTIES = 0x9
ZES_STRUCTURE_TYPE_FREQ_STATE = 0x1B
ZES_STRUCTURE_TYPE_POWER_PROPERTIES = 0xD
ZES_STRUCTURE_TYPE_POWER_LIMIT_EXT_DESC = 0x27
ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES = 0x28
ZES_STRUCTURE_TYPE_TEMP_PROPERTIES = 0xA
ZES_STRUCTURE_TYPE_TEMP_CONFIG = 0x1C
ZES_STRUCTURE_TYPE_ENGINE_PROPERTIES = 0x5
Expand Down Expand Up @@ -478,6 +504,54 @@ class zes_mem_bandwidth_t(_PrintableStructure):


## Power structures ##
class zes_power_properties_t(_PrintableStructure):
_fields_ = [
("stype", c_int32), # ZES_STRUCTURE_TYPE_POWER_PROPERTIES
("pNext", c_void_p),
("onSubdevice", ze_bool_t), # is on subdevice
("subdeviceId", c_uint32), # subdevice ID
("canControl", ze_bool_t), # software-controllable power domain
(
"isEnergyThresholdSupported",
ze_bool_t,
), # supports energy threshold crossed event
("defaultLimit", c_int32), # default power limit in milliwatts
("minLimit", c_int32), # minimum power limit in milliwatts
("maxLimit", c_int32), # maximum power limit in milliwatts
]
_fmt_ = {
"defaultLimit": "%d mW",
"minLimit": "%d mW",
"maxLimit": "%d mW",
}


class zes_power_limit_ext_desc_t(_PrintableStructure):
_fields_ = [
("stype", c_int32), # ZES_STRUCTURE_TYPE_POWER_LIMIT_EXT_DESC
("pNext", c_void_p),
("level", zes_power_level_t),
("source", zes_power_source_t),
("limitUnit", zes_limit_unit_t),
("enabledStateLocked", ze_bool_t),
("enabled", ze_bool_t),
("intervalValueLocked", ze_bool_t),
("interval", c_int32),
("limitValueLocked", ze_bool_t),
("limit", c_int32),
]
_fmt_ = {"interval": "%d ms", "limit": "%d"}


class zes_power_ext_properties_t(_PrintableStructure):
_fields_ = [
("stype", c_int32), # ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES
("pNext", c_void_p),
("domain", zes_power_domain_t),
("defaultLimit", POINTER(zes_power_limit_ext_desc_t)),
]


class zes_power_energy_counter_t(_PrintableStructure):
_fields_ = [
("energy", c_uint64), # monotonic energy counter in microjoules
Expand All @@ -487,6 +561,21 @@ class zes_power_energy_counter_t(_PrintableStructure):


## Frequency structures ##
class zes_freq_properties_t(_PrintableStructure):
_fields_ = [
("stype", c_int32), # ZES_STRUCTURE_TYPE_FREQ_PROPERTIES
("pNext", c_void_p),
("type", zes_freq_domain_t), # frequency domain type
("onSubdevice", ze_bool_t), # is on subdevice
("subdeviceId", c_uint32), # subdevice ID
("canControl", ze_bool_t), # software-controllable frequency domain
("isThrottleEventSupported", ze_bool_t), # supports throttled event
("min", c_double), # minimum hardware clock in MHz
("max", c_double), # maximum non-overclock hardware clock in MHz
]
_fmt_ = {"min": "%.1f MHz", "max": "%.1f MHz"}


class zes_freq_state_t(_PrintableStructure):
_fields_ = [
("stype", c_int32), # ZES_STRUCTURE_TYPE_FREQ_STATE
Expand Down Expand Up @@ -819,6 +908,25 @@ def zesDeviceEnumPowerDomains(hDevice, pCount, phPower):
return retVal


def zesPowerGetProperties(hPower, pProperties):
"""Wraps API:
ze_result_t zesPowerGetProperties(
zes_pwr_handle_t hPower,
zes_power_properties_t* pProperties)

Parameters:
hPower: power handle
pProperties: POINTER(zes_power_properties_t) - properties structure to fill
Returns:
ze_result_t - return code only, properties are filled into pProperties
"""
funcPtr = getFunctionPointerList("zesPowerGetProperties")
funcPtr.argtypes = [zes_pwr_handle_t, POINTER(zes_power_properties_t)]
funcPtr.restype = ze_result_t
retVal = funcPtr(hPower, pProperties)
return retVal


def zesPowerGetEnergyCounter(hPower, pEnergy):
"""Wraps API:
ze_result_t zesPowerGetEnergyCounter(
Expand All @@ -839,6 +947,28 @@ def zesPowerGetEnergyCounter(hPower, pEnergy):
return retVal


def zesPowerGetUsage(hPower, pInstantPower, pAveragePower):
"""Wraps API:
ze_result_t zesPowerGetUsage(
zes_pwr_handle_t hPower,
uint32_t* pInstantPower,
uint32_t* pAveragePower)

Parameters:
hPower: power handle
pInstantPower: POINTER(c_uint32) - instant power in milliwatts
pAveragePower: POINTER(c_uint32) - average power in milliwatts
Returns:
ze_result_t - return code only, usage values are filled into the output pointers
"""
funcPtr = getFunctionPointerList("zesPowerGetUsage")
funcPtr.argtypes = [zes_pwr_handle_t, POINTER(c_uint32), POINTER(c_uint32)]
funcPtr.restype = ze_result_t

retVal = funcPtr(hPower, pInstantPower, pAveragePower)
return retVal


## Frequency module functions ##
def zesDeviceEnumFrequencyDomains(hDevice, pCount, phFrequency):
"""Wraps API:
Expand All @@ -863,6 +993,26 @@ def zesDeviceEnumFrequencyDomains(hDevice, pCount, phFrequency):
return retVal


def zesFrequencyGetProperties(hFrequency, pProperties):
"""Wraps API:
ze_result_t zesFrequencyGetProperties(
zes_freq_handle_t hFrequency,
zes_freq_properties_t* pProperties)

Parameters:
hFrequency: frequency handle
pProperties: POINTER(zes_freq_properties_t) - properties structure to fill
Returns:
ze_result_t - return code only, properties are filled into pProperties
"""
funcPtr = getFunctionPointerList("zesFrequencyGetProperties")
funcPtr.argtypes = [zes_freq_handle_t, POINTER(zes_freq_properties_t)]
funcPtr.restype = ze_result_t

retVal = funcPtr(hFrequency, pProperties)
return retVal


def zesFrequencyGetState(hFrequency, pState):
"""Wraps API:
ze_result_t zesFrequencyGetState(
Expand Down
42 changes: 42 additions & 0 deletions bindings/sysman/python/test/unit_tests/test_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,48 @@ def mock_get_state(frequency_handle, state_ptr):
mock_get_func.assert_called_with("zesFrequencyGetState")
mock_func.assert_called_once()

def test_GivenValidFrequencyHandleWhenCallingZesFrequencyGetPropertiesThenCallSucceedsWithProperties(
self, mock_get_func
):
mock_type = self.pyzes.ZES_FREQ_DOMAIN_GPU
mock_on_subdevice = 1
mock_subdevice_id = 0
mock_can_control = 1
mock_throttle_event_supported = 1
mock_min = 300.0
mock_max = 2100.0

def mock_get_properties(frequency_handle, properties_ptr):
properties_ptr._obj.type = mock_type
properties_ptr._obj.onSubdevice = mock_on_subdevice
properties_ptr._obj.subdeviceId = mock_subdevice_id
properties_ptr._obj.canControl = mock_can_control
properties_ptr._obj.isThrottleEventSupported = mock_throttle_event_supported
properties_ptr._obj.min = mock_min
properties_ptr._obj.max = mock_max
return self.pyzes.ZE_RESULT_SUCCESS

mock_func = MagicMock(side_effect=mock_get_properties)
mock_get_func.return_value = mock_func

frequency_handle = self.pyzes.zes_freq_handle_t()
freq_properties = self.pyzes.zes_freq_properties_t()
result = self.pyzes.zesFrequencyGetProperties(
frequency_handle, byref(freq_properties)
)

self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
self.assertEqual(freq_properties.type, mock_type)
self.assertEqual(freq_properties.onSubdevice, mock_on_subdevice)
self.assertEqual(freq_properties.subdeviceId, mock_subdevice_id)
self.assertEqual(freq_properties.canControl, mock_can_control)
self.assertEqual(
freq_properties.isThrottleEventSupported, mock_throttle_event_supported
)
self.assertEqual(freq_properties.min, mock_min)
self.assertEqual(freq_properties.max, mock_max)
mock_get_func.assert_called_with("zesFrequencyGetProperties")
mock_func.assert_called_once()

if __name__ == "__main__":
unittest.main()
Loading
Loading