#!/bin/bash set -e bind_cpu="1" build="" cc_flags="" cc_prefix="" config="default" helper_cpu="$(($bind_cpu-1))" mcpu="" mfpu="" # Use explicit path to perf to have a record of the version perf_bin="/usr/lib/linux-tools/$(uname -r)/perf" perf_buildid_dir="global" perf_events="" profiler="none" save_temps=false sysroot="" sysinfo_program="default" toolchain="gnu" OPTS="`getopt -o ve: -l bind:,ccflags:,ccprefix:,config:,event:,helpercpu:,mcpu:,mfpu:,perf-bin:,perf-buildid-dir:,profiler:,save-temps,sysinfo:,sysroot:,toolchain: -- "$@"`" while test $# -gt 1; do case $1 in --bind) bind_cpu="$2"; shift ;; --ccflags) cc_flags="$2"; shift ;; --ccprefix) cc_prefix="$2"; shift ;; --config) config="$2"; shift ;; -e|--event) perf_events="$perf_events -e $2"; shift ;; --helpercpu) helper_cpu="$2"; shift ;; --mcpu) mcpu="$2"; shift ;; --mfpu) mfpu="$2"; shift ;; --perf-bin) perf_bin="$2"; shift ;; --perf-buildid-dir) perf_buildid_dir="$2"; shift ;; --profiler) profiler="$2"; shift ;; --save-temps) save_temps=true ;; --sysinfo) sysinfo_program="$2"; shift ;; --sysroot) sysroot="$2"; shift ;; --toolchain) toolchain="$2"; shift ;; -v) set -x ;; esac shift done spec=$(cd $1; pwd) shift if ! [ -d "$spec" ]; then echo "ERROR: SPEC directory does not exist: $spec" exit 1 fi if [ $# -gt 0 ]; then echo "ERROR: Extra arguments: $@" exit 1 fi declare -A tools case "$toolchain" in "gnu") tools[cc]="gcc" tools[cxx]="g++" tools[fortran]="gfortran" ;; "llvm") tools[cc]="clang" tools[cxx]="clang++" tools[fortran]="nofortran" ;; *) echo "ERROR: unknown toolchain: $toolchain" exit 1 ;; esac # If ${cc_prefix} has ':', it means in contains at least a host # specification. In that case, keep the last part in ${cc_prefix}, the # rest goes to ${build} for later parsing. case ${cc_prefix} in *:*) build=${cc_prefix%:*} cc_prefix=${cc_prefix##*:} ;; *) ;; esac if [ x"$build" != x"" ]; then # [:][:][:] build_host="$(echo $build | cut -d: -f 1)" build_port="$(echo $build | cut -s -d: -f 2)" parallelize="$(echo $build | cut -s -d: -f 3)" build_type="$(echo $build | cut -s -d: -f 4)" if [ x"$build_host" = x"" ]; then echo "ERROR: wrong --build: $build" exit 1 fi if [ x"$build_port" != x"" ]; then build_port="-p$build_port"; fi if [ x"$parallelize" = x"" ]; then parallelize="$(ssh $build_port $build_host getconf _NPROCESSORS_ONLN)" parallelize="$(($parallelize * 2))" fi if [ x"$build_type" = x"" ]; then build_type="rsync"; fi if [ x"$build_type" = x"rsync" ]; then lock=$spec/bin/ssh-$config.lock count=$spec/bin/ssh-$config.lockcnt rm -f $lock $count for cc in ${tools[cc]} ${tools[cxx]} ${tools[fortran]}; do cat "$(dirname $0)/ssh-cc.sh" | sed \ -e "s#@lock@#$lock#g" \ -e "s#@count@#$count#g" \ -e "s#@build_host@#$build_host#g" \ -e "s#@build_port@#$build_port#g" \ -e "s#@cc_prefix@#$cc_prefix#g" \ -e "s#@cc@#$cc#g" \ -e "s#@spec@#$spec#g" \ > $spec/bin/ssh-$config-$cc chmod +x $spec/bin/ssh-$config-$cc done cat > $spec/bin/ssh-$config-tar < $spec/bin/ssh-$config-$cc < $spec/bin/ssh-$config-tar < /dev/null 2>&1; then tools[tar]="${tools[tar]} -I pxz" else tools[tar]="${tools[tar]} -J" fi if $save_temps; then cc_flags="$cc_flags -save-temps=obj" save_temps_mark="" else save_temps_mark="#" fi cpuinfo="/proc/cpuinfo" hw_model="$(cat $cpuinfo | grep Hardware | head -n 1 | sed -e 's/.*: //')" hw_cpu="$(cat $cpuinfo | grep "model name\|Processor" | head -n 1 | sed -e 's/.*: //')" hw_fpu="$(cat $cpuinfo | grep Features | head -n 1 | sed -e 's/.*: //')" sw_os="$(uname -r | head -n 1)" sw_compiler="$(${tools[cc]} -v 2>&1 | tail -n 1)" #sw_compiler="$sw_compiler $(${tools[cc]} -v 2>&1 | grep 'Configured with' | head -n 1)" case "$mcpu:$hw_cpu" in "autodetect:"*"v7l"*) mcpu="-mcpu=cortex-a15" ;; "autodetect:"*"aarch64"*) mcpu="-mcpu=cortex-a57" ;; "autodetect:"*) echo "ERROR: Cannot autodetect -mcpu: $hw_cpu" exit 1 ;; esac case "$mfpu:$hw_fpu" in "autodetect:"*"neon"*"vfpv4"*) mfpu="-mfpu=neon-vfpv4" ;; "autodetect:"*) echo "ERROR: Cannot autodetect -mfpu: $hw_fpu" exit 1 ;; esac if [ x"$sysroot" != x"" ]; then # If $sysroot/lib64 exists, scan it. If it doesn't exist, don't # include it in the list otherwise find fails and the script # exits. if [ -d "$sysroot/lib64" ]; then ldso="$(find "$sysroot/lib" "$sysroot/lib64" -name "ld-*.so")" rpath64="-Wl,-rpath=$sysroot/lib64" libpath="$sysroot/lib:$sysroot/lib64" else ldso="$(find "$sysroot/lib" -name "ld-*.so")" rpath64="" libpath="$sysroot/lib" fi if [ "x$ldso" = "x" ]; then echo "ERROR: Could not find ld-*.so under $sysroot/lib or $sysroot/lib64" exit 1 fi if [ x"$(echo "$ldso" | tr " " "\n" | wc -l)" != x"1" ]; then echo "ERROR: Found multiple ld.so binaries; do not know which one to use: $ldso" exit 1 fi cc_flags="-Wl,-dynamic-linker=$ldso -Wl,-rpath=$sysroot/lib ${rpath64} $cc_flags" getconf_prog="$ldso --library-path $libpath $sysroot/usr/bin/getconf" else getconf_prog=getconf fi case "$($getconf_prog LONG_BIT)" in 64) spec_cpu2000_lp64="-DSPEC_CPU2000_LP64" spec_cpu_lp64="-DSPEC_CPU_LP64" setarch="linux64" ;; 32) spec_cpu2000_lp64="" spec_cpu_lp64="" setarch="linux32" ;; esac taskset_cpu="$bind_cpu" rate_copies="1" if [ "$rate_copies" -gt "1" ]; then case "$mcpu" in "-mcpu=cortex-a57.cortex-a53") bind_cpu="1,2,3,0,4,5,4,5" taskset_cpu="1" rate_copies="8" ;; "-mcpu=cortex-a53") bind_cpu="1,2,3,0" taskset_cpu="1" rate_copies="4" ;; "-mcpu=cortex-a57") bind_cpu="4,5" taskset_cpu="4" rate_copies="2" ;; esac fi free_ram="$(free | grep "Mem:" | sed -e "s/Mem: *\([0-9]*\).*/\1/")" max_mcf_rate_copies="$(($free_ram / (2*1024*1024) + 1))" if [ "$max_mcf_rate_copies" -gt "$rate_copies" ]; then max_mcf_rate_copies="$rate_copies" fi cfg_tmpl="$(dirname $0)/cpu2xxx.cfg" if grep -q CPU2000 $spec/shrc; then cfg_tmpl="$cfg_tmpl $(dirname $0)/cpu2000.cfg" iterations="3" elif grep -q CPU2006 $spec/shrc; then cfg_tmpl="$cfg_tmpl $(dirname $0)/cpu2006.cfg" iterations="1" fi if [ x"$sysinfo_program" != x"default" ]; then sysinfo_program="sysinfo_program = $sysinfo_program" else sysinfo_program="" fi case "$perf_buildid_dir" in "none") # Do not use buildid cache (might be necessary for SPEC "rate" runs). perf_record="$perf_bin record --no-buildid-cache" ;; "global") # Use default ~/.debug buildid cache (useful for basic non-parallel # runs). perf_record="$perf_bin record" ;; "local") # Use install-local buildid cache (useful for normal "speed" runs, and # might be necessary for running several SPEC installs in parallel). perf_buildid_dir='$[top]/result/perf.$lognum.data/.debug' perf_record="$perf_bin --buildid-dir $perf_buildid_dir record" ;; *) # Use custom buildid cache. perf_record="$perf_bin --buildid-dir $perf_buildid_dir record" ;; esac case "$profiler" in "none") profiler_none="" profiler_perf="#" ;; "perf"*) profiler_none="#" profiler_perf="" ;; *) echo "ERROR: Unknown profiler: $profiler" exit 1 ;; esac # --profiler perf[-cpu_all][-cg] # --profiler perf-cpu_all # --profiler perf-cpu_all case "$profiler" in "perf"*"-cpu_all"*) perf_cpu="-a" ;; "perf"*"-cpu_bind"*|"perf"*) perf_cpu="--cpu @BIND@" ;; esac case "$profiler" in "perf"*"-cg"*) perf_callgraph="-g" ;; "perf"*"-no_cg"*|"perf"*) perf_callgraph="" ;; esac cpufreq="$(cpufreq-info -c $bind_cpu -f 2>/dev/null | cat)" while [ x"$cpufreq" != x"" ]; do if [ x"$perf_events" = x"" ]; then perf_events="-e cycles/period=10HZ/" fi event_freq="$(echo "$perf_events" | sed -e "s#\(.*\)=\([0-9]*\)HZ\(.*\)#\2#")" if [ x"$event_freq" = x"$perf_events" ]; then break fi event_count=$((1000*$cpufreq/$event_freq)) perf_events="$(echo "$perf_events" | sed -e "s#\(.*\)=\([0-9]*\)HZ\(.*\)#\1=$event_count\3#")" done cat $cfg_tmpl | sed \ -e "s#@HW_MODEL@#$hw_model#g" \ -e "s#@HW_CPU@#$hw_cpu#g" \ -e "s#@HW_FPU@#$hw_fpu#g" \ -e "s#@SW_OS@#$sw_os#g" \ -e "s#@SW_COMPILER@#$sw_compiler#g" \ -e "s#@PARALLELIZE@#$parallelize#g" \ -e "s#@HELPER_CPU@#$helper_cpu#g" \ -e "s#@TASKSET_CPU@#$taskset_cpu#g" \ -e "s#@ITERATIONS@#$iterations#g" \ -e "s#@ITERATIONS_2@#$(($iterations+2))#g" \ -e "s#@ITERATIONS_4@#$(($iterations+4))#g" \ -e "s#@CC@#${tools[cc]}#g" \ -e "s#@CXX@#${tools[cxx]}#g" \ -e "s#@FORTRAN@#${tools[fortran]}#g" \ -e "s#@OPTIMIZE@#$cc_flags#g" \ -e "s#@MCPU@#$mcpu#g" \ -e "s#@MFPU@#$mfpu#g" \ -e "s#@PROFILEDIR@#$spec/profile#g" \ -e "s#@DSPEC_CPU2000_LP64@#$spec_cpu2000_lp64#g" \ -e "s#@DSPEC_CPU_LP64@#$spec_cpu_lp64#g" \ -e "s#@RATE_COPIES@#$rate_copies#g" \ -e "s#@MAX_MCF_RATE_COPIES@#$max_mcf_rate_copies#g" \ -e "s#@PERF_CALLGRAPH@#$perf_callgraph#g" \ -e "s#@PERF_CPU@#$perf_cpu#g" \ -e "s#@BIND@#$bind_cpu#g" \ -e "s#@PERF_EVENTS@#$perf_events#g" \ -e "s#@PERF_RECORD@#$perf_record#g" \ -e "s/@PROFILER_NONE@/$profiler_none/g" \ -e "s/@PROFILER_PERF@/$profiler_perf/g" \ -e "s/@SAVE_TEMPS@/$save_temps_mark/g" \ -e "s#@SETARCH@#$setarch#g" \ -e "s#@SYSINFO_PROGRAM@#$sysinfo_program#g" \ -e "s#@TAR@#${tools[tar]}#g" \ > $spec/config/$config.tmp if ! diff -u $spec/config/$config.tmp $spec/config/$config.cfg 2>&1 | head -n 8 | grep -q __MD5__; then mv $spec/config/$config.tmp $spec/config/$config.cfg else rm $spec/config/$config.tmp fi