Skip to content

Commit 1ae486c

Browse files
committed
feature: Add more APIs to L0 Sysman python binding
Related-To: NEO-18602 Added following APIs to python binding: 1. zesDevicePciGetProperties 2. zesDevicePciGetStats 3. zesDeviceEccAvailable 4. zesDeviceEccConfigurable 5. zesDeviceGetEccState 6. zesDeviceSetEccState 7. zesPowerGetLimitsExt 8. zesPowerSetLimitsExt 9. zesFrequencyGetAvailableClocks 10. zesFrequencyGetRange 11. zesFrequencySetRange 12. zesFrequencyGetThrottleTime Signed-off-by: Aviral Nigam <aviral.nigam@intel.com>
1 parent 1fa65f1 commit 1ae486c

4 files changed

Lines changed: 288 additions & 7 deletions

File tree

bindings/sysman/python/source/examples/pyzes_black_box_test.py

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,41 @@ def get_device_type_string(device_type):
139139
return type_map.get(device_type, f"UNKNOWN_DEVICE_TYPE_{device_type}")
140140

141141

142+
def get_pci_link_status_string(link_status):
143+
"""Convert PCI link status enum to string"""
144+
status_map = {
145+
pz.ZES_PCI_LINK_STATUS_UNKNOWN: "ZES_PCI_LINK_STATUS_UNKNOWN",
146+
pz.ZES_PCI_LINK_STATUS_GOOD: "ZES_PCI_LINK_STATUS_GOOD",
147+
pz.ZES_PCI_LINK_STATUS_QUALITY_ISSUES: "ZES_PCI_LINK_STATUS_QUALITY_ISSUES",
148+
pz.ZES_PCI_LINK_STATUS_STABILITY_ISSUES: "ZES_PCI_LINK_STATUS_STABILITY_ISSUES",
149+
}
150+
return status_map.get(link_status, f"UNKNOWN_PCI_LINK_STATUS_{link_status}")
151+
152+
153+
def get_pci_quality_issues_string(quality_issues):
154+
"""Convert PCI quality issue flags to string"""
155+
if quality_issues == 0:
156+
return "None"
157+
158+
issues = []
159+
if quality_issues & pz.ZES_PCI_LINK_QUAL_ISSUE_FLAG_REPLAYS:
160+
issues.append("REPLAYS")
161+
if quality_issues & pz.ZES_PCI_LINK_QUAL_ISSUE_FLAG_SPEED:
162+
issues.append("SPEED")
163+
return " | ".join(issues)
164+
165+
166+
def get_pci_stability_issues_string(stability_issues):
167+
"""Convert PCI stability issue flags to string"""
168+
if stability_issues == 0:
169+
return "None"
170+
171+
issues = []
172+
if stability_issues & pz.ZES_PCI_LINK_STAB_ISSUE_FLAG_RETRAINING:
173+
issues.append("RETRAINING")
174+
return " | ".join(issues)
175+
176+
142177
def get_frequency_domain_string(freq_domain):
143178
"""Convert frequency domain enum to string"""
144179
domain_map = {
@@ -440,9 +475,9 @@ def test_global_operation(driver_handle, device_handle, device_index):
440475

441476
# Initialize each structure
442477
for i in range(subdevice_count.value):
443-
subdevice_props[i].stype = (
444-
pz.ZES_STRUCTURE_TYPE_SUBDEVICE_EXP_PROPERTIES
445-
)
478+
subdevice_props[
479+
i
480+
].stype = pz.ZES_STRUCTURE_TYPE_SUBDEVICE_EXP_PROPERTIES
446481
subdevice_props[i].pNext = None
447482

448483
# Second call to get properties
@@ -537,7 +572,7 @@ def test_global_operation(driver_handle, device_handle, device_index):
537572

538573

539574
def test_pci_module(device_handle, device_index):
540-
"""Test PCI properties and stats operations"""
575+
"""Test PCI properties, state, and stats operations"""
541576
print(f"\n---- Device {device_index} PCI Test ----")
542577

543578
properties = pz.zes_pci_properties_t()
@@ -562,6 +597,26 @@ def test_pci_module(device_handle, device_index):
562597
print_verbose(f" Have Packet Counters: {bool(properties.havePacketCounters)}")
563598
print_verbose(f" Have Replay Counters: {bool(properties.haveReplayCounters)}")
564599

600+
state = pz.zes_pci_state_t()
601+
state.stype = pz.ZES_STRUCTURE_TYPE_PCI_STATE
602+
state.pNext = None
603+
604+
rc = pz.zesDevicePciGetState(device_handle, byref(state))
605+
if not check_rc(f"zesDevicePciGetState(device {device_index})", rc):
606+
return False
607+
608+
print_verbose("PCI State:")
609+
print_verbose(f" Link Status: {get_pci_link_status_string(state.status)}")
610+
print_verbose(
611+
f" Quality Issues: {get_pci_quality_issues_string(state.qualityIssues)}"
612+
)
613+
print_verbose(
614+
f" Stability Issues: {get_pci_stability_issues_string(state.stabilityIssues)}"
615+
)
616+
print_verbose(f" Current Gen: {state.speed.gen}")
617+
print_verbose(f" Current Width: {state.speed.width}")
618+
print_verbose(f" Current Max Bandwidth: {state.speed.maxBandwidth}")
619+
565620
stats = pz.zes_pci_stats_t()
566621
rc = pz.zesDevicePciGetStats(device_handle, byref(stats))
567622
if not check_rc(f"zesDevicePciGetStats(device {device_index})", rc):
@@ -897,9 +952,9 @@ def test_power_module(device_handle, device_index):
897952
limit_descs = PowerLimitArray()
898953

899954
for limit_index in range(limit_count.value):
900-
limit_descs[limit_index].stype = (
901-
pz.ZES_STRUCTURE_TYPE_POWER_LIMIT_EXT_DESC
902-
)
955+
limit_descs[
956+
limit_index
957+
].stype = pz.ZES_STRUCTURE_TYPE_POWER_LIMIT_EXT_DESC
903958
limit_descs[limit_index].pNext = None
904959

905960
rc = pz.zesPowerGetLimitsExt(

bindings/sysman/python/source/pyzes.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ class zes_engine_handle_t(c_void_p):
355355
# Structure type enum values
356356
ZES_STRUCTURE_TYPE_DEVICE_PROPERTIES = 0x1
357357
ZES_STRUCTURE_TYPE_PCI_PROPERTIES = 0x2
358+
ZES_STRUCTURE_TYPE_PCI_STATE = 0x17
358359
ZES_STRUCTURE_TYPE_DEVICE_ECC_DESC = 0x25
359360
ZES_STRUCTURE_TYPE_DEVICE_ECC_PROPERTIES = 0x26
360361
ZES_STRUCTURE_TYPE_POWER_LIMIT_EXT_DESC = 0x27
@@ -462,6 +463,35 @@ class zes_pci_properties_t(_PrintableStructure):
462463
]
463464

464465

466+
zes_pci_link_status_t = c_int32
467+
ZES_PCI_LINK_STATUS_UNKNOWN = 0
468+
ZES_PCI_LINK_STATUS_GOOD = 1
469+
ZES_PCI_LINK_STATUS_QUALITY_ISSUES = 2
470+
ZES_PCI_LINK_STATUS_STABILITY_ISSUES = 3
471+
ZES_PCI_LINK_STATUS_FORCE_UINT32 = 0x7FFFFFFF
472+
473+
zes_pci_link_qual_issue_flags_t = c_uint32
474+
ZES_PCI_LINK_QUAL_ISSUE_FLAG_REPLAYS = 1 << 0
475+
ZES_PCI_LINK_QUAL_ISSUE_FLAG_SPEED = 1 << 1
476+
ZES_PCI_LINK_QUAL_ISSUE_FLAG_FORCE_UINT32 = 0x7FFFFFFF
477+
478+
zes_pci_link_stab_issue_flags_t = c_uint32
479+
ZES_PCI_LINK_STAB_ISSUE_FLAG_RETRAINING = 1 << 0
480+
ZES_PCI_LINK_STAB_ISSUE_FLAG_FORCE_UINT32 = 0x7FFFFFFF
481+
482+
483+
class zes_pci_state_t(_PrintableStructure):
484+
_fields_ = [
485+
("stype", c_int32),
486+
("pNext", c_void_p),
487+
("status", zes_pci_link_status_t),
488+
("qualityIssues", zes_pci_link_qual_issue_flags_t),
489+
("stabilityIssues", zes_pci_link_stab_issue_flags_t),
490+
("speed", zes_pci_speed_t),
491+
]
492+
_fmt_ = {"qualityIssues": "0x%08X", "stabilityIssues": "0x%08X"}
493+
494+
465495
class zes_pci_stats_t(_PrintableStructure):
466496
_fields_ = [
467497
("timestamp", c_uint64),
@@ -801,6 +831,23 @@ def zesDevicePciGetProperties(hDevice, pProperties):
801831
return retVal
802832

803833

834+
def zesDevicePciGetState(hDevice, pState):
835+
"""Wraps API:
836+
ze_result_t zesDevicePciGetState(zes_device_handle_t hDevice, zes_pci_state_t* pState)
837+
838+
Parameters:
839+
hDevice: device handle
840+
pState: POINTER(zes_pci_state_t) - PCI state structure to fill
841+
Returns:
842+
ze_result_t - return code only, state is filled into pState
843+
"""
844+
funcPtr = getFunctionPointerList("zesDevicePciGetState")
845+
funcPtr.argtypes = [zes_device_handle_t, POINTER(zes_pci_state_t)]
846+
funcPtr.restype = ze_result_t
847+
retVal = funcPtr(hDevice, pState)
848+
return retVal
849+
850+
804851
def zesDevicePciGetStats(hDevice, pStats):
805852
"""Wraps API:
806853
ze_result_t zesDevicePciGetStats(zes_device_handle_t hDevice, zes_pci_stats_t* pStats)
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
##
2+
# Copyright (C) 2026 Intel Corporation
3+
#
4+
# SPDX-License-Identifier: MIT
5+
#
6+
##
7+
8+
import os
9+
import sys
10+
import unittest
11+
from ctypes import *
12+
from unittest.mock import MagicMock, patch
13+
14+
# Add the source directory to Python path so we can import pyzes
15+
script_dir = os.path.dirname(os.path.abspath(__file__))
16+
source_dir = os.path.join(script_dir, "..", "..", "source")
17+
source_dir = os.path.abspath(source_dir)
18+
if source_dir not in sys.path:
19+
sys.path.insert(0, source_dir)
20+
21+
22+
@patch("pyzes.getFunctionPointerList")
23+
class TestEccFunctions(unittest.TestCase):
24+
def setUp(self):
25+
import pyzes
26+
27+
self.pyzes = pyzes
28+
29+
def test_GivenValidDeviceHandleWhenCallingZesDeviceEccAvailableThenCallSucceedsWithAvailability(
30+
self, mock_get_func
31+
):
32+
mock_available = 1
33+
34+
def mock_ecc_available(device_handle, available_ptr):
35+
available_ptr._obj.value = mock_available
36+
return self.pyzes.ZE_RESULT_SUCCESS
37+
38+
mock_func = MagicMock(side_effect=mock_ecc_available)
39+
mock_get_func.return_value = mock_func
40+
41+
device_handle = self.pyzes.zes_device_handle_t()
42+
available = self.pyzes.ze_bool_t(0)
43+
44+
result = self.pyzes.zesDeviceEccAvailable(device_handle, byref(available))
45+
46+
self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
47+
self.assertEqual(available.value, mock_available)
48+
mock_get_func.assert_called_with("zesDeviceEccAvailable")
49+
mock_func.assert_called_once()
50+
51+
def test_GivenValidDeviceHandleWhenCallingZesDeviceEccConfigurableThenCallSucceedsWithConfigurability(
52+
self, mock_get_func
53+
):
54+
mock_configurable = 1
55+
56+
def mock_ecc_configurable(device_handle, configurable_ptr):
57+
configurable_ptr._obj.value = mock_configurable
58+
return self.pyzes.ZE_RESULT_SUCCESS
59+
60+
mock_func = MagicMock(side_effect=mock_ecc_configurable)
61+
mock_get_func.return_value = mock_func
62+
63+
device_handle = self.pyzes.zes_device_handle_t()
64+
configurable = self.pyzes.ze_bool_t(0)
65+
66+
result = self.pyzes.zesDeviceEccConfigurable(device_handle, byref(configurable))
67+
68+
self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
69+
self.assertEqual(configurable.value, mock_configurable)
70+
mock_get_func.assert_called_with("zesDeviceEccConfigurable")
71+
mock_func.assert_called_once()
72+
73+
def test_GivenValidDeviceHandleWhenCallingZesDeviceGetEccStateThenCallSucceedsWithState(
74+
self, mock_get_func
75+
):
76+
mock_current_state = self.pyzes.ZES_DEVICE_ECC_STATE_ENABLED
77+
mock_pending_state = self.pyzes.ZES_DEVICE_ECC_STATE_DISABLED
78+
mock_pending_action = self.pyzes.ZES_DEVICE_ACTION_WARM_CARD_RESET
79+
80+
def mock_get_ecc_state(device_handle, state_ptr):
81+
state_ptr._obj.currentState = mock_current_state
82+
state_ptr._obj.pendingState = mock_pending_state
83+
state_ptr._obj.pendingAction = mock_pending_action
84+
return self.pyzes.ZE_RESULT_SUCCESS
85+
86+
mock_func = MagicMock(side_effect=mock_get_ecc_state)
87+
mock_get_func.return_value = mock_func
88+
89+
device_handle = self.pyzes.zes_device_handle_t()
90+
ecc_state = self.pyzes.zes_device_ecc_properties_t()
91+
92+
result = self.pyzes.zesDeviceGetEccState(device_handle, byref(ecc_state))
93+
94+
self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
95+
self.assertEqual(ecc_state.currentState, mock_current_state)
96+
self.assertEqual(ecc_state.pendingState, mock_pending_state)
97+
self.assertEqual(ecc_state.pendingAction, mock_pending_action)
98+
mock_get_func.assert_called_with("zesDeviceGetEccState")
99+
mock_func.assert_called_once()
100+
101+
def test_GivenValidDeviceHandleWhenCallingZesDeviceSetEccStateThenCallSucceedsWithUpdatedState(
102+
self, mock_get_func
103+
):
104+
requested_state = self.pyzes.ZES_DEVICE_ECC_STATE_ENABLED
105+
mock_current_state = self.pyzes.ZES_DEVICE_ECC_STATE_DISABLED
106+
mock_pending_state = self.pyzes.ZES_DEVICE_ECC_STATE_ENABLED
107+
mock_pending_action = self.pyzes.ZES_DEVICE_ACTION_COLD_CARD_RESET
108+
109+
def mock_set_ecc_state(device_handle, new_state_ptr, state_ptr):
110+
self.assertEqual(new_state_ptr._obj.state, requested_state)
111+
state_ptr._obj.currentState = mock_current_state
112+
state_ptr._obj.pendingState = mock_pending_state
113+
state_ptr._obj.pendingAction = mock_pending_action
114+
return self.pyzes.ZE_RESULT_SUCCESS
115+
116+
mock_func = MagicMock(side_effect=mock_set_ecc_state)
117+
mock_get_func.return_value = mock_func
118+
119+
device_handle = self.pyzes.zes_device_handle_t()
120+
new_state = self.pyzes.zes_device_ecc_desc_t()
121+
new_state.stype = self.pyzes.ZES_STRUCTURE_TYPE_DEVICE_ECC_DESC
122+
new_state.state = requested_state
123+
ecc_state = self.pyzes.zes_device_ecc_properties_t()
124+
125+
result = self.pyzes.zesDeviceSetEccState(
126+
device_handle, byref(new_state), byref(ecc_state)
127+
)
128+
129+
self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
130+
self.assertEqual(ecc_state.currentState, mock_current_state)
131+
self.assertEqual(ecc_state.pendingState, mock_pending_state)
132+
self.assertEqual(ecc_state.pendingAction, mock_pending_action)
133+
mock_get_func.assert_called_with("zesDeviceSetEccState")
134+
mock_func.assert_called_once()
135+
136+
137+
if __name__ == "__main__":
138+
unittest.main()

bindings/sysman/python/test/unit_tests/test_global_operations.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,47 @@ def mock_get_pci_stats(device_handle, stats_ptr):
195195
mock_get_func.assert_called_with("zesDevicePciGetStats")
196196
mock_func.assert_called_once()
197197

198+
def test_GivenValidDeviceHandleWhenCallingZesDevicePciGetStateThenCallSucceedsWithValidState(
199+
self, mock_get_func
200+
):
201+
mock_status = self.pyzes.ZES_PCI_LINK_STATUS_QUALITY_ISSUES
202+
mock_quality_issues = (
203+
self.pyzes.ZES_PCI_LINK_QUAL_ISSUE_FLAG_REPLAYS
204+
| self.pyzes.ZES_PCI_LINK_QUAL_ISSUE_FLAG_SPEED
205+
)
206+
mock_stability_issues = self.pyzes.ZES_PCI_LINK_STAB_ISSUE_FLAG_RETRAINING
207+
mock_gen = 4
208+
mock_width = 8
209+
mock_max_bandwidth = 16_000_000_000
210+
211+
def mock_get_pci_state(device_handle, state_ptr):
212+
state_ptr._obj.status = mock_status
213+
state_ptr._obj.qualityIssues = mock_quality_issues
214+
state_ptr._obj.stabilityIssues = mock_stability_issues
215+
state_ptr._obj.speed.gen = mock_gen
216+
state_ptr._obj.speed.width = mock_width
217+
state_ptr._obj.speed.maxBandwidth = mock_max_bandwidth
218+
return self.pyzes.ZE_RESULT_SUCCESS
219+
220+
mock_func = MagicMock(side_effect=mock_get_pci_state)
221+
mock_get_func.return_value = mock_func
222+
223+
device_handle = self.pyzes.zes_device_handle_t()
224+
pci_state = self.pyzes.zes_pci_state_t()
225+
226+
result = self.pyzes.zesDevicePciGetState(device_handle, byref(pci_state))
227+
228+
self.assertEqual(result, self.pyzes.ZE_RESULT_SUCCESS)
229+
self.assertEqual(pci_state.status, mock_status)
230+
self.assertEqual(pci_state.qualityIssues, mock_quality_issues)
231+
self.assertEqual(pci_state.stabilityIssues, mock_stability_issues)
232+
self.assertEqual(pci_state.speed.gen, mock_gen)
233+
self.assertEqual(pci_state.speed.width, mock_width)
234+
self.assertEqual(pci_state.speed.maxBandwidth, mock_max_bandwidth)
235+
236+
mock_get_func.assert_called_with("zesDevicePciGetState")
237+
mock_func.assert_called_once()
238+
198239
def test_GivenValidDeviceHandleWhenCallingZesDeviceProcessesGetStateThenCallSucceedsWithProcessCount(
199240
self, mock_get_func
200241
):

0 commit comments

Comments
 (0)