2023-03-20 13:29:28 -05:00
#!/usr/bin/env python3
2023-03-06 06:20:21 -06:00
#
2024-11-14 11:27:38 -06:00
# Copyright (C) Advanced Micro Devices. All rights reserved.
2023-03-06 06:20:21 -06:00
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import argparse
import errno
import os
2023-10-16 03:26:17 -05:00
import sys
2023-03-06 06:20:21 -06:00
import time
2024-09-12 13:54:18 -05:00
import collections
2024-12-20 16:32:10 -05:00
from amdsmi import amdsmi_interface
2024-09-18 16:59:12 -05:00
from typing import Optional
from typing import Union
2023-10-16 03:26:17 -05:00
2023-03-06 06:20:21 -06:00
from pathlib import Path
from _version import __version__
from amdsmi_helpers import AMDSMIHelpers
2023-12-12 15:54:00 -06:00
from rocm_version import get_rocm_version
2023-03-17 14:58:50 +01:00
import amdsmi_cli_exceptions
2023-03-06 06:20:21 -06:00
2023-10-13 06:32:34 -05:00
# Custom Help Formatter for increasing the action max length
2023-10-13 14:03:24 -05:00
class AMDSMIParserHelpFormatter ( argparse . HelpFormatter ) :
def __init__ ( self , prog ) :
super ( ) . __init__ ( prog = prog ,
indent_increment = 2 ,
max_help_position = 24 ,
width = 90 )
2023-10-13 06:32:34 -05:00
self . _action_max_length = 20
2023-10-13 14:03:24 -05:00
# Custom Help Formatter for not duplicating the metavar in the subparsers
class AMDSMISubparserHelpFormatter ( argparse . RawTextHelpFormatter ) :
def __init__ ( self , prog ) :
super ( ) . __init__ ( prog , max_help_position = 80 , width = 90 )
def _format_action_invocation ( self , action ) :
if not action . option_strings or action . nargs == 0 :
return super ( ) . _format_action_invocation ( action )
default = self . _get_default_metavar_for_optional ( action )
args_string = self . _format_args ( action , default )
return ' , ' . join ( action . option_strings ) + ' ' + args_string
2023-03-06 06:20:21 -06:00
class AMDSMIParser ( argparse . ArgumentParser ) :
2023-04-15 02:00:37 -05:00
""" Unified Parser for AMDSMI CLI.
This parser doesn ' t access amdsmi ' s lib directly,but via AMDSMIHelpers,
this allows for us to use this parser with future OS & Platform integration.
Args:
argparse (ArgumentParser): argparse.ArgumentParser
"""
2023-09-18 03:39:03 -05:00
def __init__ ( self , version , list , static , firmware , bad_pages , metric ,
2023-12-06 16:57:26 -06:00
process , profile , event , topology , set_value , reset , monitor ,
2024-09-25 22:44:38 -05:00
rocmsmi , xgmi , partition ) :
2023-03-06 06:20:21 -06:00
# Helper variables
2023-04-15 02:00:37 -05:00
self . helpers = AMDSMIHelpers ( )
2024-02-21 03:48:09 -06:00
# Get choices based on driver initialized
if self . helpers . is_amdgpu_initialized ( ) :
self . gpu_choices , self . gpu_choices_str = self . helpers . get_gpu_choices ( )
else :
self . gpu_choices = { }
self . gpu_choices_str = " "
if self . helpers . is_amd_hsmp_initialized ( ) :
self . cpu_choices , self . cpu_choices_str = self . helpers . get_cpu_choices ( )
self . core_choices , self . core_choices_str = self . helpers . get_core_choices ( )
else :
self . cpu_choices = { }
self . cpu_choices_str = " "
self . core_choices = { }
self . core_choices_str = " "
2023-03-06 06:20:21 -06:00
self . vf_choices = [ ' 3 ' , ' 2 ' , ' 1 ' ]
version_string = f " Version: { __version__ } "
2023-04-15 02:00:37 -05:00
platform_string = f " Platform: { self . helpers . os_info ( ) } "
2024-01-21 02:44:44 -06:00
rocm_version = get_rocm_version ( )
2023-12-12 15:54:00 -06:00
rocm_version_string = f " ROCm version: { rocm_version } "
2023-04-24 21:34:44 -05:00
program_name = ' amd-smi '
2023-03-06 06:20:21 -06:00
# Adjust argument parser options
super ( ) . __init__ (
2023-10-13 14:03:24 -05:00
formatter_class = lambda prog : AMDSMIParserHelpFormatter ( prog ) ,
2023-12-12 15:54:00 -06:00
description = f " AMD System Management Interface | { version_string } | { rocm_version_string } | { platform_string } " ,
2023-03-06 06:20:21 -06:00
add_help = True ,
2023-04-24 21:34:44 -05:00
prog = program_name )
2023-03-06 06:20:21 -06:00
# Setup subparsers
2023-10-13 14:03:24 -05:00
self . subparsers = self . add_subparsers (
2023-03-06 06:20:21 -06:00
title = " AMD-SMI Commands " ,
parser_class = argparse . ArgumentParser ,
help = " Descriptions: " ,
2023-04-24 21:34:44 -05:00
metavar = ' ' )
2023-03-06 06:20:21 -06:00
2024-06-20 13:05:51 -05:00
# Store possible subcommands & aliases for later errors
2024-06-24 12:07:34 -05:00
self . possible_commands = [ ' version ' , ' list ' , ' static ' , ' firmware ' , ' ucode ' , ' bad-pages ' ,
' metric ' , ' process ' , ' profile ' , ' event ' , ' topology ' , ' set ' ,
2024-09-25 22:44:38 -05:00
' reset ' , ' monitor ' , ' dmon ' , ' xgmi ' , ' partition ' ]
2024-06-24 12:07:34 -05:00
2023-03-06 06:20:21 -06:00
# Add all subparsers
2023-10-13 14:03:24 -05:00
self . _add_version_parser ( self . subparsers , version )
self . _add_list_parser ( self . subparsers , list )
self . _add_static_parser ( self . subparsers , static )
self . _add_firmware_parser ( self . subparsers , firmware )
self . _add_bad_pages_parser ( self . subparsers , bad_pages )
self . _add_metric_parser ( self . subparsers , metric )
self . _add_process_parser ( self . subparsers , process )
self . _add_profile_parser ( self . subparsers , profile )
self . _add_event_parser ( self . subparsers , event )
self . _add_topology_parser ( self . subparsers , topology )
self . _add_set_value_parser ( self . subparsers , set_value )
self . _add_reset_parser ( self . subparsers , reset )
2023-12-06 16:57:26 -06:00
self . _add_monitor_parser ( self . subparsers , monitor )
2023-10-13 14:03:24 -05:00
self . _add_rocm_smi_parser ( self . subparsers , rocmsmi )
2024-02-22 23:08:37 -06:00
self . _add_xgmi_parser ( self . subparsers , xgmi )
2024-09-25 22:44:38 -05:00
self . _add_partition_parser ( self . subparsers , partition )
2023-03-06 06:20:21 -06:00
2025-01-07 17:13:00 -06:00
def _not_negative_int ( self , int_value , sub_arg = None ) :
2023-03-06 06:20:21 -06:00
# Argument type validator
2023-10-17 00:08:43 -05:00
if int_value . isdigit ( ) : # Is digit doesn't work on negative numbers
2023-03-06 06:20:21 -06:00
return int ( int_value )
2023-10-17 00:08:43 -05:00
outputformat = self . helpers . get_output_format ( )
2024-07-12 09:11:56 -05:00
if int_value == " " :
2025-01-07 17:13:00 -06:00
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( sub_arg , outputformat )
2024-07-12 09:11:56 -05:00
else :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( int_value , outputformat )
2023-10-17 00:08:43 -05:00
2025-01-07 17:13:00 -06:00
def _positive_int ( self , int_value , sub_arg = None ) :
2023-10-17 00:08:43 -05:00
# Argument type validator
if int_value . isdigit ( ) : # Is digit doesn't work on negative numbers
if int ( int_value ) > 0 :
return int ( int_value )
outputformat = self . helpers . get_output_format ( )
2024-07-12 09:11:56 -05:00
if int_value == " " :
2025-01-07 17:13:00 -06:00
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( sub_arg , outputformat )
2024-07-12 09:11:56 -05:00
else :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( int_value , outputformat )
2023-03-06 06:20:21 -06:00
2025-01-07 17:13:00 -06:00
def _is_valid_string ( self , string_value , sub_arg = None ) :
2024-06-08 05:36:01 -05:00
# Argument type validator
# This is for triggering a cli exception if an empty string is detected
if string_value :
return string_value
outputformat = self . helpers . get_output_format ( )
2024-07-12 09:11:56 -05:00
if string_value == " " :
2025-01-07 17:13:00 -06:00
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( sub_arg , outputformat )
2024-07-12 09:11:56 -05:00
else :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( string_value , outputformat )
2024-06-08 05:36:01 -05:00
2025-01-15 20:28:45 -06:00
def _is_command_supported ( self , user_input , acceptable_values , command_name ) :
if acceptable_values == " N/A " :
raise amdsmi_cli_exceptions . AmdSmiCommandNotSupportedException ( command_name , self . helpers . get_output_format ( ) )
elif str ( user_input ) . upper ( ) not in acceptable_values :
print ( f " Valid inputs are { acceptable_values } " )
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( str ( user_input ) . upper ( ) , self . helpers . get_output_format ( ) )
else :
return str ( user_input ) . upper ( )
2024-08-05 17:18:37 -05:00
2024-09-12 13:54:18 -05:00
def _limit_select ( self ) :
""" Custom action for setting clock limits """
output_format = self . helpers . get_output_format ( )
class AMDSMILimitArgs ( argparse . Action ) :
def __call__ ( self , parser : AMDSMIParser , namespace : argparse . Namespace ,
2024-09-18 16:59:12 -05:00
values : Union [ str , list , None ] , option_string : Optional [ str ] = None ) - > None :
2024-09-12 13:54:18 -05:00
# valid values
valid_clk_types = ( ' sclk ' , ' mclk ' )
valid_lim_types = ( ' min ' , ' max ' )
clk_type , lim_type , val = values
2024-11-11 16:57:15 -06:00
# Check if the sclk and mclk parameters are valid
2024-09-12 13:54:18 -05:00
if clk_type not in valid_clk_types :
2024-11-11 16:57:15 -06:00
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterException ( clk_type , output_format )
2024-09-12 13:54:18 -05:00
if lim_type not in valid_lim_types :
2024-11-11 16:57:15 -06:00
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterException ( lim_type , output_format )
# Check if the val is a valid integer value
if not val . isdigit ( ) :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( val , output_format )
2024-09-12 13:54:18 -05:00
val = int ( val )
2024-11-11 16:57:15 -06:00
if val < 0 :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( val , output_format )
2024-09-12 13:54:18 -05:00
clk_limit_args = collections . namedtuple ( ' clk_limit_args ' , [ ' clk_type ' , ' lim_type ' , ' val ' ] )
setattr ( namespace , self . dest , clk_limit_args ( clk_type , lim_type , val ) )
return AMDSMILimitArgs
2024-12-04 11:46:59 -06:00
def _level_select ( self ) :
""" Custom action for setting clock frequencies to particular performance level """
output_format = self . helpers . get_output_format ( )
class AMDSMIFreqArgs ( argparse . Action ) :
def __call__ ( self , parser : AMDSMIParser , namespace : argparse . Namespace ,
values : list , option_string : Optional [ str ] = None ) - > None :
# valid values
valid_clk_types = ( ' sclk ' , ' mclk ' , ' pcie ' , ' fclk ' , ' socclk ' )
clk_type = values [ 0 ]
perf_levels_str = values [ 1 : ]
# Check if the sclk and mclk parameters are valid
if clk_type not in valid_clk_types :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterException ( clk_type , output_format )
perf_levels = [ ]
# Check if every item in perf level is valid
for level in perf_levels_str :
if not level . isdigit ( ) :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( level , output_format )
level = int ( level )
if level < 0 :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( level , output_format )
perf_levels . append ( level )
clk_level_args = collections . namedtuple ( ' clk_level_args ' , [ ' clk_type ' , ' perf_levels ' ] )
setattr ( namespace , self . dest , clk_level_args ( clk_type , perf_levels ) )
return AMDSMIFreqArgs
2023-03-06 06:20:21 -06:00
def _check_output_file_path ( self ) :
""" Argument action validator:
Returns a path to a file from the output file path provided.
If the path is a directory then create a file within it and return that file path
If the path is a file and it exists return the file path
If the path is a file and it doesn ' t exist create and return the file path
"""
class CheckOutputFilePath ( argparse . Action ) :
2023-04-15 02:00:37 -05:00
outputformat = self . helpers . get_output_format ( )
2023-03-06 06:20:21 -06:00
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
path = Path ( values )
if not path . exists ( ) :
if path . parent . is_dir ( ) :
path . touch ( )
else :
2023-04-15 02:00:37 -05:00
raise amdsmi_cli_exceptions . AmdSmiInvalidFilePathException ( path , CheckOutputFilePath . outputformat )
2023-03-06 06:20:21 -06:00
if path . is_dir ( ) :
2023-04-19 23:58:33 -05:00
file_name = f " { int ( time . time ( ) ) } -amdsmi-output "
if args . json :
file_name + = " .json "
elif args . csv :
file_name + = " .csv "
else :
2023-04-21 08:02:53 -05:00
file_name + = " .txt "
2023-04-19 23:58:33 -05:00
path = path / file_name
2023-03-06 06:20:21 -06:00
path . touch ( )
setattr ( args , self . dest , path )
elif path . is_file ( ) :
2023-07-31 09:31:40 -05:00
path . touch ( )
2023-03-06 06:20:21 -06:00
setattr ( args , self . dest , path )
else :
2023-04-15 02:00:37 -05:00
raise amdsmi_cli_exceptions . AmdSmiInvalidFilePathException ( path , CheckOutputFilePath . outputformat )
2023-03-06 06:20:21 -06:00
return CheckOutputFilePath
def _check_input_file_path ( self ) :
""" Argument action validator:
Returns a path to a file from the input file path provided.
If the file doesn ' t exist or is empty raise error
"""
class _CheckInputFilePath ( argparse . Action ) :
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
path = Path ( values )
if not path . exists ( ) :
raise FileNotFoundError (
errno . ENOENT , os . strerror ( errno . ENOENT ) , values )
if path . is_dir ( ) :
raise argparse . ArgumentTypeError (
f " Invalid Path: { path } is directory when it needs to be a specific file " )
if path . is_file ( ) :
if os . stat ( values ) . st_size == 0 :
2023-03-28 15:32:17 -05:00
raise argparse . ArgumentTypeError ( f " Invalid Path: { path } Input file is empty " )
2023-03-06 06:20:21 -06:00
setattr ( args , self . dest , path )
else :
raise argparse . ArgumentTypeError (
f " Invalid path: { path } Could not determine if value given is a valid path " )
return _CheckInputFilePath
def _check_watch_selected ( self ) :
2023-03-17 14:58:50 +01:00
""" Validate that the -w/--watch argument was selected
2023-03-06 06:20:21 -06:00
This is because -W/--watch_time and -i/--iterations are dependent on watch
"""
2023-03-17 14:58:50 +01:00
class WatchSelectedAction ( argparse . Action ) :
2023-03-06 06:20:21 -06:00
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
if args . watch is None :
2023-03-17 14:58:50 +01:00
raise argparse . ArgumentError ( self , f " invalid argument: ' { self . dest } ' needs to be paired with -w/--watch " )
else :
setattr ( args , self . dest , values )
return WatchSelectedAction
2023-03-06 06:20:21 -06:00
2023-04-21 08:02:53 -05:00
2023-03-06 06:20:21 -06:00
def _gpu_select ( self , gpu_choices ) :
2023-03-17 14:58:50 +01:00
""" Custom argparse action to return the device handle(s) for the gpu(s) selected
2023-03-06 06:20:21 -06:00
This will set the destination (args.gpu) to a list of 1 or more device handles
If 1 or more device handles are not found then raise an ArgumentError for the first invalid gpu seen
"""
2023-03-17 14:58:50 +01:00
2023-04-15 02:00:37 -05:00
amdsmi_helpers = self . helpers
2023-03-06 06:20:21 -06:00
class _GPUSelectAction ( argparse . Action ) :
2023-04-15 02:00:37 -05:00
ouputformat = self . helpers . get_output_format ( )
2023-03-06 06:20:21 -06:00
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
2023-10-16 03:26:17 -05:00
if " all " in gpu_choices :
del gpu_choices [ " all " ]
2024-07-29 19:13:52 -05:00
status , gpu_format , selected_device_handles = amdsmi_helpers . get_device_handles_from_gpu_selections ( gpu_selections = values ,
2023-03-06 06:20:21 -06:00
gpu_choices = gpu_choices )
if status :
setattr ( args , self . dest , selected_device_handles )
else :
2023-04-15 02:00:37 -05:00
if selected_device_handles == ' ' :
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( " --gpu " , _GPUSelectAction . ouputformat )
2024-07-29 19:13:52 -05:00
elif not gpu_format :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( selected_device_handles ,
_GPUSelectAction . ouputformat )
2023-03-17 14:58:50 +01:00
else :
2024-06-24 12:07:34 -05:00
raise amdsmi_cli_exceptions . AmdSmiDeviceNotFoundException ( selected_device_handles ,
_GPUSelectAction . ouputformat ,
True , False , False )
2023-03-17 14:58:50 +01:00
2023-03-06 06:20:21 -06:00
return _GPUSelectAction
2023-12-07 07:33:17 -08:00
def _cpu_select ( self , cpu_choices ) :
""" Custom argparse action to return the device handle(s) for the cpu(s) selected
This will set the destination (args.cpu) to a list of 1 or more device handles
If 1 or more device handles are not found then raise an ArgumentError for the first invalid cpu seen
"""
amdsmi_helpers = self . helpers
class _CPUSelectAction ( argparse . Action ) :
ouputformat = self . helpers . get_output_format ( )
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
if " all " in cpu_choices :
del cpu_choices [ " all " ]
2024-07-29 19:13:52 -05:00
status , cpu_format , selected_device_handles = amdsmi_helpers . get_device_handles_from_cpu_selections ( cpu_selections = values ,
2023-12-07 07:33:17 -08:00
cpu_choices = cpu_choices )
if status :
setattr ( args , self . dest , selected_device_handles )
else :
if selected_device_handles == ' ' :
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( " --cpu " , _CPUSelectAction . ouputformat )
2024-07-29 19:13:52 -05:00
elif not cpu_format :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( selected_device_handles ,
_CPUSelectAction . ouputformat )
2023-12-07 07:33:17 -08:00
else :
raise amdsmi_cli_exceptions . AmdSmiDeviceNotFoundException ( selected_device_handles ,
2024-06-24 12:07:34 -05:00
_CPUSelectAction . ouputformat ,
False , True , False )
2023-12-07 07:33:17 -08:00
return _CPUSelectAction
def _core_select ( self , core_choices ) :
""" Custom argparse action to return the device handle(s) for the core(s) selected
This will set the destination (args.core) to a list of 1 or more device handles
If 1 or more device handles are not found then raise an ArgumentError for the first invalid core seen
"""
amdsmi_helpers = self . helpers
class _CoreSelectAction ( argparse . Action ) :
ouputformat = self . helpers . get_output_format ( )
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
if " all " in core_choices :
del core_choices [ " all " ]
2024-07-29 19:13:52 -05:00
status , core_format , selected_device_handles = amdsmi_helpers . get_device_handles_from_core_selections ( core_selections = values ,
2023-12-07 07:33:17 -08:00
core_choices = core_choices )
if status :
setattr ( args , self . dest , selected_device_handles )
else :
if selected_device_handles == ' ' :
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( " --core " , _CoreSelectAction . ouputformat )
2024-07-29 19:13:52 -05:00
elif not core_format :
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( selected_device_handles ,
_CoreSelectAction . ouputformat )
2023-12-07 07:33:17 -08:00
else :
raise amdsmi_cli_exceptions . AmdSmiDeviceNotFoundException ( selected_device_handles ,
2024-06-24 12:07:34 -05:00
_CoreSelectAction . ouputformat ,
False , False , True )
2023-12-07 07:33:17 -08:00
return _CoreSelectAction
2025-01-15 20:28:45 -06:00
def _add_command_modifiers ( self , subcommand_parser : argparse . ArgumentParser ) :
2023-03-06 06:20:21 -06:00
json_help = " Displays output in JSON format (human readable by default). "
csv_help = " Displays output in CSV format (human readable by default). "
file_help = " Saves output into a file on the provided path (stdout by default). "
2023-10-13 14:03:24 -05:00
loglevel_choices = [ " DEBUG " , " INFO " , " WARNING " , " ERROR " , " CRITICAL " ]
2023-10-16 11:11:03 -05:00
loglevel_choices_str = " , " . join ( loglevel_choices )
loglevel_help = f " Set the logging level from the possible choices: \n \t { loglevel_choices_str } "
2023-03-06 06:20:21 -06:00
command_modifier_group = subcommand_parser . add_argument_group ( ' Command Modifiers ' )
# Output Format options
logging_args = command_modifier_group . add_mutually_exclusive_group ( )
logging_args . add_argument ( ' --json ' , action = ' store_true ' , required = False , help = json_help )
logging_args . add_argument ( ' --csv ' , action = ' store_true ' , required = False , help = csv_help )
command_modifier_group . add_argument ( ' --file ' , action = self . _check_output_file_path ( ) , type = str , required = False , help = file_help )
# Placing loglevel outside the subcommands so it can be used with any subcommand
2023-11-22 03:32:55 -06:00
command_modifier_group . add_argument ( ' --loglevel ' , action = ' store ' , type = str . upper , required = False , help = loglevel_help , default = ' ERROR ' , metavar = ' LEVEL ' ,
2023-10-13 14:03:24 -05:00
choices = loglevel_choices )
2023-03-06 06:20:21 -06:00
2023-04-15 02:00:37 -05:00
def _add_watch_arguments ( self , subcommand_parser ) :
# Device arguments help text
2023-10-13 14:03:24 -05:00
watch_help = " Reprint the command in a loop of INTERVAL seconds "
watch_time_help = " The total TIME to watch the given command "
iterations_help = " Total number of ITERATIONS to loop on the given command "
2023-04-15 02:00:37 -05:00
# Mutually Exclusive Args within the subparser
2023-10-13 14:03:24 -05:00
subcommand_parser . add_argument ( ' -w ' , ' --watch ' , action = ' store ' , metavar = ' INTERVAL ' ,
2025-01-07 17:13:00 -06:00
type = lambda value : self . _positive_int ( value , ' --watch ' ) , required = False , help = watch_help )
2023-10-13 14:03:24 -05:00
subcommand_parser . add_argument ( ' -W ' , ' --watch_time ' , action = self . _check_watch_selected ( ) , metavar = ' TIME ' ,
2025-01-07 17:13:00 -06:00
type = lambda value : self . _positive_int ( value , ' --watch_time ' ) , required = False , help = watch_time_help )
2023-10-13 14:03:24 -05:00
subcommand_parser . add_argument ( ' -i ' , ' --iterations ' , action = self . _check_watch_selected ( ) , metavar = ' ITERATIONS ' ,
2025-01-07 17:13:00 -06:00
type = lambda value : self . _positive_int ( value , ' --iterations ' ) , required = False , help = iterations_help )
2023-04-15 02:00:37 -05:00
2024-01-03 08:01:33 -05:00
def _validate_cpu_core ( self , value ) :
2024-08-05 13:05:12 -05:00
if value == ' ' :
outputformat = self . helpers . get_output_format ( )
raise amdsmi_cli_exceptions . AmdSmiMissingParameterValueException ( value , outputformat )
2024-02-21 03:48:09 -06:00
if isinstance ( value , str ) :
if value . lower ( ) == " all " :
return value
if value . isdigit ( ) :
if int ( value ) < 0 :
outputformat = self . helpers . get_output_format ( )
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( value , outputformat )
else :
outputformat = self . helpers . get_output_format ( )
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( value , outputformat )
if isinstance ( value , int ) :
if int ( value ) < 0 :
outputformat = self . helpers . get_output_format ( )
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterValueException ( value , outputformat )
2024-01-03 08:01:33 -05:00
return value
2025-01-15 20:28:45 -06:00
def _add_device_arguments ( self , subcommand_parser : argparse . ArgumentParser , required = False ) :
2023-03-06 06:20:21 -06:00
# Device arguments help text
gpu_help = f " Select a GPU ID, BDF, or UUID from the possible choices: \n { self . gpu_choices_str } "
vf_help = " Gets general information about the specified VF (timeslice, fb info, …). \
\n Available only on virtualization OSs "
2023-12-07 07:33:17 -08:00
cpu_help = f " Select a CPU ID from the possible choices: \n { self . cpu_choices_str } "
core_help = f " Select a Core ID from the possible choices: \n { self . core_choices_str } "
2023-03-06 06:20:21 -06:00
# Mutually Exclusive Args within the subparser
device_args = subcommand_parser . add_mutually_exclusive_group ( required = required )
2024-02-21 03:48:09 -06:00
if self . helpers . is_amdgpu_initialized ( ) :
device_args . add_argument ( ' -g ' , ' --gpu ' , action = self . _gpu_select ( self . gpu_choices ) ,
nargs = ' + ' , help = gpu_help )
if self . helpers . is_amd_hsmp_initialized ( ) :
device_args . add_argument ( ' -U ' , ' --cpu ' , type = self . _validate_cpu_core ,
action = self . _cpu_select ( self . cpu_choices ) ,
nargs = ' + ' , help = cpu_help )
2024-02-22 23:40:00 -06:00
if subcommand_parser . _optionals . title != " Static Arguments " :
device_args . add_argument ( ' -O ' , ' --core ' , type = self . _validate_cpu_core ,
action = self . _core_select ( self . core_choices ) ,
nargs = ' + ' , help = core_help )
2023-03-06 06:20:21 -06:00
2023-04-15 02:00:37 -05:00
if self . helpers . is_hypervisor ( ) :
2023-03-06 06:20:21 -06:00
device_args . add_argument ( ' -v ' , ' --vf ' , action = ' store ' , nargs = ' + ' ,
help = vf_help , choices = self . vf_choices )
2024-02-21 03:48:09 -06:00
def _validate_set_clock ( self , validate_clock_type = True ) :
""" Validate Clock input """
amdsmi_helpers = self . helpers
class _ValidateClockType ( argparse . Action ) :
# Checks the clock type and clock values
def __call__ ( self , parser , args , values , option_string = None ) :
if validate_clock_type :
clock_type = values [ 0 ]
clock_types = amdsmi_helpers . get_clock_types ( ) [ 0 ]
valid_clock_type , amdsmi_clock_type = amdsmi_helpers . validate_clock_type ( input_clock_type = clock_type )
if not valid_clock_type :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { clock_type } ' needs to be a valid clock type: { clock_types } " )
clock_levels = values [ 1 : ]
else :
clock_levels = values
freq_bitmask = 0
for level in clock_levels :
if level > 63 :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { level } ' needs to be a valid clock level 0-63 " )
freq_bitmask | = ( 1 << level )
if validate_clock_type :
setattr ( args , self . dest , ( amdsmi_clock_type , freq_bitmask ) )
else :
setattr ( args , self . dest , freq_bitmask )
return _ValidateClockType
def _prompt_spec_warning ( self ) :
""" Prompt out of spec warning """
amdsmi_helpers = self . helpers
class _PromptSpecWarning ( argparse . Action ) :
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
amdsmi_helpers . confirm_out_of_spec_warning ( )
setattr ( args , self . dest , values )
return _PromptSpecWarning
def _validate_fan_speed ( self ) :
""" Validate fan speed input """
amdsmi_helpers = self . helpers
class _ValidateFanSpeed ( argparse . Action ) :
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
if isinstance ( values , str ) :
# Convert percentage to fan level
if ' % ' in values :
try :
amdsmi_helpers . confirm_out_of_spec_warning ( )
values = int ( int ( values [ : - 1 ] ) / 100 * 255 )
setattr ( args , self . dest , values )
except ValueError as e :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be 0-100% " )
else : # Store the fan level as fan_speed
values = int ( values )
if 0 < = values < = 255 :
amdsmi_helpers . confirm_out_of_spec_warning ( )
setattr ( args , self . dest , values )
else :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be 0-255 " )
else :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be 0-255 or 0-100% " )
return _ValidateFanSpeed
def _validate_overdrive_percent ( self ) :
""" Validate overdrive percentage input """
amdsmi_helpers = self . helpers
class _ValidateOverdrivePercent ( argparse . Action ) :
# Checks the values
def __call__ ( self , parser , args , values , option_string = None ) :
if isinstance ( values , str ) :
try :
if values [ - 1 ] == ' % ' :
over_drive_percent = int ( values [ : - 1 ] )
else :
over_drive_percent = int ( values )
if 0 < = over_drive_percent < = 20 :
amdsmi_helpers . confirm_out_of_spec_warning ( )
setattr ( args , self . dest , over_drive_percent )
else :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be within range 0-20 or 0-20% " )
except ValueError :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be 0-20 or 0-20% " )
else :
raise argparse . ArgumentError ( self , f " Invalid argument: ' { values } ' needs to be 0-20 or 0-20% " )
return _ValidateOverdrivePercent
2025-01-15 20:28:45 -06:00
def _add_version_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2023-03-06 06:20:21 -06:00
# Subparser help text
version_help = " Display version information "
# Create version subparser
version_parser = subparsers . add_parser ( ' version ' , help = version_help , description = None )
version_parser . _optionals . title = None
2023-10-13 14:03:24 -05:00
version_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
version_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
2023-03-06 06:20:21 -06:00
self . _add_command_modifiers ( version_parser )
2025-01-22 19:05:25 -05:00
# help info; CPU version code will be added back in once amd_hsmp code has been completed
gpu_version_help = " Display the current amdgpu driver version "
# cpu_version_help = "Display the current amd_hsmp driver version"
# Add GPU and CPU version Arguments
version_parser . add_argument ( ' -g ' , ' --gpu_version ' , action = ' store_true ' , required = False , help = gpu_version_help )
# version_parser.add_argument('-c', '--cpu_version', action='store_true', required=False, help=cpu_version_help)
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_list_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The list subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
2023-09-18 03:39:03 -05:00
list_help = " List GPU information "
2024-11-11 16:07:11 -06:00
list_subcommand_help = " Lists all detected devices on the system. \
\n Lists the BDF, UUID, KFD_ID, and NODE_ID for each GPU and/or CPUs. \
2023-04-24 21:34:44 -05:00
\n In virtualization environments, it can also list VFs associated to each \
2023-03-06 06:20:21 -06:00
\n GPU with some basic information for each VF. "
2023-09-18 03:39:03 -05:00
# Create list subparser
list_parser = subparsers . add_parser ( ' list ' , help = list_help , description = list_subcommand_help )
2023-10-13 14:03:24 -05:00
list_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-09-18 03:39:03 -05:00
list_parser . set_defaults ( func = func )
2023-03-06 06:20:21 -06:00
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
2023-09-18 03:39:03 -05:00
self . _add_command_modifiers ( list_parser )
self . _add_device_arguments ( list_parser , required = False )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_static_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2023-03-06 06:20:21 -06:00
# Subparser help text
static_help = " Gets static information about the specified GPU "
2023-04-21 08:02:53 -05:00
static_subcommand_help = " If no GPU is specified, returns static information for all GPUs on the system. \
\n If no static argument is provided, all static information will be displayed. "
2023-03-06 06:20:21 -06:00
static_optionals_title = " Static Arguments "
# Optional arguments help text
asic_help = " All asic information "
bus_help = " All bus information "
vbios_help = " All video bios information (if available) "
limit_help = " All limit metric values (i.e. power and thermal limits) "
driver_help = " Displays driver version "
2023-10-10 20:42:52 -05:00
vram_help = " All vram information "
cache_help = " All cache information "
board_help = " All board information "
2024-05-23 10:31:37 -05:00
soc_pstate_help = " The available soc pstate policy "
2024-03-20 12:06:24 -05:00
xgmi_plpd_help = " The available XGMI per-link power down policy "
2024-04-08 10:35:24 -05:00
process_isolation_help = " The process isolation status "
2024-12-04 00:10:32 -06:00
clk_options = self . helpers . get_clock_types ( ) [ 0 ]
clk_options . remove ( ' PCIE ' )
clk_option_str = " , " . join ( clk_options ) + " , ALL "
clock_help = f " Show one or more valid clock frequency levels. Available options: \n \t { clk_option_str } "
2023-03-06 06:20:21 -06:00
# Options arguments help text for Hypervisors and Baremetal
ras_help = " Displays RAS features information "
2023-04-21 15:10:38 -05:00
numa_help = " All numa node information " # Linux Baremetal only
2023-10-13 04:57:34 -05:00
partition_help = " Partition information "
2023-03-06 06:20:21 -06:00
# Options arguments help text for Hypervisors
dfc_help = " All DFC FW table information "
fb_help = " Displays Frame Buffer information "
num_vf_help = " Displays number of supported and enabled VFs "
2024-02-21 03:48:09 -06:00
# Options arguments help text for CPUs
2023-12-07 07:33:17 -08:00
smu_help = " All SMU FW information "
interface_help = " Displays hsmp interface version "
2023-03-06 06:20:21 -06:00
# Create static subparser
static_parser = subparsers . add_parser ( ' static ' , help = static_help , description = static_subcommand_help )
static_parser . _optionals . title = static_optionals_title
2023-10-13 14:03:24 -05:00
static_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
static_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( static_parser , required = False )
2024-02-21 03:48:09 -06:00
# Handle GPU Options
if self . helpers . is_amdgpu_initialized ( ) :
static_parser . add_argument ( ' -a ' , ' --asic ' , action = ' store_true ' , required = False , help = asic_help )
static_parser . add_argument ( ' -b ' , ' --bus ' , action = ' store_true ' , required = False , help = bus_help )
static_parser . add_argument ( ' -V ' , ' --vbios ' , action = ' store_true ' , required = False , help = vbios_help )
static_parser . add_argument ( ' -d ' , ' --driver ' , action = ' store_true ' , required = False , help = driver_help )
static_parser . add_argument ( ' -v ' , ' --vram ' , action = ' store_true ' , required = False , help = vram_help )
static_parser . add_argument ( ' -c ' , ' --cache ' , action = ' store_true ' , required = False , help = cache_help )
static_parser . add_argument ( ' -B ' , ' --board ' , action = ' store_true ' , required = False , help = board_help )
2024-05-28 11:26:25 -05:00
static_parser . add_argument ( ' -R ' , ' --process-isolation ' , action = ' store_true ' , required = False , help = process_isolation_help )
2024-11-04 15:36:48 -06:00
static_parser . add_argument ( ' -r ' , ' --ras ' , action = ' store_true ' , required = False , help = ras_help )
2024-12-20 12:27:29 -06:00
static_parser . add_argument ( ' -C ' , ' --clock ' , action = ' store ' , default = False , nargs = ' * ' , type = str , required = False , help = clock_help )
2024-02-21 03:48:09 -06:00
# Options to display on Hypervisors and Baremetal
if self . helpers . is_hypervisor ( ) or self . helpers . is_baremetal ( ) :
static_parser . add_argument ( ' -p ' , ' --partition ' , action = ' store_true ' , required = False , help = partition_help )
static_parser . add_argument ( ' -l ' , ' --limit ' , action = ' store_true ' , required = False , help = limit_help )
2024-05-23 10:31:37 -05:00
static_parser . add_argument ( ' -P ' , ' --soc-pstate ' , action = ' store_true ' , required = False , help = soc_pstate_help )
2024-03-20 12:06:24 -05:00
static_parser . add_argument ( ' -x ' , ' --xgmi-plpd ' , action = ' store_true ' , required = False , help = xgmi_plpd_help )
2024-02-21 03:48:09 -06:00
if self . helpers . is_linux ( ) and not self . helpers . is_virtual_os ( ) :
static_parser . add_argument ( ' -u ' , ' --numa ' , action = ' store_true ' , required = False , help = numa_help )
# Options to only display on a Hypervisor TODO: Add hypervisor driver check
if self . helpers . is_hypervisor ( ) :
static_parser . add_argument ( ' -d ' , ' --dfc-ucode ' , action = ' store_true ' , required = False , help = dfc_help )
static_parser . add_argument ( ' -f ' , ' --fb-info ' , action = ' store_true ' , required = False , help = fb_help )
static_parser . add_argument ( ' -n ' , ' --num-vf ' , action = ' store_true ' , required = False , help = num_vf_help )
# Handle CPU Options
if self . helpers . is_amd_hsmp_initialized ( ) :
cpu_group = static_parser . add_argument_group ( " CPU Arguments " )
cpu_group . add_argument ( ' -s ' , ' --smu ' , action = ' store_true ' , required = False , help = smu_help )
cpu_group . add_argument ( ' -i ' , ' --interface-ver ' , action = ' store_true ' , required = False , help = interface_help )
# Add command modifiers to the bottom
self . _add_command_modifiers ( static_parser )
2023-03-06 06:20:21 -06:00
def _add_firmware_parser ( self , subparsers , func ) :
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The firmware subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
firmware_help = " Gets firmware information about the specified GPU "
2023-04-21 08:02:53 -05:00
firmware_subcommand_help = " If no GPU is specified, return firmware information for all GPUs on the system. "
2023-03-06 06:20:21 -06:00
firmware_optionals_title = " Firmware Arguments "
# Optional arguments help text
fw_list_help = " All FW list information "
err_records_help = " All error records information "
# Create firmware subparser
2023-09-28 19:08:37 -05:00
firmware_parser = subparsers . add_parser ( ' firmware ' , help = firmware_help , description = firmware_subcommand_help , aliases = [ ' ucode ' ] )
2023-03-06 06:20:21 -06:00
firmware_parser . _optionals . title = firmware_optionals_title
2023-10-13 14:03:24 -05:00
firmware_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
firmware_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( firmware_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( firmware_parser , required = False )
# Optional Args
firmware_parser . add_argument ( ' -f ' , ' --ucode-list ' , ' --fw-list ' , dest = ' fw_list ' , action = ' store_true ' , required = False , help = fw_list_help , default = True )
# Options to only display on a Hypervisor
2023-04-15 02:00:37 -05:00
if self . helpers . is_hypervisor ( ) :
2023-03-06 06:20:21 -06:00
firmware_parser . add_argument ( ' -e ' , ' --error-records ' , action = ' store_true ' , required = False , help = err_records_help )
def _add_bad_pages_parser ( self , subparsers , func ) :
2023-04-15 02:00:37 -05:00
if not ( self . helpers . is_baremetal ( ) and self . helpers . is_linux ( ) ) :
2023-03-06 06:20:21 -06:00
# The bad_pages subcommand is only applicable to Linux Baremetal systems
return
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The bad_pages subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
bad_pages_help = " Gets bad page information about the specified GPU "
2023-04-21 08:02:53 -05:00
bad_pages_subcommand_help = " If no GPU is specified, return bad page information for all GPUs on the system. "
bad_pages_optionals_title = " Bad Pages Arguments "
2023-03-06 06:20:21 -06:00
# Optional arguments help text
pending_help = " Displays all pending retired pages "
retired_help = " Displays retired pages "
un_res_help = " Displays unreservable pages "
# Create bad_pages subparser
2023-04-15 02:00:37 -05:00
bad_pages_parser = subparsers . add_parser ( ' bad-pages ' , help = bad_pages_help , description = bad_pages_subcommand_help )
2023-03-06 06:20:21 -06:00
bad_pages_parser . _optionals . title = bad_pages_optionals_title
2023-10-13 14:03:24 -05:00
bad_pages_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
bad_pages_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( bad_pages_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( bad_pages_parser , required = False )
# Optional Args
bad_pages_parser . add_argument ( ' -p ' , ' --pending ' , action = ' store_true ' , required = False , help = pending_help )
bad_pages_parser . add_argument ( ' -r ' , ' --retired ' , action = ' store_true ' , required = False , help = retired_help )
bad_pages_parser . add_argument ( ' -u ' , ' --un-res ' , action = ' store_true ' , required = False , help = un_res_help )
def _add_metric_parser ( self , subparsers , func ) :
# Subparser help text
metric_help = " Gets metric/performance information about the specified GPU "
2023-04-21 08:02:53 -05:00
metric_subcommand_help = " If no GPU is specified, returns metric information for all GPUs on the system. \
2024-11-11 16:07:11 -06:00
\n If no metric argument is provided, all metric information will be displayed. "
2023-03-06 06:20:21 -06:00
metric_optionals_title = " Metric arguments "
# Optional arguments help text
usage_help = " Displays engine usage information "
2023-10-27 09:39:31 -05:00
# Help text for Arguments only Available on Linux Virtual OS and Baremetal platforms
2023-09-22 06:19:38 -05:00
mem_usage_help = " Memory usage per block "
2023-03-06 06:20:21 -06:00
# Help text for Arguments only on Hypervisor and Baremetal platforms
power_help = " Current power usage "
clock_help = " Average, max, and current clock frequencies "
temperature_help = " Current temperatures "
2023-10-10 13:22:36 -05:00
ecc_help = " Total number of ECC errors "
2024-02-22 02:39:31 -06:00
ecc_blocks_help = " Number of ECC errors per block "
2023-09-22 06:34:47 -05:00
pcie_help = " Current PCIe speed, width, and replay count "
2023-03-06 06:20:21 -06:00
# Help text for Arguments only on Linux Baremetal platforms
fan_help = " Current fan speed "
2024-05-02 15:27:16 -05:00
vc_help = " Display voltage curve "
2024-08-29 10:21:06 -05:00
overdrive_help = " Current GPU clock overdrive and GPU memory clock overdrive level "
2023-03-06 06:20:21 -06:00
perf_level_help = " Current DPM performance level "
xgmi_err_help = " XGMI error information since last read "
energy_help = " Amount of energy consumed "
2024-05-21 20:30:16 -05:00
throttle_help = " Displays throttle accumulators; Only available for MI300 or newer ASICs "
2023-03-06 06:20:21 -06:00
# Help text for Arguments only on Hypervisors
schedule_help = " All scheduling information "
guard_help = " All guard information "
2023-10-27 09:39:31 -05:00
guest_data_help = " All guest data information "
fb_usage_help = " Displays total and used Frame Buffer usage information "
xgmi_help = " Table of current XGMI metrics information "
2023-03-06 06:20:21 -06:00
2023-12-07 07:33:17 -08:00
# Help text for cpu options
2024-02-21 03:48:09 -06:00
cpu_power_metrics_help = " CPU power metrics "
2023-12-07 07:33:17 -08:00
cpu_proc_help = " Displays prochot status "
cpu_freq_help = " Displays currentFclkMemclk frequencies and cclk frequency limit "
cpu_c0_res_help = " Displays C0 residency "
2024-02-21 03:48:09 -06:00
cpu_lclk_dpm_help = " Displays lclk dpm level range. Requires socket ID and NBOID as inputs "
2023-12-07 07:33:17 -08:00
cpu_pwr_svi_telemtry_rails_help = " Displays svi based telemetry for all rails "
cpu_io_bandwidth_help = " Displays current IO bandwidth for the selected CPU. \
\n input parameters are bandwidth type(1) and link ID encodings \
\n i.e. P2, P3, G0 - G7 "
cpu_xgmi_bandwidth_help = " Displays current XGMI bandwidth for the selected CPU \
\n input parameters are bandwidth type(1,2,4) and link ID encodings \
\n i.e. P2, P3, G0 - G7 "
cpu_metrics_ver_help = " Displays metrics table version "
cpu_metrics_table_help = " Displays metric table "
2024-02-21 03:48:09 -06:00
cpu_socket_energy_help = " Displays socket energy for the selected CPU socket "
cpu_ddr_bandwidth_help = " Displays per socket max ddr bw, current utilized bw, \
\n and current utilized ddr bw in percentage "
2023-12-07 07:33:17 -08:00
cpu_temp_help = " Displays cpu socket temperature "
cpu_dimm_temp_range_rate_help = " Displays dimm temperature range and refresh rate "
2024-02-21 03:48:09 -06:00
cpu_dimm_pow_consumption_help = " Displays dimm power consumption "
2023-12-07 07:33:17 -08:00
cpu_dimm_thermal_sensor_help = " Displays dimm thermal sensor "
2024-02-21 03:48:09 -06:00
# Help text for core options
core_energy_help = " Displays core energy for the selected core "
core_boost_limit_help = " Get boost limit for the selected cores "
core_curr_active_freq_core_limit_help = " Get Current CCLK limit set per Core "
2023-12-07 07:33:17 -08:00
2023-03-06 06:20:21 -06:00
# Create metric subparser
metric_parser = subparsers . add_parser ( ' metric ' , help = metric_help , description = metric_subcommand_help )
metric_parser . _optionals . title = metric_optionals_title
2023-10-13 14:03:24 -05:00
metric_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
metric_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( metric_parser , required = False )
2023-04-15 02:00:37 -05:00
# Add Watch args
self . _add_watch_arguments ( metric_parser )
2023-10-27 09:39:31 -05:00
# Optional Args for Linux Virtual OS and Baremetal systems
if not self . helpers . is_hypervisor ( ) and not self . helpers . is_windows ( ) :
2023-04-19 17:40:03 +02:00
metric_parser . add_argument ( ' -m ' , ' --mem-usage ' , action = ' store_true ' , required = False , help = mem_usage_help )
2023-03-06 06:20:21 -06:00
2024-02-21 03:48:09 -06:00
if self . helpers . is_amdgpu_initialized ( ) :
# Optional Args for Hypervisors and Baremetal systems
if self . helpers . is_hypervisor ( ) or self . helpers . is_baremetal ( ) or self . helpers . is_linux ( ) :
metric_parser . add_argument ( ' -u ' , ' --usage ' , action = ' store_true ' , required = False , help = usage_help )
metric_parser . add_argument ( ' -p ' , ' --power ' , action = ' store_true ' , required = False , help = power_help )
metric_parser . add_argument ( ' -c ' , ' --clock ' , action = ' store_true ' , required = False , help = clock_help )
metric_parser . add_argument ( ' -t ' , ' --temperature ' , action = ' store_true ' , required = False , help = temperature_help )
metric_parser . add_argument ( ' -P ' , ' --pcie ' , action = ' store_true ' , required = False , help = pcie_help )
2024-11-04 15:36:48 -06:00
metric_parser . add_argument ( ' -e ' , ' --ecc ' , action = ' store_true ' , required = False , help = ecc_help )
metric_parser . add_argument ( ' -k ' , ' --ecc-blocks ' , action = ' store_true ' , required = False , help = ecc_blocks_help )
2024-08-08 00:34:05 -05:00
# Options that only apply to Hypervisors and Baremetal Linux
if self . helpers . is_hypervisor ( ) or ( self . helpers . is_baremetal ( ) and self . helpers . is_linux ( ) ) :
2024-11-04 15:36:48 -06:00
pass
2024-02-21 03:48:09 -06:00
# Optional Args for Linux Baremetal Systems
if self . helpers . is_baremetal ( ) and self . helpers . is_linux ( ) :
metric_parser . add_argument ( ' -f ' , ' --fan ' , action = ' store_true ' , required = False , help = fan_help )
2024-05-02 15:27:16 -05:00
metric_parser . add_argument ( ' -C ' , ' --voltage-curve ' , action = ' store_true ' , required = False , help = vc_help )
2024-02-21 03:48:09 -06:00
metric_parser . add_argument ( ' -o ' , ' --overdrive ' , action = ' store_true ' , required = False , help = overdrive_help )
metric_parser . add_argument ( ' -l ' , ' --perf-level ' , action = ' store_true ' , required = False , help = perf_level_help )
metric_parser . add_argument ( ' -x ' , ' --xgmi-err ' , action = ' store_true ' , required = False , help = xgmi_err_help )
metric_parser . add_argument ( ' -E ' , ' --energy ' , action = ' store_true ' , required = False , help = energy_help )
2024-05-21 20:30:16 -05:00
metric_parser . add_argument ( ' -T ' , ' --throttle ' , action = ' store_true ' , required = False , help = throttle_help )
2024-02-21 03:48:09 -06:00
# Options to only display to Hypervisors
if self . helpers . is_hypervisor ( ) :
metric_parser . add_argument ( ' -s ' , ' --schedule ' , action = ' store_true ' , required = False , help = schedule_help )
metric_parser . add_argument ( ' -G ' , ' --guard ' , action = ' store_true ' , required = False , help = guard_help )
metric_parser . add_argument ( ' -u ' , ' --guest-data ' , action = ' store_true ' , required = False , help = guest_data_help )
metric_parser . add_argument ( ' -f ' , ' --fb-usage ' , action = ' store_true ' , required = False , help = fb_usage_help )
metric_parser . add_argument ( ' -m ' , ' --xgmi ' , action = ' store_true ' , required = False , help = xgmi_help )
if self . helpers . is_amd_hsmp_initialized ( ) :
# Optional Args for CPUs
cpu_group = metric_parser . add_argument_group ( " CPU Arguments " )
cpu_group . add_argument ( ' --cpu-power-metrics ' , action = ' store_true ' , required = False , help = cpu_power_metrics_help )
cpu_group . add_argument ( ' --cpu-prochot ' , action = ' store_true ' , required = False , help = cpu_proc_help )
cpu_group . add_argument ( ' --cpu-freq-metrics ' , action = ' store_true ' , required = False , help = cpu_freq_help )
cpu_group . add_argument ( ' --cpu-c0-res ' , action = ' store_true ' , required = False , help = cpu_c0_res_help )
2024-09-16 16:07:44 -05:00
cpu_group . add_argument ( ' --cpu-lclk-dpm-level ' , action = ' append ' , required = False , type = self . _not_negative_int ,
2024-02-21 03:48:09 -06:00
nargs = 1 , metavar = ( " NBIOID " ) , help = cpu_lclk_dpm_help )
cpu_group . add_argument ( ' --cpu-pwr-svi-telemtry-rails ' , action = ' store_true ' , required = False ,
help = cpu_pwr_svi_telemtry_rails_help )
cpu_group . add_argument ( ' --cpu-io-bandwidth ' , action = ' append ' , required = False , nargs = 2 ,
metavar = ( " IO_BW " , " LINKID_NAME " ) , help = cpu_io_bandwidth_help )
cpu_group . add_argument ( ' --cpu-xgmi-bandwidth ' , action = ' append ' , required = False , nargs = 2 ,
metavar = ( " XGMI_BW " , " LINKID_NAME " ) , help = cpu_xgmi_bandwidth_help )
cpu_group . add_argument ( ' --cpu-metrics-ver ' , action = ' store_true ' , required = False , help = cpu_metrics_ver_help )
cpu_group . add_argument ( ' --cpu-metrics-table ' , action = ' store_true ' , required = False , help = cpu_metrics_table_help )
cpu_group . add_argument ( ' --cpu-socket-energy ' , action = ' store_true ' , required = False , help = cpu_socket_energy_help )
cpu_group . add_argument ( ' --cpu-ddr-bandwidth ' , action = ' store_true ' , required = False , help = cpu_ddr_bandwidth_help )
cpu_group . add_argument ( ' --cpu-temp ' , action = ' store_true ' , required = False , help = cpu_temp_help )
cpu_group . add_argument ( ' --cpu-dimm-temp-range-rate ' , action = ' append ' , required = False , type = lambda x : int ( x , 0 ) ,
nargs = 1 , metavar = ( " DIMM_ADDR " ) , help = cpu_dimm_temp_range_rate_help )
cpu_group . add_argument ( ' --cpu-dimm-pow-consumption ' , action = ' append ' , required = False , type = lambda x : int ( x , 0 ) ,
nargs = 1 , metavar = ( " DIMM_ADDR " ) , help = cpu_dimm_pow_consumption_help )
cpu_group . add_argument ( ' --cpu-dimm-thermal-sensor ' , action = ' append ' , required = False , type = lambda x : int ( x , 0 ) ,
nargs = 1 , metavar = ( " DIMM_ADDR " ) , help = cpu_dimm_thermal_sensor_help )
# Optional Args for CPU cores
core_group = metric_parser . add_argument_group ( " CPU Core Arguments " )
core_group . add_argument ( ' --core-boost-limit ' , action = ' store_true ' , required = False , help = core_boost_limit_help )
core_group . add_argument ( ' --core-curr-active-freq-core-limit ' , action = ' store_true ' , required = False ,
help = core_curr_active_freq_core_limit_help )
core_group . add_argument ( ' --core-energy ' , action = ' store_true ' , required = False , help = core_energy_help )
# Add command modifiers to the bottom
self . _add_command_modifiers ( metric_parser )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_process_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2023-04-15 02:00:37 -05:00
if self . helpers . is_hypervisor ( ) :
2023-03-06 06:20:21 -06:00
# Don't add this subparser on Hypervisors
# This subparser is only available to Guest and Baremetal systems
return
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The process subcommand is currently only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
process_help = " Lists general process information running on the specified GPU "
2023-04-21 08:02:53 -05:00
process_subcommand_help = " If no GPU is specified, returns information for all GPUs on the system. \
2024-11-11 16:07:11 -06:00
\n If no process argument is provided, all process information will be displayed. "
2023-03-06 06:20:21 -06:00
process_optionals_title = " Process arguments "
# Optional Arguments help text
general_help = " pid, process name, memory usage "
engine_help = " All engine usages "
pid_help = " Gets all process information about the specified process based on Process ID "
name_help = " Gets all process information about the specified process based on Process Name. \
2024-11-11 16:07:11 -06:00
\n If multiple processes have the same name, information is returned for all of them. "
2023-04-15 02:00:37 -05:00
2023-03-06 06:20:21 -06:00
# Create process subparser
process_parser = subparsers . add_parser ( ' process ' , help = process_help , description = process_subcommand_help )
process_parser . _optionals . title = process_optionals_title
2023-10-13 14:03:24 -05:00
process_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
process_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( process_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( process_parser , required = False )
2023-04-15 02:00:37 -05:00
# Add Watch args
self . _add_watch_arguments ( process_parser )
2023-03-06 06:20:21 -06:00
# Optional Args
process_parser . add_argument ( ' -G ' , ' --general ' , action = ' store_true ' , required = False , help = general_help )
process_parser . add_argument ( ' -e ' , ' --engine ' , action = ' store_true ' , required = False , help = engine_help )
2025-01-07 17:13:00 -06:00
process_parser . add_argument ( ' -p ' , ' --pid ' , action = ' store ' , type = lambda value : self . _not_negative_int ( value , ' --pid ' ) , required = False , help = pid_help )
process_parser . add_argument ( ' -n ' , ' --name ' , action = ' store ' , type = lambda value : self . _is_valid_string ( value , ' --name ' ) , required = False , help = name_help )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_profile_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2023-04-15 02:00:37 -05:00
if not ( self . helpers . is_windows ( ) and self . helpers . is_hypervisor ( ) ) :
2023-03-06 06:20:21 -06:00
# This subparser only applies to Hypervisors
return
# Subparser help text
profile_help = " Displays information about all profiles and current profile "
2023-04-21 08:02:53 -05:00
profile_subcommand_help = " If no GPU is specified, returns information for all GPUs on the system. "
2023-03-06 06:20:21 -06:00
profile_optionals_title = " Profile Arguments "
# Create profile subparser
profile_parser = subparsers . add_parser ( ' profile ' , help = profile_help , description = profile_subcommand_help )
profile_parser . _optionals . title = profile_optionals_title
2023-10-13 14:03:24 -05:00
profile_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
profile_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( profile_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( profile_parser , required = False )
2025-01-15 20:28:45 -06:00
def _add_event_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The event subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
event_help = " Displays event information for the given GPU "
2023-04-21 08:02:53 -05:00
event_subcommand_help = " If no GPU is specified, returns event information for all GPUs on the system. "
2023-03-06 06:20:21 -06:00
event_optionals_title = " Event Arguments "
# Create event subparser
event_parser = subparsers . add_parser ( ' event ' , help = event_help , description = event_subcommand_help )
event_parser . _optionals . title = event_optionals_title
2023-10-13 14:03:24 -05:00
event_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
event_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( event_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( event_parser , required = False )
2025-01-15 20:28:45 -06:00
def _add_topology_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2023-04-15 02:00:37 -05:00
if not ( self . helpers . is_baremetal ( ) and self . helpers . is_linux ( ) ) :
2023-03-06 06:20:21 -06:00
# This subparser is only applicable to Baremetal Linux
return
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The topology subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
2023-09-24 19:08:37 -05:00
topology_help = " Displays topology information of the devices "
2023-04-21 08:02:53 -05:00
topology_subcommand_help = " If no GPU is specified, returns information for all GPUs on the system. \
2024-11-11 16:07:11 -06:00
\n If no topology argument is provided, all topology information will be displayed. "
2023-03-06 06:20:21 -06:00
topology_optionals_title = " Topology arguments "
# Help text for Arguments only on Guest and BM platforms
2023-03-28 15:32:17 -05:00
access_help = " Displays link accessibility between GPUs "
weight_help = " Displays relative weight between GPUs "
hops_help = " Displays the number of hops between GPUs "
2023-04-21 15:10:38 -05:00
link_type_help = " Displays the link type between GPUs "
2023-03-28 15:32:17 -05:00
numa_bw_help = " Display max and min bandwidth between nodes "
2024-08-21 11:26:36 +08:00
coherent_help = " Display cache coherant (or non-coherant) link capability between nodes "
atomics_help = " Display 32 and 64-bit atomic io link capability between nodes "
dma_help = " Display P2P direct memory access (DMA) link capability between nodes "
bi_dir_help = " Display P2P bi-directional link capability between nodes "
2023-03-06 06:20:21 -06:00
# Create topology subparser
topology_parser = subparsers . add_parser ( ' topology ' , help = topology_help , description = topology_subcommand_help )
topology_parser . _optionals . title = topology_optionals_title
2023-10-13 14:03:24 -05:00
topology_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
topology_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( topology_parser )
2023-03-06 06:20:21 -06:00
self . _add_device_arguments ( topology_parser , required = False )
# Optional Args
2023-03-28 15:32:17 -05:00
topology_parser . add_argument ( ' -a ' , ' --access ' , action = ' store_true ' , required = False , help = access_help )
topology_parser . add_argument ( ' -w ' , ' --weight ' , action = ' store_true ' , required = False , help = weight_help )
topology_parser . add_argument ( ' -o ' , ' --hops ' , action = ' store_true ' , required = False , help = hops_help )
2023-04-21 15:10:38 -05:00
topology_parser . add_argument ( ' -t ' , ' --link-type ' , action = ' store_true ' , required = False , help = link_type_help )
2023-04-15 02:00:37 -05:00
topology_parser . add_argument ( ' -b ' , ' --numa-bw ' , action = ' store_true ' , required = False , help = numa_bw_help )
2024-08-21 11:26:36 +08:00
topology_parser . add_argument ( ' -c ' , ' --coherent ' , action = ' store_true ' , required = False , help = coherent_help )
topology_parser . add_argument ( ' -n ' , ' --atomics ' , action = ' store_true ' , required = False , help = atomics_help )
topology_parser . add_argument ( ' -d ' , ' --dma ' , action = ' store_true ' , required = False , help = dma_help )
topology_parser . add_argument ( ' -z ' , ' --bi-dir ' , action = ' store_true ' , required = False , help = bi_dir_help )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_set_value_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-05-23 11:07:58 -05:00
if not self . helpers . is_linux ( ) :
# This subparser is only applicable to Linux
2023-03-06 06:20:21 -06:00
return
# Subparser help text
2023-09-24 19:08:37 -05:00
set_value_help = " Set options for devices "
2024-11-08 17:31:25 -06:00
set_value_subcommand_help = " If no GPU is specified, will select all GPUs on the system. \
2023-04-21 08:02:53 -05:00
\n A set argument must be provided; Multiple set arguments are accepted "
2023-03-06 06:20:21 -06:00
set_value_optionals_title = " Set Arguments "
2023-10-13 04:57:34 -05:00
# Help text for Arguments only on BM platforms
2023-10-16 11:11:03 -05:00
set_fan_help = " Set GPU fan speed (0-255 or 0-100 %% ) "
2024-12-20 16:32:10 -05:00
perf_level_help_choices_str = " , " . join ( self . helpers . get_perf_levels ( ) [ 0 ] [ 0 : - 1 ] )
set_perf_level_help = f " Set one of the following performance levels: \n \t { perf_level_help_choices_str } "
power_profile_choices_str = " , " . join ( self . helpers . get_power_profiles ( ) [ 0 : - 1 ] )
set_profile_help = f " Set power profile level (#) or choose one of available profiles: \n \t { power_profile_choices_str } "
perf_det_choices_str = " , " . join ( self . helpers . get_perf_det_levels ( ) )
set_perf_det_help = f " Set performance determinism and select one of the corresponding performance levels: \n \t { perf_det_choices_str } "
2025-01-15 20:28:45 -06:00
( accelerator_set_choices , _ ) = self . helpers . get_accelerator_choices_types_indices ( )
2023-10-16 11:11:03 -05:00
memory_partition_choices_str = " , " . join ( self . helpers . get_memory_partition_types ( ) )
2025-01-15 20:28:45 -06:00
set_compute_partition_help = f " Set one of the following the accelerator type or profile index: \n \t { accelerator_set_choices } . \n \t Use `sudo amd-smi partition --accelerator` to find acceptable values. "
2023-10-16 11:11:03 -05:00
set_memory_partition_help = f " Set one of the following the memory partition modes: \n \t { memory_partition_choices_str } "
2024-12-20 16:32:10 -05:00
power_cap_min , power_cap_max = self . helpers . get_power_caps ( )
power_cap_max = self . helpers . convert_SI_unit ( power_cap_max , AMDSMIHelpers . SI_Unit . MICRO )
power_cap_min = self . helpers . convert_SI_unit ( power_cap_min , AMDSMIHelpers . SI_Unit . MICRO )
set_power_cap_help = f " Set power capacity limit: \n \t min cap: { power_cap_min } W, max cap: { power_cap_max } W "
soc_pstate_help_info = " , " . join ( self . helpers . get_soc_pstates ( ) )
set_soc_pstate_help = f " Set the GPU soc pstate policy using policy id, an integer. Valid id ' s include: \n \t { soc_pstate_help_info } "
xgmi_plpd_help_info = " , " . join ( self . helpers . get_xgmi_plpd_policies ( ) )
set_xgmi_plpd_help = f " Set the GPU XGMI per-link power down policy using policy id, an integer. Valid id ' s include: \n \t { xgmi_plpd_help_info } "
set_clk_limit_help = " Sets the sclk (aka gfxclk) or mclk minimum and maximum frequencies. \n \t ex: amd-smi set -L (sclk | mclk) (min | max) value "
set_clock_freq_help = " Set a number of sclk (aka gfxclk), mclk, fclk, pcie, or socclk frequency performance levels. \n \t Use `amd-smi static --clock` to find acceptable levels. "
set_process_isolation_help = " Enable or disable the GPU process isolation on a per partition basis: 0 for disable and 1 for enable. \n "
2023-03-06 06:20:21 -06:00
2024-02-21 03:48:09 -06:00
# Help text for CPU set options
set_cpu_pwr_limit_help = " Set power limit for the given socket. Input parameter is power limit value. "
set_cpu_xgmi_link_width_help = " Set max and Min linkwidth. Input parameters are min and max link width values "
set_cpu_lclk_dpm_level_help = " Sets the max and min dpm level on a given NBIO. \
\n Input parameters are die_index, min dpm, max dpm. "
set_cpu_pwr_eff_mode_help = " Sets the power efficency mode policy. Input parameter is mode. "
set_cpu_gmi3_link_width_help = " Sets max and min gmi3 link width range "
set_cpu_pcie_link_rate_help = " Sets pcie link rate "
set_cpu_df_pstate_range_help = " Sets max and min df-pstates "
set_cpu_enable_apb_help = " Enables the DF p-state performance boost algorithm "
set_cpu_disable_apb_help = " Disables the DF p-state performance boost algorithm. Input parameter is DFPstate (0-3) "
set_soc_boost_limit_help = " Sets the boost limit for the given socket. Input parameter is socket BOOST_LIMIT value "
# Help text for CPU Core set options
set_core_boost_limit_help = " Sets the boost limit for the given core. Input parameter is core BOOST_LIMIT value "
2023-03-06 06:20:21 -06:00
# Create set_value subparser
set_value_parser = subparsers . add_parser ( ' set ' , help = set_value_help , description = set_value_subcommand_help )
set_value_parser . _optionals . title = set_value_optionals_title
2023-10-13 14:03:24 -05:00
set_value_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
set_value_parser . set_defaults ( func = func )
2024-11-08 17:31:25 -06:00
# Providing no -g 0 or -g all, is not required
self . _add_device_arguments ( set_value_parser , required = False )
2023-03-06 06:20:21 -06:00
2024-02-21 03:48:09 -06:00
if self . helpers . is_amdgpu_initialized ( ) :
2025-01-07 17:48:01 -05:00
# set value should only take one of these at a time so args below will be mutually exclusive
set_value_exclusive_group = set_value_parser . add_mutually_exclusive_group ( )
2024-05-23 11:07:58 -05:00
if self . helpers . is_baremetal ( ) :
# Optional GPU Args
2025-01-07 17:48:01 -05:00
set_value_exclusive_group . add_argument ( ' -f ' , ' --fan ' , action = self . _validate_fan_speed ( ) , required = False , help = set_fan_help , metavar = ' % ' )
set_value_exclusive_group . add_argument ( ' -l ' , ' --perf-level ' , action = ' store ' , choices = self . helpers . get_perf_levels ( ) [ 0 ] , type = str . upper , required = False , help = set_perf_level_help , metavar = ' LEVEL ' )
set_value_exclusive_group . add_argument ( ' -P ' , ' --profile ' , action = ' store ' , required = False , help = set_profile_help , metavar = ' SETPROFILE ' )
2025-01-07 17:13:00 -06:00
set_value_exclusive_group . add_argument ( ' -d ' , ' --perf-determinism ' , action = ' store ' , type = lambda value : self . _not_negative_int ( value , ' --perf-determinism ' ) , required = False , help = set_perf_det_help , metavar = ' SCLKMAX ' )
2025-01-15 20:28:45 -06:00
set_value_exclusive_group . add_argument ( ' -C ' , ' --compute-partition ' , action = ' store ' , choices = accelerator_set_choices , type = lambda value : self . _is_command_supported ( value , accelerator_set_choices , ' --compute-partition ' ) , required = False , help = set_compute_partition_help , metavar = ' <ACCELERATOR_TYPE> or <PROFILE_INDEX> ' )
2025-01-07 17:48:01 -05:00
set_value_exclusive_group . add_argument ( ' -M ' , ' --memory-partition ' , action = ' store ' , choices = self . helpers . get_memory_partition_types ( ) , type = str . upper , required = False , help = set_memory_partition_help , metavar = ' PARTITION ' )
2025-01-07 17:13:00 -06:00
set_value_exclusive_group . add_argument ( ' -o ' , ' --power-cap ' , action = ' store ' , type = lambda value : self . _positive_int ( value , ' --power-cap ' ) , required = False , help = set_power_cap_help , metavar = ' WATTS ' )
set_value_exclusive_group . add_argument ( ' -p ' , ' --soc-pstate ' , action = ' store ' , required = False , type = lambda value : self . _not_negative_int ( value , ' --soc-pstate ' ) , help = set_soc_pstate_help , metavar = ' POLICY_ID ' )
set_value_exclusive_group . add_argument ( ' -x ' , ' --xgmi-plpd ' , action = ' store ' , required = False , type = lambda value : self . _not_negative_int ( value , ' --xgmi-plpd ' ) , help = set_xgmi_plpd_help , metavar = ' POLICY_ID ' )
2025-01-07 17:48:01 -05:00
set_value_exclusive_group . add_argument ( ' -c ' , ' --clk-level ' , action = self . _level_select ( ) , nargs = ' + ' , required = False , help = set_clock_freq_help , metavar = ( ' CLK_TYPE ' , ' PERF_LEVELS ' ) )
set_value_exclusive_group . add_argument ( ' -L ' , ' --clk-limit ' , action = self . _limit_select ( ) , nargs = 3 , required = False , help = set_clk_limit_help , metavar = ( ' CLK_TYPE ' , ' LIM_TYPE ' , ' VALUE ' ) )
2025-01-07 17:13:00 -06:00
set_value_exclusive_group . add_argument ( ' -R ' , ' --process-isolation ' , action = ' store ' , choices = [ 0 , 1 ] , type = lambda value : self . _not_negative_int ( value , ' --process-isolation ' ) , required = False , help = set_process_isolation_help , metavar = ' STATUS ' )
2024-02-21 03:48:09 -06:00
2025-01-08 17:24:05 -05:00
2024-02-21 03:48:09 -06:00
if self . helpers . is_amd_hsmp_initialized ( ) :
2024-05-23 11:07:58 -05:00
if self . helpers . is_baremetal ( ) :
# Optional CPU Args
cpu_group = set_value_parser . add_argument_group ( " CPU Arguments " )
2024-09-16 16:07:44 -05:00
cpu_group . add_argument ( ' --cpu-pwr-limit ' , action = ' append ' , required = False , type = self . _positive_int , nargs = 1 , metavar = ( " PWR_LIMIT " ) , help = set_cpu_pwr_limit_help )
cpu_group . add_argument ( ' --cpu-xgmi-link-width ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 2 , metavar = ( " MIN_WIDTH " , " MAX_WIDTH " ) , help = set_cpu_xgmi_link_width_help )
cpu_group . add_argument ( ' --cpu-lclk-dpm-level ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 3 , metavar = ( " NBIOID " , " MIN_DPM " , " MAX_DPM " ) , help = set_cpu_lclk_dpm_level_help )
cpu_group . add_argument ( ' --cpu-pwr-eff-mode ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 1 , metavar = ( " MODE " ) , help = set_cpu_pwr_eff_mode_help )
cpu_group . add_argument ( ' --cpu-gmi3-link-width ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 2 , metavar = ( " MIN_LW " , " MAX_LW " ) , help = set_cpu_gmi3_link_width_help )
cpu_group . add_argument ( ' --cpu-pcie-link-rate ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 1 , metavar = ( " LINK_RATE " ) , help = set_cpu_pcie_link_rate_help )
cpu_group . add_argument ( ' --cpu-df-pstate-range ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 2 , metavar = ( " MAX_PSTATE " , " MIN_PSTATE " ) , help = set_cpu_df_pstate_range_help )
2024-05-23 11:07:58 -05:00
cpu_group . add_argument ( ' --cpu-enable-apb ' , action = ' store_true ' , required = False , help = set_cpu_enable_apb_help )
2024-09-16 16:07:44 -05:00
cpu_group . add_argument ( ' --cpu-disable-apb ' , action = ' append ' , required = False , type = self . _not_negative_int , nargs = 1 , metavar = ( " DF_PSTATE " ) , help = set_cpu_disable_apb_help )
cpu_group . add_argument ( ' --soc-boost-limit ' , action = ' append ' , required = False , type = self . _positive_int , nargs = 1 , metavar = ( " BOOST_LIMIT " ) , help = set_soc_boost_limit_help )
2024-05-23 11:07:58 -05:00
# Optional CPU Core Args
core_group = set_value_parser . add_argument_group ( " CPU Core Arguments " )
2024-09-16 16:07:44 -05:00
core_group . add_argument ( ' --core-boost-limit ' , action = ' append ' , required = False , type = self . _positive_int , nargs = 1 , metavar = ( " BOOST_LIMIT " ) , help = set_core_boost_limit_help )
2024-02-21 03:48:09 -06:00
# Add command modifiers to the bottom
self . _add_command_modifiers ( set_value_parser )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_reset_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-05-28 11:26:25 -05:00
if not self . helpers . is_linux ( ) :
# This subparser is only applicable to Linux
2023-03-06 06:20:21 -06:00
return
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The reset subcommand is only applicable to systems with amdgpu initialized
return
2023-03-06 06:20:21 -06:00
# Subparser help text
2023-09-24 19:08:37 -05:00
reset_help = " Reset options for devices "
2024-11-08 17:31:25 -06:00
reset_subcommand_help = " If no GPU is specified, will select all GPUs on the system. \
2023-04-21 08:02:53 -05:00
\n A reset argument must be provided; Multiple reset arguments are accepted "
2023-03-06 06:20:21 -06:00
reset_optionals_title = " Reset Arguments "
# Help text for Arguments only on Guest and BM platforms
gpureset_help = " Reset the specified GPU "
2023-10-13 04:57:34 -05:00
reset_clocks_help = " Reset clocks and overdrive to default "
reset_fans_help = " Reset fans to automatic (driver) control "
reset_profile_help = " Reset power profile back to default "
reset_xgmierr_help = " Reset XGMI error counts "
2023-10-16 11:11:03 -05:00
reset_perf_det_help = " Disable performance determinism "
2023-10-17 00:08:43 -05:00
reset_power_cap_help = " Reset power capacity limit to max capable "
2024-10-09 15:02:47 -05:00
reset_gpu_clean_local_data_help = " Clean up local data in LDS/GPRs on a per partition basis "
2023-03-06 06:20:21 -06:00
# Create reset subparser
reset_parser = subparsers . add_parser ( ' reset ' , help = reset_help , description = reset_subcommand_help )
reset_parser . _optionals . title = reset_optionals_title
2023-10-13 14:03:24 -05:00
reset_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
reset_parser . set_defaults ( func = func )
2023-10-16 06:24:42 -05:00
# Add Universal Arguments
self . _add_command_modifiers ( reset_parser )
2024-11-08 17:31:25 -06:00
# Providing no -g 0 or -g all, is not required
self . _add_device_arguments ( reset_parser , required = False )
2023-03-06 06:20:21 -06:00
2025-01-08 17:24:05 -05:00
# make reset args mutually exclusive
reset_exclusive_group = reset_parser . add_mutually_exclusive_group ( )
2024-05-28 11:26:25 -05:00
if self . helpers . is_baremetal ( ) :
# Add Baremetal reset arguments
2025-01-08 17:24:05 -05:00
reset_exclusive_group . add_argument ( ' -G ' , ' --gpureset ' , action = ' store_true ' , required = False , help = gpureset_help )
reset_exclusive_group . add_argument ( ' -c ' , ' --clocks ' , action = ' store_true ' , required = False , help = reset_clocks_help )
reset_exclusive_group . add_argument ( ' -f ' , ' --fans ' , action = ' store_true ' , required = False , help = reset_fans_help )
reset_exclusive_group . add_argument ( ' -p ' , ' --profile ' , action = ' store_true ' , required = False , help = reset_profile_help )
reset_exclusive_group . add_argument ( ' -x ' , ' --xgmierr ' , action = ' store_true ' , required = False , help = reset_xgmierr_help )
reset_exclusive_group . add_argument ( ' -d ' , ' --perf-determinism ' , action = ' store_true ' , required = False , help = reset_perf_det_help )
reset_exclusive_group . add_argument ( ' -o ' , ' --power-cap ' , action = ' store_true ' , required = False , help = reset_power_cap_help )
2024-05-28 11:26:25 -05:00
# Add Baremetal and Virtual OS reset arguments
2025-01-08 17:24:05 -05:00
reset_exclusive_group . add_argument ( ' -l ' , ' --clean-local-data ' , action = ' store_true ' , required = False , help = reset_gpu_clean_local_data_help )
2023-03-06 06:20:21 -06:00
2025-01-15 20:28:45 -06:00
def _add_monitor_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-05-23 11:07:58 -05:00
if not self . helpers . is_linux ( ) :
2024-02-14 09:10:04 -06:00
# This subparser is only applicable to Linux
2023-12-06 16:57:26 -06:00
return
2024-02-21 03:48:09 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The monitor subcommand is only applicable to systems with amdgpu initialized
return
2023-12-06 16:57:26 -06:00
# Subparser help text
monitor_help = " Monitor metrics for target devices "
monitor_subcommand_help = " Monitor a target device for the specified arguments. \
\n If no arguments are provided, all arguments will be enabled. \
2024-11-11 16:07:11 -06:00
\n Use the watch arguments to run continuously. "
2023-12-06 16:57:26 -06:00
monitor_optionals_title = " Monitor Arguments "
# Help text for Arguments only on Guest and BM platforms
power_usage_help = " Monitor power usage in Watts "
temperature_help = " Monitor temperature in Celsius "
gfx_util_help = " Monitor graphics utilization ( %% ) and clock (MHz) "
mem_util_help = " Monitor memory utilization ( %% ) and clock (MHz) "
encoder_util_help = " Monitor encoder utilization ( %% ) and clock (MHz) "
decoder_util_help = " Monitor decoder utilization ( %% ) and clock (MHz) "
ecc_help = " Monitor ECC single bit, ECC double bit, and PCIe replay error counts "
mem_usage_help = " Monitor memory usage in MB "
2024-04-24 06:11:32 -05:00
pcie_bandwidth_help = " Monitor PCIe bandwidth in Mb/s "
2024-06-09 16:31:34 -05:00
process_help = " Enable Process information table below monitor output "
2024-05-21 20:30:16 -05:00
violation_help = " Monitor power and thermal violation status ( %% ); Only available for MI300 or newer ASICs "
2023-12-06 16:57:26 -06:00
# Create monitor subparser
2024-06-20 13:05:51 -05:00
monitor_parser = subparsers . add_parser ( ' monitor ' , help = monitor_help , description = monitor_subcommand_help , aliases = [ " dmon " ] )
2023-12-06 16:57:26 -06:00
monitor_parser . _optionals . title = monitor_optionals_title
monitor_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
monitor_parser . set_defaults ( func = func )
# Add Universal Arguments
self . _add_command_modifiers ( monitor_parser )
self . _add_device_arguments ( monitor_parser , required = False )
self . _add_watch_arguments ( monitor_parser )
# Add monitor arguments
monitor_parser . add_argument ( ' -p ' , ' --power-usage ' , action = ' store_true ' , required = False , help = power_usage_help )
monitor_parser . add_argument ( ' -t ' , ' --temperature ' , action = ' store_true ' , required = False , help = temperature_help )
monitor_parser . add_argument ( ' -u ' , ' --gfx ' , action = ' store_true ' , required = False , help = gfx_util_help )
monitor_parser . add_argument ( ' -m ' , ' --mem ' , action = ' store_true ' , required = False , help = mem_util_help )
monitor_parser . add_argument ( ' -n ' , ' --encoder ' , action = ' store_true ' , required = False , help = encoder_util_help )
monitor_parser . add_argument ( ' -d ' , ' --decoder ' , action = ' store_true ' , required = False , help = decoder_util_help )
2024-11-04 15:36:48 -06:00
monitor_parser . add_argument ( ' -e ' , ' --ecc ' , action = ' store_true ' , required = False , help = ecc_help )
2023-12-06 16:57:26 -06:00
monitor_parser . add_argument ( ' -v ' , ' --vram-usage ' , action = ' store_true ' , required = False , help = mem_usage_help )
2024-04-24 06:11:32 -05:00
monitor_parser . add_argument ( ' -r ' , ' --pcie ' , action = ' store_true ' , required = False , help = pcie_bandwidth_help )
2024-06-09 16:31:34 -05:00
monitor_parser . add_argument ( ' -q ' , ' --process ' , action = ' store_true ' , required = False , help = process_help )
2024-05-21 20:30:16 -05:00
monitor_parser . add_argument ( ' -V ' , ' --violation ' , action = ' store_true ' , required = False , help = violation_help )
2023-12-06 16:57:26 -06:00
2023-03-06 06:20:21 -06:00
def _add_rocm_smi_parser ( self , subparsers , func ) :
2023-03-28 15:32:17 -05:00
return
2023-03-06 06:20:21 -06:00
# Subparser help text
rocm_smi_help = " Legacy rocm_smi commands ported for backward compatibility "
2023-04-21 08:02:53 -05:00
rocm_smi_subcommand_help = " If no GPU is specified, returns showall and print the information for all \
2023-03-06 06:20:21 -06:00
GPUs on the system. "
rocm_smi_optionals_title = " rocm_smi Arguments "
# Optional arguments help text
load_help = " Load clock, fan, performance, and profile settings from a given file. "
save_help = " Save clock, fan, performance, and profile settings to a given file. "
2023-03-28 15:32:17 -05:00
showtempgraph_help = " Show Temperature Graph "
showmclkrange_help = " Show mclk range "
showsclkrange_help = " Show sclk range "
showmaxpower_help = " Show maximum graphics package power this GPU will consume "
showmemvendor_help = " Show GPU memory vendor "
showproductname_help = " Show SKU/Vendor name "
showclkvolt_help = " Show supported GPU and Memory Clocks and Voltages "
showclkfrq_help = " Show supported GPU and Memory Clock "
2023-03-06 06:20:21 -06:00
# Create rocm_smi subparser
2023-03-28 15:32:17 -05:00
rocm_smi_parser = subparsers . add_parser ( ' rocm-smi ' , help = rocm_smi_help , description = rocm_smi_subcommand_help )
2023-03-06 06:20:21 -06:00
rocm_smi_parser . _optionals . title = rocm_smi_optionals_title
2023-10-13 14:03:24 -05:00
rocm_smi_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
2023-03-06 06:20:21 -06:00
rocm_smi_parser . set_defaults ( func = func )
self . _add_command_modifiers ( rocm_smi_parser )
# Add Device args
self . _add_device_arguments ( rocm_smi_parser , required = False )
# Optional Args
rocm_smi_parser . add_argument ( ' -l ' , ' --load ' , action = self . _check_input_file_path ( ) , type = str , required = False , help = load_help )
rocm_smi_parser . add_argument ( ' -s ' , ' --save ' , action = self . _check_output_file_path ( ) , type = str , required = False , help = save_help )
2023-04-15 02:00:37 -05:00
rocm_smi_parser . add_argument ( ' -b ' , ' --showbw ' , action = ' store_true ' , required = False , help = showbw_help )
2023-03-28 15:32:17 -05:00
rocm_smi_parser . add_argument ( ' -t ' , ' --showtempgraph ' , action = ' store_true ' , required = False , help = showtempgraph_help )
rocm_smi_parser . add_argument ( ' -m ' , ' --showmclkrange ' , action = ' store_true ' , required = False , help = showmclkrange_help )
rocm_smi_parser . add_argument ( ' -c ' , ' --showsclkrange ' , action = ' store_true ' , required = False , help = showsclkrange_help )
rocm_smi_parser . add_argument ( ' -P ' , ' --showmaxpower ' , action = ' store_true ' , required = False , help = showmaxpower_help )
rocm_smi_parser . add_argument ( ' -M ' , ' --showmemvendor ' , action = ' store_true ' , required = False , help = showmemvendor_help )
rocm_smi_parser . add_argument ( ' -p ' , ' --showproductname ' , action = ' store_true ' , required = False , help = showproductname_help )
rocm_smi_parser . add_argument ( ' -v ' , ' --showclkvolt ' , action = ' store_true ' , required = False , help = showclkvolt_help )
rocm_smi_parser . add_argument ( ' -f ' , ' --showclkfrq ' , action = ' store_true ' , required = False , help = showclkfrq_help )
2023-03-17 14:58:50 +01:00
2023-04-15 02:00:37 -05:00
2025-01-15 20:28:45 -06:00
def _add_xgmi_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-02-22 23:08:37 -06:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The xgmi subcommand is only applicable to systems with amdgpu initialized
return
# Subparser help text
xgmi_help = " Displays xgmi information of the devices "
xgmi_subcommand_help = " If no GPU is specified, returns information for all GPUs on the system. \
2024-11-11 16:07:11 -06:00
\n If no xgmi argument is provided, all xgmi information will be displayed. "
2024-02-22 23:08:37 -06:00
xgmi_optionals_title = " XGMI arguments "
# Help text for Arguments only on Guest and BM platforms
metrics_help = " Metric XGMI information "
2024-11-07 16:35:17 -06:00
xgmi_link_status_help = " XGMI Link Status information "
2024-02-22 23:08:37 -06:00
# Create xgmi subparser
xgmi_parser = subparsers . add_parser ( ' xgmi ' , help = xgmi_help , description = xgmi_subcommand_help )
xgmi_parser . _optionals . title = xgmi_optionals_title
xgmi_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
xgmi_parser . set_defaults ( func = func )
# Add Universal Arguments
self . _add_command_modifiers ( xgmi_parser )
self . _add_device_arguments ( xgmi_parser , required = False )
# Optional Args
xgmi_parser . add_argument ( ' -m ' , ' --metric ' , action = ' store_true ' , required = False , help = metrics_help )
2024-11-07 16:35:17 -06:00
xgmi_parser . add_argument ( ' -l ' , ' --link-status ' , action = ' store_true ' , required = False , help = xgmi_link_status_help )
2024-02-22 23:08:37 -06:00
2025-01-15 20:28:45 -06:00
def _add_partition_parser ( self , subparsers : argparse . _SubParsersAction , func ) :
2024-09-25 22:44:38 -05:00
if not self . helpers . is_amdgpu_initialized ( ) :
# The partition subcommand is only applicable to systems with amdgpu initialized
return
# Subparser help text
partition_help = " Displays partition information of the devices "
partition_subcommand_help = " If no GPU is specified, returns information for all GPUs on the system. \
2024-11-11 16:07:11 -06:00
\n If no partition argument is provided, all partition information will be displayed. "
2024-09-25 22:44:38 -05:00
partition_optionals_title = " partition arguments "
# Options help text
current_help = " display the current partition information "
memory_help = " display the current memory partition mode and capabilities "
accelerator_help = " display accelerator partition information "
# Create partition subparser
partition_parser = subparsers . add_parser ( ' partition ' , help = partition_help , description = partition_subcommand_help )
partition_parser . _optionals . title = partition_optionals_title
partition_parser . formatter_class = lambda prog : AMDSMISubparserHelpFormatter ( prog )
partition_parser . set_defaults ( func = func )
# Add Universal Arguments
self . _add_device_arguments ( partition_parser , required = False )
# Handle GPU Options
partition_parser . add_argument ( ' -c ' , ' --current ' , action = ' store_true ' , required = False , help = current_help )
partition_parser . add_argument ( ' -m ' , ' --memory ' , action = ' store_true ' , required = False , help = memory_help )
partition_parser . add_argument ( ' -a ' , ' --accelerator ' , action = ' store_true ' , required = False , help = accelerator_help )
# Add command modifiers to the bottom
self . _add_command_modifiers ( partition_parser )
2023-03-17 14:58:50 +01:00
def error ( self , message ) :
2023-04-15 02:00:37 -05:00
outputformat = self . helpers . get_output_format ( )
2023-03-17 14:58:50 +01:00
if " argument : invalid choice: " in message :
l = len ( " argument : invalid choice: " ) + 1
message = message [ l : ]
message = message . split ( " ' " ) [ 0 ]
2024-06-24 12:07:34 -05:00
# Check if the command is possible in other system configurations and error accordingly
if message in self . possible_commands :
2024-06-28 08:58:52 -05:00
raise amdsmi_cli_exceptions . AmdSmiCommandNotSupportedException ( message , outputformat )
2023-03-17 14:58:50 +01:00
raise amdsmi_cli_exceptions . AmdSmiInvalidCommandException ( message , outputformat )
elif " unrecognized arguments: " in message :
l = len ( " unrecognized arguments: " )
message = message [ l : ]
raise amdsmi_cli_exceptions . AmdSmiInvalidParameterException ( message , outputformat )
else :
print ( message )