74 lines
3.6 KiB
Bash
Executable File
74 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# Copyright (C) 2026 David (Corey) Herrera
|
|
#
|
|
# rebuild_all_tensix_programs.sh
|
|
# Rebuild EVERY program directory under a programs root from its own provenance records
|
|
# into a new root, then compare each image against the original with the instruction-stream
|
|
# diff. The build-side gate for a toolchain-level change (clean-room phases): it answers
|
|
# "does everything still build, and exactly which images moved".
|
|
#
|
|
# Usage: rebuild_all_tensix_programs.sh <programs-root> <out-root> [program ...]
|
|
# EXTRA_KERNEL_DEFINES passed through to every rebuild (a red build)
|
|
# Output: <out-root>/<program>/ images, <out-root>/<program>.rebuild.log,
|
|
# <out-root>/<program>.diff, <out-root>/summary.txt
|
|
#
|
|
# Per image the summary says IDENTICAL (byte-equal .text), DIFFERS, or MISSING; whether it
|
|
# is LOAD-IDENTICAL (tools/compare_tensix_load_images.py: what reaches the card); and the
|
|
# kernel's .text size, so a change that pushes a kernel toward its 12 KiB text slab is
|
|
# visible here before it reaches a card.
|
|
#
|
|
# Status: added 2026-10-08 (clean-room Phase 2).
|
|
# Issues: None
|
|
# Todo: None
|
|
#
|
|
set -uo pipefail
|
|
|
|
SRC=${1:?usage: rebuild_all_tensix_programs.sh <programs-root> <out-root> [program ...]}
|
|
OUT=${2:?usage: rebuild_all_tensix_programs.sh <programs-root> <out-root> [program ...]}
|
|
shift 2
|
|
HERE=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
SIZE=${SFPI:-/opt/tenstorrent/sfpi}/compiler/bin/riscv-tt-elf-size
|
|
OBJCOPY=${SFPI:-/opt/tenstorrent/sfpi}/compiler/bin/riscv-tt-elf-objcopy
|
|
|
|
mkdir -p "$OUT"
|
|
OUT=$(cd "$OUT" && pwd)
|
|
PROGRAMS=("$@")
|
|
if [ ${#PROGRAMS[@]} -eq 0 ]; then
|
|
for dir in "$SRC"/*/; do [ -f "$dir/brisc.elf.prov" ] && PROGRAMS+=("$(basename "$dir")"); done
|
|
fi
|
|
|
|
failed=0 identical=0 differing=0 missing=0 load_identical=0
|
|
: > "$OUT/summary.txt"
|
|
for name in "${PROGRAMS[@]}"; do
|
|
rm -rf "$OUT/$name"; mkdir -p "$OUT/$name"
|
|
if ! bash "$HERE/rebuild_tensix_program.sh" "$SRC/$name" "$OUT/$name" > "$OUT/$name.rebuild.log" 2>&1; then
|
|
echo "$name REBUILD FAILED (see $name.rebuild.log)" >> "$OUT/summary.txt"; failed=$((failed + 1)); continue
|
|
fi
|
|
bash "$HERE/diff_tensix_kernel_instructions.sh" --dir "$SRC/$name" "$OUT/$name" > "$OUT/$name.diff" 2>&1
|
|
for image in "$SRC/$name"/*.elf; do
|
|
file=$(basename "$image")
|
|
new="$OUT/$name/$file"
|
|
if [ ! -f "$new" ]; then verdict=MISSING; missing=$((missing + 1))
|
|
elif "$OBJCOPY" -O binary -j .text "$image" "$OUT/.a.text" 2>/dev/null &&
|
|
"$OBJCOPY" -O binary -j .text "$new" "$OUT/.b.text" 2>/dev/null &&
|
|
cmp -s "$OUT/.a.text" "$OUT/.b.text"; then
|
|
verdict=IDENTICAL; identical=$((identical + 1))
|
|
else verdict=DIFFERS; differing=$((differing + 1)); fi
|
|
text=$("$SIZE" -A "$new" 2>/dev/null | awk '$1 == ".text" {print $2}')
|
|
load=MISSING
|
|
[ -f "$new" ] && load=$(python3 "$HERE/compare_tensix_load_images.py" "$image" "$new" | cut -d: -f1)
|
|
[ "$load" = LOAD-IDENTICAL ] && load_identical=$((load_identical + 1))
|
|
printf '%-18s %-16s %-9s %-14s text %s\n' "$name" "$file" "$verdict" "$load" "${text:-?}" >> "$OUT/summary.txt"
|
|
done
|
|
done
|
|
{
|
|
echo
|
|
echo "programs: ${#PROGRAMS[@]} rebuild failures: $failed"
|
|
echo "images: $identical .text-identical, $differing differing, $missing missing"
|
|
echo "images LOAD-IDENTICAL (entry, every PT_LOAD, .segments): $load_identical"
|
|
echo "largest kernel .text: $(grep -v ' fw_' "$OUT/summary.txt" | awk '/ text [0-9]/ {print $NF, $1"/"$2}' | sort -n | tail -1)"
|
|
} >> "$OUT/summary.txt"
|
|
rm -f "$OUT/.a.text" "$OUT/.b.text"
|
|
echo DONE > "$OUT/DONE"
|