1*c217d954SCole Faust#!/usr/bin/python 2*c217d954SCole Faust# -*- coding: utf-8 -*- 3*c217d954SCole Faust 4*c217d954SCole Faust# Copyright (c) 2017-2022 Arm Limited. 5*c217d954SCole Faust# 6*c217d954SCole Faust# SPDX-License-Identifier: MIT 7*c217d954SCole Faust# 8*c217d954SCole Faust# Permission is hereby granted, free of charge, to any person obtaining a copy 9*c217d954SCole Faust# of this software and associated documentation files (the "Software"), to 10*c217d954SCole Faust# deal in the Software without restriction, including without limitation the 11*c217d954SCole Faust# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12*c217d954SCole Faust# sell copies of the Software, and to permit persons to whom the Software is 13*c217d954SCole Faust# furnished to do so, subject to the following conditions: 14*c217d954SCole Faust# 15*c217d954SCole Faust# The above copyright notice and this permission notice shall be included in all 16*c217d954SCole Faust# copies or substantial portions of the Software. 17*c217d954SCole Faust# 18*c217d954SCole Faust# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*c217d954SCole Faust# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*c217d954SCole Faust# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21*c217d954SCole Faust# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22*c217d954SCole Faust# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23*c217d954SCole Faust# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24*c217d954SCole Faust# SOFTWARE. 25*c217d954SCole Faustimport os.path 26*c217d954SCole Faust 27*c217d954SCole FaustImport('env') 28*c217d954SCole FaustImport('vars') 29*c217d954SCole FaustImport('install_bin') 30*c217d954SCole Faust 31*c217d954SCole Faust# vars is imported from arm_compute: 32*c217d954SCole Faustvariables = [ 33*c217d954SCole Faust BoolVariable("benchmark_examples", "Build benchmark examples programs", False), 34*c217d954SCole Faust BoolVariable("validate_examples", "Build validate examples programs", False), 35*c217d954SCole Faust BoolVariable("reference_openmp", "Build reference validation with openmp", True), 36*c217d954SCole Faust BoolVariable("validation_tests", "Build validation test programs", False), 37*c217d954SCole Faust BoolVariable("benchmark_tests", "Build benchmark test programs", False), 38*c217d954SCole Faust ("test_filter", "Pattern to specify the tests' filenames to be compiled", "*.cpp") 39*c217d954SCole Faust] 40*c217d954SCole Faust 41*c217d954SCole Faust# We need a separate set of Variables for the Help message (Otherwise the global variables will get displayed twice) 42*c217d954SCole Faustnew_options = Variables('scons') 43*c217d954SCole Faust 44*c217d954SCole Faustfor v in variables: 45*c217d954SCole Faust new_options.Add(v) 46*c217d954SCole Faust vars.Add(v) 47*c217d954SCole Faust 48*c217d954SCole Faust# Clone the environment to make sure we're not polluting the arm_compute one: 49*c217d954SCole Fausttest_env = env.Clone() 50*c217d954SCole Faustvars.Update(test_env) 51*c217d954SCole Faust 52*c217d954SCole FaustHelp(new_options.GenerateHelpText(test_env)) 53*c217d954SCole Faust 54*c217d954SCole Faust# Check if we need to build the test framework 55*c217d954SCole Faustbuild_test_framework = False 56*c217d954SCole Faustfor opt in new_options.keys(): 57*c217d954SCole Faust option_value = test_env[opt] 58*c217d954SCole Faust if type(option_value) is bool and option_value: 59*c217d954SCole Faust build_test_framework = True 60*c217d954SCole Faust break 61*c217d954SCole Faust 62*c217d954SCole Faustif not build_test_framework: 63*c217d954SCole Faust Return() 64*c217d954SCole Faustelse: 65*c217d954SCole Faust SConscript('./framework/SConscript', duplicate=0) 66*c217d954SCole Faust 67*c217d954SCole FaustImport("arm_compute_test_framework") 68*c217d954SCole Fausttest_env.Append(LIBS = arm_compute_test_framework) 69*c217d954SCole Faust 70*c217d954SCole Faust# Disable floating-point expression contraction (e.g. fused multiply-add operations) 71*c217d954SCole Faustif not 'windows' in env['os']: 72*c217d954SCole Faust test_env.Append(CXXFLAGS = ['-ffp-contract=off']) 73*c217d954SCole Faust 74*c217d954SCole Faust# Remove -Wnoexcept from tests 75*c217d954SCole Faustif 'g++' in test_env['CXX'] and '-Wnoexcept' in test_env['CXXFLAGS']: 76*c217d954SCole Faust test_env['CXXFLAGS'].remove("-Wnoexcept") 77*c217d954SCole Faust 78*c217d954SCole Faustload_whole_archive = '-Wl,--whole-archive' 79*c217d954SCole Faustnoload_whole_archive = '-Wl,--no-whole-archive' 80*c217d954SCole Faustif 'macos' in test_env['os']: 81*c217d954SCole Faust load_whole_archive = '-Wl,-force_load' 82*c217d954SCole Faust noload_whole_archive = '-Wl,-noall_load' 83*c217d954SCole Faust 84*c217d954SCole Faustif env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 85*c217d954SCole Faust Import("arm_compute_a") 86*c217d954SCole Faust Import("arm_compute_core_a") 87*c217d954SCole Faust Import("arm_compute_graph_a") 88*c217d954SCole Faust if env['os']=='windows': 89*c217d954SCole Faust test_env.Append(LIBS = [arm_compute_graph_a, arm_compute_a]) 90*c217d954SCole Faust else: 91*c217d954SCole Faust test_env.Append(LIBS = [arm_compute_graph_a, arm_compute_a, arm_compute_core_a]) 92*c217d954SCole Faust arm_compute_lib = arm_compute_graph_a 93*c217d954SCole Faustelse: 94*c217d954SCole Faust Import("arm_compute_graph_so") 95*c217d954SCole Faust Import("arm_compute_core_a") 96*c217d954SCole Faust test_env.Append(LIBS = ["arm_compute_graph", "arm_compute", "arm_compute_core"]) 97*c217d954SCole Faust arm_compute_lib = arm_compute_graph_so 98*c217d954SCole Faust 99*c217d954SCole Faustif env['os'] in ['bare_metal']: 100*c217d954SCole Faust Import("bootcode_o") 101*c217d954SCole Faust 102*c217d954SCole Faustif env['external_tests_dir']: 103*c217d954SCole Faust test_env.Append(CPPPATH = [env['external_tests_dir'] + "/include"]) 104*c217d954SCole Faust test_env.Append(LIBPATH = [env['external_tests_dir'] + "/%s/%s" % (env['os'], env['arch'])]) 105*c217d954SCole Faust 106*c217d954SCole Faustcommon_files = Glob('*.cpp') 107*c217d954SCole Faustcommon_objects = [test_env.StaticObject(f) for f in common_files] 108*c217d954SCole Faust 109*c217d954SCole Faustfiles_benchmark = Glob('benchmark/*.cpp') 110*c217d954SCole Faustif env['external_tests_dir']: 111*c217d954SCole Faust files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/*.cpp') 112*c217d954SCole Faust 113*c217d954SCole Faust# Add unit tests 114*c217d954SCole Faustfiles_validation = Glob('validation/UNIT/*/*.cpp') 115*c217d954SCole Faustfiles_validation += Glob('validation/UNIT/*.cpp') 116*c217d954SCole Faust 117*c217d954SCole Faust# Add CPP tests 118*c217d954SCole Faustfilter_pattern = test_env['test_filter'] 119*c217d954SCole Faustfiles_validation += Glob('validation/CPP/' + filter_pattern) 120*c217d954SCole Faust 121*c217d954SCole Faustif env['opencl']: 122*c217d954SCole Faust if env['experimental_dynamic_fusion']: 123*c217d954SCole Faust files_validation += Glob('validation/dynamic_fusion/gpu/' + filter_pattern) 124*c217d954SCole Faust files_validation += Glob('validation/dynamic_fusion/gpu/cl/' + filter_pattern) 125*c217d954SCole Faust 126*c217d954SCole Faust filter_pattern = test_env['test_filter'] 127*c217d954SCole Faust 128*c217d954SCole Faust test_env.Append(CPPDEFINES=['ARM_COMPUTE_CL']) 129*c217d954SCole Faust 130*c217d954SCole Faust files_benchmark += Glob('benchmark/CL/*/' + filter_pattern) 131*c217d954SCole Faust files_benchmark += Glob('benchmark/CL/' + filter_pattern) 132*c217d954SCole Faust if env['external_tests_dir']: 133*c217d954SCole Faust files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/CL/' + filter_pattern) 134*c217d954SCole Faust 135*c217d954SCole Faust files_validation += Glob('validation/CL/*/' + filter_pattern) 136*c217d954SCole Faust files_validation += Glob('validation/CL/' + filter_pattern) 137*c217d954SCole Faust 138*c217d954SCole Faust if env['external_tests_dir']: 139*c217d954SCole Faust files_validation += Glob(env['external_tests_dir'] + '/tests/validation/CL/' + filter_pattern) 140*c217d954SCole Faust files_validation += Glob('validation/gpu/unit/*.cpp') 141*c217d954SCole Faust 142*c217d954SCole Faustif env['neon']: 143*c217d954SCole Faust filter_pattern = test_env['test_filter'] 144*c217d954SCole Faust files_benchmark += Glob('benchmark/NEON/*/' + filter_pattern) 145*c217d954SCole Faust files_benchmark += Glob('benchmark/NEON/' + filter_pattern) 146*c217d954SCole Faust test_env.Append(CPPPATH = ["#/src/cpu/kernels/assembly/"]) 147*c217d954SCole Faust if env['external_tests_dir']: 148*c217d954SCole Faust files_benchmark += Glob(env['external_tests_dir'] + '/tests/benchmark/NEON/' + filter_pattern) 149*c217d954SCole Faust 150*c217d954SCole Faust files_validation += Glob('validation/NEON/' + filter_pattern) 151*c217d954SCole Faust if env['os'] == 'bare_metal': 152*c217d954SCole Faust files_validation += Glob('validation/NEON/UNIT/MemoryManager.cpp' + filter_pattern) 153*c217d954SCole Faust files_validation += Glob('validation/NEON/UNIT/DynamicTensor.cpp' + filter_pattern) 154*c217d954SCole Faust files_validation += Glob('validation/NEON/UNIT/TensorAllocator.cpp' + filter_pattern) 155*c217d954SCole Faust else: 156*c217d954SCole Faust files_validation += Glob('validation/NEON/*/' + filter_pattern) 157*c217d954SCole Faust if env['external_tests_dir']: 158*c217d954SCole Faust files_validation += Glob(env['external_tests_dir'] + '/tests/validation/NEON/' + filter_pattern) 159*c217d954SCole Faust files_validation += Glob('validation/cpu/unit/*.cpp') 160*c217d954SCole Faust 161*c217d954SCole Faustextra_link_flags = [] 162*c217d954SCole Faustif env['os'] == 'android': 163*c217d954SCole Faust test_env.Append(LIBS = ["log"]) 164*c217d954SCole Faustelif env['os'] not in ['windows','bare_metal', 'macos']: 165*c217d954SCole Faust test_env.Append(LIBS = ["rt"]) 166*c217d954SCole Faust extra_link_flags += ['-fstack-protector-strong'] 167*c217d954SCole Faust 168*c217d954SCole Faustif test_env['benchmark_tests']: 169*c217d954SCole Faust arm_compute_benchmark = test_env.Program('arm_compute_benchmark', files_benchmark + common_objects) 170*c217d954SCole Faust arm_compute_benchmark = install_bin(arm_compute_benchmark) 171*c217d954SCole Faust Depends(arm_compute_benchmark, arm_compute_test_framework) 172*c217d954SCole Faust Depends(arm_compute_benchmark, arm_compute_lib) 173*c217d954SCole Faust Default(arm_compute_benchmark) 174*c217d954SCole Faust Export('arm_compute_benchmark') 175*c217d954SCole Faust 176*c217d954SCole Faustbm_link_flags = [] 177*c217d954SCole Faustif test_env['linker_script']: 178*c217d954SCole Faust bm_link_flags += ['-Wl,--build-id=none', '-T', env['linker_script']] 179*c217d954SCole Faust 180*c217d954SCole Faustif test_env['reference_openmp'] and env['os'] not in ['bare_metal', 'macos','windows']: 181*c217d954SCole Faust test_env['CXXFLAGS'].append('-fopenmp') 182*c217d954SCole Faust test_env['LINKFLAGS'].append('-fopenmp') 183*c217d954SCole Faust 184*c217d954SCole Faust if 'ndk_above_r21' in env: 185*c217d954SCole Faust test_env['LINKFLAGS'].append('-static-openmp') 186*c217d954SCole Faust 187*c217d954SCole Faust# Testing for fixed format GEMM kernels. 188*c217d954SCole Faustif env['experimental_fixed_format_kernels'] and test_env['validation_tests']: 189*c217d954SCole Faust test_env.Append(CPPDEFINES = ['ARM_COMPUTE_ENABLE_FIXED_FORMAT_KERNELS']) 190*c217d954SCole Faust 191*c217d954SCole Faustif test_env['validation_tests']: 192*c217d954SCole Faust arm_compute_validation_framework = env.StaticLibrary('arm_compute_validation_framework', Glob('validation/reference/*.cpp') + Glob('validation/*.cpp'), LINKFLAGS=test_env['LINKFLAGS'], CXXFLAGS=test_env['CXXFLAGS'], LIBS= [ arm_compute_test_framework, arm_compute_core_a]) 193*c217d954SCole Faust Depends(arm_compute_validation_framework , arm_compute_test_framework) 194*c217d954SCole Faust Depends(arm_compute_validation_framework , arm_compute_core_a) 195*c217d954SCole Faust 196*c217d954SCole Faust program_objects = files_validation + common_objects 197*c217d954SCole Faust if test_env['os'] == 'bare_metal': 198*c217d954SCole Faust Depends(arm_compute_validation_framework , bootcode_o) 199*c217d954SCole Faust program_objects += bootcode_o 200*c217d954SCole Faust 201*c217d954SCole Faust 202*c217d954SCole Faust arm_compute_validation = test_env.Program('arm_compute_validation', program_objects, LIBS=[arm_compute_validation_framework] + test_env['LIBS'], LINKFLAGS=test_env['LINKFLAGS'] + bm_link_flags) 203*c217d954SCole Faust arm_compute_validation = install_bin(arm_compute_validation) 204*c217d954SCole Faust Depends(arm_compute_validation, arm_compute_validation_framework) 205*c217d954SCole Faust Depends(arm_compute_validation, arm_compute_test_framework) 206*c217d954SCole Faust Depends(arm_compute_validation, arm_compute_lib) 207*c217d954SCole Faust 208*c217d954SCole Faust Default(arm_compute_validation) 209*c217d954SCole Faust Export('arm_compute_validation') 210*c217d954SCole Faust 211*c217d954SCole Faust if test_env['validate_examples']: 212*c217d954SCole Faust files_validate_examples = [ test_env.Object('validate_examples/RunExample.cpp') ] + [ x for x in common_objects if not "main.o" in str(x)] 213*c217d954SCole Faust if test_env['os'] == 'bare_metal': 214*c217d954SCole Faust files_validate_examples += bootcode_o 215*c217d954SCole Faust 216*c217d954SCole Faust arm_compute_validate_examples = [] 217*c217d954SCole Faust if test_env['neon']: 218*c217d954SCole Faust for file in Glob("validate_examples/neon_*.cpp"): 219*c217d954SCole Faust example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 220*c217d954SCole Faust arm_compute_validate_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_validate_examples, LIBS = [ arm_compute_validation_framework], LINKFLAGS=test_env['LINKFLAGS'] + bm_link_flags) ] 221*c217d954SCole Faust if test_env['opencl']: 222*c217d954SCole Faust cl_examples = [] 223*c217d954SCole Faust files = Glob("validate_examples/cl_*.cpp") 224*c217d954SCole Faust if test_env['neon']: 225*c217d954SCole Faust files += Glob("validate_examples/neoncl_*.cpp") 226*c217d954SCole Faust for file in files: 227*c217d954SCole Faust example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 228*c217d954SCole Faust cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_validate_examples, LIBS = test_env["LIBS"] + [ arm_compute_validation_framework ]) ] 229*c217d954SCole Faust arm_compute_validate_examples += cl_examples 230*c217d954SCole Faust if test_env['opencl'] and test_env['neon']: 231*c217d954SCole Faust graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils") 232*c217d954SCole Faust for file in Glob("validate_examples/graph_*.cpp"): 233*c217d954SCole Faust example = "validate_" + os.path.basename(os.path.splitext(str(file))[0]) 234*c217d954SCole Faust if env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 235*c217d954SCole Faust prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils]+ files_validate_examples, LIBS = test_env["LIBS"] + [ arm_compute_validation_framework ], LINKFLAGS=test_env["LINKFLAGS"]+[load_whole_archive, arm_compute_lib, noload_whole_archive] + bm_link_flags + extra_link_flags) 236*c217d954SCole Faust arm_compute_validate_examples += [ prog ] 237*c217d954SCole Faust else: 238*c217d954SCole Faust #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies 239*c217d954SCole Faust prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils]+ files_validate_examples, LIBS = test_env["LIBS"] + ["arm_compute_graph", arm_compute_validation_framework], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--allow-shlib-undefined'] ) 240*c217d954SCole Faust arm_compute_validate_examples += [ prog ] 241*c217d954SCole Faust arm_compute_validate_examples = install_bin(arm_compute_validate_examples) 242*c217d954SCole Faust Depends(arm_compute_validate_examples, arm_compute_validation_framework) 243*c217d954SCole Faust Depends(arm_compute_validate_examples, arm_compute_test_framework) 244*c217d954SCole Faust Depends(arm_compute_validate_examples, arm_compute_lib) 245*c217d954SCole Faust Default(arm_compute_validate_examples) 246*c217d954SCole Faust Export('arm_compute_validate_examples') 247*c217d954SCole Faust 248*c217d954SCole Faustif test_env['benchmark_examples']: 249*c217d954SCole Faust files_benchmark_examples = test_env.Object('benchmark_examples/RunExample.cpp') 250*c217d954SCole Faust if test_env['os'] == 'bare_metal': 251*c217d954SCole Faust files_benchmark_examples += bootcode_o 252*c217d954SCole Faust graph_utils = test_env.Object(source="../utils/GraphUtils.cpp", target="GraphUtils") 253*c217d954SCole Faust graph_params = test_env.Object(source="../utils/CommonGraphOptions.cpp", target="CommonGraphOptions") 254*c217d954SCole Faust arm_compute_benchmark_examples = [] 255*c217d954SCole Faust all_examples_folders = ["../examples"] 256*c217d954SCole Faust if env['external_tests_dir']: 257*c217d954SCole Faust all_examples_folders.append(env['external_tests_dir'] + "/examples") 258*c217d954SCole Faust for examples_folder in all_examples_folders: 259*c217d954SCole Faust if test_env['neon']: 260*c217d954SCole Faust for file in Glob("%s/neon_*.cpp" % examples_folder): 261*c217d954SCole Faust example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 262*c217d954SCole Faust arm_compute_benchmark_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_benchmark_examples, LINKFLAGS=test_env["LINKFLAGS"]+ bm_link_flags) ] 263*c217d954SCole Faust if test_env['opencl']: 264*c217d954SCole Faust cl_examples = [] 265*c217d954SCole Faust files = Glob("%s/cl_*.cpp" % examples_folder) 266*c217d954SCole Faust if test_env['neon']: 267*c217d954SCole Faust files += Glob("%s/neoncl_*.cpp" % examples_folder) 268*c217d954SCole Faust for file in files: 269*c217d954SCole Faust example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 270*c217d954SCole Faust cl_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example) ] + files_benchmark_examples, LIBS = test_env["LIBS"]) ] 271*c217d954SCole Faust arm_compute_benchmark_examples += cl_examples 272*c217d954SCole Faust 273*c217d954SCole Faust if test_env['gemm_tuner'] and test_env['opencl']: 274*c217d954SCole Faust gemm_tuner_examples = [] 275*c217d954SCole Faust gemm_tuner_common_options = test_env.Object(source="../examples/gemm_tuner/CommonGemmExampleOptions.cpp", target="CommonGemmExampleOptions") 276*c217d954SCole Faust files = Glob("%s/gemm_tuner/cl_*.cpp" % examples_folder) 277*c217d954SCole Faust for file in files: 278*c217d954SCole Faust example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 279*c217d954SCole Faust example = os.path.join("gemm_tuner", example) 280*c217d954SCole Faust gemm_tuner_examples += [ test_env.Program(example, [ test_env.Object(source=file, target=example), gemm_tuner_common_options ] + files_benchmark_examples, LIBS = test_env["LIBS"]) ] 281*c217d954SCole Faust arm_compute_benchmark_examples += gemm_tuner_examples 282*c217d954SCole Faust 283*c217d954SCole Faust # Graph examples 284*c217d954SCole Faust for file in Glob("%s/graph_*.cpp" % examples_folder ): 285*c217d954SCole Faust example = "benchmark_" + os.path.basename(os.path.splitext(str(file))[0]) 286*c217d954SCole Faust if env['os'] in ['android', 'macos', 'bare_metal'] or env['standalone']: 287*c217d954SCole Faust prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils, graph_params]+ files_benchmark_examples, LIBS = test_env["LIBS"], LINKFLAGS=test_env["LINKFLAGS"]+[load_whole_archive, arm_compute_lib, noload_whole_archive] + bm_link_flags + extra_link_flags) 288*c217d954SCole Faust arm_compute_benchmark_examples += [ prog ] 289*c217d954SCole Faust else: 290*c217d954SCole Faust #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies 291*c217d954SCole Faust prog = test_env.Program(example, [ test_env.Object(source=file, target=example), graph_utils, graph_params]+ files_benchmark_examples, LIBS = test_env["LIBS"] + ["arm_compute_graph"], LINKFLAGS=test_env["LINKFLAGS"]+['-Wl,--allow-shlib-undefined']) 292*c217d954SCole Faust arm_compute_benchmark_examples += [ prog ] 293*c217d954SCole Faust 294*c217d954SCole Faust arm_compute_benchmark_examples = install_bin(arm_compute_benchmark_examples) 295*c217d954SCole Faust Depends(arm_compute_benchmark_examples, arm_compute_test_framework) 296*c217d954SCole Faust Depends(arm_compute_benchmark_examples, arm_compute_lib) 297*c217d954SCole Faust Default(arm_compute_benchmark_examples) 298*c217d954SCole Faust Export('arm_compute_benchmark_examples') 299