/* SPDX-License-Identifier: AGPL-3.0-or-later */ /* Copyright (C) 2026 David (Corey) Herrera */ /** * @file fm_golden_vectors.h * @brief Reader for the PNGOLDEN1 CPU-reference vectors the Metal kernel * tests check against. Header-only so a test file just includes it. * * PROVENANCE: the .bin files in metal/tests/golden are byte copies of the * qwen35moe golden set generated by Pantheon's gen_golden_qwen35.c from a * fixed xorshift32 seed (0x9E3779B9), regenerated there with * `make USE_BLAS=1 golden`. They are checked in here so foundry's tests * need no sibling checkout. Point FM_GOLDEN_DIR at a freshly regenerated * Pantheon set to check for drift. * * FILE FORMAT (self-describing): * line 1, ASCII: PNGOLDEN1 seed=0x9E3779B9\n * remainder: little-endian values * * @status Reads the f32 files, which is every vector these tests use. * @issues None * @todo None */ #ifndef FOUNDRY_METAL_TEST_GOLDEN_VECTORS_H #define FOUNDRY_METAL_TEST_GOLDEN_VECTORS_H #include #include #include /* Directory the vectors are read from. Set once at startup. */ static char fm_golden_dir[1024] = "metal/tests/golden"; /** * Points the reader at the golden directory: $FM_GOLDEN_DIR if set, * otherwise the `golden` directory beside the test binary, which makes the * tests runnable from any working directory. * * @param argv0 argv[0] of the test binary */ static void fm_golden_locate(const char *argv0) { const char *env = getenv("FM_GOLDEN_DIR"); if (env && env[0]) { snprintf(fm_golden_dir, sizeof(fm_golden_dir), "%s", env); return; } const char *slash = argv0 ? strrchr(argv0, '/') : NULL; if (slash) snprintf(fm_golden_dir, sizeof(fm_golden_dir), "%.*s/golden", (int)(slash - argv0), argv0); } /** * Reads a PNGOLDEN1 f32 vector. * * Never returns a short or silently defaulted buffer: a missing file, a bad * magic, a non-f32 dtype, a count that disagrees with `expect_count`, or a * truncated payload all print the reason and return NULL, so a test can * only ever run against the real oracle. * * @param name File name inside the golden directory * @param expect_count Element count the caller requires * @return malloc'd array of expect_count floats (caller frees), * or NULL */ static float *fm_golden_load_f32(const char *name, size_t expect_count) { char path[1152]; char header[256]; char magic[16] = {0}, vec_name[64] = {0}, dtype[8] = {0}; unsigned long count = 0; float *values = NULL; FILE *f = NULL; snprintf(path, sizeof(path), "%s/%s", fm_golden_dir, name); f = fopen(path, "rb"); if (!f) { fprintf(stderr, " golden: cannot open %s\n", path); return NULL; } if (!fgets(header, sizeof(header), f)) { fprintf(stderr, " golden: %s has no header line\n", path); goto cleanup; } if (sscanf(header, "%15s %63s %7s %lu", magic, vec_name, dtype, &count) != 4 || strcmp(magic, "PNGOLDEN1") != 0 || strcmp(dtype, "f32") != 0) { fprintf(stderr, " golden: %s has a bad header: %s", path, header); goto cleanup; } if (count != expect_count) { fprintf(stderr, " golden: %s holds %lu values, expected %zu\n", path, count, expect_count); goto cleanup; } values = (float *)malloc(expect_count * sizeof(float)); if (!values) { fprintf(stderr, " golden: out of memory for %s\n", path); goto cleanup; } if (fread(values, sizeof(float), expect_count, f) != expect_count) { fprintf(stderr, " golden: %s payload is truncated\n", path); free(values); values = NULL; } cleanup: fclose(f); return values; } #endif /* FOUNDRY_METAL_TEST_GOLDEN_VECTORS_H */