From 24de35bb4a908ef93e7dd038c35177afc0c16cc7 Mon Sep 17 00:00:00 2001 From: good-circle Date: Mon, 21 Sep 2026 15:36:18 +0800 Subject: [PATCH] feat(spec2006): add PROFILING=0 like SPEC2017 Follow the existing SPEC2017 single-hart run script: emit nemu-trap 256/257 around the benchmark by default, always end with nemu-trap , and start /spec/run.sh from inittab instead of wrapping it with nemu-exec. PROFILING=0 drops the begin traps. Multi-hart still uses the existing task wrappers. --- workloads/linux/spec2006/README.md | 20 ++++++ workloads/linux/spec2006/build.sh | 4 ++ workloads/linux/spec2006/rules.mk | 13 +++- workloads/linux/spec2006/spec2006-package.py | 66 +++++++++++--------- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/workloads/linux/spec2006/README.md b/workloads/linux/spec2006/README.md index b682f5f..674193b 100644 --- a/workloads/linux/spec2006/README.md +++ b/workloads/linux/spec2006/README.md @@ -94,6 +94,26 @@ make linux/spec2006 BENCH=astar INPUT=biglakes \ SPEC2006_ISO=/path/to/cpu2006.iso -jN ``` +For single-hart images, the generated run script emits NEMU profiling traps by +default: + +```text +echo "CMD: ..." +nemu-trap 256 +nemu-trap 257 + +nemu-trap +``` + +Disable the begin profiling traps with: + +```sh +PROFILING=0 make linux/spec2006 BENCH=mcf INPUT=ref \ + SPEC2006_ISO=/path/to/cpu2006.iso -jN +``` + +The final `nemu-trap ` is always emitted for single-hart images. + ## Build a multi-hart workload Add `MULTIHART=1 HARTS=`, where `` matches the QEMU checkpoint diff --git a/workloads/linux/spec2006/build.sh b/workloads/linux/spec2006/build.sh index d5ebe9c..a996b93 100644 --- a/workloads/linux/spec2006/build.sh +++ b/workloads/linux/spec2006/build.sh @@ -12,6 +12,8 @@ set -euo pipefail : "${SPEC2006_JEMALLOC_COMMIT:=1a15fe33a48c52bfe26ea83e49f0d317a47da3ea}" : "${SPEC2006_DOWNLOAD_RETRIES:=3}" : "${SPEC2006_ELF_ONLY:=false}" +: "${SPEC2006_PROFILING:=1}" +: "${SPEC2006_MULTIHART:=0}" : "${SPEC2006_LOG_DIR:=$WORKLOAD_BUILD_DIR/logs}" : "${PKG_DIR:=$WORKLOAD_BUILD_DIR/package}" @@ -232,4 +234,6 @@ python3 "$WORKLOAD_DIR/spec2006-package.py" \ --log-dir "$SPEC2006_LOG_DIR" \ --tune "$SPEC2006_TUNE" \ --jobs "$SPEC2006_JOBS" \ + --profiling "$SPEC2006_PROFILING" \ + --multihart "$SPEC2006_MULTIHART" \ "${python_args[@]}" diff --git a/workloads/linux/spec2006/rules.mk b/workloads/linux/spec2006/rules.mk index ff5ce69..b32661f 100644 --- a/workloads/linux/spec2006/rules.mk +++ b/workloads/linux/spec2006/rules.mk @@ -20,6 +20,7 @@ SPEC2006_COMPILER_ROOT ?= SPEC2006_GNU_TOOLCHAIN_ROOT ?= SPEC2006_JEMALLOC_ROOT ?= SPEC2006_MULTIHART ?= $(MULTIHART) +SPEC2006_PROFILING ?= $(if $(PROFILING),$(PROFILING),1) SPEC2006_HARTS ?= $(if $(HARTS),$(HARTS),2) PLATFORM ?= $(if $(filter 1,$(SPEC2006_MULTIHART)),qemu,nemu) ifeq ($(filter $(PLATFORM),nemu qemu),) @@ -62,7 +63,7 @@ SPEC2006_DTS_SOURCES := $(SPEC2006_REPO_ROOT)/dts/generate-nemu-board-dts.py $(S $(wildcard $(SPEC2006_REPO_ROOT)/dts/$(SPEC2006_DEFAULT_DTB).dts.in) SPEC2006_CFG_HASH := $(shell if [ -f "$(abspath $(SPEC2006_CFG))" ]; then sha256sum "$(abspath $(SPEC2006_CFG))" | cut -d ' ' -f 1; else printf 'missing'; fi) SPEC2006_DEFAULT_DTB_STAMP := $(SPEC2006_BUILD_DIR)/dtb.$(shell printf '%s\n' "$(SPEC2006_DEFAULT_DTB)" "$(DTS_ISA_CONFIG)" | sha256sum | cut -d ' ' -f 1) -SPEC2006_BUILD_VARS_HASH := $(shell printf '%s\n' '$(SPEC2006_INPUT)' '$(SPEC2006_TUNE)' '$(SPEC2006_JOBS)' '$(SPEC2006_CROSS_COMPILE)' 'multihart=$(SPEC2006_MULTIHART)' 'harts=$(SPEC2006_HARTS)' | sha256sum | cut -d ' ' -f 1) +SPEC2006_BUILD_VARS_HASH := $(shell printf '%s\n' '$(SPEC2006_PROFILING)' '$(SPEC2006_INPUT)' '$(SPEC2006_TUNE)' '$(SPEC2006_JOBS)' '$(SPEC2006_CROSS_COMPILE)' 'multihart=$(SPEC2006_MULTIHART)' 'harts=$(SPEC2006_HARTS)' | sha256sum | cut -d ' ' -f 1) spec2006_case_image_stamp = $(SPEC2006_IMAGE_DIR)/stamps/$(1).images.stamp WORKLOAD_DIRS += $(SPEC2006_BUILD_DIR) @@ -88,6 +89,10 @@ spec2006-check-spec-iso: case "$(SPEC2006_INPUT)" in \ ref|train|test|all) ;; \ *) echo "SPEC2006_INPUT must be one of: ref, train, test, all"; exit 1 ;; \ + esac; \ + case "$(SPEC2006_PROFILING)" in \ + 0|1) ;; \ + *) echo "SPEC2006_PROFILING/PROFILING must be 0 or 1"; exit 1 ;; \ esac spec2006-prepare: $(SPEC2006_PREPARE_STAMP) @@ -112,7 +117,7 @@ $(SPEC2006_BUILD_DIR)/$(1)/download/sentinel: $(SPEC2006_BUILD_DIR)/$(1)/build-vars.$(SPEC2006_BUILD_VARS_HASH).stamp: @mkdir -p "$$(@D)" @rm -f "$$(@D)"/build-vars.*.stamp - @printf '%s\n' "input=$(SPEC2006_INPUT)" "tune=$(SPEC2006_TUNE)" "jobs=$(SPEC2006_JOBS)" "cross_compile=$(SPEC2006_CROSS_COMPILE)" "multihart=$(SPEC2006_MULTIHART)" "harts=$(SPEC2006_HARTS)" > "$$@" + @printf '%s\n' "profiling=$(SPEC2006_PROFILING)" "input=$(SPEC2006_INPUT)" "tune=$(SPEC2006_TUNE)" "jobs=$(SPEC2006_JOBS)" "cross_compile=$(SPEC2006_CROSS_COMPILE)" "multihart=$(SPEC2006_MULTIHART)" "harts=$(SPEC2006_HARTS)" > "$$@" $(SPEC2006_BUILD_DIR)/$(1)/cfg.stamp: spec2006-force @mkdir -p "$$(@D)" @@ -138,6 +143,8 @@ $(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf: $(SPEC2006_PREPARE_STAMP) $(SPEC2006_BU SPEC2006_JEMALLOC_ROOT="$$(SPEC2006_JEMALLOC_ROOT)" \ SPEC2006_TUNE="$$(SPEC2006_TUNE)" \ SPEC2006_JOBS="$$(SPEC2006_JOBS)" \ + SPEC2006_PROFILING="$$(SPEC2006_PROFILING)" \ + SPEC2006_MULTIHART="$$(SPEC2006_MULTIHART)" \ SPEC2006_ELF_ONLY=1 \ bash "$$(abspath $$(SPEC2006_WORKLOAD_DIR))/build.sh" @@ -154,6 +161,8 @@ $(SPEC2006_BUILD_DIR)/$(1)/rootfs.cpio: $(SPEC2006_PREPARE_STAMP) $(SPEC2006_BUI SPEC2006_JEMALLOC_ROOT="$$(SPEC2006_JEMALLOC_ROOT)" \ SPEC2006_TUNE="$$(SPEC2006_TUNE)" \ SPEC2006_JOBS="$$(SPEC2006_JOBS)" \ + SPEC2006_PROFILING="$$(SPEC2006_PROFILING)" \ + SPEC2006_MULTIHART="$$(SPEC2006_MULTIHART)" \ MULTIHART="$$(SPEC2006_MULTIHART)" \ HARTS="$$(SPEC2006_HARTS)" \ MULTIHART_PAYLOAD_DIR=spec \ diff --git a/workloads/linux/spec2006/spec2006-package.py b/workloads/linux/spec2006/spec2006-package.py index 4fb25af..6ffffdd 100644 --- a/workloads/linux/spec2006/spec2006-package.py +++ b/workloads/linux/spec2006/spec2006-package.py @@ -329,41 +329,49 @@ def shell_command(binary_name, args): return cmd -def write_runtime_files(pkg_dir, case_name, binary_name, args): +def write_runtime_files(pkg_dir, case_name, binary_name, args, profiling="1", multihart="0"): 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", - 'SPEC_ROOT="${SPEC_ROOT:-/spec}"', - "export SPEC_ROOT", - "ulimit -s unlimited 2>/dev/null || true", - 'cd "$SPEC_ROOT"', - 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", + lines = [ + "#!/bin/sh", + "set -e", + 'SPEC_ROOT="${SPEC_ROOT:-/spec}"', + "export SPEC_ROOT", + "ulimit -s unlimited 2>/dev/null || true", + 'cd "$SPEC_ROOT"', + 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", + ] + if profiling == "1" and multihart != "1": + lines.extend(["nemu-trap 256", "nemu-trap 257"]) + lines.extend( + [ + "sh -c \"$spec_cmd\"", + "status=$?", + "set -e", + ] + ) + if multihart != "1": + lines.append("nemu-trap \"$status\"") + lines.extend( + [ + "date -R || true", + f"echo '======== END {case_name} ========'", + "exit $status", + "", + ] ) + run_sh.write_text("\n".join(lines), 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") + (etc / "inittab").write_text("::once:/bin/sh /spec/run.sh\n", encoding="utf-8") def export_elf_artifact(elf, case_name, out_dir): @@ -631,7 +639,7 @@ def package_case(args): install_case_files(case, stage_root, pkg_dir / "spec") apply_benchmark_post_setup(bench_dir, pkg_dir / "spec", elf, spec_cfg) install_runtime_binary(elf, base_name, pkg_dir) - write_runtime_files(pkg_dir, args.case, base_name, case.get("args", [])) + write_runtime_files(pkg_dir, args.case, base_name, case.get("args", []), args.profiling, args.multihart) def main(): @@ -652,6 +660,8 @@ def main(): 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") + parser.add_argument("--profiling", choices=("0", "1"), default="1") + parser.add_argument("--multihart", choices=("0", "1"), default="0") args = parser.parse_args() if args.list_cases: