The lock and reloads. load takes the board lock before it reconfigures, and the session check sees other runs of this tool and its scripts (their own parents excepted), so a reload waits for the job that holds the board. The scripts do not hold the lock across the steps they run. A reload of the same design, which passes the signature and the ID, is seen by the engine's uptime counter and its reset BOUND register: the engine checks both before it takes a workload or a table as loaded and after every job, and refuses a result read across a reload. A batch that comes back short, and a sampled chain whose sweep count is wrong, are refused. The AXI port. It checks the port's write width as well as its read width; it fills a result page with the illegal cell pair before a write-back and refuses a result still holding it; it refuses a transfer whose page moved. It is written against two traits, so a software link tests it off the board: the guard, the DMA, the sequencer's count, the write-back's layout, dropped accesses. Tests. lowered_settle's five cases and 300 random workloads with fields to 2^40 against the reference; the joint test counts against the chains requested and checks the control's cell family. CI gates on the change, requires tests to run, denies clippy warnings, certifies the model member, runs a job on it, builds on linux-arm64, and replays both testbenches in Icarus Verilog (scripts/run_tb.sh). The names check reads .v, .tcl, .xdc and .dat files. The build. The tool version and each block's version are enforced; the multi-core build refuses the AXI link. The documents. The latency table says how each row was timed; the engine's share of a chain is its own clock count; the sampling energy carries its error and its floor; the known answer is placed in time; the step response is reported; derived figures are marked; the scope of the meter, the guard's window and the DMA's locked pages are stated; provenance says what the private code declared; old names are gone; the build and simulator results have a raw record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
171 lines
6.7 KiB
Shell
Executable file
171 lines
6.7 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# check-public-names.sh
|
|
#
|
|
# Holds WAI's public text to its naming rule: it names no company, vendor,
|
|
# customer or commercial product. Standards, standards bodies, protocols,
|
|
# papers and open-source projects may be named, factually.
|
|
#
|
|
# The patterns for other parties' names are NOT in this repository. They are
|
|
# read from the environment variable WAI_NAME_DENYLIST: newline-separated
|
|
# POSIX extended regular expressions, matched case-sensitively (write `[Ff]oo`
|
|
# where both cases matter). In CI the variable comes from a forge Actions
|
|
# secret of the same name; locally, export it from a private file before
|
|
# committing:
|
|
#
|
|
# WAI_NAME_DENYLIST="$(cat /path/to/private/patterns)" scripts/check-public-names.sh
|
|
#
|
|
# A public list would itself publish the names it exists to keep out.
|
|
#
|
|
# The products of WAI's maintainers that their public site names
|
|
# (waiTransport, waiOS) are in this script, as MAINTAINER_PRODUCTS below. They
|
|
# are public already, so listing them here publishes nothing. The private list
|
|
# cannot hold them: it also checks the text of the product sites, which name
|
|
# them. A product the maintainers have not announced is named on no site, so
|
|
# the private list holds it until the day it is announced, when it moves here.
|
|
# The script requires the private list as before, and applies both lists
|
|
# together, with the same opt-out.
|
|
#
|
|
# With --maintainer-products-only as its first argument, the script applies
|
|
# MAINTAINER_PRODUCTS alone and reads no private list, so it needs no secret;
|
|
# CI runs it so on every change, a pull request included.
|
|
#
|
|
# Scope: the tracked files under wai/ with the extensions .md .rs .toml .py
|
|
# .sh .mjs .js .json .html .css .ttl .h .c .txt .wgsl, the logic's sources and
|
|
# build files (.v .tcl .xdc) and the measurements' logs (.dat), and wai/'s
|
|
# .gitignore files;
|
|
# or, when files are given as arguments, those files (the self-test,
|
|
# scripts/test-public-text-checks.sh, uses this), each a path relative to the
|
|
# directory the script is run from, or absolute. No file is excluded: the
|
|
# OER/2 documents and corpus once were, as settled text, until a minor version
|
|
# edited them; they pass, and a change to them is checked like any other.
|
|
#
|
|
# Opt-out, for a functional identifier only (a model-hub id a tool defaults
|
|
# to, a repository URL, an OS API name, a security advisory id, a capability
|
|
# string): put `allow-name: <reason>` on the same line, in a comment of the
|
|
# file's own syntax (`<!-- allow-name: reason -->`, `// allow-name: reason`,
|
|
# `# allow-name: reason`). The reason is required: it must contain a letter or
|
|
# a digit. Prose around such an identifier describes the standard or the
|
|
# function, not the owner.
|
|
#
|
|
# Exit status: 0 clean; 1 a hit; 2 WAI_NAME_DENYLIST unset or empty (unless
|
|
# --maintainer-products-only is given), a pattern grep cannot compile, a file
|
|
# given that is not a readable regular file (each such file is named), or any
|
|
# other grep error. The check never reads an error as "clean".
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
# The files given as arguments are paths from the caller's directory: remember it
|
|
# before moving to the repository's root, where the default scope is listed.
|
|
CALLER_DIR="$(pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
products_only=0
|
|
lists="WAI_NAME_DENYLIST and MAINTAINER_PRODUCTS"
|
|
if [ "${1:-}" = "--maintainer-products-only" ]; then
|
|
products_only=1
|
|
lists="MAINTAINER_PRODUCTS"
|
|
shift
|
|
fi
|
|
|
|
if [ $products_only -eq 0 ] && [ -z "${WAI_NAME_DENYLIST:-}" ]; then
|
|
echo "WAI_NAME_DENYLIST is not set: nothing to check against (see the header of $0)" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# The products of WAI's maintainers, in any case, joined or with one hyphen or
|
|
# underscore (a crate or a namespace spells them so). The shorter name must
|
|
# stand alone, so that a run of letters inside an encoded string is not a hit.
|
|
MAINTAINER_PRODUCTS=(
|
|
'[Ww][Aa][Ii][-_]?[Tt][Rr][Aa][Nn][Ss][Pp][Oo][Rr][Tt]'
|
|
'(^|[^[:alnum:]])[Ww][Aa][Ii][-_]?[Oo][Ss]([^[:alnum:]]|$)'
|
|
)
|
|
|
|
patterns="$(mktemp)"
|
|
out="$(mktemp)"
|
|
trap 'rm -f "$patterns" "$out"' EXIT
|
|
if [ $products_only -eq 0 ]; then
|
|
printf '%s\n' "$WAI_NAME_DENYLIST" | grep -v '^[[:space:]]*$' > "$patterns" || true
|
|
if [ ! -s "$patterns" ]; then
|
|
echo "WAI_NAME_DENYLIST holds no pattern" >&2
|
|
exit 2
|
|
fi
|
|
fi
|
|
printf '%s\n' "${MAINTAINER_PRODUCTS[@]}" >> "$patterns"
|
|
# Compile every pattern once before scanning. grep exits 1 when nothing matches
|
|
# and 2 on an error; only 0 and 1 mean the patterns are usable. grep's message
|
|
# is suppressed: it could quote a private pattern.
|
|
set +e
|
|
grep -E -f "$patterns" /dev/null >/dev/null 2>&1
|
|
rc=$?
|
|
set -e
|
|
if [ $rc -gt 1 ]; then
|
|
echo "::error::a pattern grep cannot compile is among $lists (grep exit $rc); nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
files=()
|
|
if [ $# -gt 0 ]; then
|
|
for f in "$@"; do
|
|
case "$f" in
|
|
/*) files+=("$f") ;;
|
|
*) files+=("$CALLER_DIR/$f") ;;
|
|
esac
|
|
done
|
|
else
|
|
while IFS= read -r f; do
|
|
files+=("$f")
|
|
done < <(git ls-files 'wai/*.md' 'wai/*.rs' 'wai/*.toml' 'wai/*.py' 'wai/*.sh' 'wai/*.mjs' 'wai/*.js' \
|
|
'wai/*.json' 'wai/*.html' 'wai/*.css' 'wai/*.ttl' 'wai/*.h' 'wai/*.c' 'wai/*.txt' \
|
|
'wai/*.gitignore' 'wai/*.wgsl' 'wai/*.v' 'wai/*.tcl' 'wai/*.xdc' 'wai/*.dat')
|
|
fi
|
|
if [ ${#files[@]} -eq 0 ]; then
|
|
echo "::error::no file to check" >&2
|
|
exit 2
|
|
fi
|
|
|
|
# A file grep cannot read makes it exit 2 with the whole list unchecked; name each
|
|
# such file instead of reporting a bare grep failure. File names are not private.
|
|
unreadable=0
|
|
for f in "${files[@]}"; do
|
|
if [ ! -f "$f" ] || [ ! -r "$f" ]; then
|
|
echo "::error::not a readable file: $f" >&2
|
|
unreadable=$((unreadable + 1))
|
|
fi
|
|
done
|
|
if [ $unreadable -gt 0 ]; then
|
|
echo "::error::$unreadable of ${#files[@]} files given cannot be read; nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
set +e
|
|
grep -HnE -f "$patterns" -- "${files[@]}" > "$out" 2>/dev/null
|
|
rc=$?
|
|
set -e
|
|
if [ $rc -gt 1 ]; then
|
|
echo "::error::grep failed (exit $rc) while scanning; nothing was checked" >&2
|
|
exit 2
|
|
fi
|
|
|
|
hits=0
|
|
while IFS= read -r line; do
|
|
content="${line#*:}"
|
|
content="${content#*:}"
|
|
if printf '%s' "$content" | grep -qE 'allow-name:[[:space:]]*[[:alnum:]]'; then
|
|
continue
|
|
fi
|
|
# Print the location only: the matched text may be a name the list keeps private.
|
|
if [ $hits -eq 0 ]; then
|
|
echo "::error::public text names a company, vendor, customer or product (patterns: $lists)"
|
|
fi
|
|
echo "${line%%:*}:$(printf '%s' "${line#*:}" | cut -d: -f1)"
|
|
hits=$((hits + 1))
|
|
done < "$out"
|
|
|
|
if [ $hits -gt 0 ]; then
|
|
echo "Fix: name the standard, the standards body, the open-source project or the function instead;"
|
|
echo "for a functional identifier, mark the line with allow-name: <reason>."
|
|
exit 1
|
|
fi
|
|
echo "public-name check ($lists): clean (${#files[@]} files)"
|