fix: [SWDEV-458862] [rocm/rocm_smi_lib]

Fixes reading pp_od_clk_voltage new variable format and size.

Code changes related to the following:
  * get_od_clk_volt_info()
  * get_od_clk_volt_curve_regions()
  * Unit tests
  * CLI options restored: --showclkvolt, --showvc, --showvoltagerange, --setvc
    * Rework: 162d1d24
  * Bump CLI version
  * CHANGELOG.md

Change-Id: I817ca224de923fdaa992df84592d63b4d5a12b22
Signed-off-by: Oliveira, Daniel <daniel.oliveira@amd.com>


[ROCm/rocm_smi_lib commit: 8e6d66e15b]
This commit is contained in:
Oliveira, Daniel
2024-05-03 02:58:31 -05:00
committed by Maisam Arif
parent 02a862bde1
commit af02873dfb
8 changed files with 294 additions and 90 deletions
+2 -1
View File
@@ -21,7 +21,8 @@ Added `RSMI_EVT_NOTIF_RING_HANG` to the possible events in the `rsmi_evt_notific
### Fixed ### Fixed
- N/A - **Fixed parsing of `pp_od_clk_voltage` within `get_od_clk_volt_info`**
The parsing of `pp_od_clk_voltage` was not dynamic enough to work with the dropping of voltage curve support on MI series cards.
### Known Issues ### Known Issues
@@ -2870,8 +2870,6 @@ rsmi_status_t rsmi_dev_od_clk_info_set(uint32_t dv_ind, rsmi_freq_ind_t level,
/** /**
* @brief This function sets 1 of the 3 voltage curve points. * @brief This function sets 1 of the 3 voltage curve points.
* *
* @deprecated This function is deprecated due to driver changes.
*
* @details Given a device index @p dv_ind, a voltage point @p vpoint * @details Given a device index @p dv_ind, a voltage point @p vpoint
* and a voltage value @p voltvalue this function will set voltage curve point * and a voltage value @p voltvalue this function will set voltage curve point
* *
@@ -2897,8 +2895,6 @@ rsmi_status_t rsmi_dev_od_volt_info_set(uint32_t dv_ind, uint32_t vpoint,
* @brief This function will retrieve the current valid regions in the * @brief This function will retrieve the current valid regions in the
* frequency/voltage space. * frequency/voltage space.
* *
* @deprecated This function is deprecated due to driver changes.
*
* @details Given a device index @p dv_ind, a pointer to an unsigned integer * @details Given a device index @p dv_ind, a pointer to an unsigned integer
* @p num_regions and a buffer of ::rsmi_freq_volt_region_t structures, @p * @p num_regions and a buffer of ::rsmi_freq_volt_region_t structures, @p
* buffer, this function will populate @p buffer with the current * buffer, this function will populate @p buffer with the current
@@ -554,9 +554,9 @@ class TagTextContents_t
++line_counter; ++line_counter;
} }
// Any remaining elements? // Any remaining elements? If so, the data belongs to the last found section title
if (line_counter > bottom_title_line) { if (line_counter > bottom_title_line) {
update_primary_tbl(bottom_title_line, (line_counter - 1)); update_primary_tbl(bottom_title_line, line_counter);
} }
} }
@@ -570,15 +570,24 @@ class TagTextContents_t
// Note: Organizes table with Title as a Key, a Key/ID for values and values. // Note: Organizes table with Title as a Key, a Key/ID for values and values.
// It takes into consideration the initial constraints were all good and // It takes into consideration the initial constraints were all good and
// that the primary table has been populated. // that the primary table has been populated.
auto sec_key = std::string();
auto sec_data = std::string();
auto auto_key = uint32_t(0);
for (const auto& [prim_key, prim_values] : m_primary) { for (const auto& [prim_key, prim_values] : m_primary) {
for (const auto& value : prim_values) { for (const auto& value : prim_values) {
if (auto mark_pos = value.find_first_of(m_line_splitter_mark.c_str()); if (auto mark_pos = value.find_first_of(m_line_splitter_mark.c_str());
mark_pos != std::string::npos) { mark_pos != std::string::npos) {
auto sec_key = trim(value.substr(0, mark_pos + 1)); sec_key = trim(value.substr(0, mark_pos + 1));
auto sec_data = trim(value.substr((mark_pos + 1), value.size())); sec_data = trim(value.substr((mark_pos + 1), value.size()));
if (!sec_key.empty()) { }
m_structured[prim_key].insert(std::make_pair(sec_key, sec_data)); // In case there is no 'key' based on the data token marker, generate one.
} else {
sec_key = std::to_string(auto_key) + m_line_splitter_mark;
sec_data = trim(value.substr(0, value.size()));
++auto_key;
}
if (!sec_key.empty()) {
m_structured[prim_key].insert(std::make_pair(sec_key, sec_data));
} }
} }
} }
@@ -31,7 +31,7 @@ from rsmiBindings import *
# Patch version - Increment when adding a fix, set to 0 when minor is incremented # Patch version - Increment when adding a fix, set to 0 when minor is incremented
# Hash version - Shortened commit hash. Print here and not with lib for consistency with amd-smi # Hash version - Shortened commit hash. Print here and not with lib for consistency with amd-smi
SMI_MAJ = 2 SMI_MAJ = 2
SMI_MIN = 1 SMI_MIN = 2
SMI_PAT = 0 SMI_PAT = 0
# SMI_HASH is provided by rsmiBindings # SMI_HASH is provided by rsmiBindings
__version__ = '%s.%s.%s+%s' % (SMI_MAJ, SMI_MIN, SMI_PAT, SMI_HASH) __version__ = '%s.%s.%s+%s' % (SMI_MAJ, SMI_MIN, SMI_PAT, SMI_HASH)
@@ -1270,6 +1270,34 @@ def setClockExtremum(deviceList, level, clkType, clkValue, autoRespond):
printLog(device, 'Setting %s %s clock is not supported for this device.' % (level, clkType), None) printLog(device, 'Setting %s %s clock is not supported for this device.' % (level, clkType), None)
def setVoltageCurve(deviceList, point, clk, volt, autoRespond):
""" Set voltage curve for a point in the PowerPlay table for a list of devices.
:param deviceList: List of DRM devices (can be a single-item list)
:param point: Point on the voltage curve to modify
:param clk: Clock speed specified for this curve point
:param volt: Voltage specified for this curve point
:param autoRespond: Response to automatically provide for all prompts
"""
global RETCODE
value = '%s %s %s' % (point, clk, volt)
try:
any(int(item) for item in value.split())
except ValueError:
printErrLog(None, 'Unable to set Voltage curve')
printErrLog(None, 'Non-integer characters are present in %s' %value)
RETCODE = 1
return
confirmOutOfSpecWarning(autoRespond)
for device in deviceList:
ret = rocmsmi.rsmi_dev_od_volt_info_set(device, int(point), int(clk), int(volt))
if rsmi_ret_ok(ret, device, 'set_voltage_curve'):
printLog(device, 'Successfully set voltage point %s to %s(MHz) %s(mV)' % (point, clk, volt), None)
else:
printErrLog(device, 'Unable to set voltage point %s to %s(MHz) %s(mV)' % (point, clk, volt))
RETCODE = 1
def setPowerPlayTableLevel(deviceList, clkType, point, clk, volt, autoRespond): def setPowerPlayTableLevel(deviceList, clkType, point, clk, volt, autoRespond):
""" Set clock frequency and voltage for a level in the PowerPlay table for a list of devices. """ Set clock frequency and voltage for a level in the PowerPlay table for a list of devices.
@@ -2683,6 +2711,38 @@ def showPower(deviceList):
printLogSpacer() printLogSpacer()
def showPowerPlayTable(deviceList):
""" Display current GPU Memory clock frequencies and voltages for a list of devices
:param deviceList: List of DRM devices (can be a single-item list)
"""
global PRINT_JSON
if PRINT_JSON:
return
printLogSpacer(' GPU Memory clock frequencies and voltages ')
odvf = rsmi_od_volt_freq_data_t()
for device in deviceList:
ret = rocmsmi.rsmi_dev_od_volt_info_get(device, byref(odvf))
if rsmi_ret_ok(ret, device, 'get_od_volt'):
# TODO: Make this more dynamic and less hard-coded if possible
printLog(device, 'OD_SCLK:', None)
printLog(device, '0: %sMhz' % (int(odvf.curr_sclk_range.lower_bound / 1000000)), None)
printLog(device, '1: %sMhz' % (int(odvf.curr_sclk_range.upper_bound / 1000000)), None)
printLog(device, 'OD_MCLK:', None)
printLog(device, '0: %sMhz' % (int(odvf.curr_mclk_range.lower_bound / 1000000)), None)
printLog(device, '1: %sMhz' % (int(odvf.curr_mclk_range.upper_bound / 1000000)), None)
if odvf.sclk_freq_limits.lower_bound > 0 or odvf.sclk_freq_limits.upper_bound > 0 \
or odvf.mclk_freq_limits.lower_bound >0 or odvf.mclk_freq_limits.upper_bound > 0:
printLog(device, 'OD_RANGE:', None)
if odvf.sclk_freq_limits.lower_bound > 0 or odvf.sclk_freq_limits.upper_bound > 0:
printLog(device, 'SCLK: %sMhz %sMhz' % (
int(odvf.sclk_freq_limits.lower_bound / 1000000), int(odvf.sclk_freq_limits.upper_bound / 1000000)), None)
if odvf.mclk_freq_limits.lower_bound >0 or odvf.mclk_freq_limits.upper_bound > 0:
printLog(device, 'MCLK: %sMhz %sMhz' % (
int(odvf.mclk_freq_limits.lower_bound / 1000000), int(odvf.mclk_freq_limits.upper_bound / 1000000)), None)
printLogSpacer()
def showProduct(deviceList): def showProduct(deviceList):
""" Show the requested product information for a list of devices """ Show the requested product information for a list of devices
@@ -2754,7 +2814,7 @@ def showRange(deviceList, rangeType):
:param rangeType: [sclk|voltage] Type of range to return :param rangeType: [sclk|voltage] Type of range to return
""" """
global RETCODE global RETCODE
if rangeType not in {'sclk', 'mclk'}: if rangeType not in {'sclk', 'mclk', 'voltage'}:
printLog(None, 'Invalid range identifier %s' % (rangeType), None) printLog(None, 'Invalid range identifier %s' % (rangeType), None)
RETCODE = 1 RETCODE = 1
return return
@@ -2769,6 +2829,21 @@ def showRange(deviceList, rangeType):
if rangeType == 'mclk': if rangeType == 'mclk':
printLog(device, 'Valid mclk range: %sMhz - %sMhz' % ( printLog(device, 'Valid mclk range: %sMhz - %sMhz' % (
int(odvf.curr_mclk_range.lower_bound / 1000000), int(odvf.curr_mclk_range.upper_bound / 1000000)), None) int(odvf.curr_mclk_range.lower_bound / 1000000), int(odvf.curr_mclk_range.upper_bound / 1000000)), None)
if rangeType == 'voltage':
if odvf.num_regions == 0:
printErrLog(device, 'Voltage curve regions unsupported.')
continue
num_regions = c_uint32(odvf.num_regions)
regions = (rsmi_freq_volt_region_t * odvf.num_regions)()
ret = rocmsmi.rsmi_dev_od_volt_curve_regions_get(device, byref(num_regions), byref(regions))
if rsmi_ret_ok(ret, device, 'volt'):
for i in range(num_regions.value):
printLog(device,
'Region %d: Valid voltage range: %smV - %smV' % (i, regions[i].volt_range.lower_bound,
regions[i].volt_range.upper_bound),
None)
else:
printLog(device, 'Unable to display %s range' % (rangeType), None)
printLogSpacer() printLogSpacer()
@@ -3086,6 +3161,25 @@ def showVoltage(deviceList):
printLogSpacer() printLogSpacer()
def showVoltageCurve(deviceList):
""" Show the voltage curve points for the specified devices
:param deviceList: List of DRM devices (can be a single-item list)
"""
printLogSpacer(' Voltage Curve Points ')
odvf = rsmi_od_volt_freq_data_t()
for device in deviceList:
ret = rocmsmi.rsmi_dev_od_volt_info_get(device, byref(odvf))
if rsmi_ret_ok(ret, device, 'get_od_volt_info', silent=False) and odvf.num_regions > 0:
for position in range(3):
printLog(device, 'Voltage point %d: %sMhz %smV' % (
position, int(list(odvf.curve.vc_points)[position].frequency / 1000000),
int(list(odvf.curve.vc_points)[position].voltage)), None)
else:
printErrLog(device, 'Voltage curve Points unsupported.')
printLogSpacer()
def showXgmiErr(deviceList): def showXgmiErr(deviceList):
""" Display the XGMI Error status """ Display the XGMI Error status
@@ -3739,6 +3833,7 @@ if __name__ == '__main__':
groupDisplayTop.add_argument('--showproductname', help='Show product details', action='store_true') groupDisplayTop.add_argument('--showproductname', help='Show product details', action='store_true')
groupDisplayTop.add_argument('--showserial', help='Show GPU\'s Serial Number', action='store_true') groupDisplayTop.add_argument('--showserial', help='Show GPU\'s Serial Number', action='store_true')
groupDisplayTop.add_argument('--showuniqueid', help='Show GPU\'s Unique ID', action='store_true') groupDisplayTop.add_argument('--showuniqueid', help='Show GPU\'s Unique ID', action='store_true')
groupDisplayTop.add_argument('--showvoltagerange', help='Show voltage range', action='store_true')
groupDisplayTop.add_argument('--showbus', help='Show PCI bus number', action='store_true') groupDisplayTop.add_argument('--showbus', help='Show PCI bus number', action='store_true')
groupDisplayPages.add_argument('--showpagesinfo', help='Show retired, pending and unreservable pages', groupDisplayPages.add_argument('--showpagesinfo', help='Show retired, pending and unreservable pages',
action='store_true') action='store_true')
@@ -3763,6 +3858,8 @@ if __name__ == '__main__':
groupDisplay.add_argument('-o', '--showoverdrive', help='Show current GPU Clock OverDrive level', groupDisplay.add_argument('-o', '--showoverdrive', help='Show current GPU Clock OverDrive level',
action='store_true') action='store_true')
groupDisplay.add_argument('-p', '--showperflevel', help='Show current DPM Performance Level', action='store_true') groupDisplay.add_argument('-p', '--showperflevel', help='Show current DPM Performance Level', action='store_true')
groupDisplay.add_argument('-S', '--showclkvolt', help='Show supported GPU and Memory Clocks and Voltages',
action='store_true')
groupDisplay.add_argument('-s', '--showclkfrq', help='Show supported GPU and Memory Clock', action='store_true') groupDisplay.add_argument('-s', '--showclkfrq', help='Show supported GPU and Memory Clock', action='store_true')
groupDisplay.add_argument('--showmeminfo', help='Show Memory usage information for given block(s) TYPE', groupDisplay.add_argument('--showmeminfo', help='Show Memory usage information for given block(s) TYPE',
metavar='TYPE', type=str, nargs='+') metavar='TYPE', type=str, nargs='+')
@@ -3774,6 +3871,7 @@ if __name__ == '__main__':
groupDisplay.add_argument('--showrasinfo', groupDisplay.add_argument('--showrasinfo',
help='Show RAS enablement information and error counts for the specified block(s) (all if no arg given)', help='Show RAS enablement information and error counts for the specified block(s) (all if no arg given)',
nargs='*') nargs='*')
groupDisplay.add_argument('--showvc', help='Show voltage curve', action='store_true')
groupDisplay.add_argument('--showxgmierr', help='Show XGMI error information since last read', action='store_true') groupDisplay.add_argument('--showxgmierr', help='Show XGMI error information since last read', action='store_true')
groupDisplay.add_argument('--showtopo', help='Show hardware topology information', action='store_true') groupDisplay.add_argument('--showtopo', help='Show hardware topology information', action='store_true')
groupDisplay.add_argument('--showtopoaccess', help='Shows the link accessibility between GPUs ', action='store_true') groupDisplay.add_argument('--showtopoaccess', help='Shows the link accessibility between GPUs ', action='store_true')
@@ -3813,6 +3911,8 @@ if __name__ == '__main__':
groupAction.add_argument('--setmlevel', groupAction.add_argument('--setmlevel',
help='Change GPU Memory clock frequency (MHz) and Voltage for (mV) a specific Level', help='Change GPU Memory clock frequency (MHz) and Voltage for (mV) a specific Level',
metavar=('MCLKLEVEL', 'MCLK', 'MVOLT'), nargs=3) metavar=('MCLKLEVEL', 'MCLK', 'MVOLT'), nargs=3)
groupAction.add_argument('--setvc', help='Change SCLK Voltage Curve (MHz mV) for a specific point',
metavar=('POINT', 'SCLK', 'SVOLT'), nargs=3)
groupAction.add_argument('--setsrange', help='Set min and max SCLK speed', metavar=('SCLKMIN', 'SCLKMAX'), nargs=2) groupAction.add_argument('--setsrange', help='Set min and max SCLK speed', metavar=('SCLKMIN', 'SCLKMAX'), nargs=2)
groupAction.add_argument('--setextremum', help='Set min/max of SCLK/MCLK speed', metavar=('min|max', "sclk|mclk", 'CLK'), nargs=3) groupAction.add_argument('--setextremum', help='Set min/max of SCLK/MCLK speed', metavar=('min|max', "sclk|mclk", 'CLK'), nargs=3)
groupAction.add_argument('--setmrange', help='Set min and max MCLK speed', metavar=('MCLKMIN', 'MCLKMAX'), nargs=2) groupAction.add_argument('--setmrange', help='Set min and max MCLK speed', metavar=('MCLKMIN', 'MCLKMAX'), nargs=2)
@@ -3882,7 +3982,7 @@ if __name__ == '__main__':
or args.resetclocks or args.setprofile or args.resetprofile or args.setoverdrive or args.setmemoverdrive \ or args.resetclocks or args.setprofile or args.resetprofile or args.setoverdrive or args.setmemoverdrive \
or args.setpoweroverdrive or args.resetpoweroverdrive or args.rasenable or args.rasdisable or \ or args.setpoweroverdrive or args.resetpoweroverdrive or args.rasenable or args.rasdisable or \
args.rasinject or args.gpureset or args.setperfdeterminism or args.setslevel or args.setmlevel or \ args.rasinject or args.gpureset or args.setperfdeterminism or args.setslevel or args.setmlevel or \
args.setsrange or args.setextremum or args.setmrange or args.setclock or \ args.setvc or args.setsrange or args.setextremum or args.setmrange or args.setclock or \
args.setcomputepartition or args.setmemorypartition or args.resetcomputepartition or args.resetmemorypartition: args.setcomputepartition or args.setmemorypartition or args.resetcomputepartition or args.resetmemorypartition:
relaunchAsSudo() relaunchAsSudo()
@@ -3929,6 +4029,7 @@ if __name__ == '__main__':
args.showproductname = True args.showproductname = True
args.showserial = True args.showserial = True
args.showuniqueid = True args.showuniqueid = True
args.showvoltagerange = True
args.showbus = True args.showbus = True
args.showpagesinfo = True args.showpagesinfo = True
args.showfan = True args.showfan = True
@@ -3946,12 +4047,14 @@ if __name__ == '__main__':
args.showpids = "summary" args.showpids = "summary"
args.showpidgpus = [] args.showpidgpus = []
args.showreplaycount = True args.showreplaycount = True
args.showvc = True
args.showcomputepartition = True args.showcomputepartition = True
args.showmemorypartition = True args.showmemorypartition = True
if not PRINT_JSON: if not PRINT_JSON:
args.showprofile = True args.showprofile = True
args.showclkfrq = True args.showclkfrq = True
args.showclkvolt = True
# Don't do reset in combination with any other command # Don't do reset in combination with any other command
if args.gpureset: if args.gpureset:
@@ -4022,6 +4125,8 @@ if __name__ == '__main__':
showPids(args.showpids) showPids(args.showpids)
if args.showpidgpus or str(args.showpidgpus) == '[]': if args.showpidgpus or str(args.showpidgpus) == '[]':
showGpusByPid(args.showpidgpus) showGpusByPid(args.showpidgpus)
if args.showclkvolt:
showPowerPlayTable(deviceList)
if args.showvoltage: if args.showvoltage:
showVoltage(deviceList) showVoltage(deviceList)
if args.showbus: if args.showbus:
@@ -4065,6 +4170,10 @@ if __name__ == '__main__':
showRange(deviceList, 'sclk') showRange(deviceList, 'sclk')
if args.showmclkrange: if args.showmclkrange:
showRange(deviceList, 'mclk') showRange(deviceList, 'mclk')
if args.showvoltagerange:
showRange(deviceList, 'voltage')
if args.showvc:
showVoltageCurve(deviceList)
if args.showenergycounter: if args.showenergycounter:
showEnergy(deviceList) showEnergy(deviceList)
if args.showcomputepartition: if args.showcomputepartition:
@@ -4101,6 +4210,8 @@ if __name__ == '__main__':
resetPowerOverDrive(deviceList, args.autorespond) resetPowerOverDrive(deviceList, args.autorespond)
if args.setprofile: if args.setprofile:
setProfile(deviceList, args.setprofile) setProfile(deviceList, args.setprofile)
if args.setvc:
setVoltageCurve(deviceList, args.setvc[0], args.setvc[1], args.setvc[2], args.autorespond)
if args.setextremum: if args.setextremum:
setClockExtremum(deviceList, args.setextremum[0], args.setextremum[1], args.setextremum[2], args.autorespond) setClockExtremum(deviceList, args.setextremum[0], args.setextremum[1], args.setextremum[2], args.autorespond)
if args.setsrange: if args.setsrange:
+56 -2
View File
@@ -1286,12 +1286,16 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind,
return RSMI_STATUS_NOT_YET_IMPLEMENTED; return RSMI_STATUS_NOT_YET_IMPLEMENTED;
} }
// // Tags expected in this file
const std::string kTAG_OD_SCLK{"OD_SCLK:"}; const std::string kTAG_OD_SCLK{"OD_SCLK:"};
const std::string kTAG_GFXCLK{"GFXCLK:"};
const std::string KTAG_OD_MCLK{"OD_MCLK:"}; const std::string KTAG_OD_MCLK{"OD_MCLK:"};
const std::string kTAG_GFXCLK{"GFXCLK:"};
const std::string KTAG_MCLK{"MCLK:"}; const std::string KTAG_MCLK{"MCLK:"};
const std::string KTAG_SCLK{"SCLK:"};
const std::string KTAG_OD_RANGE{"OD_RANGE:"};
const std::string KTAG_OD_VDDGFX_OFFSET{"OD_VDDGFX_OFFSET:"};
const std::string KTAG_FIRST_FREQ_IDX{"0:"}; const std::string KTAG_FIRST_FREQ_IDX{"0:"};
amd::smi::TextFileTagContents_t txt_power_dev_od_voltage(val_vec); amd::smi::TextFileTagContents_t txt_power_dev_od_voltage(val_vec);
txt_power_dev_od_voltage txt_power_dev_od_voltage
.set_title_terminator(":", amd::smi::TagSplitterPositional_t::kLAST) .set_title_terminator(":", amd::smi::TagSplitterPositional_t::kLAST)
@@ -1337,6 +1341,20 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind,
p->curr_mclk_range.lower_bound = freq_string_to_int(build_lower_bound(KTAG_OD_MCLK), nullptr, nullptr, 0); p->curr_mclk_range.lower_bound = freq_string_to_int(build_lower_bound(KTAG_OD_MCLK), nullptr, nullptr, 0);
p->curr_mclk_range.upper_bound = freq_string_to_int(build_upper_bound(KTAG_OD_MCLK), nullptr, nullptr, 0); p->curr_mclk_range.upper_bound = freq_string_to_int(build_upper_bound(KTAG_OD_MCLK), nullptr, nullptr, 0);
} }
// Validates 'OD_RANGE' is in the structure
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
KTAG_SCLK)) {
od_value_pair_str_to_range(txt_power_dev_od_voltage
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_SCLK),
&p->sclk_freq_limits);
}
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
KTAG_MCLK)) {
od_value_pair_str_to_range(txt_power_dev_od_voltage
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_MCLK),
&p->mclk_freq_limits);
}
} }
// Validates 'GFXCLK' is in the structure // Validates 'GFXCLK' is in the structure
else if (txt_power_dev_od_voltage.contains_structured_key(kTAG_GFXCLK, else if (txt_power_dev_od_voltage.contains_structured_key(kTAG_GFXCLK,
@@ -1354,6 +1372,8 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind,
else { else {
return RSMI_STATUS_NOT_YET_IMPLEMENTED; return RSMI_STATUS_NOT_YET_IMPLEMENTED;
} }
// Note: No curve entries.
p->num_regions = 0; p->num_regions = 0;
return RSMI_STATUS_SUCCESS; return RSMI_STATUS_SUCCESS;
@@ -1562,6 +1582,36 @@ rsmi_status_t rsmi_dev_od_volt_info_set(uint32_t dv_ind, uint32_t vpoint,
} }
static void get_vc_region(const std::vector<std::string>& val_vec, rsmi_freq_volt_region_t& p)
{
std::ostringstream ss;
ss << __PRETTY_FUNCTION__ << " | ======= start =======";
LOG_TRACE(ss);
//
amd::smi::TextFileTagContents_t txt_power_dev_od_voltage(val_vec);
txt_power_dev_od_voltage
.set_title_terminator(":", amd::smi::TagSplitterPositional_t::kLAST)
.set_key_data_splitter(":", amd::smi::TagSplitterPositional_t::kBETWEEN)
.structure_content();
const std::string KTAG_OD_RANGE{"OD_RANGE:"};
const std::string KTAG_MCLK{"MCLK:"};
const std::string KTAG_SCLK{"SCLK:"};
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
KTAG_SCLK)) {
od_value_pair_str_to_range(txt_power_dev_od_voltage
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_SCLK),
&p.freq_range);
}
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
KTAG_MCLK)) {
od_value_pair_str_to_range(txt_power_dev_od_voltage
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_MCLK),
&p.volt_range);
}
}
/* /*
* num_regions [inout] on calling, the number of regions requested to be read * num_regions [inout] on calling, the number of regions requested to be read
* in. At completion, the number of regions actually read in * in. At completion, the number of regions actually read in
@@ -1606,7 +1656,11 @@ static rsmi_status_t get_od_clk_volt_curve_regions(uint32_t dv_ind,
<< " | val_vec_size = " << std::dec << " | val_vec_size = " << std::dec
<< val_vec_size; << val_vec_size;
LOG_DEBUG(ss); LOG_DEBUG(ss);
// Note: No curve entries.
*num_regions = 0; *num_regions = 0;
// Get OD ranges.
get_vc_region(val_vec, *p);
return RSMI_STATUS_SUCCESS; return RSMI_STATUS_SUCCESS;
CATCH CATCH
@@ -1076,6 +1076,7 @@ static std::string print_pnt(rsmi_od_vddc_point_t *pt) {
ss << "\t\t** Voltage: " << pt->voltage << " mV\n"; ss << "\t\t** Voltage: " << pt->voltage << " mV\n";
return ss.str(); return ss.str();
} }
static std::string pt_vddc_curve(rsmi_od_volt_curve *c) { static std::string pt_vddc_curve(rsmi_od_volt_curve *c) {
std::ostringstream ss; std::ostringstream ss;
if (c == nullptr) { if (c == nullptr) {
@@ -1098,6 +1099,14 @@ std::string print_rsmi_od_volt_freq_data_t(rsmi_od_volt_freq_data_t *odv) {
ss << pt_rng_Mhz("\t**Current SCLK frequency range: ", &odv->curr_sclk_range); ss << pt_rng_Mhz("\t**Current SCLK frequency range: ", &odv->curr_sclk_range);
ss << pt_rng_Mhz("\t**Current MCLK frequency range: ", &odv->curr_mclk_range); ss << pt_rng_Mhz("\t**Current MCLK frequency range: ", &odv->curr_mclk_range);
ss << pt_rng_Mhz("\t**Min/Max Possible SCLK frequency range: ",
&odv->sclk_freq_limits);
ss << pt_rng_Mhz("\t**Min/Max Possible MCLK frequency range: ",
&odv->mclk_freq_limits);
ss << "\t**Current Freq/Volt. curve: " << "\n";
ss << "\t\t N/A" << "\n";
ss << "\t**Number of Freq./Volt. regions: " << odv->num_regions << "\n\n"; ss << "\t**Number of Freq./Volt. regions: " << odv->num_regions << "\n\n";
return ss.str(); return ss.str();
} }
@@ -93,9 +93,9 @@ void TestPerfDeterminism::Close() {
void TestPerfDeterminism::Run(void) { void TestPerfDeterminism::Run(void) {
rsmi_status_t err; rsmi_status_t err;
rsmi_dev_perf_level_t pfl; rsmi_dev_perf_level_t pfl;
rsmi_od_volt_freq_data_t odv; rsmi_od_volt_freq_data_t odv{};
rsmi_status_t ret; rsmi_status_t ret;
uint64_t clkvalue; uint64_t clkvalue(0);
TestBase::Run(); TestBase::Run();
if (setup_failed_) { if (setup_failed_) {
std::cout << "** SetUp Failed for this test. Skipping.**" << std::endl; std::cout << "** SetUp Failed for this test. Skipping.**" << std::endl;
@@ -113,22 +113,7 @@ void TestVoltCurvRead::Run(void) {
<< amd::smi::getRSMIStatusString(ret, false) << "\n"; << amd::smi::getRSMIStatusString(ret, false) << "\n";
} }
CHK_ERR_ASRT(ret) CHK_ERR_ASRT(ret)
err = rsmi_dev_od_volt_info_get(i, &odv);
IF_VERB(STANDARD) {
std::cout << "\t**rsmi_dev_od_volt_info_get(i, &odv): "
<< amd::smi::getRSMIStatusString(err, false)
<< "\n"
<< amd::smi::print_rsmi_od_volt_freq_data_t(&odv)
<< "\n";
}
if (err != RSMI_STATUS_SUCCESS) {
IF_VERB(STANDARD) {
std::cout <<
"\t**rsmi_dev_od_volt_info_get: Not supported on this machine"
<< std::endl;
}
continue;
}
// Verify api support checking functionality is working // Verify api support checking functionality is working
err = rsmi_dev_od_volt_info_get(i, nullptr); err = rsmi_dev_od_volt_info_get(i, nullptr);
IF_VERB(STANDARD) { IF_VERB(STANDARD) {
@@ -144,5 +129,44 @@ void TestVoltCurvRead::Run(void) {
<< "\t**odv.num_regions = " << std::dec << "\t**odv.num_regions = " << std::dec
<< odv.num_regions << "\n"; << odv.num_regions << "\n";
} }
if (err == RSMI_STATUS_SUCCESS) {
std::cout << "\t**Frequency-voltage curve data:" << "\n";
std::cout << amd::smi::print_rsmi_od_volt_freq_data_t(&odv);
rsmi_freq_volt_region_t *regions{};
uint32_t num_regions;
regions = new rsmi_freq_volt_region_t[odv.num_regions];
ASSERT_TRUE(regions != nullptr);
num_regions = odv.num_regions;
err = rsmi_dev_od_volt_curve_regions_get(i, &num_regions, regions);
IF_VERB(STANDARD) {
std::cout << "\t**rsmi_dev_od_volt_curve_regions_get("
<< "i, &num_regions, regions): "
<< amd::smi::getRSMIStatusString(err, false) << "\n"
<< "\t**Number of regions: " << std::dec << num_regions
<< "\n";
}
ASSERT_TRUE(err == RSMI_STATUS_SUCCESS
|| err == RSMI_STATUS_NOT_SUPPORTED
|| err == RSMI_STATUS_UNEXPECTED_DATA
|| err == RSMI_STATUS_UNEXPECTED_SIZE
|| err == RSMI_STATUS_INVALID_ARGS);
if (err != RSMI_STATUS_SUCCESS) {
IF_VERB(STANDARD) {
std::cout << "\t**rsmi_dev_od_volt_curve_regions_get: "
"Not supported on this machine" << std::endl;
}
continue;
}
CHK_ERR_ASRT(err)
ASSERT_TRUE(num_regions == odv.num_regions);
std::cout << "\t**Frequency-voltage curve regions:" << std::endl;
std::cout << amd::smi::print_rsmi_od_volt_freq_regions(num_regions,
regions);
delete []regions;
}
} }
} }