|
1 | 1 | #!/usr/bin/env python3
|
2 | 2 |
|
| 3 | +import argparse |
3 | 4 | from itertools import chain
|
4 | 5 | import csv
|
5 | 6 | import glob
|
|
8 | 9 | import sys
|
9 | 10 | import timeit
|
10 | 11 |
|
| 12 | +parser = argparse.ArgumentParser(description="Run code_benches.") |
| 13 | +parser.add_argument("--target", |
| 14 | + help="Target triple to use, defaults to host triple. You probably want to " |
| 15 | + "set this if you're doing anything non-trivial.") |
| 16 | +parser.add_argument("--debug", action='store_true', |
| 17 | + help="Use debug build of silverfish. Defaults to most recent that exists.") |
| 18 | +parser.add_argument("--release", action='store_true', |
| 19 | + help="Use release build of silverfish. Defaults to most recent that exists.") |
| 20 | +parser.add_argument("--wasmception", action='store_true', |
| 21 | + help="Use Wasmception for the WebAssembly libc. Defaults to most recent that exists.") |
| 22 | +parser.add_argument("--wasi-sdk", action='store_true', |
| 23 | + help="Use WASI-SDK for the WebAssembly libc. Defaults to most recent that exists.") |
| 24 | +parser.add_argument("--custom", action='append_const', dest='suites', const='custom', |
| 25 | + help="Run custom benches.") |
| 26 | +parser.add_argument("--app", action='append_const', dest='suites', const='app', |
| 27 | + help="Run app benches.") |
| 28 | +parser.add_argument("--polybench", action='append_const', dest='suites', const='pb', |
| 29 | + help="Run polybench benches.") |
| 30 | +parser.add_argument("-o", "--output", default="benchmarks.csv", |
| 31 | + help="Destination csv file to write benchmark results. Defaults to %(default)r.") |
| 32 | +args = parser.parse_args() |
| 33 | +assert not (args.debug and args.release), "Both --debug and --release provided" |
| 34 | +assert not (args.wasi_sdk and args.wasmception), "Both --wask-sdk and --wasmception provided" |
| 35 | + |
11 | 36 | # Note: This is a major configuration option, you probably want to set this if you're doing anything non-trivial
|
12 |
| -SILVERFISH_TARGET = None |
| 37 | +SILVERFISH_TARGET = args.target |
13 | 38 | # SILVERFISH_TARGET = "thumbv7em-none-unknown-eabi"
|
14 | 39 | # SILVERFISH_TARGET = "x86_64-apple-macosx10.15.0"
|
15 | 40 | # SILVERFISH_TARGET = "x86_64-pc-linux-gnu"
|
16 | 41 |
|
17 | 42 | # CSV file name
|
18 |
| -CSV_NAME = "benchmarks.csv" |
| 43 | +CSV_NAME = args.output |
19 | 44 |
|
20 | 45 | # Make sure we're in the code_benches directory
|
21 | 46 | if os.path.dirname(sys.argv[0]):
|
|
27 | 52 |
|
28 | 53 | RUNTIME_PATH = ROOT_PATH + "/runtime"
|
29 | 54 |
|
30 |
| -SILVERFISH_RELEASE_PATH = ROOT_PATH + "/target/release/silverfish" |
31 |
| -SILVERFISH_DEBUG_PATH = ROOT_PATH + "/target/debug/silverfish" |
32 |
| -assert all(arg in {"--release", "--debug"} for arg in sys.argv[1:]) |
33 |
| -if "--release" in sys.argv: |
34 |
| - SILVERFISH_PATH = SILVERFISH_RELEASE_PATH |
35 |
| -elif "--debug" in sys.argv: |
36 |
| - SILVERFISH_PATH = SILVERFISH_DEBUG_PATH |
37 |
| -else: |
38 |
| - def getmtime_or_zero(path): |
| 55 | +def bestpath(paths): |
| 56 | + """ |
| 57 | + Determine best path based on: |
| 58 | + 1. exists |
| 59 | + 2. most recently modified |
| 60 | + """ |
| 61 | + def getmtime_or_zero(x): |
| 62 | + path, *_, use_this_one = x |
| 63 | + |
| 64 | + if use_this_one: |
| 65 | + return (1, 0) |
| 66 | + |
39 | 67 | try:
|
40 |
| - return os.path.getmtime(path) |
| 68 | + return (0, os.path.getmtime(path)) |
41 | 69 | except FileNotFoundError:
|
42 |
| - return 0 |
43 |
| - SILVERFISH_PATH = max( |
44 |
| - [SILVERFISH_RELEASE_PATH, SILVERFISH_DEBUG_PATH], |
45 |
| - key=getmtime_or_zero) |
| 70 | + return (0, 0) |
| 71 | + |
| 72 | + *best, _ = max(paths, key=getmtime_or_zero) |
| 73 | + return best |
| 74 | + |
| 75 | +SILVERFISH_RELEASE_PATH = ROOT_PATH + "/target/release/silverfish" |
| 76 | +SILVERFISH_DEBUG_PATH = ROOT_PATH + "/target/debug/silverfish" |
| 77 | + |
| 78 | +SILVERFISH_PATH, = bestpath([ |
| 79 | + (SILVERFISH_RELEASE_PATH, args.release), |
| 80 | + (SILVERFISH_DEBUG_PATH, args.debug), |
| 81 | +]) |
46 | 82 |
|
47 | 83 | WASMCEPTION_PATH = ROOT_PATH + "/wasmception"
|
| 84 | +WASMCEPTION_CLANG = WASMCEPTION_PATH + "/dist/bin/clang" |
| 85 | +WASMCEPTION_SYSROOT = WASMCEPTION_PATH + "/sysroot" |
| 86 | +WASMCEPTION_FLAGS = "--target=wasm32-unknown-unknown-wasm -nostartfiles -O3 -flto" |
| 87 | +WASMCEPTION_BACKING = "wasmception_backing.c" |
| 88 | + |
| 89 | +WASI_SDK_PATH = ROOT_PATH + "/wasi-sdk" |
| 90 | +WASI_SDK_CLANG = WASI_SDK_PATH + "/bin/clang" |
| 91 | +WASI_SDK_SYSROOT = WASI_SDK_PATH + "/share/wasi-sysroot" |
| 92 | +WASI_SDK_FLAGS = "--target=wasm32-wasi -mcpu=mvp -nostartfiles -O3 -flto" |
| 93 | +WASI_SDK_BACKING = "wasi_sdk_backing.c" |
| 94 | +WASI_SDK_URL = "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz" |
| 95 | + |
| 96 | +# download WASI-SDK if it is not in the expected path |
| 97 | +if args.wasi_sdk: |
| 98 | + if not os.path.exists(WASI_SDK_PATH): |
| 99 | + cwd = os.path.dirname(WASI_SDK_PATH) |
| 100 | + sp.check_call(['wget', WASI_SDK_URL, '-O', 'wasi-sdk.tar.gz'], cwd=cwd) |
| 101 | + sp.check_call(['mkdir', '-p', WASI_SDK_PATH], cwd=cwd) |
| 102 | + sp.check_call(['tar', 'xvfz', 'wasi-sdk.tar.gz', '--strip-components=1', '-C', WASI_SDK_PATH], cwd=cwd) |
| 103 | + sp.check_call(['rm', 'wasi-sdk.tar.gz'], cwd=cwd) |
| 104 | + |
| 105 | +# determine best toolchain to use |
| 106 | +WASM_CLANG, WASM_SYSROOT, WASM_FLAGS, WASM_BACKING = bestpath([ |
| 107 | + (WASMCEPTION_CLANG, WASMCEPTION_SYSROOT, WASMCEPTION_FLAGS, WASMCEPTION_BACKING, args.wasmception), |
| 108 | + (WASI_SDK_CLANG, WASI_SDK_SYSROOT, WASI_SDK_FLAGS, WASI_SDK_BACKING, args.wasi_sdk), |
| 109 | +]) |
48 | 110 |
|
49 |
| -# Our special WASM clang is under this wasmception path |
50 |
| -WASM_CLANG = WASMCEPTION_PATH + "/dist/bin/clang" |
51 | 111 | # These flags are all somewhat important -- see @Others for more information
|
52 | 112 | WASM_LINKER_FLAGS = "-Wl,--allow-undefined,-z,stack-size={stack_size},--no-threads,--stack-first,--no-entry,--export-all,--export=main,--export=dummy"
|
53 |
| -# Point WASM to our custom libc |
54 |
| -WASM_SYSROOT_FLAGS = "--sysroot={}/sysroot".format(WASMCEPTION_PATH) |
55 |
| -WASM_FLAGS = WASM_LINKER_FLAGS + " --target=wasm32-unknown-unknown-wasm -nostartfiles -O3 -flto " + WASM_SYSROOT_FLAGS |
| 113 | + |
| 114 | +WASM_FLAGS = ' '.join([ |
| 115 | + WASM_LINKER_FLAGS, |
| 116 | + WASM_FLAGS, |
| 117 | + "--sysroot={}".format(WASM_SYSROOT) |
| 118 | +]) |
56 | 119 |
|
57 | 120 | # What is the machine we're running on like?
|
58 | 121 | IS_64_BIT = sys.maxsize > 2**32
|
@@ -105,17 +168,18 @@ def sources(self):
|
105 | 168 | # == Custom Benchmarks ==
|
106 | 169 | Program("custom_binarytrees", [16], 2 ** 14),
|
107 | 170 | Program("custom_function_pointers", [], 2 ** 14),
|
108 |
| - Program("custom_libjpeg", [], 2 ** 15, |
109 |
| - custom_arguments=["-Wno-incompatible-library-redeclaration", "-Wno-implicit-function-declaration", |
110 |
| - "-Wno-shift-negative-value"]), |
| 171 | + #Program("custom_libjpeg", [], 2 ** 15, |
| 172 | + # custom_arguments=["-Wno-incompatible-library-redeclaration", "-Wno-implicit-function-declaration", |
| 173 | + # "-Wno-shift-negative-value"]), |
111 | 174 | Program("custom_matrix_multiply", [], 2 ** 14),
|
112 | 175 | Program("custom_memcmp", [], 2 ** 14),
|
113 |
| - Program("custom_sqlite", [], 2 ** 15, custom_arguments=["-DSQLITE_MUTEX_NOOP", "-ldl"]), |
| 176 | + # TODO need to remove dependency on posix headers |
| 177 | + #Program("custom_sqlite", [], 2 ** 15, custom_arguments=["-DSQLITE_MUTEX_NOOP", "-ldl"]), |
114 | 178 |
|
115 | 179 | # == Apps ==
|
116 | 180 | #Program("app_nn", [], 2 ** 14, custom_arguments=["-std=c99", "-Wno-unknown-attributes", "-DARM_MATH_CM3", "-I/Users/peachg/Projects/CMSIS_5_NN/CMSIS_5/CMSIS/DSP/Include", "-I/Users/peachg/Projects/CMSIS_5_NN/CMSIS_5/CMSIS/Core/Include", "-I/Users/peachg/Projects/CMSIS_5_NN/CMSIS_5/CMSIS/NN/Include"]),
|
117 | 181 | Program("app_pid", ["-std=c++11", "-Wall"], 2 ** 8, custom_arguments=[], is_cpp=True),
|
118 |
| - Program("app_tiny_ekf", ["-std=c++11", "-Wall"], 2 ** 14, custom_arguments=[], is_cpp=True), |
| 182 | + Program("app_tiny_ekf", ["-std=c++11", "-Wall"], 2 ** 14, custom_arguments=["-fno-rtti"], is_cpp=True), |
119 | 183 | Program("app_tinycrypt", [], 2 ** 15 + 2**14, custom_arguments=[ "-Wall", "-Wpedantic", "-Wno-gnu-zero-variadic-macro-arguments", "-std=c11", "-DENABLE_TESTS", "-I."]),
|
120 | 184 | # Program("app_v9", [], 2 ** 18, custom_arguments=[], do_lto=False),
|
121 | 185 |
|
@@ -251,8 +315,8 @@ def compile_wasm_to_executable(program, exe_postfix, memory_impl, unsafe_impls=F
|
251 | 315 | else:
|
252 | 316 | target_flag = "-target " + SILVERFISH_TARGET
|
253 | 317 |
|
254 |
| - command = "clang -lm {target} {opt} {bc_file} {runtime}/runtime.c {runtime}/libc/libc_backing.c {runtime}/libc/env.c {runtime}/memory/{mem_impl} -o bin/{pname}_{postfix}"\ |
255 |
| - .format(target=target_flag, opt=opt, bc_file=bc_file, pname=program.name, runtime=RUNTIME_PATH, mem_impl=memory_impl, postfix=exe_postfix) |
| 318 | + command = "clang -lm {target} {opt} {bc_file} {runtime}/runtime.c {runtime}/libc/{backing} {runtime}/libc/env.c {runtime}/memory/{mem_impl} -o bin/{pname}_{postfix}"\ |
| 319 | + .format(target=target_flag, opt=opt, bc_file=bc_file, pname=program.name, runtime=RUNTIME_PATH, backing=WASM_BACKING, mem_impl=memory_impl, postfix=exe_postfix) |
256 | 320 | print(command)
|
257 | 321 | sp.check_call(command, shell=True, cwd=program.name)
|
258 | 322 |
|
@@ -291,6 +355,9 @@ def output_run(base_time, execution_time):
|
291 | 355 | # print(p.name)
|
292 | 356 | # sp.call("wasm2wat {} | grep 'global (;1;) i32'".format(path), shell=True)
|
293 | 357 |
|
| 358 | + # Filter tests if explicit tests are requested |
| 359 | + if args.suites: |
| 360 | + programs = [p for p in programs if any(p.name.startswith(suite) for suite in args.suites)] |
294 | 361 |
|
295 | 362 | # Compile all our programs
|
296 | 363 | for i, p in enumerate(programs):
|
|
0 commit comments