Skip to content

Commit fa6e003

Browse files
authored
Add support for WASI-SDK (v8) (#19)
* Modified code_benches to use wasi-sdk-8.0 * Added minimal WASI implementation as needed by the code_benches * Fixed rtti issue in app_tiny_ekf code bench * Cleaned up wasi-sdk specific libc_backing - Removed wasmception integration for now - Consistent readv/writev implementation - Changed some magic numbers to enums - Added predeclaration of (get|set)_(i8|16|32|64|f32|f64) stubs - Consistent offset type in get/set stubs - Moved env_(sin|cos) to runtime/libc/env.c * Added a couple other WASI functions These aren't needed to pass code_benches, but may be used depending on what functions the wasm binary uses (unlink -> wasi_unstable_path_unlink_file for example). Note this the WASI API backing is still not exhaustive. * Added support for float copysign/ceil/nearest These were emitted by wasi-sdk-8.0. * Renamed libc_backing.c -> wasi_sdk_backing.c * Renamed libc_backing.c -> wasmception_backing.c * Added handling of both wasmception+wasi-sdk in code_benches/run.py * Adopted argparse in code_benches/run.py And some cleanup around wasm-libc selection * Added test filtering to let you run fewer code benches Currently: - code_benches/run.py --polybench - code_benches/run.py --app - code_benches/run.py --custom * Deduplicated memory-instruction implementations into runtime The memory instruction implementation is just a thing wrapper around the memory_size/memory_expand API in aWsm. * Better WASI errno handling, now with proper conversions from system errno * Added exclusivity asserts for some of the code_benches/run.py args * Added script for downloading WASI-SDK in run.py Currently fixed as WASI-SDK v8, downloads and untars if --wasi-sdk is specified and WASI_SDK_PATH does not exist.
1 parent fa5d9ee commit fa6e003

File tree

13 files changed

+789
-90
lines changed

13 files changed

+789
-90
lines changed

code_benches/run.py

Lines changed: 95 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python3
22

3+
import argparse
34
from itertools import chain
45
import csv
56
import glob
@@ -8,14 +9,38 @@
89
import sys
910
import timeit
1011

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+
1136
# 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
1338
# SILVERFISH_TARGET = "thumbv7em-none-unknown-eabi"
1439
# SILVERFISH_TARGET = "x86_64-apple-macosx10.15.0"
1540
# SILVERFISH_TARGET = "x86_64-pc-linux-gnu"
1641

1742
# CSV file name
18-
CSV_NAME = "benchmarks.csv"
43+
CSV_NAME = args.output
1944

2045
# Make sure we're in the code_benches directory
2146
if os.path.dirname(sys.argv[0]):
@@ -27,32 +52,70 @@
2752

2853
RUNTIME_PATH = ROOT_PATH + "/runtime"
2954

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+
3967
try:
40-
return os.path.getmtime(path)
68+
return (0, os.path.getmtime(path))
4169
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+
])
4682

4783
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+
])
48110

49-
# Our special WASM clang is under this wasmception path
50-
WASM_CLANG = WASMCEPTION_PATH + "/dist/bin/clang"
51111
# These flags are all somewhat important -- see @Others for more information
52112
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+
])
56119

57120
# What is the machine we're running on like?
58121
IS_64_BIT = sys.maxsize > 2**32
@@ -105,17 +168,18 @@ def sources(self):
105168
# == Custom Benchmarks ==
106169
Program("custom_binarytrees", [16], 2 ** 14),
107170
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"]),
111174
Program("custom_matrix_multiply", [], 2 ** 14),
112175
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"]),
114178

115179
# == Apps ==
116180
#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"]),
117181
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),
119183
Program("app_tinycrypt", [], 2 ** 15 + 2**14, custom_arguments=[ "-Wall", "-Wpedantic", "-Wno-gnu-zero-variadic-macro-arguments", "-std=c11", "-DENABLE_TESTS", "-I."]),
120184
# Program("app_v9", [], 2 ** 18, custom_arguments=[], do_lto=False),
121185

@@ -251,8 +315,8 @@ def compile_wasm_to_executable(program, exe_postfix, memory_impl, unsafe_impls=F
251315
else:
252316
target_flag = "-target " + SILVERFISH_TARGET
253317

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)
256320
print(command)
257321
sp.check_call(command, shell=True, cwd=program.name)
258322

@@ -291,6 +355,9 @@ def output_run(base_time, execution_time):
291355
# print(p.name)
292356
# sp.call("wasm2wat {} | grep 'global (;1;) i32'".format(path), shell=True)
293357

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)]
294361

295362
# Compile all our programs
296363
for i, p in enumerate(programs):

runtime/libc/env.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,6 @@ env_do_barrier(i32 x)
120120
}
121121

122122
// Get cycles logic
123-
124-
125123
INLINE unsigned long long
126124
env_getcycles(void)
127125
{
@@ -147,3 +145,15 @@ env_getcycles(void)
147145

148146
#endif
149147
}
148+
149+
// Floating point routines
150+
// TODO: Do a fair comparison between musl and wasm-musl
151+
INLINE double
152+
env_sin(double d) {
153+
return sin(d);
154+
}
155+
156+
INLINE double
157+
env_cos(double d) {
158+
return cos(d);
159+
}

0 commit comments

Comments
 (0)