diff --git a/scripts/build-firmware-linux.sh b/scripts/build-firmware-linux.sh index 219b0d2..77f59b7 100644 --- a/scripts/build-firmware-linux.sh +++ b/scripts/build-firmware-linux.sh @@ -47,8 +47,8 @@ if ! [ -f "$DEFAULT_DTB_FILE" ]; then echo "Default device tree not found: $DEFAULT_DTB_FILE" >&2 exit 1 fi -dd if="$STARTUP_FILE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" -dd if="$DEFAULT_DTB_FILE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$KILOBYTE" seek="$DTB_OFFSET_KB" conv=notrunc -dd if="$SBI_BUILD_DIR/build/platform/generic/firmware/fw_jump.bin" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$KILOBYTE" seek="$SBI_OFFSET_KB" conv=notrunc -dd if="$KERNEL_IMAGE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$MEGABYTE" seek="$KERNEL_OFFSET_MB" conv=notrunc -dd if="$CPIO_ARCHIVE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$MEGABYTE" seek="$INITRAMFS_OFFSET_MB" conv=notrunc +dd if="$STARTUP_FILE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" status=none +dd if="$DEFAULT_DTB_FILE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$KILOBYTE" seek="$DTB_OFFSET_KB" conv=notrunc status=none +dd if="$SBI_BUILD_DIR/build/platform/generic/firmware/fw_jump.bin" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$KILOBYTE" seek="$SBI_OFFSET_KB" conv=notrunc status=none +dd if="$KERNEL_IMAGE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$MEGABYTE" seek="$KERNEL_OFFSET_MB" conv=notrunc status=none +dd if="$CPIO_ARCHIVE" of="$WORKLOAD_BUILD_DIR/fw_payload.bin" bs="$MEGABYTE" seek="$INITRAMFS_OFFSET_MB" conv=notrunc status=none diff --git a/scripts/build-workload-linux.sh b/scripts/build-workload-linux.sh index 040002f..ee9df27 100644 --- a/scripts/build-workload-linux.sh +++ b/scripts/build-workload-linux.sh @@ -31,7 +31,7 @@ pack-cpio() { local cpio_file="$2" rm -f "$cpio_file" cd "$root_dir" - find . | fakeroot cpio -o -H newc > "$cpio_file" + find . | fakeroot cpio -o -H newc > "$cpio_file" 2>/dev/null } populate-src-dir diff --git a/workloads/linux/spec2006/README.md b/workloads/linux/spec2006/README.md new file mode 100644 index 0000000..e140e44 --- /dev/null +++ b/workloads/linux/spec2006/README.md @@ -0,0 +1,177 @@ +# SPEC CPU2006 Linux workload + +`workloads/linux/spec2006` now builds SPEC CPU2006 workloads with the original +SPEC tools (`runspec`) against an external SPEC installation. + +## Build one case + +Either point `SPEC` at the SPEC tree: + +```sh +make linux/spec2006 BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN +``` + +or pass `SPEC2006` explicitly: + +```sh +make linux/spec2006 BENCH=astar INPUT=biglakes SPEC2006=/path/to/cpu2006 -jN +``` + +`BENCH` may also be a full case name from `spec06.json`: + +```sh +make linux/spec2006 BENCH=astar_biglakes SPEC=/path/to/cpu2006 -jN +``` + +The build flow is: + +1. Generate a build-local SPEC cfg copy under the case build directory. +2. Inject `output_root` into that cfg so SPEC build artifacts stay under this + repository instead of modifying the original SPEC installation. +3. Run `runspec --action build`. +4. Export the built SPEC ELF, package the benchmark plus input files into the + Linux rootfs, and produce: + +```text +build/linux-workloads/spec2006//fw_payload.bin +``` + +## Build and export images + +Export all selected cases to `build/images/spec2006`: + +```sh +make spec2006-images SPEC=/path/to/cpu2006 -jN +``` + +By default, export builds only `ref` cases. Select another input set with +`SPEC2006_INPUT`; use `all` to export every configured case: + +```sh +make spec2006-images SPEC=/path/to/cpu2006 SPEC2006_INPUT=test -jN +make spec2006-images SPEC=/path/to/cpu2006 SPEC2006_INPUT=all -jN +``` + +Selected SPEC cases are built one by one to avoid concurrent `runspec` +instances contending on shared temporary state inside the SPEC tool tree. + +The export directory is organized as: + +```text +build/images/spec2006/ + bin/.fw_payload.bin + kernel/.Image + elf/.elf + gcpt/gcpt.elf + gcpt/gcpt.bin + cfg/ +``` + +`gcpt/` and `cfg/` are copied once per export tree, not once per case. + +Override the destination with `SPEC2006_IMAGE_DIR=/path/to/image`. + +## Build ELF only + +Build one case without packaging it into the Linux rootfs: + +```sh +make spec2006-elf BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN +``` + +This writes: + +```text +build/linux-workloads/spec2006//elf/.elf +``` + +Build every selected case as ELF only: + +```sh +make spec2006-elfs SPEC=/path/to/cpu2006 SPEC2006_INPUT=ref -jN +make spec2006-elfs SPEC=/path/to/cpu2006 SPEC2006_INPUT=all -jN +``` + +If you only want the standalone ELF build flow, you can run it from this +directory without the top-level Makefile: + +```sh +cd workloads/linux/spec2006 +make -f rules.mk spec2006-elf BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN +make -f rules.mk spec2006-elfs SPEC=/path/to/cpu2006 SPEC2006_INPUT=all -jN +``` + +## Configuration + +The default SPEC cfg is: + +```text +workloads/linux/spec2006/riscv_gcc15_base.cfg +``` + +Override it with: + +```sh +make linux/spec2006 BENCH=bzip2_source \ + SPEC=/path/to/cpu2006 \ + SPEC2006_CFG=/path/to/other.cfg \ + -jN +``` + +The default tuning level is `base`. Override it with `SPEC2006_TUNE=peak`. + +Case definitions remain in `spec06.json`; they describe the benchmark name, +required input files/directories, command-line arguments, and input set. + +## Toolchain and jemalloc + +The default cross prefix is: + +```text +riscv64-unknown-linux-gnu- +``` + +Override it with `SPEC2006_CROSS_COMPILE=/path/to/bin/riscv64-unknown-linux-gnu-`. + +The helper derives the toolchain root from `SPEC2006_CROSS_COMPILE` and exports +the env vars expected by `riscv_gcc15_base.cfg`: + +- `LLVM_INSTALL_PATH` +- `GNU_RISCV64_PATH` +- `JEMALLOC_INSTALL_PATH` + +If you need to override them directly, use: + +- `SPEC2006_COMPILER_ROOT` +- `SPEC2006_GNU_TOOLCHAIN_ROOT` +- `SPEC2006_JEMALLOC_ROOT` + +If the selected cfg references jemalloc and the library is missing, the build +automatically clones upstream jemalloc and installs it into: + +```text +build/linux-workloads/spec2006/jemalloc/install +``` + +Override the install prefix with `SPEC2006_JEMALLOC_ROOT` or +`JEMALLOC_INSTALL_PATH`. Override the jemalloc source/checkout with: + +- `SPEC2006_JEMALLOC_REPO` +- `SPEC2006_JEMALLOC_COMMIT` +- `SPEC2006_JEMALLOC_CONFIGURE_HOST` +- `SPEC2006_DOWNLOAD_RETRIES` + +## Logs + +SPEC2006 builds keep console output concise. Detailed logs are written to: + +- `build/linux-workloads/spec2006//logs/build.log` +- `build/linux-workloads/spec2006/jemalloc/build.log` + +## Notes + +- The original SPEC tree is used read-only for sources and input data. +- Build logs, copied cfg files, build directories, and built executables are + redirected into the case-local `runspec-output` directory via `output_root`. +- The source cfg in this repository is never passed to `runspec` directly; + `runspec` is allowed to rewrite only the generated local cfg copy. diff --git a/workloads/linux/spec2006/build.sh b/workloads/linux/spec2006/build.sh new file mode 100644 index 0000000..999991f --- /dev/null +++ b/workloads/linux/spec2006/build.sh @@ -0,0 +1,228 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${SPEC2006_CASE:?SPEC2006_CASE is required}" +: "${SPEC2006:?SPEC2006 is required}" +: "${SPEC2006_CASE_CONFIG:?SPEC2006_CASE_CONFIG is required}" +: "${SPEC2006_CFG:?SPEC2006_CFG is required}" +: "${CROSS_COMPILE:=riscv64-unknown-linux-gnu-}" +: "${SPEC2006_TUNE:=base}" +: "${SPEC2006_JOBS:=$(nproc)}" +: "${SPEC2006_JEMALLOC_REPO:=https://github.com/jemalloc/jemalloc.git}" +: "${SPEC2006_JEMALLOC_COMMIT:=da66aa391f853ccf2300845b3873cc8f1cf48f2d}" +: "${SPEC2006_DOWNLOAD_RETRIES:=3}" +: "${SPEC2006_ELF_ONLY:=false}" +: "${SPEC2006_LOG_DIR:=$WORKLOAD_BUILD_DIR/logs}" +: "${PKG_DIR:=$WORKLOAD_BUILD_DIR/package}" + +SPEC2006_JEMALLOC_ROOT="${SPEC2006_JEMALLOC_ROOT:-${JEMALLOC_INSTALL_PATH:-}}" + +jemalloc_lock_dir="" +cleanup() { + if [ -n "$jemalloc_lock_dir" ]; then + rmdir "$jemalloc_lock_dir" 2>/dev/null || true + fi +} +trap cleanup EXIT + +mkdir -p "$SPEC2006_LOG_DIR" + +spec2006_progress_prefix() { + local k="${SPEC2006_PROGRESS_K:-1}" + local n="${SPEC2006_PROGRESS_N:-1}" + printf '[spec2006 %s/%s]' "$k" "$n" +} + +status() { + printf '%s %s\n' "$(spec2006_progress_prefix)" "$*" +} + +show_log_tail() { + local log_file="$1" + if [ -f "$log_file" ]; then + echo "$(spec2006_progress_prefix) Last 40 lines from $log_file:" >&2 + tail -n 40 "$log_file" >&2 || true + fi +} + +retry() { + local attempt=1 + while true; do + if "$@"; then + return 0 + fi + if [ "$attempt" -ge "$SPEC2006_DOWNLOAD_RETRIES" ]; then + return 1 + fi + printf '%s Retrying failed command (%s/%s): %s\n' \ + "$(spec2006_progress_prefix)" \ + "$attempt" \ + "$SPEC2006_DOWNLOAD_RETRIES" \ + "$*" >&2 + sleep $((attempt * 2)) + attempt=$((attempt + 1)) + done +} + +retry_git_clone() { + local repo="$1" + local dest="$2" + local attempt=1 + while true; do + rm -rf "$dest" + if git clone "$repo" "$dest"; then + return 0 + fi + if [ "$attempt" -ge "$SPEC2006_DOWNLOAD_RETRIES" ]; then + return 1 + fi + printf '%s Retrying failed git clone (%s/%s): %s\n' \ + "$(spec2006_progress_prefix)" \ + "$attempt" \ + "$SPEC2006_DOWNLOAD_RETRIES" \ + "$repo" >&2 + sleep $((attempt * 2)) + attempt=$((attempt + 1)) + done +} + +prepare_git_checkout() { + local repo="$1" + local commit="$2" + local dest="$3" + local current_commit target_commit + + if [ ! -d "$dest/.git" ]; then + retry_git_clone "$repo" "$dest" + else + git -C "$dest" remote set-url origin "$repo" + fi + + if ! git -C "$dest" cat-file -e "$commit^{commit}" 2>/dev/null; then + retry git -C "$dest" fetch --tags origin + fi + + current_commit="$(git -C "$dest" rev-parse HEAD 2>/dev/null || true)" + target_commit="$(git -C "$dest" rev-parse "$commit")" + if [ "$current_commit" != "$target_commit" ]; then + git -C "$dest" checkout --detach "$commit" + fi +} + +is_true() { + case "$1" in + 1|true|yes|on) return 0 ;; + *) return 1 ;; + esac +} + +cfg_requires_jemalloc() { + grep -Eq 'JEMALLOC_PATH|-ljemalloc' "$SPEC2006_CFG" +} + +resolve_jemalloc_root() { + if [ -n "$SPEC2006_JEMALLOC_ROOT" ]; then + realpath -m "$SPEC2006_JEMALLOC_ROOT" + else + realpath -m "$(dirname "$WORKLOAD_BUILD_DIR")/jemalloc/install" + fi +} + +resolve_jemalloc_host() { + if [ -n "${SPEC2006_JEMALLOC_CONFIGURE_HOST:-}" ]; then + printf '%s\n' "$SPEC2006_JEMALLOC_CONFIGURE_HOST" + else + "${CROSS_COMPILE}gcc" -dumpmachine + fi +} + +prepare_jemalloc() { + local base_dir source_dir prefix host log_file + base_dir="$(realpath -m "$(dirname "$WORKLOAD_BUILD_DIR")/jemalloc")" + source_dir="$base_dir/source" + prefix="$(resolve_jemalloc_root)" + host="$(resolve_jemalloc_host)" + log_file="$base_dir/build.log" + + if [ -f "$prefix/lib/libjemalloc.a" ]; then + SPEC2006_JEMALLOC_ROOT="$prefix" + export SPEC2006_JEMALLOC_ROOT + status "Using cached jemalloc: $prefix" + return + fi + + jemalloc_lock_dir="$base_dir/.lock" + mkdir -p "$base_dir" + while ! mkdir "$jemalloc_lock_dir" 2>/dev/null; do + sleep 1 + done + + if [ -f "$prefix/lib/libjemalloc.a" ]; then + rmdir "$jemalloc_lock_dir" + jemalloc_lock_dir="" + SPEC2006_JEMALLOC_ROOT="$prefix" + export SPEC2006_JEMALLOC_ROOT + status "Using cached jemalloc: $prefix" + return + fi + + status "Preparing jemalloc (log: $log_file)" + : > "$log_file" + + if ! { + echo "# jemalloc repo: $SPEC2006_JEMALLOC_REPO" + echo "# jemalloc commit: $SPEC2006_JEMALLOC_COMMIT" + echo "# install prefix: $prefix" + echo "# configure host: $host" + prepare_git_checkout "$SPEC2006_JEMALLOC_REPO" "$SPEC2006_JEMALLOC_COMMIT" "$source_dir" + + ( + cd "$source_dir" + CC="${CROSS_COMPILE}gcc" \ + CXX="${CROSS_COMPILE}g++" \ + AR="${CROSS_COMPILE}ar" \ + LD="${CROSS_COMPILE}ld" \ + RANLIB="${CROSS_COMPILE}ranlib" \ + STRIP="${CROSS_COMPILE}strip" \ + ./autogen.sh --prefix="$prefix" --host="$host" + make -j"$SPEC2006_JOBS" + make install + ) + } >>"$log_file" 2>&1; then + echo "$(spec2006_progress_prefix) jemalloc build failed; see $log_file" >&2 + show_log_tail "$log_file" + return 1 + fi + + rmdir "$jemalloc_lock_dir" + jemalloc_lock_dir="" + + SPEC2006_JEMALLOC_ROOT="$prefix" + export SPEC2006_JEMALLOC_ROOT + status "jemalloc ready: $prefix" +} + +if cfg_requires_jemalloc; then + prepare_jemalloc +fi + +python_args=() +if is_true "$SPEC2006_ELF_ONLY"; then + python_args+=(--elf-only) +fi + +python3 "$WORKLOAD_DIR/spec2006-package.py" \ + --case "$SPEC2006_CASE" \ + --cases-config "$SPEC2006_CASE_CONFIG" \ + --spec "$SPEC2006" \ + --spec-config "$SPEC2006_CFG" \ + --pkg-dir "$PKG_DIR" \ + --out-dir "$WORKLOAD_BUILD_DIR" \ + --cross-compile "$CROSS_COMPILE" \ + --compiler-root "${SPEC2006_COMPILER_ROOT:-}" \ + --gnu-toolchain-root "${SPEC2006_GNU_TOOLCHAIN_ROOT:-}" \ + --jemalloc-root "${SPEC2006_JEMALLOC_ROOT:-}" \ + --log-dir "$SPEC2006_LOG_DIR" \ + --tune "$SPEC2006_TUNE" \ + --jobs "$SPEC2006_JOBS" \ + "${python_args[@]}" diff --git a/workloads/linux/spec2006/riscv_gcc15_base.cfg b/workloads/linux/spec2006/riscv_gcc15_base.cfg new file mode 100644 index 0000000..e44394d --- /dev/null +++ b/workloads/linux/spec2006/riscv_gcc15_base.cfg @@ -0,0 +1,195 @@ +#################################################################### +# RISC-V Config file for SPEC CPU2006 + +# Please see http://www.spec.org/cpu2006/Docs/config.html (also available in +# the Docs directory of your SPEC tree) for details on config file setup. The +# config.html page has a list of all of the fields required for a full +# publication ofresults. + +##################################################################### +# System Under Test (SUT) Section + +# If it affects performance, you need to describe it, either in the +# pre-defined fields or by adding it to the notes section. Replace the +# setting below with the ones that match your machine. + +####################################################################### + +# Tester Description +test_sponsor = OpenXiangShan +tester = OpenXiangShan + +# System Description +hw_model = XiangShan Kunminghu +hw_memory = 2 GiB DDR +hw_disk = None +hw_vendor = Institute of Computing Technology, Chinese Academy of Sciences +hw_other = N/A +hw_avail = Dec-9999 + +# CPU description +# See http://www.spec.org/cpu2006/Docs/runrules.html#cpucount +# for a discussion of these fields + +hw_cpu_name = XiangShan Kunminghu +hw_cpu_char = +hw_cpu_mhz = 3000 +hw_fpu = Integrated +hw_nchips = 1 +hw_ncores = 1 +hw_ncoresperchip = 1 +hw_nthreadspercore = 1 +hw_ncpuorder = N/A + +# Cache description + +hw_pcache = N/A +hw_scache = N/A +hw_tcache = N/A +hw_ocache = N/A + +# Tester description + +license_num = 0 + +# Operating system, file system + +sw_os = Linux with OpenSBI firmware boot +sw_file = initramfs rootfs +sw_state = Single-user +sw_other = None + +## SW config +sw_compiler = gcc, g++ 15.2.0 +sw_avail = Apr-2026 +sw_base_ptrsize = 64-bit +sw_peak_ptrsize = 64-bit + +####################################################################### +# End of SUT section +# If this config file were to be applied to several SUTs, edits would +# be needed only ABOVE this point. +###################################################################### + +ignore_errors = yes +tune = base +basepeak = no +ext = riscv_gcc15_base +teeout = yes +teerunout = yes +output_format = asc, csv, html +makeflags = -j64 + +reportable = yes + +default=default=default=default: +##################################################################### +# +# Compiler selection +# +##################################################################### + +COMPILER_PATH = ${LLVM_INSTALL_PATH} +JEMALLOC_PATH = ${JEMALLOC_INSTALL_PATH} +GCC_TOOLCHAIN_PATH = ${GNU_RISCV64_PATH} + +JEMALLOC_LIBS = -L$(JEMALLOC_PATH)/lib -ljemalloc -lm +# jemalloc also exports C++ operator new/delete. Some SPEC C++ benchmarks +# define replaceable allocation symbols in their own objects, so keep +# muldefs enabled for the final static link. +STATIC_LDFLAGS = -z muldefs -static + +CC = $(COMPILER_PATH)/bin/riscv64-unknown-linux-gnu-gcc -std=gnu89 +CXX = $(COMPILER_PATH)/bin/riscv64-unknown-linux-gnu-g++ +FC = $(COMPILER_PATH)/bin/riscv64-unknown-linux-gnu-gfortran + +##################################################################### +# Optimization +##################################################################### + +int=base=default: + COPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=off -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + CXXOPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=off -std=c++98 -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + + EXTRA_LIBS = $(JEMALLOC_LIBS) + EXTRA_LDFLAGS = $(STATIC_LDFLAGS) + +fp=base=default: + COPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + CXXOPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -std=c++98 -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + FOPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + + EXTRA_LIBS = $(JEMALLOC_LIBS) + EXTRA_LDFLAGS = $(STATIC_LDFLAGS) + +int=peak=default: + COPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=off -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + CXXOPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=off -std=c++98 -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + + EXTRA_LIBS = $(JEMALLOC_LIBS) + EXTRA_LDFLAGS = $(STATIC_LDFLAGS) + +fp=peak=default: + COPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + CXXOPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -std=c++98 -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + FOPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -ffast-math -flto -ffp-contract=fast -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + + EXTRA_LIBS = $(JEMALLOC_LIBS) + EXTRA_LDFLAGS = $(STATIC_LDFLAGS) + + +##################################################################### +# 32/64 bit Portability Flags - all +##################################################################### + +default=default=default=default: +PORTABILITY = -DSPEC_CPU_LP64 + +##################################################################### +# Portability Flags +##################################################################### + +400.perlbench=default=default=default: +CPORTABILITY = -DSPEC_CPU_LINUX_X64 -std=gnu89 + +401.bzip2=default=default=default: +CPORTABILITY = -std=gnu89 + +416.gamess=default=default=default: +CPORTABILITY = -funconstrained-commons +FPORTABILITY = -std=legacy -funconstrained-commons -fno-strict-aliasing + +436.cactusADM=default=default=default: +CPORTABILITY = -std=gnu17 + +462.libquantum=default=default=default: +CPORTABILITY = -DSPEC_CPU_LINUX + +464.h264ref=default=default=default: +CPORTABILITY = -fsigned-char + +482.sphinx3=default=default=default: +CPORTABILITY = -fsigned-char + +483.xalancbmk=default=default=default: +CXXPORTABILITY = -DSPEC_CPU_LINUX -include cstring -Wno-c++11-narrowing -Wno-template-body + +453.povray=base=default=default: +CXXOPTIMIZE = -static -O3 -march=rv64gc_zba_zbb_zbs_zbc -flto -ffp-contract=fast -std=c++98 -fno-tree-vectorize -fno-tree-loop-vectorize -fno-strict-aliasing + +453.povray=peak=default=default: +CXXOPTIMIZE = -static -O3 -march=rv64gcv_zba_zbb_zbs_zbc -flto -ffp-contract=fast -std=c++98 -ftree-vectorize -ftree-loop-vectorize -fno-strict-aliasing + +481.wrf=default=default=default: +CPORTABILITY = -DSPEC_CPU_CASE_FLAG -DSPEC_CPU_LINUX +FPORTABILITY = -std=legacy -fallow-argument-mismatch + +447.dealII=default=default=default: +CXXPORTABILITY = -fpermissive -include cstring -std=c++11 + +450.soplex=default=default=default: +CXXPORTABILITY = -std=gnu++98 + +##################################################################### +# Notes +##################################################################### diff --git a/workloads/linux/spec2006/rules.mk b/workloads/linux/spec2006/rules.mk new file mode 100644 index 0000000..d889bff --- /dev/null +++ b/workloads/linux/spec2006/rules.mk @@ -0,0 +1,180 @@ +SPEC2006_WORKLOAD_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +SPEC2006_REPO_ROOT := $(abspath $(SPEC2006_WORKLOAD_DIR)/../../..) +SPEC2006_SELF_MAKEFILE := $(SPEC2006_WORKLOAD_DIR)/rules.mk +SPEC2006_ROOT_MAKEFILE := $(SPEC2006_REPO_ROOT)/Makefile +SPEC2006_RECURSE_MAKEFILE := $(if $(filter $(SPEC2006_ROOT_MAKEFILE),$(abspath $(firstword $(MAKEFILE_LIST)))),$(SPEC2006_ROOT_MAKEFILE),$(SPEC2006_SELF_MAKEFILE)) +SPEC2006_SCRIPTS_DIR := $(SPEC2006_REPO_ROOT)/scripts +SPEC2006_DTS_DIR := $(SPEC2006_REPO_ROOT)/dts +SPEC2006_BUILD_DIR ?= $(SPEC2006_REPO_ROOT)/build/linux-workloads/spec2006 +SPEC2006_CASE_CONFIG := $(SPEC2006_WORKLOAD_DIR)/spec06.json +SPEC2006_CFG ?= $(SPEC2006_WORKLOAD_DIR)/riscv_gcc15_base.cfg +SPEC2006_HELPER := $(SPEC2006_WORKLOAD_DIR)/spec2006-package.py +SPEC2006_IMAGE_DIR ?= $(SPEC2006_REPO_ROOT)/build/images/spec2006 +SPEC2006_SPEC_ROOT := $(if $(SPEC2006),$(SPEC2006),$(SPEC)) +SPEC2006_CROSS_COMPILE ?= riscv64-unknown-linux-gnu- +SPEC2006_COMPILER_ROOT ?= +SPEC2006_GNU_TOOLCHAIN_ROOT ?= +SPEC2006_JEMALLOC_ROOT ?= +SPEC2006_DEFAULT_DTB ?= xiangshan-fpga-noAIA +SPEC2006_TUNE ?= base +SPEC2006_JOBS ?= $(shell nproc) +SPEC2006_INPUT ?= ref +SPEC2006_PROGRESS_K ?= 1 +SPEC2006_PROGRESS_N ?= 1 +SPEC2006_PROGRESS_PREFIX := [spec2006 $(SPEC2006_PROGRESS_K)/$(SPEC2006_PROGRESS_N)] +SPEC2006_BUILDROOT_DIR ?= $(if $(BUILDROOT_DIR),$(BUILDROOT_DIR),$(SPEC2006_REPO_ROOT)/build/buildroot) +SPEC2006_LINUX_IMAGE ?= $(if $(LINUX_IMAGE),$(LINUX_IMAGE),$(SPEC2006_BUILDROOT_DIR)/output/images/Image) +SPEC2006_GCPT_ELF ?= $(if $(GCPT_ELF),$(GCPT_ELF),$(SPEC2006_REPO_ROOT)/build/LibCheckpointAlpha/build/gcpt) +SPEC2006_GCPT_BIN ?= $(if $(GCPT_BIN),$(GCPT_BIN),$(SPEC2006_REPO_ROOT)/build/LibCheckpointAlpha/build/gcpt.bin) +SPEC2006_SBI_BUILD_DIR ?= $(if $(SBI_BUILD_DIR),$(SBI_BUILD_DIR),$(SPEC2006_REPO_ROOT)/build/opensbi) +SPEC2006_SBI_BIN ?= $(if $(SBI_BIN),$(SBI_BIN),$(SPEC2006_SBI_BUILD_DIR)/build/platform/generic/firmware/fw_jump.bin) +SPEC2006_BUILDROOT_CROSS_COMPILE ?= $(SPEC2006_BUILDROOT_DIR)/output/host/bin/riscv64-linux- +SPEC2006_DTC ?= $(SPEC2006_BUILDROOT_DIR)/output/host/bin/dtc +SPEC2006_CASE := $(if $(INPUT),$(BENCH)_$(INPUT),$(BENCH)) +SPEC2006_ALL_CASES := $(shell python3 $(SPEC2006_HELPER) --cases-config $(SPEC2006_CASE_CONFIG) --list-cases 2>/dev/null) +SPEC2006_SELECTED_CASES := $(shell python3 $(SPEC2006_HELPER) --cases-config $(SPEC2006_CASE_CONFIG) --list-cases --input-set $(SPEC2006_INPUT) 2>/dev/null) +SPEC2006_IMAGE_CASES := $(SPEC2006_SELECTED_CASES) +SPEC2006_ELF_TARGETS := $(foreach case,$(SPEC2006_SELECTED_CASES),$(SPEC2006_BUILD_DIR)/$(case)/elf/$(case).elf) +SPEC2006_DTS_SOURCES := $(shell find $(SPEC2006_DTS_DIR) -type f 2>/dev/null) + +WORKLOAD_DIRS += $(SPEC2006_BUILD_DIR) + +spec2006-check-spec-dir: + @if [ -z "$(SPEC2006_SPEC_ROOT)" ]; then \ + echo "SPEC or SPEC2006 is required, for example:"; \ + echo " make linux/spec2006 BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN"; \ + echo " make linux/spec2006 BENCH=astar INPUT=biglakes SPEC2006=/path/to/cpu2006 -jN"; \ + exit 1; \ + fi; \ + if ! [ -d "$(SPEC2006_SPEC_ROOT)" ]; then \ + echo "SPEC path does not exist or is not a directory: $(SPEC2006_SPEC_ROOT)"; \ + exit 1; \ + fi; \ + if ! [ -x "$(SPEC2006_SPEC_ROOT)/bin/runspec" ]; then \ + echo "runspec not found under $(SPEC2006_SPEC_ROOT)/bin/runspec"; \ + exit 1; \ + fi; \ + if ! [ -f "$(SPEC2006_CFG)" ]; then \ + echo "SPEC2006 cfg does not exist: $(SPEC2006_CFG)"; \ + exit 1; \ + fi; \ + if ! [ -f "$(SPEC2006_CASE_CONFIG)" ]; then \ + echo "SPEC2006 case config does not exist: $(SPEC2006_CASE_CONFIG)"; \ + exit 1; \ + fi; \ + case "$(SPEC2006_INPUT)" in \ + ref|train|test|all) ;; \ + *) echo "SPEC2006_INPUT must be one of: ref, train, test, all"; exit 1 ;; \ + esac + +define add_spec2006_case +$(SPEC2006_BUILD_DIR)/$(1)/download/sentinel: + @mkdir -p $$(@D) + @touch $$@ + +$(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf: spec2006-check-spec-dir $$(SPEC2006_HELPER) $$(SPEC2006_WORKLOAD_DIR)/build.sh $$(SPEC2006_CASE_CONFIG) $$(SPEC2006_CFG) + @mkdir -p "$$(dir $$@)" + @WORKLOAD_DIR="$$(abspath $$(SPEC2006_WORKLOAD_DIR))" \ + WORKLOAD_BUILD_DIR="$$(abspath $(SPEC2006_BUILD_DIR)/$(1))" \ + PKG_DIR="$$(abspath $(SPEC2006_BUILD_DIR)/$(1)/package)" \ + CROSS_COMPILE="$$(SPEC2006_CROSS_COMPILE)" \ + SPEC2006_PROGRESS_K="$$(SPEC2006_PROGRESS_K)" \ + SPEC2006_PROGRESS_N="$$(SPEC2006_PROGRESS_N)" \ + SPEC2006_CASE="$(1)" \ + SPEC2006="$$(SPEC2006_SPEC_ROOT)" \ + SPEC2006_CASE_CONFIG="$$(abspath $$(SPEC2006_CASE_CONFIG))" \ + SPEC2006_CFG="$$(abspath $$(SPEC2006_CFG))" \ + SPEC2006_COMPILER_ROOT="$$(SPEC2006_COMPILER_ROOT)" \ + SPEC2006_GNU_TOOLCHAIN_ROOT="$$(SPEC2006_GNU_TOOLCHAIN_ROOT)" \ + SPEC2006_JEMALLOC_ROOT="$$(SPEC2006_JEMALLOC_ROOT)" \ + SPEC2006_TUNE="$$(SPEC2006_TUNE)" \ + SPEC2006_JOBS="$$(SPEC2006_JOBS)" \ + SPEC2006_ELF_ONLY=1 \ + bash "$$(abspath $$(SPEC2006_WORKLOAD_DIR))/build.sh" + +$(SPEC2006_BUILD_DIR)/$(1)/rootfs.cpio: spec2006-check-spec-dir $$(SPEC2006_HELPER) $$(SPEC2006_WORKLOAD_DIR)/build.sh $$(SPEC2006_CASE_CONFIG) $$(SPEC2006_CFG) $(SPEC2006_BUILD_DIR)/$(1)/download/sentinel $$(SPEC2006_SCRIPTS_DIR)/build-workload-linux.sh + @CROSS_COMPILE="$$(SPEC2006_CROSS_COMPILE)" \ + SPEC2006_PROGRESS_K="$$(SPEC2006_PROGRESS_K)" \ + SPEC2006_PROGRESS_N="$$(SPEC2006_PROGRESS_N)" \ + SPEC2006_CASE="$(1)" \ + SPEC2006="$$(SPEC2006_SPEC_ROOT)" \ + SPEC2006_CASE_CONFIG="$$(abspath $$(SPEC2006_CASE_CONFIG))" \ + SPEC2006_CFG="$$(abspath $$(SPEC2006_CFG))" \ + SPEC2006_COMPILER_ROOT="$$(SPEC2006_COMPILER_ROOT)" \ + SPEC2006_GNU_TOOLCHAIN_ROOT="$$(SPEC2006_GNU_TOOLCHAIN_ROOT)" \ + SPEC2006_JEMALLOC_ROOT="$$(SPEC2006_JEMALLOC_ROOT)" \ + SPEC2006_TUNE="$$(SPEC2006_TUNE)" \ + SPEC2006_JOBS="$$(SPEC2006_JOBS)" \ + bash "$$(SPEC2006_SCRIPTS_DIR)/build-workload-linux.sh" "$$(SPEC2006_WORKLOAD_DIR)" "$(SPEC2006_BUILD_DIR)/$(1)" + +$(SPEC2006_BUILD_DIR)/$(1)/fw_payload.bin: $$(SPEC2006_DTS_SOURCES) $$(SPEC2006_GCPT_BIN) $$(SPEC2006_SCRIPTS_DIR)/build-firmware-linux.sh $(SPEC2006_BUILD_DIR)/$(1)/rootfs.cpio $$(SPEC2006_LINUX_IMAGE) $$(SPEC2006_SBI_BIN) + @printf '$(SPEC2006_PROGRESS_PREFIX) Assembling firmware for $(1)\n' + @CROSS_COMPILE="$$(SPEC2006_BUILDROOT_CROSS_COMPILE)" \ + DTC="$$(SPEC2006_DTC)" \ + DEFAULT_DTB="$$(SPEC2006_DEFAULT_DTB)" \ + SPEC2006_PROGRESS_K="$$(SPEC2006_PROGRESS_K)" \ + SPEC2006_PROGRESS_N="$$(SPEC2006_PROGRESS_N)" \ + bash "$$(SPEC2006_SCRIPTS_DIR)/build-firmware-linux.sh" "$$(SPEC2006_GCPT_BIN)" "$$(SPEC2006_SBI_BUILD_DIR)" "$$(SPEC2006_DTS_DIR)" "$$(SPEC2006_LINUX_IMAGE)" "$(SPEC2006_BUILD_DIR)/$(1)" + +linux/$(1): $(SPEC2006_BUILD_DIR)/$(1)/fw_payload.bin + +WORKLOAD_PHONY_TARGETS += linux/$(1) + +$(SPEC2006_IMAGE_DIR)/bin/$(1).fw_payload.bin: $(SPEC2006_BUILD_DIR)/$(1)/fw_payload.bin $(SPEC2006_LINUX_IMAGE) + @printf '$(SPEC2006_PROGRESS_PREFIX) Exporting $(1) artifacts to $(SPEC2006_IMAGE_DIR)\n' + @mkdir -p "$(SPEC2006_IMAGE_DIR)/bin" "$(SPEC2006_IMAGE_DIR)/kernel" "$(SPEC2006_IMAGE_DIR)/elf" "$(SPEC2006_IMAGE_DIR)/cfg" "$(SPEC2006_IMAGE_DIR)/gcpt" + @if [ ! -f "$(SPEC2006_IMAGE_DIR)/cfg/$(notdir $(SPEC2006_CFG))" ]; then \ + printf '$(SPEC2006_PROGRESS_PREFIX) Exporting spec2006 cfg to $(SPEC2006_IMAGE_DIR)/cfg\n'; \ + cp "$(SPEC2006_CFG)" "$(SPEC2006_IMAGE_DIR)/cfg/$(notdir $(SPEC2006_CFG))"; \ + fi + @if [ ! -f "$(SPEC2006_IMAGE_DIR)/gcpt/gcpt.elf" ] || [ ! -f "$(SPEC2006_IMAGE_DIR)/gcpt/gcpt.bin" ]; then \ + printf '$(SPEC2006_PROGRESS_PREFIX) Exporting gcpt artifacts to $(SPEC2006_IMAGE_DIR)/gcpt\n'; \ + cp "$(SPEC2006_GCPT_ELF)" "$(SPEC2006_IMAGE_DIR)/gcpt/gcpt.elf"; \ + cp "$(SPEC2006_GCPT_BIN)" "$(SPEC2006_IMAGE_DIR)/gcpt/gcpt.bin"; \ + fi + @cp $(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf $(SPEC2006_IMAGE_DIR)/elf/$(1).elf + @cp $(SPEC2006_LINUX_IMAGE) $(SPEC2006_IMAGE_DIR)/kernel/$(1).Image + @cp $(SPEC2006_BUILD_DIR)/$(1)/fw_payload.bin $(SPEC2006_IMAGE_DIR)/bin/$(1).fw_payload.bin +endef + +$(foreach case,$(SPEC2006_ALL_CASES),$(eval $(call add_spec2006_case,$(case)))) + +linux/spec2006: spec2006-check-spec-dir + @if [ -z "$(BENCH)" ]; then \ + echo "Usage: make linux/spec2006 BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN"; \ + echo " or: make linux/spec2006 BENCH=astar_biglakes SPEC=/path/to/cpu2006 -jN"; \ + exit 1; \ + fi + @$(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" $(SPEC2006_BUILD_DIR)/$(SPEC2006_CASE)/fw_payload.bin + +spec2006-elf: spec2006-check-spec-dir + @if [ -z "$(BENCH)" ]; then \ + echo "Usage: make spec2006-elf BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN"; \ + echo " or: make spec2006-elf BENCH=astar_biglakes SPEC=/path/to/cpu2006 -jN"; \ + exit 1; \ + fi + @$(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" $(SPEC2006_BUILD_DIR)/$(SPEC2006_CASE)/elf/$(SPEC2006_CASE).elf + +spec2006-elfs: spec2006-check-spec-dir + @if [ -z "$(SPEC2006_SELECTED_CASES)" ]; then \ + echo "No SPEC2006 cases selected by SPEC2006_INPUT=$(SPEC2006_INPUT)"; \ + exit 1; \ + fi; \ + for case in $(SPEC2006_SELECTED_CASES); do \ + $(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" "$(SPEC2006_BUILD_DIR)/$$case/elf/$$case.elf" || exit $$?; \ + done + +spec2006-images: spec2006-check-spec-dir + @if [ -z "$(SPEC2006_IMAGE_CASES)" ]; then \ + echo "No SPEC2006 cases selected by SPEC2006_INPUT=$(SPEC2006_INPUT)"; \ + exit 1; \ + fi; \ + total="$(words $(SPEC2006_IMAGE_CASES))"; \ + i=0; \ + for case in $(SPEC2006_IMAGE_CASES); do \ + i=$$((i + 1)); \ + SPEC2006_PROGRESS_K="$$i" SPEC2006_PROGRESS_N="$$total" $(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" "$(SPEC2006_IMAGE_DIR)/bin/$$case.fw_payload.bin" || exit $$?; \ + done + @printf '[spec2006 %s/%s] Output written to %s\n' "$(words $(SPEC2006_IMAGE_CASES))" "$(words $(SPEC2006_IMAGE_CASES))" "$(abspath $(SPEC2006_IMAGE_DIR))" + +.PHONY: linux/spec2006 spec2006-check-spec-dir spec2006-elf spec2006-elfs spec2006-images diff --git a/workloads/linux/spec2006/spec06.json b/workloads/linux/spec2006/spec06.json new file mode 100644 index 0000000..1faa7c0 --- /dev/null +++ b/workloads/linux/spec2006/spec06.json @@ -0,0 +1,2241 @@ +{ + "astar_biglakes": { + "base_name": "astar", + "files": [ + "astar/BigLakes2048.bin", + "astar/BigLakes2048.cfg" + ], + "args": [ + "BigLakes2048.cfg" + ], + "type": [ + "int", + "ref" + ] + }, + "astar_rivers": { + "base_name": "astar", + "files": [ + "astar/rivers.bin", + "astar/rivers.cfg" + ], + "args": [ + "rivers.cfg" + ], + "type": [ + "int", + "ref" + ] + }, + "bwaves": { + "base_name": "bwaves", + "files": [ + "bwaves/bwaves.in" + ], + "args": [], + "type": [ + "fp", + "ref" + ] + }, + "bzip2_chicken": { + "base_name": "bzip2", + "files": [ + "bzip2/chicken.jpg" + ], + "args": [ + "chicken.jpg", + "30" + ], + "type": [ + "int", + "ref" + ] + }, + "bzip2_combined": { + "base_name": "bzip2", + "files": [ + "bzip2/input.combined" + ], + "args": [ + "input.combined", + "200" + ], + "type": [ + "int", + "ref" + ] + }, + "bzip2_html": { + "base_name": "bzip2", + "files": [ + "bzip2/text.html" + ], + "args": [ + "text.html", + "280" + ], + "type": [ + "int", + "ref" + ] + }, + "bzip2_liberty": { + "base_name": "bzip2", + "files": [ + "bzip2/liberty.jpg" + ], + "args": [ + "liberty.jpg", + "30" + ], + "type": [ + "int", + "ref" + ] + }, + "bzip2_program": { + "base_name": "bzip2", + "files": [ + "bzip2/input.program" + ], + "args": [ + "input.program", + "280" + ], + "type": [ + "int", + "ref" + ] + }, + "bzip2_source": { + "base_name": "bzip2", + "files": [ + "bzip2/input.source" + ], + "args": [ + "input.source", + "280" + ], + "type": [ + "int", + "ref" + ] + }, + "cactusADM": { + "base_name": "cactusADM", + "files": [ + "cactusADM/benchADM.par" + ], + "args": [ + "benchADM.par" + ], + "type": [ + "fp", + "ref" + ] + }, + "calculix": { + "base_name": "calculix", + "files": [ + "calculix/hyperviscoplastic.inp" + ], + "args": [ + "-i", + "hyperviscoplastic" + ], + "type": [ + "fp", + "ref" + ] + }, + "dealII": { + "base_name": "dealII", + "files": [ + "dealII/DummyData" + ], + "args": [ + "23" + ], + "type": [ + "fp", + "ref" + ] + }, + "gamess_cytosine": { + "base_name": "gamess", + "files": [ + "gamess/cytosine.2.config", + "gamess/cytosine.2.inp" + ], + "args": [ + "<", + "cytosine.2.config" + ], + "type": [ + "fp", + "ref" + ] + }, + "gamess_gradient": { + "base_name": "gamess", + "files": [ + "gamess/h2ocu2+.gradient.config", + "gamess/h2ocu2+.gradient.inp" + ], + "args": [ + "<", + "h2ocu2+.gradient.config" + ], + "type": [ + "fp", + "ref" + ] + }, + "gamess_triazolium": { + "base_name": "gamess", + "files": [ + "gamess/triazolium.config", + "gamess/triazolium.inp" + ], + "args": [ + "<", + "triazolium.config" + ], + "type": [ + "fp", + "ref" + ] + }, + "gcc_166": { + "base_name": "gcc", + "files": [ + "gcc/166.in" + ], + "args": [ + "166.in", + "-o", + "166.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_200": { + "base_name": "gcc", + "files": [ + "gcc/200.in" + ], + "args": [ + "200.in", + "-o", + "200.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_cpdecl": { + "base_name": "gcc", + "files": [ + "gcc/cp-decl.in" + ], + "args": [ + "cp-decl.in", + "-o", + "cp-decl.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_expr2": { + "base_name": "gcc", + "files": [ + "gcc/expr2.in" + ], + "args": [ + "expr2.in", + "-o", + "expr2.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_expr": { + "base_name": "gcc", + "files": [ + "gcc/expr.in" + ], + "args": [ + "expr.in", + "-o", + "expr.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_g23": { + "base_name": "gcc", + "files": [ + "gcc/g23.in" + ], + "args": [ + "g23.in", + "-o", + "g23.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_s04": { + "base_name": "gcc", + "files": [ + "gcc/s04.in" + ], + "args": [ + "s04.in", + "-o", + "s04.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_scilab": { + "base_name": "gcc", + "files": [ + "gcc/scilab.in" + ], + "args": [ + "scilab.in", + "-o", + "scilab.s" + ], + "type": [ + "int", + "ref" + ] + }, + "gcc_typeck": { + "base_name": "gcc", + "files": [ + "gcc/c-typeck.in" + ], + "args": [ + "c-typeck.in", + "-o", + "c-typeck.s" + ], + "type": [ + "int", + "ref" + ] + }, + "GemsFDTD": { + "base_name": "GemsFDTD", + "files": [ + "GemsFDTD/ref.in", + "GemsFDTD/sphere.pec", + "GemsFDTD/yee.dat" + ], + "args": [], + "type": [ + "fp", + "ref" + ] + }, + "gobmk_13x13": { + "base_name": "gobmk", + "files": [ + "gobmk/13x13.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "13x13.tst" + ], + "type": [ + "int", + "ref" + ] + }, + "gobmk_nngs": { + "base_name": "gobmk", + "files": [ + "gobmk/nngs.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "nngs.tst" + ], + "type": [ + "int", + "ref" + ] + }, + "gobmk_score2": { + "base_name": "gobmk", + "files": [ + "gobmk/score2.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "score2.tst" + ], + "type": [ + "int", + "ref" + ] + }, + "gobmk_trevorc": { + "base_name": "gobmk", + "files": [ + "gobmk/trevorc.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "trevorc.tst" + ], + "type": [ + "int", + "ref" + ] + }, + "gobmk_trevord": { + "base_name": "gobmk", + "files": [ + "gobmk/trevord.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "trevord.tst" + ], + "type": [ + "int", + "ref" + ] + }, + "gromacs": { + "base_name": "gromacs", + "files": [ + "gromacs/gromacs.tpr" + ], + "args": [ + "-silent", + "-deffnm", + "gromacs.tpr", + "-nice", + "0" + ], + "type": [ + "fp", + "ref" + ] + }, + "h264ref_foreman.baseline": { + "base_name": "h264ref", + "files": [ + "h264ref/foreman_ref_encoder_baseline.cfg", + "h264ref/foreman_qcif.yuv" + ], + "args": [ + "-d", + "foreman_ref_encoder_baseline.cfg" + ], + "type": [ + "int", + "ref" + ] + }, + "h264ref_foreman.main": { + "base_name": "h264ref", + "files": [ + "h264ref/foreman_ref_encoder_main.cfg", + "h264ref/foreman_qcif.yuv" + ], + "args": [ + "-d", + "foreman_ref_encoder_main.cfg" + ], + "type": [ + "int", + "ref" + ] + }, + "h264ref_sss": { + "base_name": "h264ref", + "files": [ + "h264ref/sss_encoder_main.cfg", + "h264ref/sss.yuv" + ], + "args": [ + "-d", + "sss_encoder_main.cfg" + ], + "type": [ + "int", + "ref" + ] + }, + "hmmer_nph3": { + "base_name": "hmmer", + "files": [ + "hmmer/nph3.hmm", + "hmmer/swiss41" + ], + "args": [ + "nph3.hmm", + "swiss41" + ], + "type": [ + "int", + "ref" + ] + }, + "hmmer_retro": { + "base_name": "hmmer", + "files": [ + "hmmer/retro.hmm" + ], + "args": [ + "--fixed", + "0", + "--mean", + "500", + "--num", + "500000", + "--sd", + "350", + "--seed", + "0", + "retro.hmm" + ], + "type": [ + "int", + "ref" + ] + }, + "lbm": { + "base_name": "lbm", + "files": [ + "lbm/100_100_130_ldc.of", + "lbm/lbm.in" + ], + "args": [ + "3000", + "reference.dat", + "0", + "0", + "100_100_130_ldc.of" + ], + "type": [ + "fp", + "ref" + ] + }, + "leslie3d": { + "base_name": "leslie3d", + "files": [ + "leslie3d/leslie3d.in" + ], + "args": [ + "<", + "leslie3d.in" + ], + "type": [ + "fp", + "ref" + ] + }, + "libquantum": { + "base_name": "libquantum", + "files": [], + "args": [ + "1397", + "8" + ], + "type": [ + "int", + "ref" + ] + }, + "mcf": { + "base_name": "mcf", + "files": [ + "mcf/inp.in" + ], + "args": [ + "inp.in" + ], + "type": [ + "int", + "ref" + ] + }, + "milc": { + "base_name": "milc", + "files": [ + "milc/su3imp.in" + ], + "args": [ + "<", + "su3imp.in" + ], + "type": [ + "fp", + "ref" + ] + }, + "namd": { + "base_name": "namd", + "files": [ + "namd/namd.input" + ], + "args": [ + "--input", + "namd.input", + "--iterations", + "38", + "--output", + "namd.out" + ], + "type": [ + "fp", + "ref" + ] + }, + "omnetpp": { + "base_name": "omnetpp", + "files": [ + "omnetpp/omnetpp.ini" + ], + "args": [ + "omnetpp.ini" + ], + "type": [ + "int", + "ref" + ] + }, + "perlbench_checkspam": { + "base_name": "perlbench", + "files": [ + "perlbench/cpu2006_mhonarc.rc", + "perlbench/checkspam.pl", + "perlbench/checkspam.in", + "dir lib perlbench/lib", + "dir rules perlbench/rules" + ], + "args": [ + "-I./lib", + "checkspam.pl", + "2500", + "5", + "25", + "11", + "150", + "1", + "1", + "1", + "1" + ], + "type": [ + "int", + "ref" + ] + }, + "perlbench_diffmail": { + "base_name": "perlbench", + "files": [ + "perlbench/cpu2006_mhonarc.rc", + "perlbench/diffmail.pl", + "perlbench/diffmail.in", + "dir lib perlbench/lib", + "dir rules perlbench/rules" + ], + "args": [ + "-I./lib", + "diffmail.pl", + "4", + "800", + "10", + "17", + "19", + "300" + ], + "type": [ + "int", + "ref" + ] + }, + "perlbench_splitmail": { + "base_name": "perlbench", + "files": [ + "perlbench/cpu2006_mhonarc.rc", + "perlbench/splitmail.pl", + "perlbench/splitmail.in", + "dir lib perlbench/lib", + "dir rules perlbench/rules" + ], + "args": [ + "-I./lib", + "splitmail.pl", + "1600", + "12", + "26", + "16", + "4500" + ], + "type": [ + "int", + "ref" + ] + }, + "povray": { + "base_name": "povray", + "files": [ + "dir . povray" + ], + "args": [ + "SPEC-benchmark-ref.ini" + ], + "type": [ + "fp", + "ref" + ] + }, + "sjeng": { + "base_name": "sjeng", + "files": [ + "sjeng/ref.txt" + ], + "args": [ + "ref.txt" + ], + "type": [ + "int", + "ref" + ] + }, + "soplex_pds-50": { + "base_name": "soplex", + "files": [ + "soplex/pds-50.mps" + ], + "args": [ + "-s1", + "-e", + "-m45000", + "pds-50.mps" + ], + "type": [ + "fp", + "ref" + ] + }, + "soplex_ref": { + "base_name": "soplex", + "files": [ + "soplex/ref.mps" + ], + "args": [ + "-m3500", + "ref.mps" + ], + "type": [ + "fp", + "ref" + ] + }, + "sphinx3": { + "base_name": "sphinx3", + "files": [ + "dir . sphinx3" + ], + "args": [ + "ctlfile", + ".", + "args.an4" + ], + "type": [ + "fp", + "ref" + ] + }, + "tonto": { + "base_name": "tonto", + "files": [ + "tonto/stdin" + ], + "args": [], + "type": [ + "fp", + "ref" + ] + }, + "wrf": { + "base_name": "wrf", + "files": [ + "dir . wrf" + ], + "args": [], + "type": [ + "fp", + "ref" + ] + }, + "xalancbmk": { + "base_name": "xalancbmk", + "files": [ + "dir . xalancbmk" + ], + "args": [ + "-v", + "t5.xml", + "xalanc.xsl" + ], + "type": [ + "int", + "ref" + ] + }, + "zeusmp": { + "base_name": "zeusmp", + "files": [ + "zeusmp/zmp_inp" + ], + "args": [], + "type": [ + "fp", + "ref" + ] + }, + "gamess_exam29": { + "base_name": "gamess", + "files": [ + "gamess/exam29.config", + "gamess/exam29.inp" + ], + "args": [ + "<", + "exam29.config" + ], + "type": [ + "fp", + "test" + ] + }, + "perlbench_attrs": { + "base_name": "perlbench", + "files": [ + "perlbench/attrs.pl" + ], + "args": [ + "-I.", + "-I./lib", + "attrs.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_gv": { + "base_name": "perlbench", + "files": [ + "perlbench/gv.pl" + ], + "args": [ + "-I.", + "-I./lib", + "gv.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_makerand": { + "base_name": "perlbench", + "files": [ + "perlbench/makerand.pl" + ], + "args": [ + "-I.", + "-I./lib", + "makerand.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_pack": { + "base_name": "perlbench", + "files": [ + "perlbench/pack.pl", + "perlbench/test.pm" + ], + "args": [ + "-I.", + "-I./lib", + "pack.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_redef": { + "base_name": "perlbench", + "files": [ + "perlbench/redef.pl" + ], + "args": [ + "-I.", + "-I./lib", + "redef.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_ref": { + "base_name": "perlbench", + "files": [ + "perlbench/ref.pl" + ], + "args": [ + "-I.", + "-I./lib", + "ref.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_regmesg": { + "base_name": "perlbench", + "files": [ + "perlbench/regmesg.pl" + ], + "args": [ + "-I.", + "-I./lib", + "regmesg.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_test": { + "base_name": "perlbench", + "files": [ + "perlbench/test.pl", + "perlbench/test.pm", + "perlbench/re_tests", + "perlbench/append.t", + "perlbench/args.t", + "perlbench/arith.t", + "perlbench/array.t", + "perlbench/auto.t", + "perlbench/base_cond.t", + "perlbench/base_pat.t", + "perlbench/base_term.t", + "perlbench/bless.t", + "perlbench/bop.t", + "perlbench/bproto.t", + "perlbench/chars.t", + "perlbench/chop.t", + "perlbench/cmdopt.t", + "perlbench/cmp.t", + "perlbench/comp_term.t", + "perlbench/concat.t", + "perlbench/context.t", + "perlbench/decl.t", + "perlbench/defins.t", + "perlbench/delete.t", + "perlbench/die.t", + "perlbench/do.t", + "perlbench/each.t", + "perlbench/eval.t", + "perlbench/exists_sub.t", + "perlbench/exp.t", + "perlbench/fh.t", + "perlbench/grep.t", + "perlbench/hashwarn.t", + "perlbench/if.t", + "perlbench/inc.t", + "perlbench/index.t", + "perlbench/int.t", + "perlbench/join.t", + "perlbench/length.t", + "perlbench/lex.t", + "perlbench/list.t", + "perlbench/loopctl.t", + "perlbench/lop.t", + "perlbench/method.t", + "perlbench/my.t", + "perlbench/nothr5005.t", + "perlbench/oct.t", + "perlbench/op_cond.t", + "perlbench/op_pat.t", + "perlbench/ord.t", + "perlbench/override.t", + "perlbench/package.t", + "perlbench/pos.t", + "perlbench/push.t", + "perlbench/quotemeta.t", + "perlbench/range.t", + "perlbench/recurse.t", + "perlbench/regexp.t", + "perlbench/regexp_noamp.t", + "perlbench/repeat.t", + "perlbench/reverse.t", + "perlbench/rs.t", + "perlbench/sleep.t", + "perlbench/sort.t", + "perlbench/splice.t", + "perlbench/study.t", + "perlbench/sub_lval.t", + "perlbench/subst.t", + "perlbench/subst_amp.t", + "perlbench/subst_wamp.t", + "perlbench/tr.t", + "perlbench/undef.t", + "perlbench/unshift.t", + "perlbench/vec.t", + "perlbench/wantarray.t" + ], + "args": [ + "-I.", + "-I./lib", + "test.pl" + ], + "type": [ + "int", + "test" + ] + }, + "perlbench_diffmail_train": { + "base_name": "perlbench", + "files": [ + "perlbench/cpu2006_mhonarc.rc", + "perlbench/diffmail.pl", + "perlbench/diffmail.in", + "dir lib perlbench/lib", + "dir rules perlbench/rules" + ], + "args": [ + "-I./lib", + "diffmail.pl", + "4", + "800", + "10", + "17", + "19", + "300" + ], + "type": [ + "int", + "train" + ] + }, + "perlbench_perfect": { + "base_name": "perlbench", + "files": [ + "perlbench/perfect.pl", + "perlbench/perfect.in" + ], + "args": [ + "-I./lib", + "perfect.pl", + "b", + "3" + ], + "type": [ + "int", + "train" + ] + }, + "perlbench_splitmail_train": { + "base_name": "perlbench", + "files": [ + "perlbench/cpu2006_mhonarc.rc", + "perlbench/splitmail.pl", + "perlbench/splitmail.in", + "dir lib perlbench/lib", + "dir rules perlbench/rules" + ], + "args": [ + "-I./lib", + "splitmail.pl", + "1600", + "12", + "26", + "16", + "4500" + ], + "type": [ + "int", + "train" + ] + }, + "perlbench_scrabbl": { + "base_name": "perlbench", + "files": [ + "perlbench/scrabbl.pl", + "perlbench/scrabbl.in", + "perlbench/dictionary" + ], + "args": [ + "-I.", + "-I./lib", + "scrabbl.pl", + "<", + "scrabbl.in" + ], + "type": [ + "int", + "train" + ] + }, + "perlbench_suns": { + "base_name": "perlbench", + "files": [ + "perlbench/suns.pl", + "perlbench/WORDS" + ], + "args": [ + "-I.", + "-I./lib", + "suns.pl" + ], + "type": [ + "int", + "train" + ] + }, + "bzip2_dryer": { + "base_name": "bzip2", + "files": [ + "bzip2/dryer.jpg" + ], + "args": [ + "dryer.jpg", + "2" + ], + "type": [ + "int", + "test" + ] + }, + "bzip2_program_test": { + "base_name": "bzip2", + "files": [ + "bzip2/input.program" + ], + "args": [ + "input.program", + "5" + ], + "type": [ + "int", + "test" + ] + }, + "bzip2_byoudoin": { + "base_name": "bzip2", + "files": [ + "bzip2/byoudoin.jpg" + ], + "args": [ + "byoudoin.jpg", + "5" + ], + "type": [ + "int", + "train" + ] + }, + "bzip2_program_train": { + "base_name": "bzip2", + "files": [ + "bzip2/input.program" + ], + "args": [ + "input.program", + "10" + ], + "type": [ + "int", + "train" + ] + }, + "bzip2_combined_train": { + "base_name": "bzip2", + "files": [ + "bzip2/input.combined" + ], + "args": [ + "input.combined", + "80" + ], + "type": [ + "int", + "train" + ] + }, + "gcc_cccp": { + "base_name": "gcc", + "files": [ + "gcc/cccp.in" + ], + "args": [ + "cccp.in", + "-o", + "cccp.s" + ], + "type": [ + "int", + "test" + ] + }, + "gcc_integrate": { + "base_name": "gcc", + "files": [ + "gcc/integrate.in" + ], + "args": [ + "integrate.in", + "-o", + "integrate.s" + ], + "type": [ + "int", + "train" + ] + }, + "bwaves_test": { + "base_name": "bwaves", + "files": [ + "bwaves/bwaves.in" + ], + "args": [], + "type": [ + "fp", + "test" + ] + }, + "bwaves_train": { + "base_name": "bwaves", + "files": [ + "bwaves/bwaves.in" + ], + "args": [], + "type": [ + "fp", + "train" + ] + }, + "gamess_h2ocu2_energy": { + "base_name": "gamess", + "files": [ + "gamess/h2ocu2+.energy.config", + "gamess/h2ocu2+.energy.inp" + ], + "args": [ + "<", + "h2ocu2+.energy.config" + ], + "type": [ + "fp", + "train" + ] + }, + "mcf_test": { + "base_name": "mcf", + "files": [ + "mcf/inp.in" + ], + "args": [ + "inp.in" + ], + "type": [ + "int", + "test" + ] + }, + "mcf_train": { + "base_name": "mcf", + "files": [ + "mcf/inp.in" + ], + "args": [ + "inp.in" + ], + "type": [ + "int", + "train" + ] + }, + "milc_test": { + "base_name": "milc", + "files": [ + "milc/su3imp.in" + ], + "args": [ + "<", + "su3imp.in" + ], + "type": [ + "fp", + "test" + ] + }, + "milc_train": { + "base_name": "milc", + "files": [ + "milc/su3imp.in" + ], + "args": [ + "<", + "su3imp.in" + ], + "type": [ + "fp", + "train" + ] + }, + "zeusmp_test": { + "base_name": "zeusmp", + "files": [ + "zeusmp/zmp_inp" + ], + "args": [], + "type": [ + "fp", + "test" + ] + }, + "zeusmp_train": { + "base_name": "zeusmp", + "files": [ + "zeusmp/zmp_inp" + ], + "args": [], + "type": [ + "fp", + "train" + ] + }, + "gromacs_test": { + "base_name": "gromacs", + "files": [ + "gromacs/gromacs.tpr" + ], + "args": [ + "-silent", + "-deffnm", + "gromacs", + "-nice", + "0" + ], + "type": [ + "fp", + "test" + ] + }, + "gromacs_train": { + "base_name": "gromacs", + "files": [ + "gromacs/gromacs.tpr" + ], + "args": [ + "-silent", + "-deffnm", + "gromacs", + "-nice", + "0" + ], + "type": [ + "fp", + "train" + ] + }, + "cactusADM_test": { + "base_name": "cactusADM", + "files": [ + "cactusADM/benchADM.par" + ], + "args": [ + "benchADM.par" + ], + "type": [ + "fp", + "test" + ] + }, + "cactusADM_train": { + "base_name": "cactusADM", + "files": [ + "cactusADM/benchADM.par" + ], + "args": [ + "benchADM.par" + ], + "type": [ + "fp", + "train" + ] + }, + "leslie3d_test": { + "base_name": "leslie3d", + "files": [ + "leslie3d/leslie3d.in" + ], + "args": [ + "<", + "leslie3d.in" + ], + "type": [ + "fp", + "test" + ] + }, + "leslie3d_train": { + "base_name": "leslie3d", + "files": [ + "leslie3d/leslie3d.in" + ], + "args": [ + "<", + "leslie3d.in" + ], + "type": [ + "fp", + "train" + ] + }, + "namd_test": { + "base_name": "namd", + "files": [ + "namd/namd.input" + ], + "args": [ + "--input", + "namd.input", + "--iterations", + "1", + "--output", + "namd.out" + ], + "type": [ + "int", + "test" + ] + }, + "namd_train": { + "base_name": "namd", + "files": [ + "namd/namd.input" + ], + "args": [ + "--input", + "namd.input", + "--iterations", + "1", + "--output", + "namd.out" + ], + "type": [ + "int", + "train" + ] + }, + "dealII_test": { + "base_name": "dealII", + "files": [ + "dealII/DummyData" + ], + "args": [ + "8" + ], + "type": [ + "fp", + "test" + ] + }, + "dealII_train": { + "base_name": "dealII", + "files": [ + "dealII/DummyData" + ], + "args": [ + "10" + ], + "type": [ + "fp", + "train" + ] + }, + "soplex_test": { + "base_name": "soplex", + "files": [ + "soplex/test.mps" + ], + "args": [ + "-m10000", + "test.mps" + ], + "type": [ + "fp", + "test" + ] + }, + "soplex_pds-20": { + "base_name": "soplex", + "files": [ + "soplex/pds-20.mps" + ], + "args": [ + "-s1", + "-e", + "-m5000", + "pds-20.mps" + ], + "type": [ + "fp", + "train" + ] + }, + "soplex_train": { + "base_name": "soplex", + "files": [ + "soplex/train.mps" + ], + "args": [ + "-m1200", + "train.mps" + ], + "type": [ + "fp", + "train" + ] + }, + "povray_test": { + "base_name": "povray", + "files": [ + "povray/SPEC-benchmark-test.ini", + "povray/SPEC-benchmark-test.pov" + ], + "args": [ + "SPEC-benchmark-test.ini" + ], + "type": [ + "fp", + "test" + ] + }, + "povray_train": { + "base_name": "povray", + "files": [ + "povray/SPEC-benchmark-train.ini", + "povray/SPEC-benchmark-train.pov" + ], + "args": [ + "SPEC-benchmark-train.ini" + ], + "type": [ + "fp", + "train" + ] + }, + "calculix_test": { + "base_name": "calculix", + "files": [ + "calculix/beampic.inp" + ], + "args": [ + "-i", + "beampic" + ], + "type": [ + "fp", + "test" + ] + }, + "calculix_train": { + "base_name": "calculix", + "files": [ + "calculix/stairs.inp" + ], + "args": [ + "-i", + "stairs" + ], + "type": [ + "fp", + "train" + ] + }, + "hmmer_test": { + "base_name": "hmmer", + "files": [ + "hmmer/bombesin.hmm" + ], + "args": [ + "--fixed", + "0", + "--mean", + "325", + "--num", + "45000", + "--sd", + "200", + "--seed", + "0", + "bombesin.hmm" + ], + "type": [ + "fp", + "test" + ] + }, + "hmmer_train": { + "base_name": "hmmer", + "files": [ + "hmmer/leng100.hmm" + ], + "args": [ + "--fixed", + "0", + "--mean", + "425", + "--num", + "85000", + "--sd", + "300", + "--seed", + "0", + "leng100.hmm" + ], + "type": [ + "fp", + "train" + ] + }, + "sjeng_test": { + "base_name": "sjeng", + "files": [ + "sjeng/test.txt" + ], + "args": [ + "test.txt" + ], + "type": [ + "int", + "test" + ] + }, + "sjeng_train": { + "base_name": "sjeng", + "files": [ + "sjeng/train.txt" + ], + "args": [ + "train.txt" + ], + "type": [ + "int", + "train" + ] + }, + "GemsFDTD_test": { + "base_name": "GemsFDTD", + "files": [ + "GemsFDTD/sphere.pec", + "GemsFDTD/test.in", + "GemsFDTD/yee.dat" + ], + "args": [], + "type": [ + "fp", + "test" + ] + }, + "GemsFDTD_train": { + "base_name": "GemsFDTD", + "files": [ + "GemsFDTD/sphere.pec", + "GemsFDTD/train.in", + "GemsFDTD/yee.dat" + ], + "args": [], + "type": [ + "fp", + "train" + ] + }, + "tonto_test": { + "base_name": "tonto", + "files": [ + "tonto/stdin" + ], + "args": [], + "type": [ + "fp", + "test" + ] + }, + "tonto_train": { + "base_name": "tonto", + "files": [ + "tonto/stdin" + ], + "args": [], + "type": [ + "fp", + "train" + ] + }, + "lbm_test": { + "base_name": "lbm", + "files": [ + "lbm/100_100_130_cf_a.of", + "lbm/lbm.in" + ], + "args": [ + "20", + "reference.dat", + "0", + "1", + "100_100_130_cf_a.of" + ], + "type": [ + "fp", + "test" + ] + }, + "lbm_train": { + "base_name": "lbm", + "files": [ + "lbm/100_100_130_cf_b.of", + "lbm/lbm.in" + ], + "args": [ + "300", + "reference.dat", + "0", + "1", + "100_100_130_cf_b.of" + ], + "type": [ + "fp", + "train" + ] + }, + "omnetpp_test": { + "base_name": "omnetpp", + "files": [ + "omnetpp/omnetpp.ini" + ], + "args": [ + "omnetpp.ini" + ], + "type": [ + "int", + "test" + ] + }, + "omnetpp_train": { + "base_name": "omnetpp", + "files": [ + "omnetpp/omnetpp.ini" + ], + "args": [ + "omnetpp.ini" + ], + "type": [ + "int", + "train" + ] + }, + "astar_lake": { + "base_name": "astar", + "files": [ + "astar/lake.bin", + "astar/lake.cfg" + ], + "args": [ + "lake.cfg" + ], + "type": [ + "int", + "test" + ] + }, + "astar_biglakes1024": { + "base_name": "astar", + "files": [ + "astar/BigLakes1024.bin", + "astar/BigLakes1024.cfg" + ], + "args": [ + "BigLakes1024.cfg" + ], + "type": [ + "int", + "train" + ] + }, + "astar_rivers1": { + "base_name": "astar", + "files": [ + "astar/rivers.bin", + "astar/rivers1.cfg" + ], + "args": [ + "rivers1.cfg" + ], + "type": [ + "int", + "train" + ] + }, + "wrf_test": { + "base_name": "wrf", + "files": [ + "dir . wrf" + ], + "args": [], + "type": [ + "fp", + "test" + ] + }, + "wrf_train": { + "base_name": "wrf", + "files": [ + "dir . wrf" + ], + "args": [], + "type": [ + "fp", + "train" + ] + }, + "sphinx3_test": { + "base_name": "sphinx3", + "files": [ + "dir . sphinx3" + ], + "args": [ + "ctlfile", + ".", + "args.an4" + ], + "type": [ + "fp", + "test" + ] + }, + "sphinx3_train": { + "base_name": "sphinx3", + "files": [ + "dir . sphinx3" + ], + "args": [ + "ctlfile", + ".", + "args.an4" + ], + "type": [ + "fp", + "train" + ] + }, + "xalancbmk_test": { + "base_name": "xalancbmk", + "files": [ + "dir . xalancbmk" + ], + "args": [ + "-v", + "test.xml", + "xalanc.xsl" + ], + "type": [ + "int", + "test" + ] + }, + "xalancbmk_train": { + "base_name": "xalancbmk", + "files": [ + "dir . xalancbmk" + ], + "args": [ + "-v", + "allbooks.xml", + "xalanc.xsl" + ], + "type": [ + "int", + "train" + ] + }, + "h264ref_foreman.test": { + "base_name": "h264ref", + "files": [ + "h264ref/foreman_qcif.yuv", + "h264ref/foreman_test_encoder_baseline.cfg" + ], + "args": [ + "-d", + "foreman_test_encoder_baseline.cfg" + ], + "type": [ + "int", + "test" + ] + }, + "h264ref_foreman.train": { + "base_name": "h264ref", + "files": [ + "h264ref/foreman_qcif.yuv", + "h264ref/foreman_train_encoder_baseline.cfg" + ], + "args": [ + "-d", + "foreman_train_encoder_baseline.cfg" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_capture": { + "base_name": "gobmk", + "files": [ + "gobmk/capture.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "capture.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_connect": { + "base_name": "gobmk", + "files": [ + "gobmk/connect.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "connect.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_connect_rot": { + "base_name": "gobmk", + "files": [ + "gobmk/connect_rot.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "connect_rot.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_connection": { + "base_name": "gobmk", + "files": [ + "gobmk/connection.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "connection.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_connection_rot": { + "base_name": "gobmk", + "files": [ + "gobmk/connection_rot.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "connection_rot.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_cutstone": { + "base_name": "gobmk", + "files": [ + "gobmk/cutstone.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "cutstone.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_dniwog": { + "base_name": "gobmk", + "files": [ + "gobmk/dniwog.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "dniwog.tst" + ], + "type": [ + "int", + "test" + ] + }, + "gobmk_arb": { + "base_name": "gobmk", + "files": [ + "gobmk/arb.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "arb.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_arend": { + "base_name": "gobmk", + "files": [ + "gobmk/arend.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "arend.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_arion": { + "base_name": "gobmk", + "files": [ + "gobmk/arion.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "arion.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_atari_atari": { + "base_name": "gobmk", + "files": [ + "gobmk/atari_atari.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "atari_atari.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_blunder": { + "base_name": "gobmk", + "files": [ + "gobmk/blunder.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "blunder.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_buzco": { + "base_name": "gobmk", + "files": [ + "gobmk/buzco.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "buzco.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_nicklas2": { + "base_name": "gobmk", + "files": [ + "gobmk/nicklas2.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "nicklas2.tst" + ], + "type": [ + "int", + "train" + ] + }, + "gobmk_nicklas4": { + "base_name": "gobmk", + "files": [ + "gobmk/nicklas4.tst", + "dir games gobmk/games", + "dir golois gobmk/golois" + ], + "args": [ + "--quiet", + "--mode", + "gtp", + "<", + "nicklas4.tst" + ], + "type": [ + "int", + "train" + ] + } +} diff --git a/workloads/linux/spec2006/spec2006-package.py b/workloads/linux/spec2006/spec2006-package.py new file mode 100644 index 0000000..70ac9bf --- /dev/null +++ b/workloads/linux/spec2006/spec2006-package.py @@ -0,0 +1,562 @@ +#!/usr/bin/env python3 +import argparse +import hashlib +import json +import os +import shlex +import shutil +import subprocess +import sys +from collections import deque +from pathlib import Path + +INPUT_SETS = ("ref", "train", "test") + + +def format_cmd(cmd): + return " ".join(shlex.quote(str(part)) for part in cmd) + + +def progress_prefix(): + current = os.environ.get("SPEC2006_PROGRESS_K", "1") + total = os.environ.get("SPEC2006_PROGRESS_N", "1") + return f"[spec2006 {current}/{total}]" + + +def status(message): + print(f"{progress_prefix()} {message}", flush=True) + + +def read_log_tail(log_path, max_lines=40): + with open(log_path, "r", encoding="utf-8", errors="replace") as f: + lines = deque(f, maxlen=max_lines) + return "".join(lines).rstrip() + + +def maybe_read_log_tail(log_path, max_lines=40): + if log_path.is_file(): + tail = read_log_tail(log_path, max_lines=max_lines) + if tail: + return f"\nLast log lines from {log_path}:\n{tail}" + return "" + + +def run(cmd, *, env=None, cwd=None, log_path=None, summary=None): + command_text = format_cmd(cmd) + if summary: + status(summary) + + if log_path is None: + raise ValueError("log_path is required") + + log_path.parent.mkdir(parents=True, exist_ok=True) + with open(log_path, "a", encoding="utf-8") as log: + log.write(f"$ {command_text}\n") + if cwd is not None: + log.write(f"# cwd: {cwd}\n") + log.flush() + result = subprocess.run( + cmd, + cwd=cwd, + env=env, + check=False, + stdout=log, + stderr=subprocess.STDOUT, + text=True, + ) + log.write("\n") + + if result.returncode != 0: + tail = read_log_tail(log_path) + detail = f"\nLast log lines from {log_path}:\n{tail}" if tail else "" + raise RuntimeError(f"command failed: {command_text}\nSee {log_path}{detail}") + + +def load_cases(path): + with open(path, "r", encoding="utf-8") as f: + cases = json.load(f) + if not isinstance(cases, dict): + raise RuntimeError(f"case config must be a JSON object: {path}") + return cases + + +def file_sha256(path): + digest = hashlib.sha256() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def filter_cases(cases, input_set): + if input_set in (None, "", "all"): + return cases + if input_set not in INPUT_SETS: + choices = ", ".join((*INPUT_SETS, "all")) + raise RuntimeError(f"unknown SPEC2006 input set {input_set!r}; available: {choices}") + return { + name: case + for name, case in cases.items() + if input_set in case.get("type", []) + } + + +def input_set_for_case(case): + for name in INPUT_SETS: + if name in case.get("type", []): + return name + raise RuntimeError(f"case has no input set marker in type: {case.get('type')}") + + +def spec_env(spec_dir): + script = f"cd {shlex.quote(str(spec_dir))} && . ./shrc >/dev/null && env -0" + raw = subprocess.check_output(["bash", "-lc", script]) + env = {} + for item in raw.split(b"\0"): + if not item: + continue + key, value = item.split(b"=", 1) + env[key.decode()] = value.decode() + return env + + +def bench_dir_for_base(spec_dir, base_name): + root = spec_dir / "benchspec" / "CPU2006" + matches = [] + for path in root.iterdir(): + if not path.is_dir() or "." not in path.name: + continue + suffix = path.name.split(".", 1)[1] + if suffix == base_name: + matches.append(path.name) + if len(matches) != 1: + raise RuntimeError(f"cannot map base benchmark {base_name!r} to SPEC benchmark directory") + return matches[0] + + +def resolve_cross_compile(prefix): + gcc_name = prefix if prefix.endswith("gcc") else prefix + "gcc" + gcc_path = Path(gcc_name) + if not gcc_path.is_absolute(): + found = shutil.which(gcc_name) + if found is None: + raise RuntimeError(f"cannot locate compiler for CROSS_COMPILE={prefix!r}") + gcc_path = Path(found) + if not gcc_path.is_file(): + raise RuntimeError(f"compiler does not exist: {gcc_path}") + gcc_path = gcc_path.resolve() + if not gcc_path.name.endswith("gcc"): + raise RuntimeError(f"unexpected compiler name for CROSS_COMPILE={prefix!r}: {gcc_path.name}") + cross_compile = str(gcc_path)[: -len("gcc")] + toolchain_root = gcc_path.parent.parent + return cross_compile, toolchain_root + + +def copy_tree_contents(src, dst): + if not src.is_dir(): + return + dst.mkdir(parents=True, exist_ok=True) + for item in src.iterdir(): + target = dst / item.name + if item.is_dir(): + if target.exists(): + shutil.rmtree(target) + shutil.copytree(item, target, symlinks=True) + else: + shutil.copy2(item, target) + + +def stage_inputs(spec_dir, bench_dir, base_name, input_set, stage_root): + bench_data = spec_dir / "benchspec" / "CPU2006" / bench_dir / "data" + if stage_root.exists(): + shutil.rmtree(stage_root) + base_stage = stage_root / base_name + base_stage.mkdir(parents=True) + copy_tree_contents(bench_data / "all" / "input", base_stage) + copy_tree_contents(bench_data / input_set / "input", base_stage) + return stage_root + + +def install_case_files(case, stage_root, spec_root): + spec_root.mkdir(parents=True, exist_ok=True) + for entry in case.get("files", []): + parts = entry.split() + if len(parts) == 3 and parts[0] == "dir": + _, dest_name, rel_path = parts + src = stage_root / rel_path + if not src.is_dir(): + raise RuntimeError(f"missing SPEC input directory {src}") + if dest_name == ".": + copy_tree_contents(src, spec_root) + else: + dst = spec_root / dest_name + if dst.exists(): + shutil.rmtree(dst) + shutil.copytree(src, dst, symlinks=True) + elif len(parts) == 1: + src = stage_root / entry + if not src.is_file(): + raise RuntimeError(f"missing SPEC input file {src}") + shutil.copy2(src, spec_root / src.name) + else: + raise RuntimeError(f"unsupported SPEC file entry: {entry}") + + +def shell_command(binary_name, args): + before_redirect = [] + stdin_file = None + iterator = iter(args) + for arg in iterator: + if arg == "<": + try: + stdin_file = next(iterator) + except StopIteration as exc: + raise RuntimeError("input redirection without file") from exc + rest = list(iterator) + if rest: + raise RuntimeError(f"unsupported arguments after input redirection: {rest}") + break + before_redirect.append(arg) + + words = ["./" + binary_name] + before_redirect + cmd = " ".join(shlex.quote(x) for x in words) + if stdin_file is not None: + cmd += " < " + shlex.quote(stdin_file) + return cmd + + +def write_runtime_files(pkg_dir, case_name, binary_name, args): + spec_root = pkg_dir / "spec" + command = shell_command(binary_name, args) + run_sh = spec_root / "run.sh" + run_sh.write_text( + "\n".join( + [ + "#!/bin/sh", + "set -e", + "cd /spec", + f"echo '======== BEGIN {case_name} ========'", + f"md5sum ./{shlex.quote(binary_name)}", + "date -R || true", + f"spec_cmd={shlex.quote(command)}", + "echo \"CMD: $spec_cmd\"", + "set +e", + "sh -c \"$spec_cmd\"", + "status=$?", + "set -e", + "date -R || true", + f"echo '======== END {case_name} ========'", + "exit $status", + "", + ] + ), + encoding="utf-8", + ) + run_sh.chmod(0o755) + + etc = pkg_dir / "etc" + etc.mkdir(parents=True, exist_ok=True) + (etc / "inittab").write_text("::sysinit:nemu-exec /bin/sh /spec/run.sh\n", encoding="utf-8") + + +def export_elf_artifact(elf, case_name, out_dir): + elf_dir = out_dir / "elf" + elf_dir.mkdir(parents=True, exist_ok=True) + exported_elf = elf_dir / f"{case_name}.elf" + shutil.copy2(elf, exported_elf) + return exported_elf + + +def install_runtime_binary(elf, binary_name, pkg_dir): + spec_root = pkg_dir / "spec" + shutil.copy2(elf, spec_root / binary_name) + (spec_root / binary_name).chmod(0o755) + + +def build_local_config(template_cfg, generated_cfg, output_root, jobs): + text = template_cfg.read_text(encoding="utf-8") + filtered_lines = [] + for line in text.splitlines(): + stripped = line.lstrip() + if stripped.startswith("output_root") and "=" in line: + continue + if stripped.startswith("makeflags") and "=" in line: + continue + filtered_lines.append(line) + generated_cfg.parent.mkdir(parents=True, exist_ok=True) + generated_cfg.write_text( + "\n".join( + [ + "# Auto-generated by spec2006-package.py", + f"# Template: {template_cfg}", + f"output_root = {output_root}", + f"makeflags = -j{jobs}", + "", + *filtered_lines, + "", + ] + ), + encoding="utf-8", + ) + return generated_cfg + + +def shared_build_dir_for(out_dir, bench_dir, tune): + return out_dir.parent / "_bench-builds" / bench_dir / tune + + +def shared_build_metadata(spec_cfg, spec_dir, cross_compile, tune, compiler_root, gnu_toolchain_root, jemalloc_root): + return { + "spec_cfg_sha256": file_sha256(spec_cfg), + "spec_dir": str(spec_dir), + "cross_compile": cross_compile, + "tune": tune, + "compiler_root": str(compiler_root), + "gnu_toolchain_root": str(gnu_toolchain_root), + "jemalloc_root": str(jemalloc_root), + } + + +def load_json(path): + with open(path, "r", encoding="utf-8") as f: + return json.load(f) + + +def write_json(path, value): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(value, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +def select_built_elf(exe_dir, tune): + if not exe_dir.is_dir(): + raise RuntimeError(f"runspec did not create exe directory: {exe_dir}") + candidates = [path for path in exe_dir.iterdir() if path.is_file() and not path.name.endswith(".md5")] + if not candidates: + raise RuntimeError(f"no executable produced by runspec under {exe_dir}") + preferred = [path for path in candidates if f"_{tune}." in path.name] + if preferred: + candidates = preferred + return max(candidates, key=lambda path: path.stat().st_mtime) + + +def explain_missing_elf(output_root, bench_dir, tune): + build_root = output_root / "benchspec" / "CPU2006" / bench_dir / "build" + if not build_root.is_dir(): + return "" + + build_dirs = sorted(path for path in build_root.iterdir() if path.is_dir()) + if not build_dirs: + return "" + + latest = max(build_dirs, key=lambda path: path.stat().st_mtime) + details = [f"Latest build directory: {latest}"] + for name in ("make.err", "make.out"): + tail = maybe_read_log_tail(latest / name) + if tail: + details.append(tail.lstrip("\n")) + break + return "\n" + "\n".join(details) + + +def cfg_requires_jemalloc(spec_cfg): + text = spec_cfg.read_text(encoding="utf-8") + return "JEMALLOC_PATH" in text or "-ljemalloc" in text + + +def build_elf(spec_dir, bench_dir, spec_cfg, out_dir, log_dir, cross_compile, tune, jobs, compiler_root, gnu_toolchain_root, jemalloc_root): + shared_dir = shared_build_dir_for(out_dir, bench_dir, tune) + output_root = shared_dir / "runspec-output" + generated_cfg = shared_dir / "runspec-config" / spec_cfg.name + shared_log_dir = shared_dir / "logs" + build_log = shared_log_dir / "build.log" + exe_dir = output_root / "benchspec" / "CPU2006" / bench_dir / "exe" + metadata_path = shared_dir / "build-meta.json" + metadata = shared_build_metadata( + spec_cfg, + spec_dir, + cross_compile, + tune, + compiler_root, + gnu_toolchain_root, + jemalloc_root, + ) + + if metadata_path.is_file(): + try: + cached_metadata = load_json(metadata_path) + except Exception: + cached_metadata = None + if cached_metadata == metadata: + try: + elf = select_built_elf(exe_dir, tune) + except Exception: + elf = None + if elf is not None: + status(f"Reusing {bench_dir} build from {shared_dir}") + return elf, build_log + + if output_root.exists(): + shutil.rmtree(output_root) + if generated_cfg.parent.exists(): + shutil.rmtree(generated_cfg.parent) + if shared_log_dir.exists(): + shutil.rmtree(shared_log_dir) + shared_log_dir.mkdir(parents=True, exist_ok=True) + + build_local_config(spec_cfg, generated_cfg, output_root, jobs) + status(f"Generated SPEC cfg: {generated_cfg}") + + env = os.environ.copy() + env.update(spec_env(spec_dir)) + env["SPEC"] = str(spec_dir) + env["LLVM_INSTALL_PATH"] = str(compiler_root) + env["GNU_RISCV64_PATH"] = str(gnu_toolchain_root) + env["JEMALLOC_INSTALL_PATH"] = str(jemalloc_root) + + runspec = spec_dir / "bin" / "runspec" + cmd = [ + str(runspec), + "--action", + "build", + "--config", + str(generated_cfg), + "--tune", + tune, + "--noreportable", + "--iterations", + "1", + bench_dir, + ] + run( + cmd, + cwd=spec_dir, + env=env, + log_path=build_log, + summary=f"Building {bench_dir} with runspec (log: {build_log})", + ) + + try: + elf = select_built_elf(exe_dir, tune) + except RuntimeError as exc: + detail = explain_missing_elf(output_root, bench_dir, tune) + raise RuntimeError(str(exc) + detail) from exc + write_json(metadata_path, metadata) + return elf, build_log + + +def package_case(args): + cases = load_cases(args.cases_config) + if args.case not in cases: + choices = " ".join(sorted(cases)) + raise RuntimeError(f"unknown SPEC2006 case {args.case!r}; available cases: {choices}") + + spec_dir = Path(args.spec).resolve() + spec_cfg = Path(args.spec_config).resolve() + pkg_dir = Path(args.pkg_dir).resolve() if args.pkg_dir else None + out_dir = Path(args.out_dir).resolve() + log_dir = Path(args.log_dir).resolve() if args.log_dir else out_dir / "logs" + + cross_compile, detected_toolchain_root = resolve_cross_compile(args.cross_compile) + compiler_root = Path(args.compiler_root).resolve() if args.compiler_root else detected_toolchain_root + gnu_toolchain_root = Path(args.gnu_toolchain_root).resolve() if args.gnu_toolchain_root else detected_toolchain_root + env_jemalloc_root = os.environ.get("SPEC2006_JEMALLOC_ROOT") or os.environ.get("JEMALLOC_INSTALL_PATH") + if args.jemalloc_root: + jemalloc_root = Path(args.jemalloc_root).resolve() + elif env_jemalloc_root: + jemalloc_root = Path(env_jemalloc_root).resolve() + else: + jemalloc_root = (out_dir.parent / "jemalloc" / "install").resolve() + + jemalloc_library = jemalloc_root / "lib" / "libjemalloc.a" + if cfg_requires_jemalloc(spec_cfg) and not jemalloc_library.is_file(): + raise RuntimeError( + f"jemalloc library not found: {jemalloc_library}; " + "set SPEC2006_JEMALLOC_ROOT or JEMALLOC_INSTALL_PATH to a valid install prefix" + ) + + case = cases[args.case] + base_name = case["base_name"] + bench_dir = bench_dir_for_base(spec_dir, base_name) + input_set = input_set_for_case(case) + + elf, build_log = build_elf( + spec_dir, + bench_dir, + spec_cfg, + out_dir, + log_dir, + cross_compile, + args.tune, + args.jobs, + compiler_root, + gnu_toolchain_root, + jemalloc_root, + ) + exported_elf = export_elf_artifact(elf, args.case, out_dir) + status(f"Exported ELF: {exported_elf}") + + if args.elf_only: + return + + stage_root = out_dir / "spec-stage" / args.case + status(f"Staging inputs for {args.case}") + stage_inputs(spec_dir, bench_dir, base_name, input_set, stage_root) + + if pkg_dir is None: + raise RuntimeError("--pkg-dir is required unless --elf-only is set") + if pkg_dir.exists(): + shutil.rmtree(pkg_dir) + (pkg_dir / "spec").mkdir(parents=True) + + status(f"Packaging rootfs for {args.case}") + install_case_files(case, stage_root, pkg_dir / "spec") + install_runtime_binary(elf, base_name, pkg_dir) + write_runtime_files(pkg_dir, args.case, base_name, case.get("args", [])) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--cases-config") + parser.add_argument("--list-cases", action="store_true") + parser.add_argument("--input-set", choices=(*INPUT_SETS, "all"), default="all") + parser.add_argument("--case") + parser.add_argument("--spec") + parser.add_argument("--spec-config") + parser.add_argument("--pkg-dir") + parser.add_argument("--out-dir") + parser.add_argument("--cross-compile", default="riscv64-unknown-linux-gnu-") + parser.add_argument("--compiler-root") + parser.add_argument("--gnu-toolchain-root") + parser.add_argument("--jemalloc-root") + parser.add_argument("--log-dir") + parser.add_argument("--tune", default="base") + parser.add_argument("--jobs", default=str(os.cpu_count() or 1)) + parser.add_argument("--elf-only", action="store_true") + args = parser.parse_args() + + if args.list_cases: + if not args.cases_config: + parser.error("--cases-config is required with --list-cases") + try: + cases = filter_cases(load_cases(args.cases_config), args.input_set) + except Exception as exc: + parser.error(str(exc)) + print(" ".join(cases.keys())) + return + + required = ["cases_config", "case", "spec", "spec_config", "out_dir", "cross_compile"] + if not args.elf_only: + required.append("pkg_dir") + missing = [name for name in required if getattr(args, name) in (None, "")] + if missing: + parser.error("missing required arguments: " + ", ".join("--" + x.replace("_", "-") for x in missing)) + + try: + package_case(args) + except Exception as exc: + print(f"{progress_prefix()} error: {exc}", file=sys.stderr) + sys.exit(1) + + +if __name__ == "__main__": + main()