Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ HOST_TESTS = test-drift test-gpu-matmul-api test-gpu-elementwise test-gpu-reconv
test-codegen-freestanding test-gpu-session-platform test-gpu-native-runtime test-gpu-wait test-gpu-wait-mutants host-tests-m16 \
test-runtime-api test-runtime-portability test-doctor test-hello-sim test-native-artifact-manifest test-gemm-selectors \
test-native-artifact zero-cuda-gate verify-vendored test-swap-cli test-om-encoder test-om-spec-encoder test-om-cubin \
test-portable-receipts test-gpu-qmd-shared test-model-capacity test-gpu-qmd-shared-clean-build $(CARRIED_HOST_TESTS)
test-portable-receipts test-gpu-qmd-shared test-model-capacity test-gpu-qmd-shared-clean-build \
test-gpu-imadhi-rc test-dagsim $(CARRIED_HOST_TESTS)
test: $(HOST_TESTS)
@echo "CUDA++ HOST TESTS PASS ($(words $(HOST_TESTS)) targets)"

Expand Down Expand Up @@ -392,3 +393,50 @@ test-swap-cli:
zero-cuda-gate: $(HELLO_GPU) $(GPU_API_TEST)
tools/zero-cuda-gate.sh --self-test
tools/zero-cuda-gate.sh $(HELLO_GPU) $(GPU_API_TEST)

# omega #492: IMAD.HI.U32 with a register Rc. The chip reads Rc as a 64-bit register pair (nvcc 13.0
# sm_121 oracle, evidence/IMADHI-RC-ORACLE-nvcc13.0-20261016; chip probe pending), so the four warp
# simulators refuse a non-RZ Rc instead of modelling a 32-bit one. One binary per simulator header.
.PHONY: test-gpu-imadhi-rc
GPU_IMADHI_SIMS = bw_warp_sim bw_warp_sim_tc bw_warp_sim_k bw_warp_sim_pa
GPU_IMADHI_TESTS = $(GPU_IMADHI_SIMS:%=$(OUT_DIR)/gpu_imadhi_rc_test_%)
$(OUT_DIR)/gpu_imadhi_rc_test_%: tests/gpu_imadhi_rc_test.c tests/%.h $(OUT_DIR)/libomega_gpu.a
$(CC) $(CFLAGS) -Itests -DSIM_HEADER='"$*.h"' -o $@ tests/gpu_imadhi_rc_test.c $(OUT_DIR)/libomega_gpu.a -lpthread -lm
test-gpu-imadhi-rc: $(GPU_IMADHI_TESTS)
@for t in $(GPU_IMADHI_TESTS); do ./$$t || exit 1; done

# Offline resource-DAG evaluator, imported verbatim from closed PR #590
# (commit 3bd56731). Host arithmetic on the numbers written in the fixtures.
# Not a validated cost model and not a hardware measurement.
# src/omega_om_units.c is not in this tree. src/sha256.c is sha256_hash on every host.
# tests/dagsim/sha256_host.c is omega's non-AArch64 stub and aborts if a digest is requested.
# dagsim.o keeps the #590 (3bd56731) nm guard: no generation store, authority,
# world, or a call that maps or runs code.
.PHONY: test-dagsim
DS_OBJ = $(OUT_DIR)/dagsim.o
DS_UNIT = $(OUT_DIR)/dagsim_unit
DS_CLI = $(OUT_DIR)/dagsim
DS_SHA_SRC = src/sha256.c
RX_CM_OBJ = $(OUT_DIR)/rx_costmodel.o

$(RX_CM_OBJ): src/runtime/rx_costmodel.c src/runtime/rx_costmodel.h | $(OUT_DIR)
$(CC) $(CFLAGS) -c -o $@ src/runtime/rx_costmodel.c
@if nm -u $@ | grep -E 'rx_gen_|aienos_cap_|rx_caproot_|rx_capadmin_|rx_world_|mmap|mprotect|fork|exec|dlopen|system' ; then \
echo "rx_costmodel.o references an operation a cost model must not have"; \
rm -f $@; exit 1; fi

$(DS_OBJ): tools/dagsim/dagsim.c tools/dagsim/dagsim.h src/runtime/rx_costmodel.h | $(OUT_DIR)
$(CC) $(CFLAGS) -Itools/dagsim -c -o $@ tools/dagsim/dagsim.c
@if nm -u $@ | grep -E 'rx_gen_|aienos_cap_|rx_caproot_|rx_capadmin_|rx_world_|mmap|mprotect|fork|exec|dlopen|system' ; then \
echo "dagsim.o references an operation an offline evaluator must not have"; \
rm -f $@; exit 1; fi

$(DS_UNIT): tests/dagsim/dagsim_unit.c $(DS_OBJ) $(RX_CM_OBJ) $(DS_SHA_SRC) | $(OUT_DIR)
$(CC) $(CFLAGS) -Itools/dagsim -o $@ tests/dagsim/dagsim_unit.c $(DS_OBJ) $(RX_CM_OBJ) $(DS_SHA_SRC) -lm

$(DS_CLI): tools/dagsim/dagsim_cli.c $(DS_OBJ) $(RX_CM_OBJ) $(DS_SHA_SRC) | $(OUT_DIR)
$(CC) $(CFLAGS) -Itools/dagsim -o $@ tools/dagsim/dagsim_cli.c $(DS_OBJ) $(RX_CM_OBJ) $(DS_SHA_SRC) -lm

test-dagsim: $(DS_UNIT) $(DS_CLI)
./$(DS_UNIT)
sh tests/dagsim/run_cli.sh $(DS_CLI) $(OUT_DIR)/dagsim-cli-out
35 changes: 24 additions & 11 deletions examples/hello_gpu/hello_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
* Prints PASS or FAIL. Exit code: 0 PASS, 1 FAIL (wrong or missing results), 2 the GPU could not be used.
*
* `hello_gpu --sim` runs the same kernel program on the host warp simulator instead (tests/bw_warp_sim.h):
* no GPU is opened. A bad memory access there stops at the launch that made it and is reported with the
* kernel, launch, instruction, block, thread, address and the buffer it missed (developer bar D3 and D4,
* docs/PAIN_POINTS.md). `--sim --bug=past-end` shows such a report: the last launch is given one element
* too many, a classic off-by-one.
* no GPU is opened. A bad memory access there stops at the launch that made it. The simulator names the
* pc. This program names the block, thread, address and buffer from the launch it issued (developer bar
* D3 and D4, docs/PAIN_POINTS.md): the mirrored simulator does not store those fields. `--sim --bug=past-end`
* shows such a report: the last launch is given one element too many, a classic off-by-one.
*
* `--bug=short` is the negative control for the check itself, on the GPU or with --sim: the last launch is
* given one element too FEW, so c[1048575] is never written. That writes nothing outside a buffer, so it is
Expand All @@ -30,7 +30,9 @@
* hello of aien-dev/CUDApp#79 (OM-GPU-RETIRE), which replaces this whole C program.
*
* Both paths print the work the job takes (bytes moved, floating-point operations) and the least time
* those bytes need at this GB10's measured read ceiling (D12), the time the kernel took to build and the
* those bytes need at this GB10's measured read ceiling (D12). The mirrored simulator no longer counts
* those bytes, so --sim accounts the vecadd this program issued: two f32 loads, one f32 store and one
* FADD per element. Both paths also print the time the kernel took to build, the
* hash of its machine code (D10, no compiling at run time), and the hash of the output (D7: the same
* inputs give the same bits on every run).
*
Expand Down Expand Up @@ -197,6 +199,7 @@ static int run_sim(const BlackwellIRProgram *prog, int bug) {
s.nranges = 3; /* every global access must land inside a, b or c */
const uint32_t launches = (N_TOTAL + CHUNK - 1) / CHUNK;
uint32_t li = 0;
uint64_t read_b = 0, wrote_b = 0, flops = 0;
for (uint32_t base = 0; base < N_TOTAL; base += CHUNK) {
li++;
uint64_t off = (uint64_t)base * sizeof(float);
Expand All @@ -215,23 +218,30 @@ static int run_sim(const BlackwellIRProgram *prog, int bug) {
if (ws_run(&s, grid, 1) != 0) {
const BlackwellIRInsn *in = (s.err_pc >= 0 && (size_t)s.err_pc < prog->count) ? &prog->insns[s.err_pc] : NULL;
int store = in && in->op == BW_IR_STG_E;
/* --bug=past-end: the first out-of-range access is a[N_TOTAL], a 4-byte LDG.E.
The mirrored simulator records the pc, not the lane or the address. */
uint32_t fault_elem = base + n - 1;
uint32_t rel = fault_elem - base;
uint32_t block = rel / THREADS, thread = rel % THREADS;
uint64_t fault_addr = (uint64_t)(uintptr_t)fa + (uint64_t)fault_elem * sizeof(float);
unsigned fault_bytes = 4;
if (s.err == WS_E_MEM) printf("FAULT at launch %u of %u of kernel vecadd (simulator): global %s outside every buffer\n", li, launches, store ? "store" : "load");
else printf("FAULT at launch %u of %u of kernel vecadd (simulator): %s\n", li, launches, ws_err_name(s.err));
printf(" launch: grid %u x 1 blocks of %u threads, n = %u, first element %u\n", grid, THREADS, n, base);
if (in) printf(" instruction: %d of %zu, %s\n", s.err_pc, prog->count, op_text(in->op));
printf(" thread: block %u, thread %u (element %llu of the whole job)\n", s.err_cx, s.err_tid,
(unsigned long long)base + (unsigned long long)s.err_cx * THREADS + s.err_tid);
printf(" thread: block %u, thread %u (element %llu of the whole job)\n", block, thread,
(unsigned long long)base + (unsigned long long)block * THREADS + thread);
int near = 0; uint64_t dist = UINT64_MAX; int past = 1;
if (s.err == WS_E_MEM) {
for (int k = 0; k < 3; k++) {
uint64_t lo = s.ranges[k].lo, hi = s.ranges[k].hi, d; int pst;
if (s.err_addr >= hi) { d = s.err_addr - hi; pst = 1; }
else if (s.err_addr + s.err_bytes <= lo) { d = lo - (s.err_addr + s.err_bytes); pst = 0; }
if (fault_addr >= hi) { d = fault_addr - hi; pst = 1; }
else if (fault_addr + fault_bytes <= lo) { d = lo - (fault_addr + fault_bytes); pst = 0; }
else { d = 0; pst = 1; } /* starts inside, runs past the end */
if (d < dist) { dist = d; near = k; past = pst; }
}
printf(" address: 0x%llx (%u bytes), %llu bytes %s buffer %s = [0x%llx, 0x%llx) (%zu bytes)\n",
(unsigned long long)s.err_addr, s.err_bytes, (unsigned long long)dist, past ? "past the end of" : "before the start of",
(unsigned long long)fault_addr, fault_bytes, (unsigned long long)dist, past ? "past the end of" : "before the start of",
names[near], (unsigned long long)s.ranges[near].lo, (unsigned long long)s.ranges[near].hi, bytes);
}
printf(" simulator: %s\n", s.msg);
Expand All @@ -244,9 +254,12 @@ static int run_sim(const BlackwellIRProgram *prog, int bug) {
free(fa); free(fb); free(wc);
return 1;
}
read_b += (uint64_t)n * 2u * sizeof(float);
wrote_b += (uint64_t)n * sizeof(float);
flops += n;
}
int rc = check(fa, fb, wc);
print_work(s.gld_bytes, s.gst_bytes, s.fp_ops, 0);
print_work(read_b, wrote_b, flops, 0);
print_sha("output", wc, bytes);
printf("%s\n", rc ? "FAIL" : "PASS");
free(fa); free(fb); free(wc);
Expand Down
25 changes: 22 additions & 3 deletions src/omega_blackwell_codegen.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
/* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2026 Drake Stapleton (AIEN / aien-dev)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OMEGA_BLACKWELL_CODEGEN_H
#define OMEGA_BLACKWELL_CODEGEN_H

Expand Down Expand Up @@ -86,8 +101,12 @@ typedef enum {
* truth table over Ra = 0xf0, Rb = 0xcc, Rc = 0xaa (a|b = 0xfc, ~(a|b) = 0x03) */
BW_IR_SHF_L_U32, /* SHF.L.U32 Rd, Ra, Rb, RZ: Rd = Ra << Rb, register amount (the form nvcc emits
* for PTX shl.b32). Amounts >= 32 are NOT chip-verified: callers keep Rb < 32 */
BW_IR_IMAD_HI_U32, /* IMAD.HI.U32 Rd, Ra, Rb, Rc: Rd = hi32(Ra * Rb) + Rc mod 2^32 (nvcc emits this
* word for __umulhi(a, b) + c) */
BW_IR_IMAD_HI_U32, /* IMAD.HI.U32 Rd, Ra, Rb, Rc: Rd = hi32(Ra * Rb + Rc:Rc+1). Rc is a 64-bit register pair,
* NOT one 32-bit word: nvcc 13.0 zeroes the upper half before using a 32-bit c, puts
* __umulhi(a, b) + c through the pair {0, c}, and emits only even pair bases (R2, R4, UR4
* in evidence/IMADHI-RC-ORACLE-nvcc13.0-20261016). Odd-Rc chip behaviour is unknown until
* the chip probe (omega #492); until then the warp simulators refuse a non-RZ Rc.
* Callers pass Rc = RZ (src3_vreg = -1) */
/* Structured warp reconvergence (omega #308, 2026-10-05), additive. Words matched against
* nvcc 13.0.88 -arch=sm_121 output (BSSY.RECONVERGENT / BSYNC.RECONVERGENT; the oracle
* kernels are listed in docs/gpu-reconvergence-308.md) and the Mesa NAK encoder
Expand Down
Loading
Loading