#!/bin/bash
set -eo pipefail
CURRENT_DIR="$(dirname -- "$0")"
ROCPROFV2_DIR=$(dirname -- $(realpath ${BASH_SOURCE[0]}))
ROCM_DIR=$(dirname -- "$ROCPROFV2_DIR")
PLUGIN_LIST=("ctf" "perfetto" "file" "att")
RUN_FROM_BUILD=0
if [[ $ROCPROFV2_DIR == *"/build"* ]]; then
  RUN_FROM_BUILD=1
  ROCM_DIR=$ROCPROFV2_DIR
fi

export ROCPROFILER_METRICS_PATH=$ROCM_DIR/libexec/rocprofiler/counters/derived_counters.xml
export LD_LIBRARY_PATH=$ROCM_DIR/lib:$LD_LIBRARY_PATH

usage() {
  echo -e "ROCProfilerV2 Run Script Usage:"
  echo -e "-h   | --help               For showing this message"
  echo -e "--list-counters             For showing all available counters for the current GPUs"
  if [ $RUN_FROM_BUILD == 1 ]; then
    echo -e "-t   | --test               For Running the tests"
    echo -e "-mt  | --mem-test           For Running the Memory Leak tests. This run requires building using -acb | --asan-clean-build option"
  fi
  echo -e "${GREEN}--hip-api ${RESET}                    For Collecting HIP API Traces"
  echo -e "${GREEN}--hip-activity | --hip-trace ${RESET} For Collecting HIP API Activities Traces"
  echo -e "${GREEN}--hsa-api ${RESET}                    For Collecting HSA API Traces"
  echo -e "${GREEN}--hsa-activity | --hsa-trace ${RESET} For Collecting HSA API Activities Traces"
  echo -e "${GREEN}--roctx-trace ${RESET}                For Collecting ROCTx Traces"
  echo -e "${GREEN}--kernel-trace ${RESET}               For Collecting Kernel dispatch Traces"
  echo -e "${GREEN}--sys-trace ${RESET}                  For Collecting HIP and HSA APIs and their Activities Traces along ROCTX and Kernel Dispatch traces\n"
  echo -e "\t#${GREY}usage e.g: rocprofv2 --[hip-trace|hsa-trace|roctx-trace|kernel-trace|sys-trace]  <executable>\n"${RESET}

  echo -e "${GREEN}--plugin ${RESET} PLUGIN_NAME         For enabling a plugin (file/perfetto/att/ctf)"
  echo -e "\t#${GREY} usage(file/perfetto/ctf) e.g: rocprofv2 -i pmc.txt --plugin [file/perfetto/ctf] -d out_dir <executable>"
  echo -e "\t# usage(att): rocprofv2 <rocprofv2_params> --plugin att <ISA_file> <att_parameters> <executable>"
  echo -e "\t# use \"rocprofv2 --plugin att --help\" for ATT-specific parameters help.${RESET}\n"
  echo -e "${GREEN}-i   | --input ${RESET}               For adding counters file path (every line in the text file represents a counter)"
  echo -e "\t#${GREY} usage: rocprofv2 -i pmc.txt -d <executable>${RESET}\n"
  echo -e "${GREEN}-o   | --output-file ${RESET}         For the output file name"
  echo -e "\t#${GREY} usage e.g:(with current dir): rocprofv2 --hip-trace -o <file_name> <executable>"
  echo -e "\t#${GREY} usage e.g:(with custom dir):  rocprofv2 --hip-trace -d <out_dir> -o <file_name> <executable>${RESET}\n"
  echo -e "${GREEN}-d   | --output-directory ${RESET}    For adding output path where the output files will be saved"
  echo -e "\t#${GREY} usage e.g:(with custom dir):  rocprofv2 --hip-trace -d <out_dir> <executable>${RESET}\n"
  echo -e "${GREEN}-fi  | --flush-interval ${RESET}      For adding a flush interval in milliseconds, every \"flush interval\" the buffers will be flushed"
  echo -e "\t#${GREY} usage e.g:  rocprofv2 --hip-trace -fi 1000 <executable>${RESET}\n"
  echo -e "${GREEN}-tp  | --trace-period ${RESET}       Specifies a trace period in milliseconds, with format \"-tp <DELAY>:<ACTIVE_TIME>:<LOOP_RESET_TIME>\"."
  echo -e "\t#${GREY} usage e.g:  rocprofv2 --hip-trace -tp 1000:2000:4000 <executable>${RESET}\n"
  exit 1
}

if [ -z "$1" ]; then
  usage
  exit 1
fi

OUTPUT_PATH_INTERNAL="."

while [ 1 ]; do
  if [[ "$1" = "-h" || "$1" = "--help" ]]; then
    usage
    exit 1
  elif [[ "$1" = "-t" || "$1" = "--test" ]]; then
    if [ $RUN_FROM_BUILD == 1 ]; then
      ./run_tests.sh
      exit 1
    fi
  elif [[ "$1" = "-mt" || "$1" = "--mem-test" ]]; then
    if [ $RUN_FROM_BUILD == 1 ]; then
      $ROCM_DIR/tests-v2/memorytests/run_asan_tests.sh $ROCM_DIR/tests-v2/featuretests/profiler/apps/hip_vectoradd $ROCM_DIR/memleaks.log
      exit 1
    fi
  elif [[ "$1" = "--list-counters" ]]; then
    export LD_PRELOAD=$LD_PRELOAD:$ROCM_DIR/lib/rocprofiler/librocprofiler_tool.so
    eval $ROCM_DIR/libexec/rocprofiler/ctrl
    exit 1
  elif [[ "$1" = "-i" || "$1" = "--input" ]]; then
    if [ $2 ] && [ -n $2 ] && [ -r $2 ]; then
      export COUNTERS_PATH=$2
    else
      echo -e "Error: \"$2\" doesn't exist!"
      usage
      exit 1
    fi
    shift
    shift
  elif [[ "$1" = "-o" || "$1" = "--output-file-name" ]]; then
    if [ $2 ]; then
      export OUT_FILE_NAME=$2
    else
      usage
      exit 1
    fi
    shift
    shift
  elif [[ "$1" = "-d" || "$1" = "--output-directory" ]]; then
    if [ $2 ]; then
      OUTPUT_PATH_INTERNAL=$2
      export OUTPUT_PATH=$OUTPUT_PATH_INTERNAL
    else
      usage
      exit 1
    fi
    shift
    shift
  elif [[ "$1" = "-fi" || "$1" = "--flush-interval" ]]; then
    if [ $2 ] && [ $2 -gt 0 ]; then
      export ROCPROFILER_FLUSH_INTERVAL=$2
    else
      echo -e "Wrong input \"$2\" for flush interval, it needs to be integer greater than zero!"
      usage
      exit 1
    fi
    shift
    shift
  elif [[ "$1" = "-tp" || "$1" = "--trace-period" ]]; then
    if [ $2 ] && [[ "$2" == *":"* ]]; then
      export ROCPROFILER_TRACE_PERIOD=$2
    else
      echo -e "Wrong input \"$2\" for trace period!"
      usage
      exit 1
    fi
    shift
    shift
  elif [ "$1" = "--hip-api" ]; then
    export ROCPROFILER_HIP_API_TRACE=1
    shift
  elif [[ "$1" = "--hip-activity" || "$1" = "--hip-trace" ]]; then
    export ROCPROFILER_HIP_API_TRACE=1
    export ROCPROFILER_HIP_ACTIVITY_TRACE=1
    shift
  elif [ "$1" = "--hsa-api" ]; then
    export ROCPROFILER_HSA_API_TRACE=1
    shift
  elif [[ "$1" = "--hsa-activity" || "$1" = "--hsa-trace" ]]; then
    export ROCPROFILER_HSA_API_TRACE=1
    export ROCPROFILER_HSA_ACTIVITY_TRACE=1
    shift
  elif [ "$1" = "--roctx-trace" ]; then
    export ROCPROFILER_ROCTX_TRACE=1
    shift
  elif [ "$1" = "--kernel-trace" ]; then
    export ROCPROFILER_KERNEL_TRACE=1
    shift
  elif [ "$1" = "--sys-trace" ]; then
    export ROCPROFILER_HIP_API_TRACE=1
    export ROCPROFILER_HIP_ACTIVITY_TRACE=1
    export ROCPROFILER_HSA_API_TRACE=1
    export ROCPROFILER_HSA_ACTIVITY_TRACE=1
    export ROCPROFILER_ROCTX_TRACE=1
    shift
  elif [ "$1" = "--roc-sys" ]; then
    export ROCPROFILER_ENABLE_AMDSYS=$2
    shift
    shift
  elif [ "$1" = "--plugin" ]; then
    if [ -n $2 ]; then
      PLUGIN=$2
      if [[ ! "${PLUGIN_LIST[*]}" =~ $PLUGIN ]]; then
        echo -e "Wrong input \"$2\" for plugin!"
        usage
        exit 1
      fi
      export ROCPROFILER_PLUGIN_LIB=lib${PLUGIN}_plugin.so
    else
      echo -e "Wrong input \"$2\" for plugin!"
      usage
      exit 1
    fi
    if [ "$2" = "att" ]; then
      if [ $RUN_FROM_BUILD == 1 ]; then
        ATT_PATH=$ROCM_DIR/plugin/att/att/att.py
      else
        ATT_PATH=$ROCM_DIR/libexec/rocprofiler/att/att.py
        export ROCPROFV2_ATT_LIB_PATH=$ROCM_DIR/lib/hsa-amd-aqlprofile/librocprofv2_att.so
      fi
      ATT_ARGV=$3
      shift

      ATT_OPTIONS="Not done"
      ATT_PYTHON3_ARG="python3 "
      while [ "$ATT_OPTIONS" = "Not done" ]; do
        if [[ "$3" = "--trace_file" ]]; then
          ATT_ARGV="$ATT_ARGV $3 \"$4\""
          shift
          shift
        elif [[ "$3" = "--mpi" ]]; then
          ATT_PYTHON3_ARG="mpirun -np $4 python3 "
          shift
          shift
        elif [[ "$3" = "--mode" || "$3" = "--ports" || "$3" = "--genasm" || "$3" == "--att_kernel" || "$3" == "--depth" ]]; then
          ATT_ARGV="$ATT_ARGV $3 $4"
          shift
          shift
        else
          ATT_OPTIONS="Done"
        fi
      done
    fi
    shift
    shift
  elif [[ "$1" = "-"* || "$1" = "--"* ]]; then
    echo -e "Wrong option \"$1\", Please use the following options:\n"
    usage
    exit 1
  else
    break
  fi
done

PMC_LINES=()
if [ -n "$COUNTERS_PATH" ]; then
  input=$COUNTERS_PATH
  while IFS= read -r line || [[ -n "$line" ]]; do
    #skip empty lines
    if [[ -z "$line" ]]; then
      continue
    fi
    # if in att mode, only add the first line
    if [[ ! -n "$PMC_LINES" ]] || [[ ! -n "$ATT_ARGV" ]]; then
      PMC_LINES+=("$line")
    fi
  done <$input
fi

if [ -n "$PMC_LINES" ] && [ ! -n "$ATT_ARGV" ]; then
  COUNTER=1
  for i in ${!PMC_LINES[@]}; do
    export ROCPROFILER_COUNTERS="${PMC_LINES[$i]}"
    if [[ ! ${PMC_LINES[$i]} =~ "pmc" ]]; then
      continue
    fi

    FINAL_PATH="$OUTPUT_PATH_INTERNAL/pmc_$COUNTER"
    if [ -n "$OUT_FILE_NAME" ] || [ -n "$OUTPUT_PATH" ]; then
      export OUTPUT_PATH=$FINAL_PATH
    fi
    let COUNTER=COUNTER+1
    LD_PRELOAD=$LD_PRELOAD:$ROCM_DIR/lib/rocprofiler/librocprofiler_tool.so $*
    if [ -n "$OUTPUT_PATH" ]; then
      echo -e "\nThe output path for the following counters: $OUTPUT_PATH"
    fi
  done
else
  LD_PRELOAD=$LD_PRELOAD:$ROCM_DIR/lib/rocprofiler/librocprofiler_tool.so $*
fi

get_pmc_results_txt_path() {
  for file_name in $(ls $1); do
    if [[ $file_name == *results.txt ]]; then
      echo "$1/$file_name"
    fi
  done
}

if [ -n "$ATT_PATH" ]; then
  if [ -n "$ATT_ARGV" ]; then
    eval "$ATT_PYTHON3_ARG $ATT_PATH $ATT_ARGV"
  elif [ ! -n "$PMC_LINES" ]; then
    echo "ATT File  is required!"
  fi
fi
