[PATCH 3/6] umr: Complete umr completion
Luben Tuikov
luben.tuikov at amd.com
Wed Mar 23 11:48:39 UTC 2022
Complete all commands. Complete all commands' arguments which can be
completed. Data is gathered from files in the UMR_DATABASE_PATH, from the
PCI system and from the /sys filesystem in order to complete the arguments
of commands which require non-open-value argument, i.e. an argument from a
closed set.
Cc: Alex Deucher <Alexander.Deucher at amd.com>
Cc: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Cc: Tom StDenis <tom.stdenis at amd.com>
Cc: Christian König <christian.koenig at amd.com>
Signed-off-by: Luben Tuikov <luben.tuikov at amd.com>
---
scripts/umr-completion.bash | 374 ++++++++++++++++++++++++++++++++++--
1 file changed, 362 insertions(+), 12 deletions(-)
diff --git a/scripts/umr-completion.bash b/scripts/umr-completion.bash
index 79972949b9861e..7029264ca5f725 100644
--- a/scripts/umr-completion.bash
+++ b/scripts/umr-completion.bash
@@ -1,6 +1,22 @@
# bash completion for umr
+# Copyright (C) Advanced Micro Devices 2022
+#
+# You should set UMR_DATABASE_PATH before sourcing this file in your
+# .bashrc. To source it, do "source <location of this file>"--to see a
+# usual location of this file, see the FILES section in umr(1).
+#
+# I recommend you "set show-all-if-ambiguous On" in your .inputrc, for
+# matches to be listed immediately (on a first TAB key press) as
+# opposed to ring the bell the first time and seeing matches on the
+# second TAB key press. To load the keymap, do "bind -f ~/.inputrc" in
+# your .bashrc, assuming your .inputrc is in your home directory.
-_setup()
+if [[ ! -d $UMR_DATABASE_PATH ]]; then
+ echo -n "UMR_DATABASE_PATH must be set for correct operation of umr bash completion."
+ echo " See the FILES section in umr(1)."
+fi
+
+_umr_setup_ips()
{
select_gpu=""
if [ $COMP_CWORD -ge 4 ]; then
@@ -25,9 +41,9 @@ _setup()
done
}
-_comp_blocks()
+_umr_comp_blocks()
{
- _setup
+ _umr_setup_ips
if [ -z "$cur" ]; then
COMPREPLY=( $(compgen -W "${ips[*]}" -- "$cur") )
@@ -39,9 +55,9 @@ _comp_blocks()
fi
}
-_comp_regs()
+_umr_comp_regs()
{
- _setup
+ _umr_setup_ips
if [[ "$cur" =~ ^[^.]*'.'[^.]*'.'[^.]*$ ]]; then
cur_asic="${cur%%.*}"
@@ -60,24 +76,358 @@ _comp_regs()
fi
}
+_umr_comp_option_flags()
+{
+ local FLAGS=(bits bitsfull empty_log follow no_follow_ib use_pci use_colour read_smc quiet no_kernel verbose halt_waves disasm_early_term no_disasm disasm_anyways wave64 full_shader no_fold_vm_decode no_scan_waves)
+ local F G CURR_OPTIONS
+ local ACTIVE_OPTIONS=()
+ local ACTIVE_FLAGS=()
+
+ CURR_OPTIONS="`echo ${COMP_WORDS[*]} | sed -E -e 's/^.*-O[[:space:]]+(.*)$/\1/g'`"
+ CURR_OPTIONS="`echo $CURR_OPTIONS | sed -E -e 's/,/ /g'`"
+
+ # Get rid of user-input partial option string
+ for F in $CURR_OPTIONS ; do
+ if [[ $F == $cur ]] ; then
+ continue;
+ fi
+ ACTIVE_OPTIONS+=("$F")
+ done
+
+ # Offer only options which are not already part of --option/-O
+ for F in ${FLAGS[*]} ; do
+ for G in ${ACTIVE_OPTIONS[*]} ; do
+ if [[ $F == $G ]]; then
+ continue 2;
+ fi
+ done
+ ACTIVE_FLAGS+=($F)
+ done
+
+ # If the user presses TAB again after full completion, as opposed
+ # to say SPACE BAR, then give them comma and the rest of the
+ # flags.
+ COMPREPLY=( $(compgen -W "${ACTIVE_FLAGS[*]}" -- "$cur") )
+ if [[ $cur == ${COMPREPLY[0]} ]] && (( ${#COMPREPLY[*]} == 1 )) && (( ${#ACTIVE_FLAGS[*]} > 1 )) ; then
+ COMPREPLY=( $(compgen -S ',' -W "${ACTIVE_FLAGS[*]}" -- "$cur") )
+ fi
+ # Complete with a space after all options entered.
+ if [[ $cur != ${COMPREPLY[0]} ]] || (( ${#COMPREPLY[*]} != 1 )) || (( ${#ACTIVE_FLAGS[*]} > 1 )) ; then
+ compopt -o nospace
+ fi
+}
+
+_umr_comp_instance()
+{
+ local INSTANCE=(`sudo \ls -1 /sys/kernel/debug/dri/`)
+
+ COMPREPLY=( $(compgen -W "${INSTANCE[*]}" -- "$cur") )
+}
+
+_umr_comp_pci()
+{
+ local PCI_LIST=(`lspci -D | grep VGA | cut -f 1 -d \ | tr '\n' ' '`)
+
+ COMPREPLY=( $(compgen -W "${PCI_LIST[*]}" -- "$cur") )
+}
+
+_umr_comp_prof()
+{
+ local PROFS=( "pixel=" "vertex=" "compute=" )
+
+ COMPREPLY=( $(compgen -W "${PROFS[*]}" -- "$cur") )
+ compopt -o nospace
+}
+
+_umr_comp_ring()
+{
+ local INSTANCE=`echo "$COMP_LINE" | sed -E -e 's/^.*(--instance|-i)[[:space:]]+([0-9]+).*$/\2/g'`
+
+ if [[ ! $INSTANCE =~ ^[0-9]+$ ]]; then
+ # The default instance in umr is 0. See umr(1) under "--instance".
+ INSTANCE=0
+ fi
+
+ local RINGS=( `sudo $(which find) /sys/kernel/debug/dri/$INSTANCE -name amdgpu_ring_* | sed -E -e "s%/sys/kernel/debug/dri/$INSTANCE/amdgpu_ring_%%g"` )
+
+ COMPREPLY=( $(compgen -W "${RINGS[*]}" -- "$cur") )
+}
+
+_umr_comp_clock_scan()
+{
+ local CLOCKS=( `sudo $(which umr) --clock-scan | grep ".*:$" | sed -E -e 's/[: ]//g'` )
+
+ COMPREPLY=( $(compgen -W "${CLOCKS[*]}" -- "$cur") )
+}
+
+_umr_comp_force()
+{
+ local ASIC_NAMES=(`awk '{ print $2; }' $UMR_DATABASE_PATH/pci.did | sed -E -e 's/.asic//g' | sort | uniq`)
+ if [[ $cur =~ ^\..* ]] ; then
+ COMPREPLY=( $(compgen -P '.' -W "${ASIC_NAMES[*]}" -- "${cur#.}") )
+ else
+ COMPREPLY=( $(compgen -W "${ASIC_NAMES[*]}" -- "$cur") )
+ fi
+}
+
+_umr_comp_gpu()
+{
+ local INSTANCE=( `sudo \ls -1 /sys/kernel/debug/dri/` )
+ local PCI_BUS_DIR_NAMES=()
+ local PCI_BUS_IDS=()
+ local -A PCI_BUS_ASIC_NAME
+ local SUGGEST=()
+ local ASIC_NAMES=()
+ local TEMP_ASIC_NAMES=()
+ local INST_ASIC_NAME=()
+ local GPU_NAME
+ local F
+
+ # We need to do it like this, so that this works
+ # when run from non-root shell.
+ for F in ${INSTANCE[*]} ; do
+ PCI_BUS_DIR_NAMES+=("/sys/kernel/debug/dri/$F/name")
+ done
+ PCI_BUS_IDS=( `sudo cat ${PCI_BUS_DIR_NAMES[*]} | sed -E -e 's/^.* (dev=(.*)) .*$/\2/g' | sort | uniq` )
+
+ for F in ${INSTANCE[*]} ; do
+ local PCI_ID=`sudo cat "/sys/kernel/debug/dri/$F/name" | sed -E -e 's/^.* (dev=(.*)) .*$/\2/g'`
+ local DEV_ID=`cat /sys/class/pci_bus/${PCI_ID%:??.?}/device/$PCI_ID/device`
+ local DEV_ID_NAME=`grep -i $DEV_ID ${UMR_DATABASE_PATH}/pci.did | awk '{ print $2; }' | sed -E -e 's/.asic//g'`
+ TEMP_ASIC_NAMES+=($DEV_ID_NAME)
+ PCI_BUS_ASIC_NAME["$PCI_ID"]="$DEV_ID_NAME"
+ INST_ASIC_NAME["$F"]="$DEV_ID_NAME"
+ done
+ # Remove duplicates
+ ASIC_NAMES=( `(for F in ${TEMP_ASIC_NAMES[*]} ; do echo $F; done) | sort | uniq` )
+
+ if [[ ! $cur =~ .*@.* ]] && [[ ! $cur =~ .*=.* ]]; then
+ COMPREPLY=( $(compgen -W "${ASIC_NAMES[*]}" -- "$cur") )
+ if [[ ${#COMPREPLY[*]} == 1 ]]; then
+ GPU_NAME=${COMPREPLY[0]}
+ COMPREPLY=( $(compgen -W "${GPU_NAME}@ ${GPU_NAME}=" -- "$cur") )
+ fi
+ compopt -o nospace
+ return
+ fi
+
+ if [[ $cur =~ .*@.* ]]; then
+ # Find all instances of the selected ASIC name and offer them
+ local INST_OFFER=()
+ GPU_NAME="${cur%%@*}"
+ for F in ${INSTANCE[*]} ; do
+ if [[ $GPU_NAME == ${INST_ASIC_NAME["$F"]} ]] ; then
+ INST_OFFER+=("$F")
+ fi
+ done
+ SUGGEST=( $(compgen -P "${GPU_NAME}@" -W "${INST_OFFER[*]}") )
+ elif [[ $cur =~ .*=.* ]]; then
+ # Find all PCI bus IDs of the selected ASIC name and offer them
+ local PCI_ID_OFFER=()
+ GPU_NAME="${cur%%=*}"
+ for F in ${PCI_BUS_IDS[*]} ; do
+ if [[ $GPU_NAME == ${PCI_BUS_ASIC_NAME["$F"]} ]] ; then
+ PCI_ID_OFFER+=("$F")
+ fi
+ done
+ SUGGEST=( $(compgen -P "${GPU_NAME}=" -W "${PCI_ID_OFFER[*]}") )
+ fi
+
+ COMPREPLY=( $(compgen -W "${SUGGEST[*]}" -- $cur) )
+}
+
+# Sets GPU_NAME with the name of the GPU given on the command line by
+# --force, --gpu or --instance, or default, and sets up IP_BLOCKS an
+# array of the names of the IP blocks of GPU_NAME.
+#
+_umr_setup_gpu_ipblocks()
+{
+ # The regex we use to match an ASIC name is "[[:alnum:]_]+".
+ local FORCE=`echo "$COMP_LINE" | sed -E -e 's/^.*(--force|-f)[[:space:]]+([[:alnum:]_]+).*$/\2/g'`
+ local GPU=`echo "$COMP_LINE" | sed -E -e 's/^.*(--gpu|-g)[[:space:]]+([[:alnum:]_]+)(@|=)*.*$/\2/g'`
+ local INSTANCE=`echo "$COMP_LINE" | sed -E -e 's/^.*(--instance|-i)[[:space:]]+([0-9]+).*$/\2/g'`
+
+ # GPU_NAME is set only when given by a parameter on the command line.
+ # GPU_NAME2 is always set, even when not specified on the command line.
+ IP_BLOCKS=
+ GPU_NAME=
+ GPU_NAME2=
+ DEFAULT_GPU_NAME=
+
+ if [[ $COMP_LINE =~ (--force|-f) ]]; then
+ GPU_NAME="$FORCE"
+ IP_BLOCKS=( `sudo umr --force $GPU_NAME --list-blocks | sed -E -e "s/^[[:space:]]*${GPU_NAME}\.(.*)[[:space:]]+\(.*$/\1/g"` )
+ GPU_NAME2="$GPU_NAME"
+ elif [[ $COMP_LINE =~ (--gpu|-g) ]]; then
+ GPU_NAME="$GPU"
+ IP_BLOCKS=( `sudo umr --force $GPU_NAME --list-blocks | sed -E -e "s/^[[:space:]]*${GPU_NAME}\.(.*)[[:space:]]+\(.*$/\1/g"` )
+ GPU_NAME2="$GPU_NAME"
+ elif [[ $COMP_LINE =~ (--instance|-i) ]]; then
+ GPU_NAME=`sudo umr --instance $INSTANCE --list-blocks | head -1 | cut -f 1 -d . | sed -E -e 's/[[:space:]]+//g'`
+ IP_BLOCKS=( `sudo umr --instance $INSTANCE --list-blocks | sed -E -e "s/^[[:space:]]*${GPU_NAME}\.(.*) \(.*$/\1/g"` )
+ GPU_NAME2="$GPU_NAME"
+ else
+ GPU_NAME2=`sudo umr --list-blocks | head -1 | cut -f 1 -d . | sed -E -e 's/[[:space:]]+//g'`
+ IP_BLOCKS=( `sudo umr --list-blocks | sed -E -e "s/^[[:space:]]*.*\.(.*) \(.*$/\1/g"` )
+ fi
+
+ DEFAULT_GPU_NAME=`sudo umr --list-blocks | head -1 | cut -f 1 -d . | sed -E -e 's/[[:space:]]+//g'`
+}
+
+_umr_comp_lookup()
+{
+ # Should specify a GPU with --force or --gpu, of even --instance.
+ # The --gpu option also specifies an IP block and is thus
+ # redundant--better use --force.
+ # Specifying a GPU is optional--a default detected
+ # will be used.
+ # The format is --lookup <IP block>.<register> <value>.
+
+ _umr_setup_gpu_ipblocks
+ local REGS
+ local FINAL
+ local F
+
+ if [[ ! $cur =~ .*\. ]]; then
+ COMPREPLY=( $(compgen -S '.' -W "${IP_BLOCKS[*]}" -- $cur) )
+ compopt -o nospace
+ else
+ # Complete a register for the given IP block.
+ # See _umr_comp_asic_ipblock_registers() below.
+ F="${cur%.*}"
+ if [[ -z $GPU_NAME ]] || [[ $GPU_NAME == $DEFAULT_GPU_NAME ]] ; then
+ REGS=( `sudo umr --list-regs ${F} | sed -E -e "s/(.*)\.(.*)\.(.*)[[:space:]]+\(.*$/\3/g"` )
+ else
+ REGS=( `sudo umr --force $GPU_NAME --list-regs ${F%\{*} | sed -E -e "s/${GPU_NAME}\.(.*)\.(.*)[[:space:]]+\(.*$/\2/g"` )
+ if (( ${#REGS[*]} == 0 )); then
+ REGS=( `sudo umr --force $GPU_NAME --list-regs ${F} | sed -E -e "s/${GPU_NAME}\.(.*)\.(.*)[[:space:]]+\(.*$/\2/g"` )
+ fi
+ fi
+ FINAL=( $(compgen -P "${F}." -W "${REGS[*]}") )
+ COMPREPLY=( $(compgen -W "${FINAL[*]}" -- "$cur") )
+ fi
+
+ unset GPU_NAME GPU_NAME2 DEFAULT_GPU_NAME IP_BLOCKS
+}
+
+_umr_comp_asic_ipblock_registers()
+{
+ # The format is --writebit asic.ipblock.regname,
+ # the same as that of --write and --read.
+
+ _umr_setup_gpu_ipblocks
+ local ips=()
+ local FINAL=()
+ local REGS=()
+ local F
+
+ ips=( $(compgen -P "${GPU_NAME2}." -W "${IP_BLOCKS[*]}") )
+
+ if [[ ! $cur =~ ${GPU_NAME2}\..*\. ]]; then
+ COMPREPLY=( $(compgen -S '.' -W "${ips[*]}" -- $cur) )
+ compopt -o nospace
+ else
+ # cur = asic.ipblock.*
+ #
+ # When using --force with the default (installed in the
+ # system) ASIC and --list-regs together, --list-regs does not
+ # take instance numbers, so to pass an instance number, we
+ # need to know if the GPU was forced on the command line.
+ # First however, get rid of user hints.
+ F="${cur%.*}"
+ if [[ -z $GPU_NAME ]] || [[ $GPU_NAME == $DEFAULT_GPU_NAME ]] ; then
+ REGS=( `sudo umr --list-regs ${F} | sed -E -e "s/(.*)\.(.*)\.(.*)[[:space:]]+\(.*$/\3/g"` )
+ else
+ REGS=( `sudo umr --force $GPU_NAME --list-regs ${F%\{*} | sed -E -e "s/${GPU_NAME}\.(.*)\.(.*)[[:space:]]+\(.*$/\2/g"` )
+ if (( ${#REGS[*]} == 0 )); then
+ REGS=( `sudo umr --force $GPU_NAME --list-regs ${F} | sed -E -e "s/${GPU_NAME}\.(.*)\.(.*)[[:space:]]+\(.*$/\2/g"` )
+ fi
+ fi
+ # Cannot combine the compgen since a match is performed
+ # _before_ the prefix is applied! And if we want to match,
+ # we need to tack the prefix prior to asking for a match.
+ FINAL=( $(compgen -P "${F}." -W "${REGS[*]}") )
+ COMPREPLY=( $(compgen -W "${FINAL[*]}" -- $cur) )
+ fi
+
+ unset GPU_NAME GPU_NAME2 DEFAULT_GPU_NAME IP_BLOCKS
+}
+
+_umr_comp_ring_stream()
+{
+ _umr_comp_ring
+ compopt -o nospace
+}
+
_umr_completion()
{
- local cur prev
+ local ALL_LONG_ARGS=(--database-path --option --gpu --instance --force --pci --gfxoff --vm_partition --bank --sbank --cbank --config --enumerate --list-blocks --list-regs --dump-discovery-table --lookup --write --writebit --read --scan --logscan --top --waves --profiler --vm-decode --vm-read --vm-write --vm-write-word --vm-disasm --ring-stream --dump-ib --dump-ib-file --header-dump --power --clock-scan --clock-manual --clock-high --clock-low --clock-auto --ppt_read --gpu_metrics --power --vbios_info --test-log --test-harness --server --gui)
+
+ local cur prev
+
+ COMP_WORDBREAKS=" ,"
COMPREPLY=()
- cur=${COMP_WORDS[COMP_CWORD]}
- prev=${COMP_WORDS[COMP_CWORD-1]}
+ cur=$2
+ prev=$3
case $prev in
+ --database-path|--dbp)
+ compopt -o default -o dirnames
+ ;;
+ --option|-O|bits|bitsfull|empty_log|follow|no_follow_ib|use_pci|use_colour|read_smc|quiet|no_kernel|verbose|halt_waves|disasm_early_term|no_disasm|disasm_anyways|wave64|full_shader|no_fold_vm_decode|no_scan_waves|,)
+ _umr_comp_option_flags
+ ;;
+ --force|-f)
+ _umr_comp_force
+ ;;
+ --gpu|-g)
+ _umr_comp_gpu
+ ;;
+ --instance|-i)
+ _umr_comp_instance
+ ;;
+ --pci)
+ _umr_comp_pci
+ ;;
+ --gfxoff|-go)
+ COMPREPLY=( $(compgen -W "0 1" -- "$cur") )
+ ;;
-lr|--list-regs|-s|--scan)
- _comp_blocks
- return 0
+ _umr_comp_blocks
;;
-r|--read|-w|--write)
- _comp_regs
- return 0
+ _umr_comp_regs
;;
+ --lookup|-lu)
+ _umr_comp_lookup
+ ;;
+ --writebit|-wb)
+ _umr_comp_asic_ipblock_registers
+ ;;
+ --waves|-wa)
+ _umr_comp_ring
+ ;;
+ --profiler|-prof)
+ _umr_comp_prof
+ ;;
+ pixel=*|vertex=*|compute=*)
+ _umr_comp_ring
+ ;;
+ --dump-ib-file|-df|--test-log|-tl|--test-harness|-th)
+ compopt -o default -o filenames
+ ;;
+ --clock-scan|-cs|--clock-manual|-cm)
+ _umr_comp_clock_scan
+ ;;
+ --ring-stream|-RS)
+ _umr_comp_ring_stream
+ ;;
+ *)
+ COMPREPLY=( $(compgen -W "${ALL_LONG_ARGS[*]}" -- $cur) )
+ ;;
esac
+ return 0
}
complete -F _umr_completion umr
--
2.35.1.607.gf01e51a7cf
More information about the amd-gfx
mailing list