162 lines
8.1 KiB
Bash
Executable File
162 lines
8.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# Copyright (C) 2026 David (Corey) Herrera
|
|
#
|
|
# build_gdn_conv_depth_variant.sh
|
|
# Build a `gdn` program directory at a DIFFERENT CONV BLOCK DEPTH, derived from a shipped
|
|
# one's own provenance records.
|
|
#
|
|
# Usage: build_gdn_conv_depth_variant.sh <source-gdn-dir> <depth> <output-dir>
|
|
# Env: KERNELS where the named sources live (default ../kernels beside this script)
|
|
#
|
|
# ------------------------------------------------------------------------------
|
|
# WHY THIS IS NOT `rebuild_tensix_program.sh` WITH A KNOB
|
|
# ------------------------------------------------------------------------------
|
|
# `rebuild_tensix_program.sh` takes exactly one knob, `EXTRA_KERNEL_DEFINES`, and it
|
|
# APPENDS: a rebuild always applies what the directory recorded, so it can never come out as
|
|
# something other than what it was. The CONV depth is not a define, it is compile-time arg 7
|
|
# of the reader and arg 9 of the compute kernel, and moving it is a SUBSTITUTION. A
|
|
# substitution knob on the general rebuilder would be exactly the "invent a recipe" hazard
|
|
# that tool exists to refuse — a short or wrong CTARGS list folds to a literal 0 under SFPI
|
|
# GCC 15.1.0 with no diagnostic, which is how a `rope` rebuild once linked a smaller,
|
|
# functionally different kernel and reported the CONTROL as stale.
|
|
#
|
|
# So the substitution lives here, where it can be family-specific and checked:
|
|
# - the source directory must actually be a `gdn` program (its recorded sources are named)
|
|
# - the two ctargs that carry the depth must AGREE in the source before anything moves,
|
|
# because a source directory that already disagrees is not a base to derive from
|
|
# - both are rewritten to the same new value, and the arg COUNT is required to be
|
|
# unchanged, so a short list cannot come out of here
|
|
# - everything else — the CB table, watcher, relocation, defines, the writer's ctargs —
|
|
# comes from the records untouched
|
|
# The output records the substituted recipe, so the variant rebuilds itself faithfully from
|
|
# then on with `rebuild_tensix_program.sh` and needs this script exactly once.
|
|
#
|
|
# THE THIRD SIDE IS NOT THIS SCRIPT'S. The host must be told the same depth
|
|
# (`FT_TT_OP_GDN_CONV_DEPTH`), and it DECLARES that number on every CONV descriptor; both
|
|
# kernels refuse a descriptor whose declared depth is not the one they were built with. So a
|
|
# variant armed against a host at another depth REFUSES rather than running quietly at its
|
|
# own — see kGdnByteConvDepth in kernels/resident_gdn_protocol.h.
|
|
#
|
|
# Status: added 2026-08-27 for the CONV depth sweep.
|
|
# Issues: None
|
|
# Todo: None
|
|
#
|
|
set -euo pipefail
|
|
|
|
HERE=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
TT=$(cd -- "$HERE/.." && pwd)
|
|
KERNELS=${KERNELS:-$TT/kernels}
|
|
|
|
SOURCE_DIR=${1:?usage: build_gdn_conv_depth_variant.sh <source-gdn-dir> <depth> <output-dir>}
|
|
DEPTH=${2:?usage: build_gdn_conv_depth_variant.sh <source-gdn-dir> <depth> <output-dir>}
|
|
OUT=${3:?usage: build_gdn_conv_depth_variant.sh <source-gdn-dir> <depth> <output-dir>}
|
|
SOURCE_DIR=$(cd -- "$SOURCE_DIR" && pwd)
|
|
|
|
# Which compile-time arg carries the depth on each processor. Stated once here and asserted
|
|
# against the source's own values below; test_gdn_ops.c pins the same two indices against the
|
|
# kernel sources' documented build lines.
|
|
READER_DEPTH_INDEX=7
|
|
COMPUTE_DEPTH_INDEX=9
|
|
|
|
case "$DEPTH" in
|
|
''|*[!0-9]*) echo "build-gdn-depth: depth '$DEPTH' is not a number" >&2; exit 1;;
|
|
esac
|
|
if [ "$DEPTH" -lt 1 ] || [ "$DEPTH" -gt 255 ]; then
|
|
echo "build-gdn-depth: depth $DEPTH is outside 1..255 -- the host declares it in ONE BYTE" \
|
|
"of the CONV-taps word" >&2
|
|
exit 1
|
|
fi
|
|
|
|
recipe_value() {
|
|
awk -v want="$2" '$1 == "recipe" {
|
|
for (i = 2; i <= NF; i++) {
|
|
equals = index($i, "=")
|
|
if (substr($i, 1, equals - 1) == want) { print substr($i, equals + 1); exit }
|
|
}
|
|
}' "$1"
|
|
}
|
|
record_source() { awk '$1 == "source" { print $2; exit }' "$1"; }
|
|
|
|
# One comma list, one index, one new value -- and the LENGTH must not change, because a
|
|
# CTARGS list one short is the failure mode that folds to a literal 0 with no diagnostic.
|
|
substitute_ctarg() {
|
|
awk -v list="$1" -v index_wanted="$2" -v value="$3" '
|
|
BEGIN {
|
|
n = split(list, a, ",")
|
|
if (index_wanted + 1 > n) { print "SHORT"; exit }
|
|
a[index_wanted + 1] = value
|
|
out = a[1]
|
|
for (i = 2; i <= n; i++) out = out "," a[i]
|
|
print out
|
|
}'
|
|
}
|
|
ctarg_at() {
|
|
awk -v list="$1" -v index_wanted="$2" '
|
|
BEGIN { n = split(list, a, ","); if (index_wanted + 1 > n) print "SHORT"; else print a[index_wanted + 1] }'
|
|
}
|
|
|
|
for image in brisc ncrisc trisc0; do
|
|
[ -f "$SOURCE_DIR/$image.elf.prov" ] || {
|
|
echo "build-gdn-depth: $SOURCE_DIR has no $image.elf.prov -- it does not record how it" \
|
|
"was built, so nothing can be derived from it" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
READER_SRC=$(record_source "$SOURCE_DIR/brisc.elf.prov")
|
|
WRITER_SRC=$(record_source "$SOURCE_DIR/ncrisc.elf.prov")
|
|
COMPUTE_SRC=$(record_source "$SOURCE_DIR/trisc0.elf.prov")
|
|
if [ "$READER_SRC" != "resident_gdn_reader.c" ] || [ "$COMPUTE_SRC" != "resident_gdn_compute.c" ]; then
|
|
echo "build-gdn-depth: $SOURCE_DIR is not a gdn program -- it records $READER_SRC /" \
|
|
"$COMPUTE_SRC. The depth's arg indices are this family's and nothing else's." >&2
|
|
exit 1
|
|
fi
|
|
|
|
READER_CTARGS=$(recipe_value "$SOURCE_DIR/brisc.elf.prov" ctargs)
|
|
WRITER_CTARGS=$(recipe_value "$SOURCE_DIR/ncrisc.elf.prov" ctargs)
|
|
COMPUTE_CTARGS=$(recipe_value "$SOURCE_DIR/trisc0.elf.prov" ctargs)
|
|
CB_TABLE_NAME=$(recipe_value "$SOURCE_DIR/trisc0.elf.prov" cb_table)
|
|
WATCHER=$(recipe_value "$SOURCE_DIR/brisc.elf.prov" watcher)
|
|
LIGHTWEIGHT_ASSERTS=$(recipe_value "$SOURCE_DIR/brisc.elf.prov" lightweight_asserts)
|
|
RELOCATE_KERNEL_TEXT=$(recipe_value "$SOURCE_DIR/brisc.elf.prov" relocate_kernel_text)
|
|
KERNEL_DEFINES=$(recipe_value "$SOURCE_DIR/trisc0.elf.prov" defines)
|
|
|
|
SOURCE_READER_DEPTH=$(ctarg_at "$READER_CTARGS" "$READER_DEPTH_INDEX")
|
|
SOURCE_COMPUTE_DEPTH=$(ctarg_at "$COMPUTE_CTARGS" "$COMPUTE_DEPTH_INDEX")
|
|
if [ "$SOURCE_READER_DEPTH" = SHORT ] || [ "$SOURCE_COMPUTE_DEPTH" = SHORT ]; then
|
|
echo "build-gdn-depth: $SOURCE_DIR's CTARGS are too short to carry a depth" \
|
|
"(reader[$READER_DEPTH_INDEX], compute[$COMPUTE_DEPTH_INDEX])" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$SOURCE_READER_DEPTH" != "$SOURCE_COMPUTE_DEPTH" ]; then
|
|
echo "build-gdn-depth: $SOURCE_DIR ALREADY DISAGREES WITH ITSELF -- reader depth" \
|
|
"$SOURCE_READER_DEPTH, compute depth $SOURCE_COMPUTE_DEPTH. That is not a base to" \
|
|
"derive a variant from; fix the source directory first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
NEW_READER_CTARGS=$(substitute_ctarg "$READER_CTARGS" "$READER_DEPTH_INDEX" "$DEPTH")
|
|
NEW_COMPUTE_CTARGS=$(substitute_ctarg "$COMPUTE_CTARGS" "$COMPUTE_DEPTH_INDEX" "$DEPTH")
|
|
CB_TABLE=""
|
|
[ -n "$CB_TABLE_NAME" ] && CB_TABLE=$KERNELS/cb_tables/$CB_TABLE_NAME
|
|
|
|
echo "=== gdn CONV depth variant: $SOURCE_DIR ($SOURCE_READER_DEPTH) -> $OUT ($DEPTH)"
|
|
printf ' reader CTARGS %s\n -> %s\n' "$READER_CTARGS" "$NEW_READER_CTARGS"
|
|
printf ' compute CTARGS %s\n -> %s\n' "$COMPUTE_CTARGS" "$NEW_COMPUTE_CTARGS"
|
|
printf ' writer CTARGS %s (untouched)\n' "$WRITER_CTARGS"
|
|
printf ' CB_TABLE=%s WATCHER=%s LIGHTWEIGHT_ASSERTS=%s RELOCATE_KERNEL_TEXT=%s DEFINES=%s\n' \
|
|
"${CB_TABLE_NAME:-<none>}" "$WATCHER" "$LIGHTWEIGHT_ASSERTS" "$RELOCATE_KERNEL_TEXT" \
|
|
"${KERNEL_DEFINES:-<none>}"
|
|
echo " THE HOST MUST BE TOLD THE SAME NUMBER: FT_TT_OP_GDN_CONV_DEPTH=$DEPTH."
|
|
echo " A host at any other depth is REFUSED by both kernels, not silently run at $DEPTH."
|
|
|
|
mkdir -p "$OUT"
|
|
env READER_CTARGS="$NEW_READER_CTARGS" COMPUTE_CTARGS="$NEW_COMPUTE_CTARGS" \
|
|
WRITER_CTARGS="$WRITER_CTARGS" CB_TABLE="$CB_TABLE" \
|
|
WATCHER="$WATCHER" LIGHTWEIGHT_ASSERTS="$LIGHTWEIGHT_ASSERTS" \
|
|
RELOCATE_KERNEL_TEXT="$RELOCATE_KERNEL_TEXT" \
|
|
KERNEL_DEFINES="$KERNEL_DEFINES" \
|
|
bash "$TT/build_tensix_program.sh" \
|
|
"$KERNELS/$READER_SRC" "$KERNELS/$COMPUTE_SRC" "$KERNELS/$WRITER_SRC" "$OUT"
|