#!/bin/sh
#
# analyze_ftrace
# script to analyze SX-8 ftrace output
# written March 2007 by K. Benkert
#
# Description:
# The script extracts data from multiple ftrace output files for an
# easy performance comparison
#
# How to use it:
# Execute the script "analyze_ftrace" with at least one option (see below)
# the program unit and the ftrace file(s)
#

###############################################################################
# PARSE OPTIONS AND ARGUMENTS
###############################################################################
   function usage {
      echo >&2
      echo "Usage: $0 [-abfhilmopqrtv] PROGUNIT FILES" >&2
      echo "print performance data specified by options for PROGUNIT from" >&2
      echo "ftrace FILES" >&2
      echo >&2
      echo "  -a   AVER. time [msec]" >&2
      echo "  -b   BANK conf" >&2
      echo "  -f   MFLOPS" >&2
      echo "  -h   help" >&2
      echo "  -i   I-cache miss" >&2
      echo "  -l   aver. v.LENGTH" >&2
      echo "  -m   MOps" >&2
      echo "  -o   O-cache miss" >&2
      echo "  -p   exclusive time [%]" >&2
      echo "  -q   frequency" >&2
      echo "  -r   V.op RATION" >&2
      echo "  -t   exclusive TIME [sec]" >&2
      echo "  -v   VECTOR time" >&2
      echo >&2
      echo "Report comments and bugs to <benkert@hlrs.de>." >&2
   }

   function usage_and_exit {
      usage
      exit 1
   }

   # set flags to empty
   lfreq=false ltime=false ltimeperc=false lavtime=false 
   lmops=false lmflops=false lvopratio=false lavvlen=false
   lvtime=false licache=false locache=false lbankconf=false
   nopt=0 # #options

   # parse flags
   while getopts :abfhilmopqrtv opt
   do
      case $opt in
        q)     lfreq=true         nopt=$((nopt+1))
               ;;
        t)     ltime=true         nopt=$((nopt+1))
               ;;
        p)     ltimeperc=true     nopt=$((nopt+1)) 
               ;;
        a)     lavtime=true       nopt=$((nopt+1)) 
               ;;
        m)     lmops=true         nopt=$((nopt+1)) 
               ;;
        f)     lmflops=true       nopt=$((nopt+1)) 
               ;;
        r)     lvopratio=true     nopt=$((nopt+1)) 
               ;;
        l)     lavvlen=true       nopt=$((nopt+1)) 
               ;;
        v)     lvtime=true        nopt=$((nopt+1)) 
               ;;
        i)     licache=true       nopt=$((nopt+1)) 
               ;;
        o)     locache=true       nopt=$((nopt+1)) 
               ;;
        b)     lbankconf=true     nopt=$((nopt+1)) 
               ;;
        h)     usage_and_exit
               ;;
        '?')   echo "$0: invalid option -$OPTARG" >&2
               usage_and_exit
               ;;
       esac
   done
   shift $((OPTIND -1)) # remove options

   # parse arguments
   progunit=$1
   shift
   ftfiles=$*
   path="./"

###############################################################################
# OPTION AND ARGUMENT CHECKING
###############################################################################
   # no options specified
   if [ $nopt -eq 0 ]; then
      echo "$0: no option specified" >&2
      usage_and_exit
   fi

   # no programm unit specified
   if [ "X$progunit" = "X" ]; then
      echo "$0: no programm unit specified" >&2
      usage_and_exit
   fi

   # no ftrace files specified
   if [[ "X$ftfiles" = "X" ]]; then
      echo "$0: no ftrace files specified" >&2
      usage_and_exit
   fi

   # ftrace files or program unit do not exist
   for ftfile in $ftfiles
   do
      if [[ ! -f "$ftfile" ]]
      then
         echo "$0: no such ftrace file: $ftfile" >&2
         usage_and_exit
      fi

      if [[ "X`cat $ftfile | grep -e "^$progunit "`" = "X" &&
            "X`cat $ftfile | grep -e "^$progunit$"`" = "X" ]]
      then
         echo "$0: prog unit $progunit in $ftfile not found" >&2
         exit 1
      fi
   done

###############################################################################
# HANDLING OF PERFORMANCE DATA
###############################################################################

   # prelimiaries
   # 1. determine maximum length of ftrace file names for output
   totftstrlen=6
   for ftfile in $ftfiles
   do
      ftstrlen=`echo $ftfile | awk '{ print length($1) }'`
      if [[ $ftstrlen -gt $totftstrlen ]]
      then
         totftstrlen=$ftstrlen
      fi
   done
   # 2. init format string to have sufficient space for file names
   fmtstr=`echo "%$totftstrlen"s`
   # 3. check if performance data for progunit is given on one or two lines
   #    if length($progunit) > 10, than two lines output
   pustrlen=`echo $progunit | awk '{ print length($1) }'`
   if [[ pustrlen -gt 10 ]]
   then
      pattern="-A1"
   fi

   # print header
   echo Performance data for $progunit

   printf "$fmtstr" "FILE"
   if $lfreq    ; then printf "%10s" FREQUENCY; fi
   if $ltime    ; then printf "%10s" EXCLUSIVE; fi
   if $ltimeperc; then printf "%10s" EXCLUSIVE; fi
   if $lavtime  ; then printf "%10s" AVER.TIME; fi
   if $lmops    ; then printf  "%8s" MOPS     ; fi
   if $lmflops  ; then printf  "%8s" MFLOPS   ; fi
   if $lvopratio; then printf  "%6s" V.OP     ; fi
   if $lavvlen  ; then printf  "%6s" AVER.    ; fi
   if $lvtime   ; then printf  "%9s" VECTOR   ; fi
   if $licache  ; then printf  "%8s" I-CACHE  ; fi
   if $locache  ; then printf  "%8s" O-CACHE  ; fi
   if $lbankconf; then printf  "%8s" BANK     ; fi
   printf "\n"

   printf "$fmtstr"
   if $lfreq    ; then printf "%10s"          ; fi
   if $ltime    ; then printf "%10s" TIME[sec]; fi
   if $ltimeperc; then printf "%10s" TIME[%]  ; fi
   if $lavtime  ; then printf "%10s" [msec]   ; fi
   if $lmops    ; then printf  "%8s"          ; fi
   if $lmflops  ; then printf  "%8s"          ; fi
   if $lvopratio; then printf  "%6s" RATIO    ; fi
   if $lavvlen  ; then printf  "%6s" V.LEN    ; fi
   if $lvtime   ; then printf  "%9s" TIME     ; fi
   if $licache  ; then printf  "%8s" MISS     ; fi
   if $locache  ; then printf  "%8s" MISS     ; fi
   if $lbankconf; then printf  "%8s" CONF     ; fi
   printf "\n"

   for ftfile in $ftfiles
   do
      # extract performance data
      freq=`    cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 11-20`
      time=`    cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 21-30` # char 31 = (
      timeperc=`cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 32-36` # char 37 = )
      avtime=`  cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 38-47`
      mops=`    cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 48-55`
      mflops=`  cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 56-63`
      vopratio=`cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 64-69`
      avvlen=`  cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 70-75`
      vtime=`   cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 76-84`
      icache=`  cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 85-92`
      ocache=`  cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 93-100`
      bankconf=`cat $ftfile | grep $pattern $progunit | grep "(" | cut -c 101-108` 

      # print performance data
      printf "$fmtstr" $ftfile
      if $lfreq    ; then printf "%10s" $freq    ; fi
      if $ltime    ; then printf "%10s" $time    ; fi
      if $ltimeperc; then printf "%10s" $timeperc; fi
      if $lavtime  ; then printf "%10s" $avtime  ; fi
      if $lmops    ; then printf  "%8s" $mops    ; fi
      if $lmflops  ; then printf  "%8s" $mflops  ; fi
      if $lvopratio; then printf  "%6s" $vopratio; fi
      if $lavvlen  ; then printf  "%6s" $avvlen  ; fi
      if $lvtime   ; then printf  "%9s" $vtime   ; fi
      if $licache  ; then printf  "%8s" $icache  ; fi
      if $locache  ; then printf  "%8s" $ocache  ; fi
      if $lbankconf; then printf  "%8s" $bankconf; fi
      printf "\n"
   done

# end
