51bdb2ce02
Calbulator package 'bc' is not always installed, occasionally breaking the test scripts. As a fix, this patch gets rid of 'bc' and uses 'awk' instead. Change-Id: I5f4dbf018d97581a626cf95d147c415755477771
274 lines
11 KiB
Bash
Executable File
274 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
###############################################################################
|
|
# Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved.
|
|
#
|
|
# 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.
|
|
###############################################################################
|
|
|
|
BASE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
. $BASE_DIR/global.cfg
|
|
initialize
|
|
REQ_DIFF=40 # at most 30 TCC reads are not from TCP
|
|
|
|
#-- test kernel:
|
|
#-- single thread, pointer chase
|
|
#-- test settings (format: Ns|M):
|
|
#-- issue M=512k accesses access the array with N elements using different
|
|
#-- strides (s=1/2/4/...)
|
|
#-- miss rate patterns:
|
|
#-- 1) if N <= C: r = (N/b)/M
|
|
#-- array fits into the cache, causing no replacement, and thus misses
|
|
#-- only happens when the line is being loaded,
|
|
#-- i.e., cold misses
|
|
#-- 2) if N > C:
|
|
#-- a). r = s/b, s in [1, b)
|
|
#-- b). r = 100%, s in [b, N/a)
|
|
#-- c). r = 0%, s in [N/a, ]
|
|
CACHES="TCP TCC" # which caches to test
|
|
input_args="$1 $2"
|
|
caches="${input_args// }"
|
|
if [[ ! -z $caches ]]; then
|
|
if [[ $caches == TCP ]] || [[ $caches == TCC ]]; then CACHES=$caches
|
|
elif [[ $caches != TCPTCC ]]; then
|
|
printf "${RED}Supported caches are TCP and TCC ...${NC}\n"; exit
|
|
fi
|
|
fi
|
|
|
|
#-- TCP
|
|
TCP_Ns_M="64 16384|512"
|
|
#-- TCC
|
|
TCC_Ns_M="4096 8192 16384 32768 65536 131072 2097152 4194304|512@16"
|
|
|
|
|
|
headers="TCC_HIT_sum TCC_MISS_sum"
|
|
|
|
# set up outputs
|
|
OUT_DIR="outs"; [ -d $OUT_DIR ] && rm -rf $OUT_DIR; mkdir $OUT_DIR
|
|
log_file=$OUT_DIR/"prof.log"; >$log_file
|
|
|
|
kerns="cache_test_RO cache_test_WO"
|
|
# append '/' if a non-default/empty path is specified
|
|
if [[ ! -z $ROCP_PATH ]]; then ROCP_PATH=$ROCP_PATH"/"; fi
|
|
|
|
function one_run
|
|
{
|
|
local N=$1
|
|
local s=$2
|
|
local M=$3
|
|
local level=$4
|
|
rst_sym="N${N}_s${s}_M${M}k"
|
|
rst_file=$OUT_DIR/"${rst_sym}.csv"
|
|
#echo "$N: $s -- $rst_file"
|
|
printf "\n Traverse %7s-int array in %5s-int stride with %4s accesses" \
|
|
$N $s "${M}K"
|
|
${ROCP_PATH}rocprof -i ${BASE_DIR}/../pmc_config_files/cache_pmc.txt -o \
|
|
${BASE_DIR}/../$rst_file $PATH_CACHE_BENCH/cache $s $N $M \
|
|
>> $log_file 2>&1
|
|
|
|
# check the profiling result
|
|
checkProfRun $rst_file $log_file
|
|
|
|
colIds=$(getColIds $rst_file)
|
|
|
|
sed -i 's/(.*)/(args)/g' $rst_file
|
|
|
|
totTcpRds=0; totTcpWrs=0 # tcp rds/wrs
|
|
missTcpRds=0; missTcpWrs=0 # tcp rd/wr misses
|
|
hitTccReqs=0; missTccReqs=0; totTccReqs=0 # tcc hits/misses/reqs
|
|
totTccRds=0; totTccWrs=0 # tcc rds/wrs
|
|
missTccRds=0; missTccWrs=0 # tcc rd/wr misses
|
|
|
|
for kern in $kerns
|
|
do
|
|
values=`grep $kern $rst_file | sed 's/,/ /g'`
|
|
for colIdStr in $colIds
|
|
do
|
|
colId=`echo $colIdStr | cut -f1 -d'|'`
|
|
colStr=`echo $colIdStr | cut -f2 -d'|'`
|
|
colVal=`echo $values | cut -f$colId -d' '`
|
|
|
|
if [[ $kern == cache_test_RO || $kern == cache_test_WO ]]; then
|
|
if [[ $colStr == TCC_HIT_sum ]]; then hitTccReqs=$colVal
|
|
elif [[ $colStr == TCC_MISS_sum ]]; then missTccReqs=$colVal; fi
|
|
fi
|
|
done
|
|
|
|
rstdiff=1 # check result (0: pass/no-difference, 1: fail)
|
|
totTccReqs=$((hitTccReqs + missTccReqs))
|
|
|
|
#-- use kernel 'cache_test_RO' to validate read miss rate
|
|
if [[ $kern == cache_test_RO ]]; then
|
|
totTcpRds=$(( $M*1024 )); totTcpWrs=1 # tcp rds/wrs
|
|
totTccWrs=1; missTccWrs=1 # one write, and miss
|
|
missTccRds=$(($missTccReqs-$missTccWrs)) # remaining are read misses
|
|
totTccRds=$(($totTccReqs - $totTccWrs)) # remaining are reads
|
|
missTcpRds=$totTccRds # tcp rd misses + other
|
|
|
|
mn=0; md=0 # miss rate denoted using numerator and denomiator
|
|
line=$b_tcp; if (( $s > $b_tcp)); then line=$s; fi
|
|
expectedMissTcpRds=0
|
|
if (( $N > $C_tcp )) && (( $s >= $b_tcp )); then
|
|
# array size is larger than cache capacity, and stride is larger
|
|
# than a cacheline size (N>C && s>=b)
|
|
# 100% miss if s in [b, N/a), only code misses if s is [N/a,]
|
|
if (($missTcpRds - $totTcpRds < $REQ_DIFF)) \
|
|
&& (($totTcpRds - $missTcpRds < $REQ_DIFF)); then
|
|
rstdiff=0; expectedMissTcpRds=$totTcpRds
|
|
elif (($missTcpRds - $N/$s < $REQ_DIFF)) \
|
|
&& (($N/$s - $missTcpRds < $REQ_DIFF)); then
|
|
rstdiff=0; expectedMissTcpRds=$(($N/$s)); fi
|
|
else
|
|
# array size is no larger than cache size (N<=C): only cold misses
|
|
# array size is larger than cache capacity, and stride is less than
|
|
# a cacheline size (N>C && s<b)
|
|
# always miss when a line is loaded into cache
|
|
if (( $N <= $C_tcp )); then
|
|
mn=$(( $N/$line )); md=$totTcpRds; expectedMissTcpRds=$mn
|
|
else
|
|
mn=$s; md=$b_tcp
|
|
expectedMissTcpRds=$(awk -v s=$s -v b=$b_tcp -v rd=$totTcpRds \
|
|
'BEGIN{printf("%.0f", s*rd/b)}')
|
|
fi
|
|
if (($missTcpRds - $expectedMissTcpRds < $REQ_DIFF)) \
|
|
&& (($expectedMissTcpRds - $missTcpRds < $REQ_DIFF)); then
|
|
rstdiff=0; fi
|
|
fi
|
|
|
|
# tcp validation
|
|
if [[ $level == TCP ]]; then
|
|
printf "\n\tTCP-READ : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTcpRds $REQ_DIFF $missTcpRds
|
|
if (( $rstdiff == 0 )); then printf "test [${GREEN}PASS${NC}]"
|
|
else printf "test [${RED}FAIL${NC}]"; fi
|
|
# tcc validation
|
|
elif [[ $level == TCC ]]; then
|
|
if (( $rstdiff != 0 )); then
|
|
printf "\n\tTCP-READ : test [${RED}FAIL${NC}]"; fi
|
|
# tcp miss rate
|
|
tcprdmissrate=$(awk -v mr=$missTcpRds -v rd=$totTcpRds \
|
|
'BEGIN{printf("%f", mr/rd)}')
|
|
# tcc miss rate
|
|
tccrdmissrate=$(awk -v mr=$missTccRds -v rd=$totTccRds \
|
|
'BEGIN{printf("%f", mr/rd)}')
|
|
|
|
coldmisses=$(awk -v n=$N -v l=$line 'BEGIN{printf("%.0f", n/l)}')
|
|
|
|
expectedMissTccRds=$coldmisses
|
|
if (( $(awk 'BEGIN {print "'$tccrdmissrate'" > 0.98}') )) \
|
|
&& (( $(awk 'BEGIN {print "'$tcprdmissrate'" > 0.98}') )); then
|
|
expectedMissTccRds=$totTcpRds
|
|
printf "\n\tTCC-READ : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTccRds ".5%" $missTccRds
|
|
else
|
|
printf "\n\tTCC-READ : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTccRds $REQ_DIFF $missTccRds
|
|
fi
|
|
|
|
# absolute difference between profiled and expected
|
|
diff=$(( $missTccRds - $coldmisses ))
|
|
if (( $(awk 'BEGIN {print "'$diff'" < 0}') )); then
|
|
diff=$(awk -v d=$diff 'BEGIN{printf("%f", d*-1)}'); fi
|
|
if (( $(awk 'BEGIN {print "'$tccrdmissrate'" > 0.98}') )); then
|
|
printf "test [${GREEN}PASS${NC}]"
|
|
elif (( $diff < $REQ_DIFF )); then
|
|
printf "test [${GREEN}PASS${NC}]"
|
|
else printf "test [${RED}FAIL${NC}]"; fi
|
|
fi
|
|
#-- use kernel 'cache_test_WO' to validate TCP write miss rate
|
|
elif [[ $kern == cache_test_WO ]]; then
|
|
totTcpRds=0; totTcpWrs=$(( $M*1024 )); # tcp rds/wrs
|
|
totTccRds=0; missTccRds=$totTccRds # no reads from tcp
|
|
totTccWrs=$(($totTccReqs - $totTccRds)) # remaining are writes
|
|
missTccWrs=$(($missTccReqs - $missTccRds)) # remaining are write mis
|
|
missTcpWrs=$totTccWrs # all tcc wrs are from tcp
|
|
|
|
if (($missTcpWrs - $totTcpWrs < $REQ_DIFF)) \
|
|
&& (($totTcpWrs - $missTcpWrs < $REQ_DIFF)); then
|
|
rstdiff=0; fi
|
|
# tcp is write through
|
|
expectedMissTcpWrs=$totTcpWrs
|
|
|
|
if [[ $level == TCP ]]; then
|
|
printf "\n\tTCP-WRITE : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTcpWrs $REQ_DIFF $missTcpWrs
|
|
if (( $rstdiff == 0 )); then printf "test [${GREEN}PASS${NC}]"
|
|
else printf "test [${RED}FAIL${NC}]"; fi
|
|
# tcc validation
|
|
elif [[ $level == TCC ]]; then
|
|
if (( $rstdiff != 0 )); then
|
|
printf "\n\tTCP-WRITE : test [${RED}FAIL${NC}]"; fi
|
|
tccwrmissrate=$(awk -v mw=$missTccWrs -v wr=$totTccWrs \
|
|
'BEGIN{printf("%f", mw/wr)}')
|
|
|
|
coldmisses=$(awk -v n=$N -v l=$line 'BEGIN{printf("%.0f", n/l)}')
|
|
|
|
expectedMissTccWrs=$coldmisses
|
|
if (( $(awk 'BEGIN {print "'$tccwrmissrate'" > 0.98}') )); then
|
|
expectedMissTccWrs=$totTcpWrs;
|
|
printf "\n\tTCC-WRITE : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTccWrs ".5%" $missTccWrs
|
|
else
|
|
printf "\n\tTCC-WRITE : expected=%6s±%s, profiled=%6s, " \
|
|
$expectedMissTccWrs $REQ_DIFF $missTccWrs
|
|
fi
|
|
if (($missTccWrs - $coldmisses < $REQ_DIFF)) \
|
|
&& (($missTccWrs - $coldmisses < $REQ_DIFF)); then
|
|
printf "test [${GREEN}PASS${NC}]"
|
|
elif (( $(awk 'BEGIN {print "'$tccwrmissrate'" > 0.98}') )); then
|
|
printf "test [${GREEN}PASS${NC}]"
|
|
else printf "test [${RED}FAIL${NC}]"; fi
|
|
fi
|
|
fi
|
|
|
|
done
|
|
}
|
|
|
|
for cache in $CACHES
|
|
do
|
|
{
|
|
cfgname="${cache}_Ns_M"
|
|
Ns_M=${!cfgname}
|
|
|
|
Ns=`echo $Ns_M | cut -f1 -d'|'` #-- array sizes
|
|
M=`echo $Ns_M | cut -f2 -d'|' | cut -f1 -d'@'` #-- array accesses
|
|
S=""
|
|
if [[ $Ns_M == *@* ]]; then S=`echo $Ns_M | cut -f2 -d'@'`; fi #-- stride
|
|
#echo $S
|
|
|
|
printf "\n\t=========================================================\n"
|
|
printf "\t==================== Test [$cache miss] ====================\n"
|
|
printf "\t========================================================="
|
|
|
|
for N in $Ns
|
|
do
|
|
if [[ x$S == x ]]; then
|
|
m_stride=$N
|
|
for (( s=1; s<=$m_stride; s*=2 ))
|
|
do
|
|
one_run $N $s $M $cache
|
|
done
|
|
else
|
|
one_run $N $S $M $cache
|
|
fi
|
|
done
|
|
printf "\n"
|
|
}
|
|
done
|