All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luben Tuikov <luben.tuikov@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: "Alex Deucher" <Alexander.Deucher@amd.com>,
	"Pierre-Eric Pelloux-Prayer" <pierre-eric.pelloux-prayer@amd.com>,
	"Luben Tuikov" <luben.tuikov@amd.com>,
	"Christian König" <christian.koenig@amd.com>,
	"Tom StDenis" <tom.stdenis@amd.com>
Subject: [PATCH 3/6] umr: Complete umr completion
Date: Wed, 23 Mar 2022 07:48:39 -0400	[thread overview]
Message-ID: <20220323114842.78516-4-luben.tuikov@amd.com> (raw)
In-Reply-To: <20220323114842.78516-1-luben.tuikov@amd.com>

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@amd.com>
Cc: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Cc: Tom StDenis <tom.stdenis@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Signed-off-by: Luben Tuikov <luben.tuikov@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


  parent reply	other threads:[~2022-03-23 11:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-23 11:48 [PATCH 0/6] Complete and add dynamic completion to umr Luben Tuikov
2022-03-23 11:48 ` [PATCH 1/6] umr: Rename "scripts/umr" --> "scripts/umr-completion.bash" Luben Tuikov
2022-03-23 11:48 ` [PATCH 2/6] umr: Rename completion function Luben Tuikov
2022-03-23 11:48 ` Luben Tuikov [this message]
2022-03-23 11:48 ` [PATCH 4/6] umr: Replace and reuse asic.ipblock.reg completion Luben Tuikov
2022-03-23 11:48 ` [PATCH 5/6] umr: Replace and reuse ipblock completion Luben Tuikov
2022-03-23 11:48 ` [PATCH 6/6] umr: Add FILES section to the man page Luben Tuikov
2022-03-23 12:01 ` [PATCH 0/6] Complete and add dynamic completion to umr StDenis, Tom

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220323114842.78516-4-luben.tuikov@amd.com \
    --to=luben.tuikov@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=christian.koenig@amd.com \
    --cc=pierre-eric.pelloux-prayer@amd.com \
    --cc=tom.stdenis@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.