diff --git a/workloads/linux/spec2006/README.md b/workloads/linux/spec2006/README.md index e140e44..ca60c88 100644 --- a/workloads/linux/spec2006/README.md +++ b/workloads/linux/spec2006/README.md @@ -1,35 +1,31 @@ # SPEC CPU2006 Linux workload `workloads/linux/spec2006` now builds SPEC CPU2006 workloads with the original -SPEC tools (`runspec`) against an external SPEC installation. +SPEC tools (`runspec`) from a prepared workspace installed from a SPEC ISO. ## Build one case -Either point `SPEC` at the SPEC tree: +Point `SPEC2006_ISO` at the SPEC ISO: ```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 +make linux/spec2006 BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN ``` `BENCH` may also be a full case name from `spec06.json`: ```sh -make linux/spec2006 BENCH=astar_biglakes SPEC=/path/to/cpu2006 -jN +make linux/spec2006 BENCH=astar_biglakes SPEC2006_ISO=/path/to/cpu2006.iso -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 +1. Run `make spec2006-prepare SPEC2006_ISO=/path/to/cpu2006.iso` to install a build-local + writable SPEC workspace under `build/linux-workloads/spec2006/spec-src`. +2. Generate a build-local SPEC cfg copy under the case build directory. +3. Inject `output_root` into that cfg so SPEC build artifacts stay under this + repository instead of modifying the prepared SPEC workspace. +4. Run `runspec --action build` inside the prepared workspace. +5. Export the built SPEC ELF, package the benchmark plus input files into the Linux rootfs, and produce: ```text @@ -41,15 +37,15 @@ build/linux-workloads/spec2006//fw_payload.bin Export all selected cases to `build/images/spec2006`: ```sh -make spec2006-images SPEC=/path/to/cpu2006 -jN +make spec2006-images SPEC2006_ISO=/path/to/cpu2006.iso -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 +make spec2006-images SPEC2006_ISO=/path/to/cpu2006.iso SPEC2006_INPUT=test -jN +make spec2006-images SPEC2006_ISO=/path/to/cpu2006.iso SPEC2006_INPUT=all -jN ``` Selected SPEC cases are built one by one to avoid concurrent `runspec` @@ -76,7 +72,7 @@ Override the destination with `SPEC2006_IMAGE_DIR=/path/to/image`. Build one case without packaging it into the Linux rootfs: ```sh -make spec2006-elf BENCH=astar INPUT=biglakes SPEC=/path/to/cpu2006 -jN +make spec2006-elf BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN ``` This writes: @@ -88,8 +84,8 @@ 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 +make spec2006-elfs SPEC2006_ISO=/path/to/cpu2006.iso SPEC2006_INPUT=ref -jN +make spec2006-elfs SPEC2006_ISO=/path/to/cpu2006.iso SPEC2006_INPUT=all -jN ``` If you only want the standalone ELF build flow, you can run it from this @@ -97,8 +93,8 @@ 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 +make -f rules.mk spec2006-elf BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN +make -f rules.mk spec2006-elfs SPEC2006_ISO=/path/to/cpu2006.iso SPEC2006_INPUT=all -jN ``` ## Configuration @@ -113,7 +109,7 @@ Override it with: ```sh make linux/spec2006 BENCH=bzip2_source \ - SPEC=/path/to/cpu2006 \ + SPEC2006_ISO=/path/to/cpu2006.iso \ SPEC2006_CFG=/path/to/other.cfg \ -jN ``` @@ -170,7 +166,14 @@ SPEC2006 builds keep console output concise. Detailed logs are written to: ## Notes -- The original SPEC tree is used read-only for sources and input data. +- The original SPEC ISO is used read-only as installation media. +- `runspec` is never executed against the original ISO contents; it only sees the + prepared workspace under `build/linux-workloads/spec2006/spec-src`. +- The prepared workspace is installed into a writable build directory before + any SPEC tools are executed. +- Installation staging uses a temporary local filesystem; override + `SPEC2006_PREPARE_TMPDIR` if `/tmp` is not suitable. +- `xorriso` is required to extract the SPEC ISO during `spec2006-prepare`. - 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; diff --git a/workloads/linux/spec2006/prepare-spec-workspace.sh b/workloads/linux/spec2006/prepare-spec-workspace.sh new file mode 100755 index 0000000..4820b99 --- /dev/null +++ b/workloads/linux/spec2006/prepare-spec-workspace.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -euo pipefail + +source_spec_iso="$(realpath "$1")" +prepared_spec_root="$(realpath -m "$2")" + +prepare_dir="$(dirname "$prepared_spec_root")" +mkdir -p "$prepare_dir" +chmod -R u+rwX "$prepared_spec_root" 2>/dev/null || true +rm -rf "$prepared_spec_root" + +temp_root="" +cleanup() { + if [ -n "$temp_root" ]; then + chmod -R u+rwX "$temp_root" 2>/dev/null || true + rm -rf "$temp_root" 2>/dev/null || true + fi +} +trap cleanup EXIT + +if ! command -v xorriso >/dev/null 2>&1; then + echo "xorriso is required to extract $source_spec_iso" >&2 + exit 1 +fi + +tmp_parent="${SPEC2006_PREPARE_TMPDIR:-${TMPDIR:-/tmp}}" +mkdir -p "$tmp_parent" +temp_root="$(mktemp -d "$tmp_parent/spec-prepare.XXXXXX")" + +media_root="$temp_root/media" +staged_spec_root="$temp_root/spec-src" +mkdir -p "$media_root" + +xorriso -osirrox on -indev "$source_spec_iso" -extract / "$media_root" >/dev/null + +if ! [ -f "$media_root/install.sh" ]; then + echo "install.sh not found in $source_spec_iso" >&2 + exit 1 +fi + +( + cd "$media_root" + env -u SPEC sh ./install.sh -f -d "$staged_spec_root" +) + +mkdir -p "$prepared_spec_root" +cp -R "$staged_spec_root"/. "$prepared_spec_root"/ +chmod -R u+rwX "$prepared_spec_root" + +( + cd "$prepared_spec_root" + . ./shrc >/dev/null + bin/relocate >/dev/null +) diff --git a/workloads/linux/spec2006/rules.mk b/workloads/linux/spec2006/rules.mk index baf7c29..4b8c163 100644 --- a/workloads/linux/spec2006/rules.mk +++ b/workloads/linux/spec2006/rules.mk @@ -10,7 +10,11 @@ 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_SOURCE_SPEC_ISO := $(SPEC2006_ISO) +SPEC2006_PREPARED_SPEC_ROOT := $(SPEC2006_BUILD_DIR)/spec-src +SPEC2006_SOURCE_SPEC_HASH := $(shell printf '%s\n' "$(SPEC2006_SOURCE_SPEC_ISO)" | sha256sum | cut -d ' ' -f 1) +SPEC2006_PREPARE_STAMP := $(SPEC2006_BUILD_DIR)/spec-src.$(SPEC2006_SOURCE_SPEC_HASH).prepared +SPEC2006_PREPARE_SCRIPT := $(SPEC2006_WORKLOAD_DIR)/prepare-spec-workspace.sh SPEC2006_CROSS_COMPILE ?= riscv64-unknown-linux-gnu- SPEC2006_COMPILER_ROOT ?= SPEC2006_GNU_TOOLCHAIN_ROOT ?= @@ -40,19 +44,14 @@ SPEC2006_DEFAULT_DTB_STAMP := $(SPEC2006_BUILD_DIR)/dtb.$(shell printf '%s\n' "$ 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"; \ +spec2006-check-spec-iso: + @if [ -z "$(SPEC2006_SOURCE_SPEC_ISO)" ]; then \ + echo "SPEC2006_ISO is required, for example:"; \ + echo " make linux/spec2006 BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -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"; \ + if ! [ -f "$(SPEC2006_SOURCE_SPEC_ISO)" ]; then \ + echo "SPEC ISO path does not exist: $(SPEC2006_SOURCE_SPEC_ISO)"; \ exit 1; \ fi; \ if ! [ -f "$(SPEC2006_CFG)" ]; then \ @@ -68,6 +67,13 @@ spec2006-check-spec-dir: *) echo "SPEC2006_INPUT must be one of: ref, train, test, all"; exit 1 ;; \ esac +spec2006-prepare: $(SPEC2006_PREPARE_STAMP) + +$(SPEC2006_PREPARE_STAMP): $(SPEC2006_PREPARE_SCRIPT) $(SPEC2006_SOURCE_SPEC_ISO) | spec2006-check-spec-iso + @printf '$(SPEC2006_PROGRESS_PREFIX) Preparing SPEC workspace at $(SPEC2006_PREPARED_SPEC_ROOT)\n' + @bash "$(SPEC2006_PREPARE_SCRIPT)" "$(SPEC2006_SOURCE_SPEC_ISO)" "$(SPEC2006_PREPARED_SPEC_ROOT)" + @touch "$@" + $(SPEC2006_DEFAULT_DTB_STAMP): @mkdir -p "$(@D)" @rm -f "$(SPEC2006_BUILD_DIR)"/dtb.* @@ -78,7 +84,7 @@ $(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) +$(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf: $(SPEC2006_PREPARE_STAMP) $$(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))" \ @@ -87,7 +93,7 @@ $(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf: spec2006-check-spec-dir $$(SPEC2006_HEL SPEC2006_PROGRESS_K="$$(SPEC2006_PROGRESS_K)" \ SPEC2006_PROGRESS_N="$$(SPEC2006_PROGRESS_N)" \ SPEC2006_CASE="$(1)" \ - SPEC2006="$$(SPEC2006_SPEC_ROOT)" \ + SPEC2006="$$(SPEC2006_PREPARED_SPEC_ROOT)" \ SPEC2006_CASE_CONFIG="$$(abspath $$(SPEC2006_CASE_CONFIG))" \ SPEC2006_CFG="$$(abspath $$(SPEC2006_CFG))" \ SPEC2006_COMPILER_ROOT="$$(SPEC2006_COMPILER_ROOT)" \ @@ -98,12 +104,12 @@ $(SPEC2006_BUILD_DIR)/$(1)/elf/$(1).elf: spec2006-check-spec-dir $$(SPEC2006_HEL 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 +$(SPEC2006_BUILD_DIR)/$(1)/rootfs.cpio: $(SPEC2006_PREPARE_STAMP) $$(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="$$(SPEC2006_PREPARED_SPEC_ROOT)" \ SPEC2006_CASE_CONFIG="$$(abspath $$(SPEC2006_CASE_CONFIG))" \ SPEC2006_CFG="$$(abspath $$(SPEC2006_CFG))" \ SPEC2006_COMPILER_ROOT="$$(SPEC2006_COMPILER_ROOT)" \ @@ -145,23 +151,23 @@ endef $(foreach case,$(SPEC2006_ALL_CASES),$(eval $(call add_spec2006_case,$(case)))) -linux/spec2006: spec2006-check-spec-dir +linux/spec2006: spec2006-check-spec-iso @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"; \ + echo "Usage: make linux/spec2006 BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN"; \ + echo " or: make linux/spec2006 BENCH=astar_biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN"; \ exit 1; \ fi @$(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" GCPT_DEFAULT_DTB="$(SPEC2006_DEFAULT_DTB)" $(SPEC2006_BUILD_DIR)/$(SPEC2006_CASE)/fw_payload.bin -spec2006-elf: spec2006-check-spec-dir +spec2006-elf: spec2006-check-spec-iso @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"; \ + echo "Usage: make spec2006-elf BENCH=astar INPUT=biglakes SPEC2006_ISO=/path/to/cpu2006.iso -jN"; \ + echo " or: make spec2006-elf BENCH=astar_biglakes SPEC2006_ISO=/path/to/cpu2006.iso -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 +spec2006-elfs: spec2006-check-spec-iso @if [ -z "$(SPEC2006_SELECTED_CASES)" ]; then \ echo "No SPEC2006 cases selected by SPEC2006_INPUT=$(SPEC2006_INPUT)"; \ exit 1; \ @@ -170,7 +176,7 @@ spec2006-elfs: spec2006-check-spec-dir $(MAKE) --no-print-directory -f "$(SPEC2006_RECURSE_MAKEFILE)" "$(SPEC2006_BUILD_DIR)/$$case/elf/$$case.elf" || exit $$?; \ done -spec2006-images: spec2006-check-spec-dir +spec2006-images: spec2006-check-spec-iso @if [ -z "$(SPEC2006_IMAGE_CASES)" ]; then \ echo "No SPEC2006 cases selected by SPEC2006_INPUT=$(SPEC2006_INPUT)"; \ exit 1; \ @@ -183,4 +189,4 @@ spec2006-images: spec2006-check-spec-dir 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 +.PHONY: linux/spec2006 spec2006-check-spec-iso spec2006-prepare spec2006-elf spec2006-elfs spec2006-images