157 lines
7.6 KiB
Makefile
157 lines
7.6 KiB
Makefile
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# Copyright (C) 2026 David (Corey) Herrera
|
|
# Foundry Blackhole backend — the RESIDENT TRIAD gate.
|
|
#
|
|
# make -f Makefile.phase6 PHASE1B=1 all
|
|
#
|
|
# PHASE1B=1 is mandatory. Without it every device call returns FT_TT_EPERM before touching
|
|
# the NoC, which is the whole point of the fence (spec §7.3 — a wrong NoC coordinate hangs
|
|
# the chip and costs a physical power cycle).
|
|
#
|
|
# ---------------------------------------------------------------------------
|
|
# THE FOUR PROGRAM DIRECTORIES, AND WHY THERE ARE FOUR
|
|
# ---------------------------------------------------------------------------
|
|
# Three of them are the SAME SOURCE built with a different wait mode in the last
|
|
# compile-time arg. An A/B whose arms are two source files measures two implementations;
|
|
# an A/B whose arms differ by one build flag measures the flag. That is the same rule the
|
|
# Phase 5 dispatch measurement was built on (resident/one-shot from one source).
|
|
#
|
|
# K=kernels; RELOCATE_KERNEL_TEXT=1 CB_TABLE=$K/cb_tables/matmul_float16b.cbtable
|
|
#
|
|
# ../programs/rtriad wait mode 1 — stoppable (ask + bound). WHAT SHIPS.
|
|
# READER_CTARGS=0,1,2048,2048,1 COMPUTE_CTARGS=0,1,16,1 WRITER_CTARGS=16,2048,1
|
|
# ../programs/rtriad_upstream wait mode 0 — upstream's blocking waits. THE COST ARM.
|
|
# READER_CTARGS=0,1,2048,2048,0 COMPUTE_CTARGS=0,1,16,0 WRITER_CTARGS=16,2048,0
|
|
# *** NEVER DEADLOCK THIS BUILD. *** It has no escape and no bound, which is exactly
|
|
# the unstoppable wait that wedged Tensix 0 (dev notes §1). It exists to be timed.
|
|
# ../programs/rtriad_boundonly wait mode 2 — the bound, with the ask REMOVED. THE RED
|
|
# READER_CTARGS=0,1,2048,2048,2 COMPUTE_CTARGS=0,1,16,2 WRITER_CTARGS=16,2048,2
|
|
# PROOF. Deadlocking it is safe precisely because rule 4 bounds every wait independently
|
|
# of the ask, so a broken ask degrades to kErrCbWaitTimeout and not to a lost core.
|
|
# ../programs/matmul the Phase 4 arm, unchanged, from Makefile.ops
|
|
#
|
|
# All four must be built against ONE firmware build: a kernel is linked against its own
|
|
# firmware's exported symbols, so mixing directories is a wedged core, not a configuration.
|
|
#
|
|
# ---------------------------------------------------------------------------
|
|
# ../programs/rtriad_bfp8 — THE SHIPPING PRODUCTION BUILD (2026-08-14)
|
|
# ---------------------------------------------------------------------------
|
|
# The four above are bf16 (`IN1_TILE_BYTES=2048`) and serve the GATE, not a model: every
|
|
# matmul weight in a production artifact is block float. This is the same three kernels at
|
|
# the artifact's weight tile size, and it is what `pn_tt_matvec()` in Pantheon enqueues on.
|
|
#
|
|
# RELOCATE_KERNEL_TEXT=1 READER_CTARGS=0,1,2048,1088,1 COMPUTE_CTARGS=0,1,16,1 \
|
|
# WRITER_CTARGS=16,2048,1 CB_TABLE=$K/cb_tables/matmul_bfp8_b.cbtable \
|
|
# build_tensix_program.sh $K/resident_matmul_reader.c $K/resident_matmul_compute.c \
|
|
# $K/resident_matmul_writer.c ../programs/rtriad_bfp8
|
|
# (ABSOLUTE paths for every argument — build_tensix_program.sh fails on relative ones with
|
|
# a misleading `chlkc_unpack.cpp: No such file or directory`; see Makefile.ops)
|
|
#
|
|
# EVERY ctarg is READ OFF THE KERNEL rather than carried over from a neighbouring recipe —
|
|
# guessing them is what produced the Makefile.memory bug. The indices are declared in the
|
|
# three sources' own `ft_tensix_compile_time_arg(N)` lines:
|
|
# reader 0 CB_IN0 · 1 CB_IN1 · 2 IN0_TILE_BYTES · 3 IN1_TILE_BYTES · 4 WAIT_MODE
|
|
# compute 0 cb_in0 · 1 cb_in1 · 2 cb_out · 3 wait_mode
|
|
# writer 0 CB_OUT · 1 OUT_TILE_BYTES · 2 WAIT_MODE
|
|
# So 1088 is the WEIGHT (in1) ALONE: the activation and the output stay Float16_b/2048, and
|
|
# the CB table has to agree — it emits `0:Float16_b/2048B,1:Bfp8_b/1088B,16:Float16_b/2048B`
|
|
# and a reader built for 2048 against it reads a page and three quarters of the next one
|
|
# with nothing anywhere complaining.
|
|
#
|
|
# CHECK `size` ON EVERY IMAGE. The per-processor text slab is FT_TT_OP_TEXT_SLAB_BYTES,
|
|
# 0x3000 = 12288 B, and an over-slab image fails to load SILENTLY — no instruction diff sees
|
|
# it. Measured for this build: brisc 3532 · ncrisc 2160 · trisc0 2500 · trisc1 1580 ·
|
|
# trisc2 2380, so the widest is 29% of the slab. Then run
|
|
# `tools/check_tensix_program_sources.sh ../programs/rtriad_bfp8` before believing any
|
|
# result from it — it refuses a directory whose `.src` sidecars name sources that have moved.
|
|
#
|
|
# ONE build, not two. `rtriad_bfp4` is deliberately NOT built: the production ledger now
|
|
# puts `ffn_gate`/`ffn_up` at Bfp8_b (they measured +9.50% perplexity at Bfp4_b for no
|
|
# throughput), so a converted artifact holds a SINGLE matmul tile size — established by
|
|
# reading the written artifact back with `convert/tools/ft_tt_fttw_list`, not assumed. A
|
|
# core can hold one resident binary anyway (ft_tt_op_l1_layout.h divergence 2), so an
|
|
# artifact with two tile sizes would have needed two cores or two residencies.
|
|
#
|
|
# Run (detached, and never with these cores in use by another worker):
|
|
# FT_TT_FIRMWARE_DIR=../programs/rtriad FT_TT_TENSIX_INDICES=60,61 \
|
|
# ./build-phase6/test_phase6_triad ../programs/rtriad ../programs/rtriad_upstream \
|
|
# ../programs/rtriad_boundonly ../programs/matmul
|
|
#
|
|
# FT_TT_TENSIX_INDICES moves the whole run to a second, DISJOINT core pair without a
|
|
# rebuild — a result believed on one set of cores does not generalise (dev notes §3).
|
|
# FT_TT_TRIAD_AB_ITERATIONS sets how many matmuls each arm of the A/B runs.
|
|
|
|
CC ?= cc
|
|
SRC_DIR := ..
|
|
|
|
# The on-card harness opens the card through the product transport seam.
|
|
include hardware_session_sources.mk
|
|
BUILD := build-phase6
|
|
|
|
CFLAGS := -std=c99 -O1 -g \
|
|
-Wall -Wextra -Werror -pedantic \
|
|
-Wshadow -Wconversion -Wstrict-prototypes -Wformat=2 \
|
|
-fstack-protector-strong \
|
|
-I$(SRC_DIR)
|
|
|
|
DEPFLAGS := -MMD -MP
|
|
|
|
ifndef PHASE1B
|
|
$(error the triad gate drives the card: build with PHASE1B=1 or every device call is refused)
|
|
endif
|
|
CFLAGS += -DFT_TT_PHASE1B_NOC_ENABLED
|
|
|
|
SOURCES := $(SRC_DIR)/ft_tt_kmd.c \
|
|
$(SRC_DIR)/ft_tt_arch.c \
|
|
$(SRC_DIR)/ft_tt_arch_blackhole.c \
|
|
$(SRC_DIR)/ft_tt_device.c \
|
|
$(SRC_DIR)/ft_tt_tlb.c \
|
|
$(SRC_DIR)/ft_tt_coord.c \
|
|
$(SRC_DIR)/ft_tt_arc_telemetry.c \
|
|
$(SRC_DIR)/ft_tt_noc.c \
|
|
$(SRC_DIR)/ft_tt_buffer.c \
|
|
$(SRC_DIR)/ft_tt_elf.c \
|
|
$(SRC_DIR)/ft_tt_kernel_blob.c \
|
|
$(SRC_DIR)/ft_tt_udrv_claim.c \
|
|
$(SRC_DIR)/ft_tt_tensix_claim.c \
|
|
$(SRC_DIR)/ft_tt_launch.c \
|
|
$(SRC_DIR)/ft_tt_op_dispatch.c \
|
|
$(SRC_DIR)/ft_tt_op_matmul.c \
|
|
$(SRC_DIR)/ft_tt_tilize.c \
|
|
$(SRC_DIR)/ft_tt_queue.c \
|
|
$(SRC_DIR)/ft_tt_group.c \
|
|
$(SRC_DIR)/ft_tt_watchdog.c \
|
|
$(HARDWARE_SESSION_SOURCES) \
|
|
ft_tt_program_directory.c \
|
|
ft_tt_test_report.c \
|
|
test_phase6_triad.c
|
|
|
|
OBJECTS := $(sort $(addprefix $(BUILD)/,$(notdir $(SOURCES:.c=.o))))
|
|
TARGET := $(BUILD)/test_phase6_triad
|
|
|
|
.PHONY: all red clean
|
|
|
|
all: $(TARGET)
|
|
|
|
$(BUILD):
|
|
mkdir -p $(BUILD)
|
|
|
|
$(BUILD)/%.o: $(SRC_DIR)/%.c | $(BUILD)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
$(BUILD)/%.o: %.c | $(BUILD)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
$(TARGET): $(OBJECTS)
|
|
$(CC) $(CFLAGS) $(OBJECTS) -o $@ -lm
|
|
|
|
# `red` deletes the tree first. GNU make 3.81 compares mtimes at one-second granularity, so
|
|
# a source edited in the same second as its object is silently not rebuilt and a red/green
|
|
# proof runs the PREVIOUS binary (coding-best-practices §9).
|
|
red: clean all
|
|
|
|
clean:
|
|
rm -rf $(BUILD)
|
|
|
|
-include $(wildcard $(BUILD)/*.d)
|