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 )