SuperNPUBench is a high-performance operator library and benchmark platform for
NPU tile-programming ISA. It ships two architecture backends under benchmark/
(two-level-arch = LinxISA, one-level-arch = PTO ISA) plus an instruction-level
microbenchmark suite, all driven by the same Linx toolchain.
SuperNPUBench/
├── benchmark/
│ ├── two-level-arch/ # Linx two-level block ISA (was benchmark-linxisa)
│ │ ├── kernels/ # header-only operator implementations
│ │ ├── test/ # test suites + build system
│ │ │ ├── common/ # shared Makefile.common, _start.s, benchmark.h
│ │ │ └── kernel/ # per-operator test cases
│ │ └── compile_all.sh
│ ├── one-level-arch/ # PTO one-level tile ISA (was benchmark-ptoisa)
│ │ ├── kernels/
│ │ ├── test/
│ │ └── compile_all.sh
│ └── (no docs/ — comparison docs were removed)
├── microbenchmark/ # instruction-level micro-bench (cube/vector/memory/scalar)
├── architecture/ # ISA reference docs
│ ├── linxisa-reference/ # LinxISA programming guide + ISA reference
│ └── ptoisa-reference/ # PTO ISA programming guide
└── compile_all.sh # top-level: two-level | one-level | all
Build outputs (
output/,**/output/) and.DS_Storeare gitignored.
- Block-structured ISA with heterogeneous cores: BCC (main), Cube (matrix), Vector, MTC/TMA (data transfer).
- Programming model: block instructions (VPAR/VSEQ, CUBE, TMA, TEPL).
- Reference:
architecture/linxisa-reference/.
- Tile-centric ISA with explicit memory hierarchy: Vec (UB), Mat (L1), Left (L0A), Right (L0B), Acc (L0C).
- Programming model: tile operations, Auto/Manual modes.
- Reference:
architecture/ptoisa-reference/.
Both backends share the same operator set and test layout; their kernel implementations differ in ISA style.
Each backend implements 10 operator categories:
| Operator | Description |
|---|---|
| matmul | FP4/BF16/FP32/FP16/FP8 matrix multiply; quantization, mixed precision, A/B reuse |
| fa | Flash Attention; 2D unroll, HIF4 quantization, unaligned boundary |
| transpose | 3D~6D tensor transpose; multiple dtypes |
| reduction | Row/column max & sum; single-tree, unaligned, cumsum, reduceprod |
| gelu | GELU activation; exact (erf) and tanh approximation |
| broadcast | 2D~5D broadcast; vectorized variants |
| gather | Data gathering; large-scale, power-of-2 dims |
| concat | Concatenation; gather/scatter modes |
| control | hashtable_lookup_simd (pure tile-op, single-tier gfsim) |
| sort | topk |
SuperNPUBench compiles with the Linx toolchain (linx_blockisa_llvm_musl,
clang-15, target linx64v5-unknown-linux-musl). Build it once from the
linx-toolchain-build repo,
which clones the matching ISA sources and produces the linx_blockisa_llvm_musl
install tree that COMPILER_DIR points at.
git clone https://github.com/LinxISA/linx-toolchain-build.git
cd linx-toolchain-buildsudo apt-get install -y git make cmake ninja-build gcc g++ python3 autoconf m4make init-src clones the five component repos under src/ on their pinned
branches (run it again any time to fetch updates):
| Directory | Repository | Branch |
|---|---|---|
src/llvm-project |
LinxISA/llvm-project |
dev-llvm15_56 |
src/musl |
LinxISA/linx-musl |
linx |
src/jemalloc |
LinxISA/jemalloc |
linx |
src/linux-linxisa |
LinxISA/linux |
main |
src/Linx-TileOP-API |
LinxISA/Linx-TileOP-API |
linx |
make init-srcOnly linx64v5-linux-musl is supported by the top-level Makefile:
make WITH_TARGET=linx64v5-linux-muslThis builds, in order: LLVM/clang/lld → kernel headers → musl → compiler-rt →
libc++/libc++abi/libunwind → jemalloc → Linx-TileOP-API headers. Progress is
tracked by stamp files under stamps/, so re-running make resumes from the
last completed step; make clean rebuilds from scratch. The install tree is
written to output/linx_blockisa_llvm_musl/:
output/linx_blockisa_llvm_musl/
├── bin/ # clang, clang++, ld.lld, llvm-ar/nm/ranlib,
│ # linx64v5-linux-musl-clang(++) symlinks
├── lib/ # clang runtime, libc++, ...
└── sysroot/ # musl + kernel headers + runtime libs
export COMPILER_DIR=$(pwd)/output/linx_blockisa_llvm_musl/bin
$COMPILER_DIR/clang --version
# clang version 15.0.4 (linx64v5-musl-local ...)
# Target: linx64v5-unknown-linux-muslThen proceed to Quick Start.
make package # -> output/linx_blockisa_llvm_musl.tar.gzThe build also works on Apple Silicon, but the system make (GNU 3.81) and
tar (libarchive) differ from the Linux defaults, so two extra steps are
needed:
- GNU make >= 4 is required by the kernel-headers step
(
GNU Make >= 4.0 is required).brew install make(providesgmake) and run the build withgmake, or putgmakeonPATHahead of/usr/bin/make(the kernel Makefile invokesmakeliterally). - GNU tar is required by
make package(tar --format=gnu).brew install gnu-tarand prepend$(brew --prefix)/opt/gnu-tar/libexec/gnubintoPATH. - sancov host-compile fix: Apple clang rejects an initializer-list in
llvm/tools/sancov/sancov.cpp(chosen constructor is explicit in copy-initialization). If the LLVM build fails there, change the twoSpecialCaseList::createOrDie({{...}}, ...)call sites to pass an explicitstd::vector<std::string>{...}, then resume withninja -C build/build-llvm-musl.
Build the Linx toolchain once (see Setup Environment), then
point COMPILER_DIR at it:
export COMPILER_DIR=/path/to/linx_blockisa_llvm_musl/bin# two-level-arch (LinxISA)
cd benchmark/two-level-arch/test/kernel/matmul
make TESTCASE=matmul TYPE=MASK MODE=MASK_FP32 M=256 N=256 K=256 tM=64 tN=64 tK=64
# one-level-arch (PTO ISA)
cd benchmark/one-level-arch/test/kernel/matmul
make TESTCASE=matmul TYPE=HIF4_HIF4 M=256 N=2048 K=2048 tM=128 tN=128 tK=128# per-operator batch
cd benchmark/two-level-arch/test/kernel/matmul && bash compile.all
# all operators of one backend
./compile_all.sh two-level # two-level-arch only
./compile_all.sh one-level # one-level-arch only
./compile_all.sh all # both (default)Artifacts land in benchmark/<arch>/output/kernel/<operator>/elf/.
microbenchmark/ is an instruction-level bench organized by ISA family,
generated by gen_cases.py. All 231 cases compile & link on the Linx toolchain.
| family | covers | cases |
|---|---|---|
| cube (CUBE) | TMATMUL / TMATMUL_BIAS / TMATMUL_MX / ACCCVT | 9 |
| vector (TEPL) | elementwise / tile-scalar / reduce / expand (toolchain-exposed subset) | 73 |
| memory (TLSU) | TLOAD / TSTORE / TMOV / MGATHER / MSCATTER (+mask, layout) | 25 |
| scalar (GPR) | int ALU / load-store / float / conversion × throughput+latency | 124 |
| total | 231 |
cd microbenchmark && make TESTCASE=tmatmul_fp16_64x64x64 # one case
cd microbenchmark && bash compile_all.sh all # all familiesSee microbenchmark/README.md for details.
LinxCoreModel provides two simulators:
gfrun— functional model (correctness)gfsim— cycle-accurate model (timing)
bin/gfrun -f benchmark/two-level-arch/output/kernel/<op>/elf/<name>.elf
bin/gfsim -f benchmark/two-level-arch/output/kernel/<op>/elf/<name>.elfKernels written purely with tile ops using TEPL template instructions (e.g.
control/hashtable_lookup_simd) run on the VectorLite engine, which gfsim only
steps in single-tier mode:
bin/gfsim -f <elf> -s core.singleTierMode=trueWithout this flag the engine is inert and the run deadlocks. gfrun does not
need the flag.
| Parameter | Description | Example |
|---|---|---|
TESTCASE |
Test case name | matmul, fa_2d_unroll |
TYPE |
Operator type (matmul) | HIF4_HIF4, A16W4, MASK |
MODE |
Operator mode | MASK_FP32, BF16x2_NOGATHER |
M/N/K |
Matrix dimensions | M=256 N=2048 K=2048 |
tM/tN/tK |
Tile sizes | tM=128 tN=128 tK=128 |
COMPILER_DIR |
Compiler path | /path/to/linx/bin |
PLAT |
Platform | linx (default), cpu |
make TESTCASE=<case> all # compile
make TESTCASE=<case> diss # disassembly
make TESTCASE=<case> sim # run in simulator
make TESTCASE=<case> debug # debug mode
make clean # clean current operator
make clean_all # clean all- LinxISA: programming guide (zh) | programming guide (en) | ISA reference
- PTO ISA: programming guide (zh) | programming guide (en)
fa_2d_unrollcompiler crash (Issue #6):X=1,Y=1/X=2,Y=1triggerAssertion failed: (Reg != 0 && "LinxV5 CallingConv Fail!"). AvoidYdim=1.control/hashtable_lookup_simd: pure tile-op kernel; run gfsim with-s core.singleTierMode=true(see above). Its.datafiles are generated by the Makefile (gen_data.py) on first build.- microbenchmark
tmatmul_acc: skipped — toolchainmatmul.acbackend crash. - microbenchmark vector subset: only toolchain-exposed TEPL opcodes are
generated;
TGEMV*/TMOVnot yet exposed (TCOPY fallback). Seemicrobenchmark/README.md.
- Compiler:
linx_blockisa_llvm_musl(clang-15, linx64v5-musl) - Flags:
-mlxbc -fenable-matrix -O2 -mllvm -enable-all-vector-as-tilereg=true -std=c++20 - Target: Linx64 V5
- Add header-only kernel under both
benchmark/<arch>/kernels/<operator>/. - Create test dir under both
benchmark/<arch>/test/kernel/<operator>/withMakefile,compile.all,src/. - Mirror the two backends.
- Header-only kernels; PTO tile-programming paradigm.
- Build artifacts not tracked (
.gitignore). - Keep both backends in parallel.
See LICENSE.